/* StatusPulse public status page — independent from the main app's CSS on purpose.
   Keeps the status page bundle tiny so it loads under degraded network conditions. */

:root {
    /* Brand v1.1 — text/page/accent come from the new brand manual. The
       semantic warn/down colours (orange + red) are intentionally kept
       at the prior platform values: they're status indicators, not brand
       chrome, and customer-tinted views must not change them. */
    --ink:   #0E1A16;   /* color.text.primary (light) */
    --ink-3: #5A6660;   /* color.text.muted   (light) */
    --ink-4: #8FA09A;   /* derived — super-muted      */
    --paper: #FFFFFF;   /* color.page.bg      (light) */
    /* Card surface — paper tinted with the accent. Picks up the tenant's
       brand colour automatically. 10% mix is the same on both themes
       so the brand bleed is symmetric (matches preview block in the
       dashboard). */
    --paper-2: color-mix(in srgb, var(--ok) 10%, var(--paper));
    --line: rgba(14, 26, 22, 0.08);

    --ok: #18D883;   /* color.accent — identical hex in both modes */
    /* Soft variant of the accent — used as the pill background behind
       "Operational" status. Derived from --ok so customer brand colour
       flows through. 22% mix on light gives a clearly visible tint
       without overwhelming the pill text contrast. */
    --ok-soft: color-mix(in srgb, var(--ok) 22%, var(--paper));
    /* Heatmap "Up" cell colour — semantic, NOT brand-controlled. Stays
       the platform green even when the customer overrides --ok with a
       brand accent. Keeps uptime visualisation legible across themes
       regardless of brand choice. */
    --status-up-fixed: #18D883;
    --warn:      #ff7a1a;
    --warn-soft: #ffe4d0;
    --down:      #a32d2d;
    --down-soft: #fceaea;
    --unknown:   #9BA8A2;

    --radius: 10px;
    /* Compact-radius alias for sub-card controls (latency-window-select).
       Mirrors the Web app's --radius-sm so the visual language is shared
       even though the two CSS bundles are independent. */
    --radius-sm: 6px;
    /* Input control sizing tiers — mirrored from StatusPulse.Web's
       app.css so subscribe forms and inline pickers share the same
       four-height grid (lg=44px primary forms, sm=32px compact pickers).
       See docs/INPUT_CONTROL_TOKENS.md. Note: this app's body line-height
       is 1.5 (not Web's 1.6), so heights land ~1-2px shorter than the
       Web equivalents — acceptable since the two surfaces don't share
       a viewport. */
    --input-pad-y-lg: 11px; --input-pad-x-lg: 14px;
    --input-pad-y-sm: 6px;  --input-pad-x-sm: 10px;
    --container: 1440px;
}

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
    background: var(--paper);
    color: var(--ink);
    font-family: "Inter Tight", -apple-system, BlinkMacSystemFont, sans-serif;
    line-height: 1.5;
    font-size: 16px;
}

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

.status-header {
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap; gap: 16px;
    padding-bottom: 28px;
    margin-bottom: 28px;
    border-bottom: 1px solid var(--line);
}
/* Identity = logo (when present) + (h1 + domain) stacked vertically.
   Logo sits to the LEFT of the title block, both centred on the H1
   baseline. min-width:0 lets the title block ellipsis-truncate inside
   the flex parent rather than overflow. */
.status-header-identity {
    display: flex;
    align-items: center;
    gap: 14px;
    min-width: 0;
}
.status-header-logo {
    max-height: 48px;
    max-width: 200px;
    display: block;
    flex: 0 0 auto;
}
.status-header-titles {
    min-width: 0;
}
.status-header h1 {
    margin: 0;
    font-size: 28px;
    letter-spacing: -0.015em;
}
.status-domain {
    margin: 4px 0 0;
    font-family: "JetBrains Mono", ui-monospace, monospace;
    font-size: 12.5px;
    color: var(--ink-4);
}

.overall-pill {
    display: inline-flex; align-items: center; gap: 10px;
    padding: 8px 16px;
    border-radius: 999px;
    font-size: 14px; font-weight: 500;
}
.overall-pill .pulse {
    width: 8px; height: 8px; border-radius: 50%;
    animation: sp-pulse 2s ease-in-out infinite;
}
/* Operational pill text — derived from the accent so it stays readable
   regardless of the customer's brand colour. 60% accent + 40% ink gives
   a saturated text that reads against both the light and dark soft pill
   backgrounds. Warning + down pills keep semantic colours (orange/red)
   because their meaning is fixed by status, not brand. */
