/*
    Hand written CSS rather than Tailwind, because this project has no npm step. Every value below is
    the literal value the matching Tailwind utility would have produced in LobFile, so the two sites
    line up when you put them side by side. Where a rule exists to mirror a specific LobFile class, the
    class is named in a comment so the correspondence stays checkable.

    The site is dark only. There is no light theme and no toggle.

    The page is laid out to fit one screen. Body and main are a flex column sized to the viewport, and
    the incident panel is the single flexible element that takes up the slack and scrolls inside itself.
    Nothing is ever clipped: if the content genuinely does not fit, on a short laptop or a phone, the
    page scrolls normally instead.
*/

:root {
    /* Colors carried over from LobFile's @theme block. */
    --color-Primary: #3476F6;
    --color-Primary-foreground: #FFFFFF;
    --color-Secondary: #424242;
    --color-Secondary-foreground: #FFFFFF;

    /*
        Status colors, the one palette this site adds. Three of them carry health and they mean exactly
        three things: green is up, yellow is a partial issue, red is down. Gray is not a health color,
        it means there is no data to draw.
    */
    --color-Operational: #22C55E;
    --color-Degraded: #EAB308;
    --color-Outage: #EF4444;
    --color-Unknown: #4B5563;
    --color-Maintenance: #3476F6;

    /* Tailwind gray-700, which is the border color every LobFile panel uses. */
    --color-panel-border: #374151;

    --shadow-custom: 0px 4px 16.2px 2px rgba(0, 0, 0, 0.2);

    --radius: 0.5rem;
}

/*
    Open Sans is LobFile's typeface. It is not self hosted here yet because there is no build step to
    copy the files out of node_modules. Dropping the woff2 files into /fonts/open-sans/ and
    uncommenting the @font-face block below is all it takes; until then the stack falls through to the
    system UI face, which keeps the page loading without reaching out to a third party font CDN. A
    status page should not have an external dependency it does not need.

@font-face {
    font-family: 'Open Sans';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/fonts/open-sans/open-sans-latin-400-normal.woff2') format('woff2');
}
*/

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

html {
    scroll-behavior: smooth;
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    background-color: #0F1118;
    color: #FFFFFF;
    font-family: 'Open Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    font-size: 16px;
    line-height: 1.5;
}

button {
    cursor: pointer;
}

a {
    color: inherit;
    text-decoration: none;
}

/* LobFile's .section-padding-x, including its non standard 1460px step. */
.section-padding-x {
    padding-left: 16px;
    padding-right: 16px;
}

@media screen and (min-width: 650px) {
    .section-padding-x {
        padding-left: 20px;
        padding-right: 20px;
    }
}

@media screen and (min-width: 1460px) {
    .section-padding-x {
        padding-left: 120px;
        padding-right: 120px;
    }
}

/* ---------------------------------------------------------------- navbar */

/* sticky top-0 z-50 backdrop-blur-2xl, transparent until scrolled. */
.navbar {
    position: sticky;
    top: 0;
    z-index: 50;
    flex: 0 0 auto;
    backdrop-filter: blur(40px);
    -webkit-backdrop-filter: blur(40px);
    background-color: transparent;
    transition: background-color 0.2s ease, box-shadow 0.2s ease;
}

/* bg-black/70 shadow-lg once window.scrollY > 10. */
.navbar.is-scrolled {
    background-color: rgba(0, 0, 0, 0.7);
    box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
}

/* Vertical padding is tighter than LobFile's py-6, because the header is pure overhead on a page
   whose whole job is to fit on one screen. */
.navbar-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 16px;
}

@media screen and (min-width: 650px) {
    .navbar-inner {
        padding: 14px 20px;
    }
}

@media screen and (min-width: 1460px) {
    .navbar-inner {
        padding: 14px 120px;
    }
}