.pill-ok      { background: var(--ok-soft);   color: color-mix(in srgb, var(--ok) 60%, var(--ink)); }
.pill-ok      .pulse { background: var(--ok); }
.pill-warn    { background: var(--warn-soft); color: #9a3412; }
.pill-warn    .pulse { background: var(--warn); }
.pill-down    { background: var(--down-soft); color: var(--down); }
.pill-down    .pulse { background: var(--down); }
.pill-unknown { background: var(--paper-2);   color: var(--ink-3); }
.pill-unknown .pulse { background: var(--unknown); }

@keyframes sp-pulse {
    0%, 100% { transform: scale(1);   opacity: 1;   }
    50%      { transform: scale(1.4); opacity: 0.55; }
}

.services { list-style: none; margin: 0; padding: 0; }
.service-row {
    display: flex; flex-direction: column;
    gap: 12px;
    padding: 16px 18px;
    /* Tinted card — paper-2 is paper + 6-10% accent (see :root). Each
       row picks up the tenant brand without us having to touch every
       per-row rule. The 4 px left edge stays a saturated accent. */
    background: var(--paper-2);
    border: 1px solid var(--line);
    border-left-width: 4px;
    border-left-color: var(--ok);
    border-radius: var(--radius);
    margin-bottom: 8px;
    overflow: visible; /* tooltip needs to escape the row bounds */
}
.service-row-top {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 16px;
}
.service-row-chart {
    padding-top: 10px;
    border-top: 1px dashed var(--line);
}
.service-row-metrics {
    display: flex; flex-wrap: wrap; align-items: center; gap: 18px;
    padding-top: 8px;
    border-top: 1px dashed var(--line);
    font-size: 12.5px; color: var(--ink-3);
}
.metric-uptime { margin-left: auto; }
.service-info { min-width: 0; }
.service-row strong { display: block; font-size: 15px; }
.service-meta {
    display: block; margin-top: 2px;
    font-family: "JetBrains Mono", ui-monospace, monospace;
    font-size: 11.5px; color: var(--ink-4);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Heatmap chart — 24h × 6 ten-min slots (24 cols × 6 rows = 144 cells). The grid
   stretches to fill the card width via 1fr columns; cells keep 1:1 aspect so
   they scale responsively with the container. Y-axis labels align with row ticks,
   X-axis labels align with column ticks. */
.chart {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-rows: auto auto;
    column-gap: 8px;
    row-gap: 4px;
    width: 100%;
}

.chart-y-axis {
    grid-column: 1; grid-row: 1;
    display: flex; flex-direction: column; justify-content: space-between;
    font-family: "JetBrains Mono", ui-monospace, monospace;
    font-size: 10px; line-height: 1;
    color: var(--ink-4);
}

.chart-grid {
    grid-column: 2; grid-row: 1;
    display: grid;
    /* 48 columns (hours), variable width via 1fr. 6 rows (10-min slots) fixed at 10px
       so the chart stays a thin band regardless of viewport width. Cells become
       wide rectangles on large screens — intentional, width is responsive. */
    grid-template-columns: repeat(48, 1fr);
    grid-template-rows: repeat(6, 10px);
    grid-auto-flow: column;
    gap: 2px;
    width: 100%;
}

.cell {
    border-radius: 2px;
    background: var(--unknown);
    position: relative; /* anchor for ::after tooltip */
    transition: filter 0.15s, transform 0.15s;
    cursor: default;
    min-width: 0; min-height: 0;
}
.cell:hover { filter: brightness(1.15); transform: scale(1.25); z-index: 5; }
/* "Up" cell uses the fixed semantic green (not the customer's brand
   accent) — Marcelo: heatmap uptime should stay legible/identifiable
   across all customisations. */
.cell-ok      { background: var(--status-up-fixed); }
.cell-warn    { background: var(--warn); }
.cell-down    { background: var(--down); }
.cell-unknown { background: var(--unknown); }
.cell-empty   { background: var(--paper-2); }

/* Heatmap colour legend — three swatches above the language picker
   so visitors can decode the 48h cell grid without scrolling back to
   the row pills. Theme-aware: --status-up-fixed / --warn / --down all
   have dark-theme overrides further down, so the legend flips with
   body.theme-dark without an extra rule. Uses --status-up-fixed (not
   --ok) for parity with the cells: a tenant overriding --ok with
   their brand colour shouldn't desynchronise the legend from the
   heatmap. */
.heatmap-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 18px;
    justify-content: center;
    align-items: center;
    margin: 14px auto 8px;
    padding: 6px 12px;
    font-size: 12.5px;
    color: var(--ink-3);
}
.heatmap-legend-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.heatmap-legend-swatch {
    width: 10px; height: 10px;
    border-radius: 2px;
    display: inline-block;
    flex-shrink: 0;
}
.heatmap-legend-swatch-ok   { background: var(--status-up-fixed); }
.heatmap-legend-swatch-warn { background: var(--warn); }
.heatmap-legend-swatch-down { background: var(--down); }

/* CSS tooltip — replaces the default browser title tooltip, which is slow,
   unstyleable, and doesn't show on touch devices. Positions above the cell;
   the `::before` gives it a little arrow. */
.cell[data-tip]:hover::after {
    content: attr(data-tip);
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%) scale(0.8); /* counter-scale the hover zoom */
    padding: 6px 10px;
    background: var(--ink);
    color: var(--paper);
    font-family: "JetBrains Mono", ui-monospace, monospace;
    font-size: 11px; line-height: 1.3;
    border-radius: 4px;
    white-space: nowrap;
    z-index: 10;
    pointer-events: none;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
.cell[data-tip]:hover::before {
    content: "";
    position: absolute;
    bottom: calc(100% + 2px);
    left: 50%;
    transform: translateX(-50%) scale(0.8);
    border: 4px solid transparent;
    border-top-color: var(--ink);
    z-index: 10;
    pointer-events: none;
}

.chart-x-axis {
    grid-column: 2; grid-row: 2;
    display: flex; justify-content: space-between;
    font-family: "JetBrains Mono", ui-monospace, monospace;
    font-size: 10px; line-height: 1;
    color: var(--ink-4);
    padding-top: 2px;
}

.theme-toggle {
    color: var(--ink-3);
    border-bottom: 1px dotted var(--ink-4);
}
.theme-toggle:hover { color: var(--ok); border-bottom-color: var(--ok); }

.metric-pair { display: inline-flex; gap: 6px; align-items: baseline; }
.metric-pair strong {
    display: inline;
    font-family: "JetBrains Mono", ui-monospace, monospace;
    font-weight: 500; font-size: 13px;
    color: var(--ink);
}

.service-badges {
    display: flex; align-items: center; gap: 8px;
    flex-shrink: 0;
}

.service-status {
    padding: 4px 12px;
    border-radius: 6px;
    font-size: 13px; font-weight: 500;
    flex-shrink: 0;
}

/* SLA badge — twin pill next to .service-status. Reflects the rolling-window
   comparison vs. the monitor's configured SLA target; the status pill next to
   it is independent and reflects the latest check only. */
.sla-badge {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 10px;
    border-radius: 6px;
    font-size: 12px; font-weight: 500;
    font-family: "JetBrains Mono", ui-monospace, monospace;
    flex-shrink: 0;
}
.sla-badge-ok      { background: var(--ok-soft);      color: color-mix(in srgb, var(--ok) 60%, var(--ink)); }
.sla-badge-breach  { background: var(--down-soft);    color: var(--down); }
.sla-badge-unknown { background: var(--paper-2);      color: var(--ink-3); }

/* Status-driven row colour — border + tint track the current status pill.
   - OK rows pick up the **brand tint** (--paper-2 = paper + 10% accent).
     Matches the Branding tab preview; lets the customer's brand bleed into
     the operational visual.
   - Degraded / Down rows use the **site-standard** semantic tints
     (--warn-soft / --down-soft) — orange + red carry status meaning that
     should not be overridden by the customer's brand.
   - Paused / Unknown rows stay on the brand tint with a neutral border.
   SLA breach does NOT alter the row: it's conveyed only by the SLA badge. */
.service-row.status-row-ok      { background: var(--paper-2);   border-left-color: var(--ok); }
.service-row.status-row-warn    { background: var(--warn-soft); border-left-color: var(--warn); }
.service-row.status-row-down    { background: var(--down-soft); border-left-color: var(--down); }
.service-row.status-row-paused  { border-left-color: var(--unknown); }
.service-row.status-row-unknown { border-left-color: var(--unknown); }
.status-ok      { background: var(--ok-soft);   color: color-mix(in srgb, var(--ok) 60%, var(--ink)); }
.status-warn    { background: var(--warn-soft); color: #9a3412; }
.status-down    { background: var(--down-soft); color: var(--down); }
.status-paused  { background: var(--paper-2);   color: var(--ink-4); }
.status-unknown { background: var(--paper-2);   color: var(--ink-3); }

.empty {
    text-align: center;
    padding: 48px;
    background: var(--paper-2);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    color: var(--ink-3);
}

.last-updated {
    text-align: center;
    margin-top: 24px;
    font-size: 12px;
    color: var(--ink-4);
    font-family: "JetBrains Mono", ui-monospace, monospace;
}

/* Component group header — separator <li> emitted between consecutive
   monitors whose GroupId differs. Only rendered when the page has at
   least one MonitorGroup; pages without groups render a flat list. The
   row is purely visual (no semantic <h*> nested in <ul>) — section-
   level headings live in the layout above. */
.service-group-header {
    list-style: none;
    margin: 22px 0 6px;
    padding: 0 0 6px;
    border-bottom: 1px solid var(--line);
    font-size: 11.5px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--ink-3);
}
.service-group-header:first-child { margin-top: 0; }

/* Trust score panel — composite "service quality" metrics surfaced
   below the incident history on the public status page. Visually a
   subtle horizontal grid; nothing flashy because the numbers should
   speak for themselves. Auto-hides on pages with < 3 resolved
   incidents in the 90-day window (server-gated). */
.trust-score {
    max-width: var(--container);
    margin: 40px auto 0;
    padding: 20px 24px 22px;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--paper-2);
}
.trust-score-header {
    margin-bottom: 14px;
}
.trust-score-title {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--ink-2);
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.trust-score-sub {
    margin: 4px 0 0;
    font-size: 12px;
    color: var(--ink-4);
}
.trust-score-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
}
.trust-score-cell {
    text-align: center;
}
.trust-score-value {
    margin: 0;
    font-size: 24px;
    font-weight: 600;
    color: var(--ink);
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
}
.trust-score-label {
    margin: 4px 0 0;
    font-size: 11.5px;
    color: var(--ink-4);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
@media (max-width: 560px) {
    .trust-score-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: 18px 16px;
    }
}