.navbar-brand {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

/* The wordmark is roughly 7:1, so it is sized by height and given room to shrink on a narrow phone
   rather than pushing the nav button off the row. */
.navbar-logo {
    height: 22px;
    width: auto;
    max-width: 100%;
    display: block;
}

@media screen and (min-width: 480px) {
    .navbar-logo {
        height: 26px;
    }
}

/* Shown only if the logo file has not been copied into /images yet. */
.navbar-brand-fallback {
    display: none;
    font-size: 20px;
    font-weight: 700;
    letter-spacing: -0.01em;
}

.navbar-brand-label {
    color: rgba(255, 255, 255, 0.6);
    font-size: 17px;
    font-weight: 600;
}

.navbar-links {
    display: flex;
    align-items: center;
    gap: 16px;
}

/* LobFile's nav link, including the underline that grows from the left on hover. Sized a little
   smaller than LobFile's text-lg, to sit level with the button beside it in a shorter navbar. */
.nav-link {
    position: relative;
    font-weight: 600;
    font-size: 15px;
    color: #FFFFFF;
    white-space: nowrap;
    transition: color 0.3s ease;
}

.nav-link::before {
    content: "";
    position: absolute;
    left: 0;
    bottom: -4px;
    width: 0;
    height: 2px;
    background-color: var(--color-Primary);
    transition: width 0.3s ease;
}

.nav-link:hover {
    color: var(--color-Primary);
}

.nav-link:hover::before {
    width: 100%;
}

/* The current page keeps its underline drawn rather than waiting for a hover. */
.nav-link[aria-current="page"] {
    color: var(--color-Primary);
}

.nav-link[aria-current="page"]::before {
    width: 100%;
}

/* The primary variant of LobFile's shared button component. */
.button-primary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 7px 16px;
    border: 1px solid var(--color-Primary);
    border-radius: 6px;
    background-color: rgba(52, 118, 246, 0.5);
    color: #FFFFFF;
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    transition: background-color 0.2s ease;
}

.button-primary:hover {
    background-color: var(--color-Primary);
}

@media screen and (min-width: 650px) {
    .button-primary {
        padding: 8px 20px;
        font-size: 15px;
    }
}

/* ---------------------------------------------------------------- layout */

.page {
    width: 100%;
    max-width: 1400px;
    margin: 0 auto;
    padding-top: 14px;
    padding-bottom: 14px;
    display: flex;
    flex-direction: column;
    gap: 12px;

    /* Takes every pixel the navbar and footer do not, and min-height 0 is what allows a flex child to
       be smaller than its content so the incident list can scroll inside instead of pushing the page
       taller. */
    flex: 1 1 auto;
    min-height: 0;
}

@media screen and (min-width: 650px) {
    .page {
        padding-top: 20px;
        padding-bottom: 20px;
        gap: 16px;
    }
}

/* LobFile's Section component: border border-gray-700 rounded-xl, with the padding tightened from
   p-6 so the region rows and an incident list share one screen. */
.panel {
    border: 1px solid var(--color-panel-border);
    border-radius: 12px;
    padding: 14px 16px;
    color: #FFFFFF;
    flex: 0 0 auto;
}

@media screen and (min-width: 650px) {
    .panel {
        padding: 16px 20px;
    }
}

.panel-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 10px;
}

.section-heading {
    font-size: 17px;
    font-weight: 600;
    margin: 0;
}

@media screen and (min-width: 768px) {
    .section-heading {
        font-size: 19px;
    }
}

.panel-head-note {
    color: rgba(255, 255, 255, 0.5);
    font-size: 12px;
}

.muted {
    color: rgba(255, 255, 255, 0.5);
    font-size: 14px;
    margin: 0;
}

.inline-link {
    color: var(--color-Primary);
    text-decoration: underline;
}

/* ---------------------------------------------------------------- state pills */

/*
    State is never carried by color alone. Every pill pairs its color with an icon and a written label,
    which is what makes the page readable for colorblind users and legible in a grayscale screenshot.
*/
.state-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 10px;
    border-radius: 999px;
    border: 1px solid currentColor;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
}

.state-pill-large {
    padding: 6px 16px;
    font-size: 17px;
    gap: 10px;
}

@media screen and (min-width: 768px) {
    .state-pill-large {
        font-size: 21px;
    }
}

/* The written half of every state pill. It never wraps, because a pill that breaks "Limited
   (bandwidth)" across two lines changes the height of the row it sits in. */
.state-text {
    white-space: nowrap;
}

.state-icon {
    display: inline-flex;
    align-items: center;
}

.state-icon svg {
    display: block;
    width: 16px;
    height: 16px;
}

.state-pill-large .state-icon svg {
    width: 24px;
    height: 24px;
}

.state-pill[data-state="operational"] {
    color: var(--color-Operational);
    background-color: rgba(34, 197, 94, 0.12);
}

.state-pill[data-state="degraded"] {
    color: var(--color-Degraded);
    background-color: rgba(234, 179, 8, 0.12);
}

.state-pill[data-state="outage"] {
    color: var(--color-Outage);
    background-color: rgba(239, 68, 68, 0.12);
}

.state-pill[data-state="unknown"],
.state-pill[data-state="loading"],
.state-pill[data-state="error"] {
    color: #9CA3AF;
    background-color: rgba(75, 85, 99, 0.2);
}

/* ---------------------------------------------------------------- banner */

.banner {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
}

.banner-sub {
    margin: 0;
    color: rgba(255, 255, 255, 0.5);
    font-size: 13px;
}

.banner.is-error {
    border-color: rgba(239, 68, 68, 0.6);
}

/* ---------------------------------------------------------------- region rows */

/*
    One row per region rather than one card per region. Bordered cards stacked in a grid cost far
    more vertical space in borders, padding, and headings than they earn, and a status page is read by
    scanning down a column of states.
*/
.region-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.region-row {
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.region-row + .region-row {
    padding-top: 10px;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.region-row-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px 10px;
}

.region-name {
    margin: 0;
    font-size: 15px;
    font-weight: 600;
}

.region-location {
    color: rgba(255, 255, 255, 0.5);
    font-size: 13px;
}

.region-badge {
    display: inline-block;
    margin-left: 8px;
    padding: 1px 8px;
    border-radius: 999px;
    border: 1px solid rgba(52, 118, 246, 0.6);
    color: rgba(255, 255, 255, 0.7);
    font-size: 11px;
    font-weight: 600;
    vertical-align: middle;
}

/* Pushed to the right of the row on anything wider than a phone, so the uptime figures line up into a
   column that can be scanned on their own. */
.region-uptimes {
    display: flex;
    gap: 14px;
    margin-left: auto;
    color: rgba(255, 255, 255, 0.7);
    font-size: 13px;
    white-space: nowrap;
}

.region-uptime-label {
    color: rgba(255, 255, 255, 0.5);
    margin-right: 4px;
}

.region-uptime-value {
    font-variant-numeric: tabular-nums;
}

/*
    Clamped to one line, with the full text on the element's title attribute. A curl error or an
    unexpected response body can be 255 characters, and letting it wrap to four lines would change the
    height of the regions panel, which is the thing the whole one screen layout depends on staying
    fixed.
*/
.region-detail {
    margin: 0;
    color: rgba(255, 255, 255, 0.7);
    font-size: 12px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ---------------------------------------------------------------- 90 day strip */

.history-strip {
    display: flex;
    gap: 2px;
    align-items: stretch;
    width: 100%;
}

/*
    Each bar is flex-1 so 90 of them fit any width from 390px up without the page ever scrolling
    sideways. At the narrowest breakpoint a bar is under two pixels wide, which is why the tooltip and
    the aria-label carry the real information.
*/
.history-bar {
    flex: 1 1 0;
    min-width: 0;
    height: 22px;
    border-radius: 2px;
    border: 0;
    padding: 0;
    background-color: var(--color-Unknown);
}

@media screen and (min-width: 768px) {
    .history-bar {
        height: 26px;
    }
}

.history-bar[data-state="operational"] {
    background-color: var(--color-Operational);
}

/*
    Degraded and outage bars are given a texture as well as a color. Color alone would leave the two
    indistinguishable in a grayscale screenshot, and the bars are the one place on the page where there
    is no room for an icon or a label.
*/
.history-bar[data-state="degraded"] {
    background-image: linear-gradient(180deg, var(--color-Degraded) 0%, var(--color-Degraded) 60%, rgba(0, 0, 0, 0.5) 60%, rgba(0, 0, 0, 0.5) 100%);
    background-color: var(--color-Degraded);
}

.history-bar[data-state="outage"] {
    background-image: repeating-linear-gradient(45deg, var(--color-Outage) 0px, var(--color-Outage) 3px, rgba(0, 0, 0, 0.55) 3px, rgba(0, 0, 0, 0.55) 6px);
    background-color: var(--color-Outage);
}

.history-bar[data-state="unknown"] {
    opacity: 0.4;
}

.history-bar:hover {
    outline: 1px solid rgba(255, 255, 255, 0.8);
    outline-offset: 1px;
}

/* One legend for the whole panel rather than one per region, since every strip covers the same span. */
.history-legend {
    display: flex;
    justify-content: space-between;
    margin-top: 8px;
    color: rgba(255, 255, 255, 0.5);
    font-size: 11px;
}

/* ---------------------------------------------------------------- incidents */

/*
    The incident list grows downwards as far as it needs to and the page scrolls normally. It gets no
    scrollbar of its own: a scrollable region nested inside a scrollable page is awkward to use and
    hides content behind a gesture nobody expects.

    What has to stay above the fold is the overall banner and the region rows, which is why the
    compact sizing above matters. Everything below that point is reference material and is allowed to
    run past the bottom of the screen.
*/
.incidents-panel {
    display: flex;
    flex-direction: column;
}

.incident-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.incident-item {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.incident-item:last-child {
    border-bottom: 0;
    padding-bottom: 0;
}

.incident-region {
    font-weight: 600;
    font-size: 14px;
}

.incident-meta {
    color: rgba(255, 255, 255, 0.7);
    font-size: 13px;
}

.incident-ongoing {
    color: var(--color-Outage);
    font-weight: 600;
    font-size: 13px;
}

.incident-detail {
    flex-basis: 100%;
    color: rgba(255, 255, 255, 0.5);
    font-size: 12px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    word-break: break-word;
}

/*
    An entry that stands for several outages on one region says so against the region name, because
    that is the one glance which separates a bad night from a single failure. Same shape as
    .region-badge, in the gray the metadata already uses rather than the blue, since it is a count and
    not a status and the status colors on this page are spoken for.
*/
.incident-count {
    padding: 0 6px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.2);
    color: rgba(255, 255, 255, 0.7);
    font-size: 11px;
    font-weight: 600;
}

/* The control that opens a grouped entry. It reads as a link rather than as a button because the
   incident list is a list of text, and a filled button on every second row would be the loudest thing
   on a page whose loudest thing has to be the banner. */
.incident-toggle {
    margin-left: auto;
    padding: 0;
    border: 0;
    background: none;
    color: var(--color-Primary);
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
}

.incident-toggle:hover {
    text-decoration: underline;
}

/* The outages behind a grouped entry, collapsed until somebody asks for them. The hidden rule has to
   be written out: hidden is a display: none that comes from the browser's own stylesheet, and the
   display below would otherwise outrank it and leave every group permanently open. */
.incident-outages {
    flex-basis: 100%;
    list-style: none;
    margin: 2px 0 0;
    padding: 0 0 0 10px;
    border-left: 1px solid rgba(255, 255, 255, 0.15);
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.incident-outages[hidden] {
    display: none;
}

.incident-outage {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 2px 10px;
    font-size: 12px;
}

.incident-outage-time {
    color: rgba(255, 255, 255, 0.7);
    font-weight: 600;
}

.incident-outage-duration {
    color: rgba(255, 255, 255, 0.5);
}

.incident-outage .incident-ongoing {
    font-size: 12px;
}

.incident-outage-detail {
    color: rgba(255, 255, 255, 0.5);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    word-break: break-word;
}

/* ---------------------------------------------------------------- tooltip */

.tooltip {
    position: fixed;
    z-index: 100;
    max-width: 260px;
    padding: 8px 10px;
    border: 1px solid var(--color-panel-border);
    border-radius: 8px;
    background-color: #0F1118;
    box-shadow: var(--shadow-custom);
    color: #FFFFFF;
    font-size: 12px;
    line-height: 1.4;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.1s ease;
}

.tooltip.is-visible {
    opacity: 1;
}

/* ---------------------------------------------------------------- footer */

/* text-white py-2 md:py-3 px-4 sm:px-5 border-t border-white/20. */
.footer {
    flex: 0 0 auto;
    border-top: 1px solid rgba(255, 255, 255, 0.2);
    color: #FFFFFF;
    padding: 8px 16px;
}

@media screen and (min-width: 650px) {
    .footer {
        padding-left: 20px;
        padding-right: 20px;
    }
}

.footer-inner {
    max-width: 1400px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
}

@media screen and (min-width: 768px) {
    .footer-inner {
        flex-direction: row;
        justify-content: space-between;
    }
}

.footer-links {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 16px;
}

.footer-link {
    font-size: 13px;
    color: #FFFFFF;
    transition: color 0.2s ease;
}

.footer-link:hover {
    color: var(--color-Primary);
}

/* text-center md:text-right text-xs text-gray-600 font-mono leading-tight. */
.footer-build {
    text-align: center;
    font-size: 11px;
    line-height: 1.25;
    color: #4B5563;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

@media screen and (min-width: 768px) {
    .footer-build {
        text-align: right;
    }
}