.site-footer {
    max-width: var(--container);
    margin: 48px auto 32px;
    padding: 16px 24px;
    text-align: center;
    font-size: 12.5px;
    color: var(--ink-4);
    border-top: 1px solid var(--line);
}
.site-footer a { color: var(--ink-3); text-decoration: none; }
.site-footer a:hover { color: var(--ok); }

/* White-label footer override — tenant-supplied HTML rendered above
   the "Powered by" line. Inherits the parent's centred text + colour.
   Markdown anchors get the same hover treatment. */
.site-footer-custom {
    margin-bottom: 8px;
    font-size: 12.5px;
    color: var(--ink-3);
    line-height: 1.5;
}
.site-footer-custom p { margin: 0; }
.site-footer-custom a { color: var(--ink-2); text-decoration: underline; }
.site-footer-custom a:hover { color: var(--ok); }

/* Dark theme — default for the public status page. Applied via `body.theme-dark`.
   Mirrors the landing page's dark variant so a tenant's status domain visually
   matches the marketing site. Light mode is opt-in via ?theme=light.
   ============================================================================= */

body.theme-dark {
    --ink:   #F5F5F2;   /* color.text.primary (dark) */
    --ink-3: #9BA8A2;   /* color.text.muted   (dark) */
    --ink-4: #6c7872;   /* derived super-muted        */
    --paper: #0C120F;   /* color.page.bg      (dark) */
    /* Card surface (dark) — same 10% mix as light. Symmetric tint
       across both themes; light remains visible because the eye picks
       up small saturation increases against off-white. */
    --paper-2: color-mix(in srgb, var(--ok) 10%, var(--paper));
    --line: rgba(245, 245, 242, 0.08);

    --ok: #18D883;   /* color.accent — identical hex in both modes */
    /* Soft variant (dark) — same derivation as light, but 25% mix to
       compensate for the dark base (eye needs more saturation to read
       a tinted area against near-black). */
    --ok-soft:  color-mix(in srgb, var(--ok) 25%, var(--paper));
    /* Heatmap "Up" cell — same semantic-not-brand rule as light. */
    --status-up-fixed: #18D883;
    --warn:      #ff8a3a;
    --warn-soft: #3d2418;
    --down:      #ef6b6b;
    --down-soft: #3d1a1a;
    --unknown:   #555e58;

    background: var(--paper);
    color: var(--ink);
}

/* .service-row + .empty inherit `var(--paper-2)` directly. status-row-ok
   also uses --paper-2 (brand tint, matches preview), so no dark-theme
   override is needed. status-row-warn / status-row-down use the
   site-standard *-soft washes — those are already theme-aware via the
   :root vs body.theme-dark definitions of --warn-soft / --down-soft. */

/* Empty cells on dark theme blend into the row bg — raise them slightly. */
body.theme-dark .cell-empty { background: rgba(255, 255, 255, 0.06); }

/* Tooltip on dark theme — flip colors so the tooltip contrasts with its surroundings. */
body.theme-dark .cell[data-tip]:hover::after {
    background: var(--ink);
    color: var(--paper);
}
body.theme-dark .cell[data-tip]:hover::before { border-top-color: var(--ink); }

/* Pill text on dark theme — the *-ok variants now derive from --ok via
   color-mix so the customer's accent flows through (60% accent + 40%
   ink renders bright enough on the soft pill bg + dark page). The
   warn/down hexes stay static because they carry semantic meaning. */
body.theme-dark .pill-ok      { color: color-mix(in srgb, var(--ok) 60%, var(--ink)); }
body.theme-dark .pill-warn    { color: #ffb27a; }
body.theme-dark .pill-down    { color: #ff8a8a; }
body.theme-dark .status-ok    { color: color-mix(in srgb, var(--ok) 60%, var(--ink)); }
body.theme-dark .status-warn  { color: #ffb27a; }
body.theme-dark .status-down  { color: #ff8a8a; }
body.theme-dark .sla-badge-ok     { color: color-mix(in srgb, var(--ok) 60%, var(--ink)); }
body.theme-dark .sla-badge-breach { color: #ff8a8a; }

/* Latency history — small chart icon next to the "Average latency" metric,
   opens a centered modal with a line chart and period selector. All JS-driven
   (see Index.cshtml) so the SVG is rebuilt on window change without a page
   reload. Dark theme overrides at the bottom of this file. */
.latency-history-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 24px; height: 24px;
    margin-left: 6px;
    padding: 0;
    background: transparent;
    border: 1px solid var(--line);
    border-radius: 6px;
    color: var(--ink-3);
    cursor: pointer;
    transition: color 80ms ease, border-color 80ms ease, background 80ms ease;
}
.latency-history-btn:hover {
    color: var(--ok);
    border-color: var(--ok);
    background: var(--ok-soft);
}
.latency-history-btn:focus-visible {
    outline: 2px solid var(--ok);
    outline-offset: 2px;
}

.latency-modal {
    position: fixed; inset: 0;
    display: none;
    align-items: center; justify-content: center;
    z-index: 1000;
}
.latency-modal.open { display: flex; }
.latency-modal-backdrop {
    position: absolute; inset: 0;
    background: rgba(15, 18, 17, 0.55);
    backdrop-filter: blur(2px);
}
.latency-modal-content {
    position: relative;
    width: min(920px, 94vw);
    max-height: 88vh;
    overflow-y: auto;
    background: var(--paper);
    color: var(--ink);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: 0 20px 60px rgba(15, 18, 17, 0.25);
    padding: 22px 24px 20px;
}
.latency-modal-header {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 16px;
    margin-bottom: 14px;
}
.latency-modal-header h2 {
    margin: 0;
    font-size: 18px;
    letter-spacing: -0.01em;
}
.latency-modal-sub {
    margin: 4px 0 0;
    font-size: 13px; color: var(--ink-3);
}
.latency-modal-close {
    background: transparent; border: 0;
    font-size: 24px; line-height: 1;
    color: var(--ink-3);
    cursor: pointer;
    padding: 2px 8px;
    border-radius: 6px;
}
.latency-modal-close:hover { color: var(--ink); background: var(--paper-2); }

.latency-modal-controls {
    display: flex; align-items: center; gap: 10px;
    margin-bottom: 14px;
    font-size: 13px; color: var(--ink-3);
}
.latency-window-select {
    padding: var(--input-pad-y-sm) var(--input-pad-x-sm);
    font-size: 13px;
    background: var(--paper);
    color: var(--ink);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.latency-modal-chart {
    width: 100%;
    aspect-ratio: 2 / 1;
    min-height: 240px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--paper-2);
    display: flex; align-items: center; justify-content: center;
    overflow: hidden;
}
.latency-modal-meta {
    margin: 10px 0 0;
    font-family: "JetBrains Mono", ui-monospace, monospace;
    font-size: 12px; color: var(--ink-4);
}

.latency-svg { width: 100%; height: 100%; display: block; }
.latency-line {
    fill: none;
    stroke: var(--ok);
    stroke-width: 2;
    stroke-linejoin: round;
    stroke-linecap: round;
}
/* Trend line — semantic warn to stay distinct from both --ok (green
   latency) and --down (red error). Dashed to communicate "estimated"
   at a glance. */
.trend-line {
    stroke: var(--warn);
    stroke-width: 1.5;
    stroke-dasharray: 6 5;
    fill: none;
    opacity: 0.9;
}

/* Min / Avg / Max reference lines on the latency chart. Thinner than the
   trend line so the data line stays the visual focus. Brand v1.1: min
   uses a deeper accent shade (still brand-cohesive but distinct from
   the data line which is --ok); avg uses a neutral muted ink; max uses
   the semantic --down. */
.ref-line { fill: none; stroke-width: 1; stroke-dasharray: 4 3; opacity: 0.75; }
.ref-line-min { stroke: #0F9658; }
.ref-line-avg { stroke: var(--ink-3); }
.ref-line-max { stroke: var(--down); }
.ref-line-label { font-size: 11px; font-weight: 500; opacity: 0.9; }
.ref-line-label-min { fill: #0F9658; }
.ref-line-label-avg { fill: var(--ink-3); }
.ref-line-label-max { fill: var(--down); }

.latency-chart-legend {
    display: flex; flex-wrap: wrap; align-items: center; gap: 18px;
    margin-top: 12px;
    font-size: 12px; color: var(--ink-3);
}
.latency-chart-legend .legend-item {
    display: inline-flex; align-items: center; gap: 8px;
}
.latency-chart-legend .legend-swatch {
    display: inline-block;
    width: 18px; height: 0;
}
.latency-chart-legend .legend-swatch-line {
    border-top: 3px solid var(--ok);
}
.latency-chart-legend .legend-swatch-trend {
    border-top: 2px dashed var(--warn);
}
.latency-chart-legend .legend-swatch-min { border-top: 2px dashed #0F9658; }
.latency-chart-legend .legend-swatch-avg { border-top: 2px dashed var(--ink-3); }
.latency-chart-legend .legend-swatch-max { border-top: 2px dashed var(--down); }
.latency-chart-legend .legend-note {
    color: var(--ink-4);
    font-style: italic;
}

/* SLA history — tall-wide band of coloured bucket rects. Fills for each bucket
   come from inline style attributes set by JS (HSL interpolated around the SLA
   target) rather than CSS classes: every bucket has a unique colour and baking
   them into class rules would be senseless churn. */
.sla-history-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px;
    margin-left: 4px;
    padding: 0;
    background: transparent;
    border: 1px solid var(--line);
    border-radius: 6px;
    color: var(--ink-3);
    cursor: pointer;
    transition: color 80ms ease, border-color 80ms ease, background 80ms ease;
}
.sla-history-btn:hover {
    color: var(--ok);
    border-color: var(--ok);
    background: var(--ok-soft);
}
.sla-history-btn:focus-visible {
    outline: 2px solid var(--ok);
    outline-offset: 2px;
}

.sla-band-wrap {
    width: 100%;
    min-height: 120px;
    padding: 6px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--paper-2);
    display: flex; align-items: center; justify-content: center;
    overflow: hidden;
}
/* preserveAspectRatio="none" on the SVG — we want the band to stretch full
   width; the axis labels below don't need to preserve 1:1. */
.sla-band-svg {
    width: 100%;
    height: 120px;
    display: block;
}

.latency-chart-legend .sla-swatch {
    display: inline-block;
    width: 26px; height: 12px;
    border-radius: 3px;
    vertical-align: middle;
    margin-right: 6px;
}
.latency-chart-legend .sla-swatch-good {
    background: linear-gradient(to right, hsl(145, 45%, 72%), hsl(145, 70%, 32%));
}
.latency-chart-legend .sla-swatch-bad {
    background: linear-gradient(to right, hsl(2, 60%, 78%), hsl(2, 75%, 32%));
}
.latency-chart-legend .sla-swatch-gap { background: #3a3e3b; }
.chart-grid-line {
    stroke: var(--line);
    stroke-width: 1;
    stroke-dasharray: 2 4;
}
.chart-axis {
    stroke: var(--ink-4);
    stroke-width: 1;
}
.chart-axis-label {
    fill: var(--ink-3);
    font-family: "JetBrains Mono", ui-monospace, monospace;
    font-size: 14px;
}
.chart-axis-title {
    fill: var(--ink-3);
    font-family: "Inter Tight", sans-serif;
    font-size: 14px;
}

.latency-chart-loading,
.latency-chart-empty,
.latency-chart-error {
    font-size: 13px; color: var(--ink-3);
    padding: 16px;
    text-align: center;
}
.latency-chart-error { color: var(--down); }

body.theme-dark .latency-history-btn {
    border-color: rgba(255, 255, 255, 0.12);
    color: #b8c2be;
}
body.theme-dark .latency-history-btn:hover {
    color: #5fe5a7;
    border-color: #5fe5a7;
    background: rgba(95, 229, 167, 0.08);
}
body.theme-dark .latency-modal-content {
    background: #15191a;
    color: #e8ecea;
    border-color: rgba(255, 255, 255, 0.08);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
}
body.theme-dark .latency-modal-sub,
body.theme-dark .latency-modal-meta,
body.theme-dark .latency-modal-controls,
body.theme-dark .chart-axis-label,
body.theme-dark .chart-axis-title { color: #b8c2be; fill: #b8c2be; }
body.theme-dark .latency-modal-close { color: #b8c2be; }
body.theme-dark .latency-modal-close:hover { color: #e8ecea; background: rgba(255, 255, 255, 0.06); }
body.theme-dark .latency-window-select {
    background: #15191a; color: #e8ecea;
    border-color: rgba(255, 255, 255, 0.12);
}
body.theme-dark .latency-modal-chart {
    background: rgba(255, 255, 255, 0.03);
    border-color: rgba(255, 255, 255, 0.08);
}
body.theme-dark .latency-line { stroke: #5fe5a7; }
body.theme-dark .trend-line { stroke: #fbbf24; }
body.theme-dark .sla-history-btn {
    border-color: rgba(255, 255, 255, 0.12);
    color: #b8c2be;
}
body.theme-dark .sla-history-btn:hover {
    color: #5fe5a7;
    border-color: #5fe5a7;
    background: rgba(95, 229, 167, 0.08);
}
body.theme-dark .sla-band-wrap {
    background: rgba(255, 255, 255, 0.03);
    border-color: rgba(255, 255, 255, 0.08);
}
body.theme-dark .latency-chart-legend .sla-swatch-gap { background: #6a6e6b; }
body.theme-dark .latency-chart-legend .legend-swatch-line { border-top-color: #5fe5a7; }
body.theme-dark .latency-chart-legend .legend-swatch-trend { border-top-color: #fbbf24; }
body.theme-dark .ref-line-min { stroke: #38bdf8; }
body.theme-dark .ref-line-avg { stroke: #a78bfa; }
body.theme-dark .ref-line-max { stroke: #f87171; }
body.theme-dark .ref-line-label-min { fill: #38bdf8; }
body.theme-dark .ref-line-label-avg { fill: #a78bfa; }
body.theme-dark .ref-line-label-max { fill: #f87171; }
body.theme-dark .latency-chart-legend .legend-swatch-min { border-top-color: #38bdf8; }
body.theme-dark .latency-chart-legend .legend-swatch-avg { border-top-color: #a78bfa; }
body.theme-dark .latency-chart-legend .legend-swatch-max { border-top-color: #f87171; }
body.theme-dark .chart-grid-line { stroke: rgba(255, 255, 255, 0.08); }
body.theme-dark .chart-axis { stroke: rgba(255, 255, 255, 0.2); }
body.theme-dark .latency-chart-error { color: #ff8a8a; }

/* ============================================================================
   SSL monitor card — mirror of the authenticated dashboard card so the
   visual is identical across internal + public views. Uses the status-page
   tokens (--ok / --warn / --down) since this CSS is independent from the
   main app bundle.
   ============================================================================ */
.ssl-card {
    background: var(--paper-2);
    border: 1px solid var(--line);
    border-left-width: 4px;
    border-left-color: var(--unknown);
    border-radius: var(--radius);
    padding: 20px 24px;
    margin-bottom: 8px;
}

/* When the SSL card is an <li> inside the public status page's <ul.services>,
   the list item itself carries no chrome — the .ssl-card inside is the
   whole visual. Padding / margin / bg all live on .ssl-card. */
.services > li.service-row-ssl {
    display: block;
    padding: 0;
    margin: 0;
    background: transparent;
    border: 0;
}
/* Status tiers — outer tint + coloured left border, same palette as HTTP
   rows (service-row-ok / warn / down) so the public status page stays
   visually consistent across monitor types. */
/* SSL card status tints — same rule as .service-row:
   - OK uses brand tint (--paper-2, matches the Branding tab preview)
   - Warn / Down use site-standard semantic tints (orange / red)
   - Paused / Unknown rely on the base .ssl-card background */
.ssl-card-ok      { background: var(--paper-2);    border-left-color: var(--ok); }
.ssl-card-warn    { background: var(--warn-soft);  border-left-color: var(--warn); }
.ssl-card-down    { background: var(--down-soft);  border-left-color: var(--down); }
.ssl-card-paused  { border-left-color: var(--unknown); }
.ssl-card-unknown { border-left-color: var(--unknown); }
.ssl-card-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 16px;
}
.ssl-card-info strong { display: block; font-size: 16px; color: var(--ink); }
.ssl-card-info .sample-meta {
    display: block;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 12.5px;
    color: var(--ink-4);
    margin-top: 4px;
}
.ssl-card-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(180px, 200px);
    gap: 20px;
    align-items: stretch;
}
@media (max-width: 620px) {
    .ssl-card-grid { grid-template-columns: 1fr; }
}
.ssl-card-details {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 12px 24px;
}
@media (max-width: 820px) {
    .ssl-card-details { grid-template-columns: 1fr; }
}
.ssl-card-props {
    display: grid;
    grid-template-columns: 120px minmax(0, 1fr);
    gap: 6px 12px;
    margin: 0;
    padding: 0;
    font-size: 13.5px;
    align-content: start;
}
.ssl-card-props dt { color: var(--ink-4); margin: 0; }
.ssl-card-props dd {
    color: var(--ink-3);
    margin: 0;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 12.5px;
    word-break: break-word;
    overflow-wrap: anywhere;
}
.ssl-card-serial { word-break: break-all; }
.ssl-card-days {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 16px;
    border-radius: var(--radius);
    border: 1px solid var(--line);
    min-height: 140px;
}
.ssl-card-days-number {
    font-family: "Inter Tight", -apple-system, BlinkMacSystemFont, sans-serif;
    font-size: 56px;
    font-weight: 500;
    letter-spacing: -0.02em;
    line-height: 1;
    margin-bottom: 6px;
}
.ssl-card-days-unit { color: var(--ink-3); font-size: 13px; line-height: 1.4; }
.ssl-expiry-ok       { background: var(--ok-soft);   border-color: var(--ok); }
.ssl-expiry-ok       .ssl-card-days-number { color: var(--ok); }
.ssl-expiry-warn     { background: var(--warn-soft); border-color: var(--warn); }
.ssl-expiry-warn     .ssl-card-days-number { color: var(--warn); }
.ssl-expiry-down     { background: var(--down-soft); border-color: var(--down); }
.ssl-expiry-down     .ssl-card-days-number { color: var(--down); }
.ssl-expiry-unknown  { background: var(--paper-2); }
.ssl-expiry-unknown  .ssl-card-days-unit { color: var(--ink-4); }
.ssl-card-error {
    background: var(--down-soft);
    border-left: 3px solid var(--down);
    padding: 10px 14px;
    margin: 16px 0 0;
    font-size: 13.5px;
    color: var(--ink);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    border-radius: 4px;
    word-break: break-word;
}

/* ============================================================================
   Domain-expiration monitor card — mirror of the SSL card with status-page
   tokens. Same shape on the public status page as in the authenticated
   dashboard so visitors don't see a different aesthetic.
   ============================================================================ */
.domain-card {
    background: var(--paper-2);
    border: 1px solid var(--line);
    border-left-width: 4px;
    border-left-color: var(--unknown);
    border-radius: var(--radius);
    padding: 20px 24px;
    margin-bottom: 8px;
}
/* Domain card status tints — same rule as .service-row + .ssl-card:
   - OK / Active uses brand tint (--paper-2, matches Branding tab preview)
   - Warn / Down use site-standard semantic tints (orange / red)
   - Paused / Unknown rely on the base .domain-card background */
.domain-card-ok      { background: var(--paper-2);   border-left-color: var(--ok); }
.domain-card-warn    { background: var(--warn-soft); border-left-color: var(--warn); }
.domain-card-down    { background: var(--down-soft); border-left-color: var(--down); }
.domain-card-paused  { border-left-color: var(--unknown); }
.domain-card-unknown { border-left-color: var(--unknown); }
.domain-card-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 16px;
}
.domain-card-info strong { display: block; font-size: 16px; color: var(--ink); }
.domain-card-info .sample-meta {
    display: block;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 12.5px;
    color: var(--ink-4);
    margin-top: 4px;
}
.domain-card-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(180px, 200px);
    gap: 20px;
    align-items: stretch;
}
@media (max-width: 620px) {
    .domain-card-grid { grid-template-columns: 1fr; }
}
.domain-card-details {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 12px 24px;
}
@media (max-width: 820px) {
    .domain-card-details { grid-template-columns: 1fr; }
}
.domain-card-props {
    display: grid;
    grid-template-columns: 120px minmax(0, 1fr);
    gap: 6px 12px;
    margin: 0;
    padding: 0;
    font-size: 13.5px;
    align-content: start;
}
.domain-card-props dt { color: var(--ink-4); margin: 0; }
.domain-card-props dd {
    color: var(--ink-3);
    margin: 0;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 12.5px;
    word-break: break-word;
    overflow-wrap: anywhere;
}
.domain-card-status-codes { word-break: break-all; }
.domain-card-days {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 16px;
    border-radius: var(--radius);
    border: 1px solid var(--line);
    min-height: 140px;
}
.domain-card-days-number {
    font-family: "Inter Tight", -apple-system, BlinkMacSystemFont, sans-serif;
    font-size: 56px;
    font-weight: 500;
    letter-spacing: -0.02em;
    line-height: 1;
    margin-bottom: 6px;
}
.domain-card-days-unit { color: var(--ink-3); font-size: 13px; line-height: 1.4; }
.domain-expiry-ok      { background: var(--ok-soft);   border-color: var(--ok); }
.domain-expiry-ok      .domain-card-days-number { color: var(--ok); }
.domain-expiry-warn    { background: var(--warn-soft); border-color: var(--warn); }
.domain-expiry-warn    .domain-card-days-number { color: var(--warn); }
.domain-expiry-down    { background: var(--down-soft); border-color: var(--down); }
.domain-expiry-down    .domain-card-days-number { color: var(--down); }
.domain-expiry-unknown { background: var(--paper-2); }
.domain-expiry-unknown .domain-card-days-unit { color: var(--ink-4); }
.domain-card-error {
    background: var(--down-soft);
    border-left: 3px solid var(--down);
    padding: 10px 14px;
    margin: 16px 0 0;
    font-size: 13.5px;
    color: var(--ink);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    border-radius: 4px;
    word-break: break-word;
}

/* Public status page has its own pill class family (status-ok / status-warn
   / status-down) rather than sample-status-*. Alias the sample-status-*
   classes used by the shared partial so the card renders correctly here. */
.sample-status-ok      { background: var(--ok-soft);   color: var(--ok); }
.sample-status-warn    { background: var(--warn-soft); color: var(--warn); }
.sample-status-down    { background: var(--down-soft); color: var(--down); }
.sample-status-paused  { background: var(--paper-2);   color: var(--ink-3); }
.sample-status-unknown { background: var(--paper-2);   color: var(--ink-3); }
.sample-status-ok,
.sample-status-warn,
.sample-status-down,
.sample-status-paused,
.sample-status-unknown {
    padding: 3px 10px;
    border-radius: 12px;
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
}

/* ---- Incidents (Phase 1) -------------------------------------------------
   Public-facing banner above the service list (one per active incident),
   per-incident detail timeline, history list. Mirrors the dashboard
   pill colours so an operator scanning both surfaces sees the same shape. */
.incident-banner-stack {
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin: 24px 0 28px 0;
}
.incident-banner {
    border: 1px solid var(--line);
    border-left-width: 4px;
    border-radius: var(--radius);
    padding: 16px 18px;
    background: var(--paper-2);
}
.incident-banner-minor    { border-left-color: var(--warn); background: var(--warn-soft); }
.incident-banner-major    { border-left-color: var(--warn); background: var(--warn-soft); }
.incident-banner-critical { border-left-color: var(--down); background: var(--down-soft); }
.incident-banner-none     { border-left-color: var(--ink-4); }

.incident-banner-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 8px;
}
.incident-banner-title {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    min-width: 0;
}
.incident-banner-title h2 {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
}
.incident-banner-title h2 a {
    color: var(--ink);
    text-decoration: none;
}
.incident-banner-title h2 a:hover { text-decoration: underline; }
.incident-banner-body {
    color: var(--ink);
    font-size: 14px;
    line-height: 1.55;
}
.incident-banner-body p { margin: 0 0 6px 0; }
.incident-banner-body p:last-child { margin-bottom: 0; }
.incident-banner-meta {
    margin: 8px 0 0 0;
    color: var(--ink-3);
    font-size: 12.5px;
}

.incident-state-pill,
.incident-severity-pill {
    display: inline-flex;
    align-items: center;
    padding: 2px 9px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 600;
    line-height: 18px;
    letter-spacing: 0.01em;
}
.incident-state-investigating { background: var(--warn-soft); color: var(--warn); }
.incident-state-identified    { background: var(--warn-soft); color: var(--warn); }
.incident-state-monitoring    { background: var(--ok-soft);   color: var(--ok); }
.incident-state-resolved,
.incident-state-postmortempublished,
.incident-state-comment       { background: var(--paper-2);   color: var(--ink-3); }
.incident-state-scheduled     { background: var(--paper-2);   color: var(--ink-3); }

.incident-severity-none     { background: var(--paper-2); color: var(--ink-4); }
.incident-severity-minor    { background: var(--warn-soft); color: var(--warn); }
.incident-severity-major    { background: var(--warn-soft); color: var(--warn); }
.incident-severity-critical { background: var(--down-soft); color: var(--down); }

/* History block — last-30-days resolved incidents below the service list. */
.incident-history {
    margin-top: 32px;
    padding-top: 24px;
    border-top: 1px solid var(--line);
}
.incident-history-title {
    margin: 0 0 14px 0;
    font-size: 16px;
    font-weight: 600;
    color: var(--ink-3);
}
.incident-history-list { list-style: none; margin: 0; padding: 0; }
.incident-history-item {
    padding: 12px 0;
    border-bottom: 1px solid var(--line);
}
.incident-history-item:last-child { border-bottom: 0; }
.incident-history-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}
.incident-history-link {
    color: var(--ink);
    font-weight: 500;
    text-decoration: none;
    font-size: 15px;
}
.incident-history-link:hover { text-decoration: underline; }
.incident-history-meta {
    margin: 4px 0 6px 0;
    color: var(--ink-4);
    font-size: 12.5px;
}
.incident-history-summary {
    color: var(--ink-3);
    font-size: 13.5px;
    line-height: 1.5;
}
.incident-history-summary p { margin: 0 0 4px 0; }
.incident-history-summary p:last-child { margin-bottom: 0; }

/* Per-incident public detail page. */
.incident-section-title {
    margin: 24px 0 12px 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--ink-3);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.incident-empty { color: var(--ink-4); font-size: 14px; }
.incident-header-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    color: var(--ink-3);
    font-size: 13.5px;
    margin-top: 8px;
}
.incident-meta-sep { color: var(--ink-4); }

.incident-components-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.incident-component-pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    border-radius: 999px;
    font-size: 13px;
    background: var(--paper-2);
}
.incident-component-name { font-weight: 500; }
.incident-component-impact {
    color: var(--ink-3);
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.incident-component-majoroutage   { background: var(--down-soft); color: var(--down); }
.incident-component-partialoutage { background: var(--warn-soft); color: var(--warn); }
.incident-component-degraded      { background: var(--warn-soft); color: var(--warn); }
.incident-component-operational   { background: var(--ok-soft);   color: var(--ok); }
.incident-component-pill .incident-component-impact { color: inherit; }

.incident-timeline-public {
    list-style: none;
    margin: 0;
    padding: 0;
}
.incident-timeline-item {
    border-left: 2px solid var(--line);
    padding: 6px 0 18px 18px;
    margin-left: 6px;
}
.incident-timeline-item:last-child { padding-bottom: 6px; }
.incident-timeline-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    color: var(--ink-3);
    font-size: 12.5px;
    margin-bottom: 6px;
}
.incident-timeline-body {
    color: var(--ink);
    font-size: 14px;
    line-height: 1.55;
}
.incident-timeline-body p { margin: 0 0 8px 0; }
.incident-timeline-body p:last-child { margin-bottom: 0; }
.incident-timeline-body code {
    background: var(--paper-2);
    padding: 1px 6px;
    border-radius: 4px;
    font-size: 0.92em;
}
.incident-timeline-body pre {
    background: var(--paper-2);
    padding: 10px 12px;
    border-radius: var(--radius);
    overflow-x: auto;
    font-size: 13px;
}
.incident-timeline-body a { color: var(--ok); }

.back-link {
    display: inline-block;
    color: var(--ink-3);
    text-decoration: none;
    font-size: 13px;
    margin-bottom: 4px;
}
.back-link:hover { color: var(--ok); }

/* Dark-theme overrides — pill chrome already adapts via --warn-soft etc. */
body.theme-dark .incident-banner { background: var(--paper-2); }
body.theme-dark .incident-banner-minor,
body.theme-dark .incident-banner-major { background: var(--warn-soft); }
body.theme-dark .incident-banner-critical { background: var(--down-soft); }
body.theme-dark .incident-state-investigating,
body.theme-dark .incident-state-identified,
body.theme-dark .incident-severity-minor,
body.theme-dark .incident-severity-major { color: var(--warn); }
body.theme-dark .incident-severity-critical { color: var(--down); }
body.theme-dark .incident-state-monitoring { color: var(--ok); }
body.theme-dark .incident-history-link { color: var(--ink); }
body.theme-dark .incident-history-summary { color: var(--ink-3); }
body.theme-dark .incident-timeline-item { border-left-color: rgba(255, 255, 255, 0.16); }

/* ---- Public subscribe (Phase 3) -----------------------------------------
   Subscribe button in the status header, and the standalone Subscribe /
   Confirm / Unsubscribe pages. Visually quieter than the overall pill —
   subscribers are an opt-in surface, not the page's headline. */
.status-header-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}
.subscribe-button {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 14px;
    border-radius: 999px;
    border: 1px solid var(--line);
    background: var(--paper);
    color: var(--ink);
    font-size: 13px;
    font-weight: 500;
    text-decoration: none;
    transition: background 0.12s, border-color 0.12s;
}
.subscribe-button:hover {
    background: var(--paper-2);
    border-color: var(--ink-4);
}
body.theme-dark .subscribe-button {
    background: var(--paper-2);
    border-color: rgba(255, 255, 255, 0.12);
}
body.theme-dark .subscribe-button:hover {
    background: rgba(255, 255, 255, 0.08);
    border-color: rgba(255, 255, 255, 0.30);
}

.subscribe-section {
    max-width: 520px;
    margin: 0 auto;
}
.subscribe-lead {
    color: var(--ink-3);
    font-size: 15px;
    margin: 0 0 22px 0;
}
.subscribe-error {
    background: var(--down-soft);
    color: var(--down);
    padding: 12px 14px;
    border-radius: 8px;
    margin-bottom: 16px;
    font-size: 14px;
}

.subscribe-form { display: flex; flex-direction: column; gap: 16px; }

/* Submit button with inline spinner. The JS toggles [data-loading] on
   submit, which hides the label (visibility:hidden keeps the button
   width stable so it doesn't reflow) and reveals the spinner. */
.subscribe-submit { position: relative; }
.subscribe-submit-label { transition: opacity 120ms ease; }
.subscribe-submit-spinner {
    position: absolute;
    inset: 0;
    margin: auto;
    width: 16px; height: 16px;
    border-radius: 50%;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-top-color: #fff;
    opacity: 0;
    pointer-events: none;
    animation: subscribe-spin 720ms linear infinite;
}
.subscribe-submit[data-loading] .subscribe-submit-label { visibility: hidden; }
.subscribe-submit[data-loading] .subscribe-submit-spinner { opacity: 1; }
.subscribe-submit[data-loading] { cursor: progress; }
@keyframes subscribe-spin {
    to { transform: rotate(360deg); }
}
.subscribe-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    font-size: 13.5px;
    color: var(--ink-3);
}
.subscribe-field span em { font-style: italic; color: var(--ink-4); }
.subscribe-field input {
    padding: var(--input-pad-y-lg) var(--input-pad-x-lg);
    border-radius: var(--radius);
    border: 1px solid var(--line);
    background: var(--paper);
    color: var(--ink);
    font-size: 14px;
    font-family: inherit;
}
.subscribe-field input:focus {
    outline: 2px solid var(--ok);
    outline-offset: 1px;
    border-color: var(--ok);
}
body.theme-dark .subscribe-field input {
    background: var(--paper-2);
    border-color: rgba(255, 255, 255, 0.12);
    color: var(--ink);
}

.subscribe-prefs {
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 14px 16px;
    margin: 0;
    color: var(--ink);
}
.subscribe-prefs legend {
    padding: 0 6px;
    font-size: 12.5px;
    color: var(--ink-3);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.subscribe-checkbox {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 0;
    font-size: 14px;
}
.subscribe-checkbox input { margin: 0; }

.subscribe-submit {
    align-self: flex-start;
    padding: 10px 22px;
    background: var(--ok);
    color: #fff;
    border: 0;
    border-radius: 8px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.12s;
}
.subscribe-submit:hover { background: var(--ok); filter: brightness(0.92); }

.subscribe-meta {
    color: var(--ink-4);
    font-size: 12.5px;
    margin: 0;
}

.subscribe-callout {
    background: var(--paper-2);
    border-left: 3px solid var(--ok);
    padding: 18px 20px;
    border-radius: 8px;
    color: var(--ink);
}
.subscribe-callout-success { border-left-color: var(--ok); }
.subscribe-callout-error { border-left-color: var(--down); }
.subscribe-callout h2 {
    margin: 0 0 8px 0;
    font-size: 17px;
}
.subscribe-callout p {
    margin: 0 0 6px 0;
    font-size: 14px;
}

/* ============================================================================
   Public modal (CSS-only :target). Used by the Subscribe + success modals on
   the status page Index. Centered overlay; click on backdrop / Close link
   navigates to #close which clears :target.
   ============================================================================ */
.sp-modal {
    position: fixed; inset: 0;
    display: none;
    align-items: center; justify-content: center;
    z-index: 1000;
}
.sp-modal:target,
.sp-modal.sp-modal-open { display: flex; }
.sp-modal-backdrop {
    position: absolute; inset: 0;
    background: rgba(15, 18, 17, 0.55);
    backdrop-filter: blur(2px);
    text-decoration: none;
}
.sp-modal-content {
    position: relative;
    width: min(480px, 94vw);
    max-height: 88vh;
    overflow-y: auto;
    background: var(--paper);
    color: var(--ink);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: 0 20px 60px rgba(15, 18, 17, 0.25);
    padding: 22px 24px 20px;
}
body.theme-dark .sp-modal-content {
    background: var(--paper-2);
    border-color: rgba(255, 255, 255, 0.08);
}
.sp-modal-header {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 16px;
    margin-bottom: 8px;
}
.sp-modal-header h2 {
    margin: 0;
    font-size: 18px;
    letter-spacing: -0.01em;
}
.sp-modal-close {
    background: transparent; border: 0;
    font-size: 24px; line-height: 1;
    color: var(--ink-3);
    cursor: pointer;
    padding: 2px 8px;
    border-radius: 6px;
    text-decoration: none;
}
.sp-modal-close:hover { color: var(--ink); background: var(--paper-2); }
.sp-modal-lead {
    margin: 0 0 16px;
    font-size: 13.5px; color: var(--ink-3);
    line-height: 1.55;
}
.sp-modal-actions {
    display: flex; align-items: center; gap: 10px;
    margin-top: 18px;
}
.sp-modal-actions .btn {
    display: inline-flex; align-items: center; justify-content: center;
    padding: 9px 18px;
    border-radius: 8px;
    font-size: 14px; font-weight: 600;
    border: 1px solid transparent;
    cursor: pointer;
    text-decoration: none;
    font-family: inherit;
}
.sp-modal-actions .btn-primary {
    background: var(--ok);
    color: #fff;
}
.sp-modal-actions .btn-primary:hover { filter: brightness(0.92); }
.sp-modal-actions .btn-ghost {
    background: transparent;
    color: var(--ink-3);
    border-color: var(--line);
}
.sp-modal-actions .btn-ghost:hover { background: var(--paper-2); color: var(--ink); }

/* Toggle switch — minimal version of the dashboard pattern. Pairs with
   .subscribe-toggle-row so the toggle + label baseline-align. */
.subscribe-toggle-row {
    display: flex; align-items: center; gap: 12px;
    padding: 6px 0;
    font-size: 14px;
    color: var(--ink);
}
.toggle-switch {
    position: relative;
    display: inline-block;
    width: 36px; height: 22px;
    flex-shrink: 0;
}
.toggle-switch input[type="checkbox"] {
    opacity: 0; width: 0; height: 0;
    position: absolute;
}
.toggle-switch .toggle-slider {
    position: absolute; inset: 0;
    background: var(--ink-4);
    border-radius: 22px;
    cursor: pointer;
    transition: background 0.15s;
}
.toggle-switch .toggle-slider::before {
    content: "";
    position: absolute;
    left: 3px; top: 3px;
    width: 16px; height: 16px;
    background: #fff;
    border-radius: 50%;
    transition: transform 0.15s;
}
/* General-sibling selector (~) rather than adjacent (+) so the toggle
   keeps working when extra inputs sit between the checkbox and the
   slider — the subscribe modal puts a hidden companion input there
   so unchecked toggles still POST a "false" value, and an adjacent
   selector would silently break the visual state in that case. */
.toggle-switch input[type="checkbox"]:checked ~ .toggle-slider { background: var(--ok); }
.toggle-switch input[type="checkbox"]:checked ~ .toggle-slider::before {
    transform: translateX(14px);
}
.toggle-switch input[type="checkbox"]:focus-visible ~ .toggle-slider {
    outline: 2px solid var(--ok);
    outline-offset: 2px;
}
.subscribe-callout p:last-child { margin-bottom: 0; }
body.theme-dark .subscribe-callout { background: var(--paper-2); }

/* Phase 4 — public scheduled-maintenance banner. Sits between the header
   pill and the active-incident stack. Quieter colour than the incident
   banners (warn/down) — maintenance is informational, not an outage. */
.maintenance-banner-stack {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin: 24px 0 18px 0;
}
.maintenance-banner {
    border: 1px dashed var(--ink-4);
    border-radius: var(--radius);
    padding: 14px 18px;
    background: var(--paper-2);
}
.maintenance-banner-header {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
}
.maintenance-banner-kicker {
    margin: 0 0 4px 0;
    font-size: 11.5px;
    color: var(--ink-3);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
}
.maintenance-banner h2 {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
}
.maintenance-banner h2 a {
    color: var(--ink);
    text-decoration: none;
}
.maintenance-banner h2 a:hover { text-decoration: underline; }
.maintenance-banner-window {
    color: var(--ink-3);
    font-size: 12.5px;
    font-family: "JetBrains Mono", ui-monospace, monospace;
}
.maintenance-banner-body {
    margin-top: 8px;
    color: var(--ink);
    font-size: 13.5px;
    line-height: 1.55;
}
.maintenance-banner-body p { margin: 0 0 6px 0; }
.maintenance-banner-body p:last-child { margin-bottom: 0; }

body.theme-dark .maintenance-banner {
    background: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.20);
}

/* Phase 7 — Public post-mortem detail page + history-list badge. */
.postmortem-kicker {
    margin: 0 0 4px 0;
    font-size: 11.5px;
    color: var(--ink-3);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
}
.postmortem-link {
    color: var(--ok);
    text-decoration: none;
    font-weight: 500;
}
.postmortem-link:hover { text-decoration: underline; }

.postmortem-summary {
    margin: 28px 0 24px 0;
    padding: 16px 18px;
    background: var(--paper-2);
    border-left: 3px solid var(--ok);
    border-radius: var(--radius);
}
.postmortem-summary h2 { margin-top: 0; }
.postmortem-summary p {
    margin: 0;
    font-size: 16px;
    color: var(--ink);
    line-height: 1.55;
}
.postmortem-section {
    margin: 24px 0;
}
.postmortem-section-title {
    margin: 0 0 12px 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--ink-3);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.postmortem-body {
    color: var(--ink);
    font-size: 15px;
    line-height: 1.6;
}
.postmortem-body p { margin: 0 0 10px 0; }
.postmortem-body p:last-child { margin-bottom: 0; }
.postmortem-body code {
    background: var(--paper-2);
    padding: 1px 6px;
    border-radius: 4px;
    font-size: 0.92em;
}
.postmortem-body pre {
    background: var(--paper-2);
    padding: 12px 14px;
    border-radius: var(--radius);
    overflow-x: auto;
    font-size: 14px;
}
.postmortem-body ul,
.postmortem-body ol { padding-left: 22px; margin: 8px 0; }
.postmortem-body li { margin: 4px 0; }
.postmortem-body a { color: var(--ok); }

/* History-list badge linking to the post-mortem. Sits next to severity. */
.incident-history-tags {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.postmortem-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px 9px;
    border-radius: 999px;
    background: var(--paper-2);
    color: var(--ok);
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-decoration: none;
    border: 1px solid var(--ok);
}
.postmortem-badge:hover { background: var(--ok-soft); }

body.theme-dark .postmortem-summary { background: var(--paper-2); }
body.theme-dark .postmortem-badge {
    background: rgba(16, 192, 116, 0.15);
    color: var(--ok);
    border-color: var(--ok);
}
body.theme-dark .postmortem-badge:hover { background: rgba(16, 192, 116, 0.25); }

