* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/*
    The status embed runs in one of two modes, toggled on <body> by
    uptime.js:

    NATIVE (default, body.embed-native): the embedded page is served
    through a proxy that removes the HetrixTools chrome in the DOM and
    posts its true content height to this page. The iframe is sized to
    exactly that height, the page scrolls natively and ends where the
    data ends. No pixel cropping anywhere.

    FALLBACK (body.embed-fallback): no proxy reachable, the raw backend
    page is shown inside a fixed viewport-filling frame with the
    measured crop offsets below. Emergency mode only.
*/

/* Fallback-only measured offsets (see the fallback section) */
:root {
    --ht-header-crop: 24px;
    --ht-footer-crop: 169px;
    --ht-scrollbar-crop: 24px;
}

html {
    height: 100%;
}

body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
    background: #0a0a0f;
    color: #fff;
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
}

.bg-gradient {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background:
        radial-gradient(ellipse at 20% 20%, rgba(139, 92, 246, 0.15) 0%, transparent 50%),
        radial-gradient(ellipse at 80% 80%, rgba(139, 92, 246, 0.1) 0%, transparent 50%);
    pointer-events: none;
    z-index: -1;
}

nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 20px 5%;
    background: rgba(5, 5, 8, 0.85);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    flex-shrink: 0;
    position: sticky;
    top: 0;
    z-index: 100;
}

.logo {
    font-size: 1.25rem;
    font-weight: 600;
    color: #fff;
    letter-spacing: -0.5px;
    text-decoration: none;
}

.logo span {
    color: #8b5cf6;
}

nav ul {
    display: flex;
    list-style: none;
    gap: 32px;
}

nav a {
    color: #a1a1aa;
    text-decoration: none;
    font-size: 0.9rem;
    font-weight: 500;
    transition: color 0.2s ease;
}

nav a:hover,
nav a.active {
    color: #fff;
}

/* Slim strip so the embed gets as much room as possible */
.page-header {
    padding: 12px 5%;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    flex-shrink: 0;
    background: rgba(0, 0, 0, 0.3);
    z-index: 90;
}

.page-header-left {
    display: flex;
    align-items: center;
    gap: 16px;
}

.page-header h1 {
    font-size: 1.15rem;
    font-weight: 600;
    color: #fff;
}

.status-badge {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 4px 12px;
    border-radius: 50px;
    font-size: 0.75rem;
    font-weight: 500;
    background: rgba(139, 92, 246, 0.1);
    color: #a78bfa;
    border: 1px solid rgba(139, 92, 246, 0.2);
}

.status-badge::before {
    content: '';
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #8b5cf6;
    animation: pulse 2s infinite;
}

@keyframes pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.5; }
}

.external-link {
    color: #71717a;
    text-decoration: none;
    font-size: 0.8rem;
    display: flex;
    align-items: center;
    gap: 6px;
    transition: all 0.2s;
    padding: 6px 14px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 8px;
}

.external-link:hover {
    color: #a78bfa;
    border-color: rgba(139, 92, 246, 0.3);
    background: rgba(139, 92, 246, 0.05);
}

/*
    NATIVE MODE (and initial loading state)

    The container wraps the iframe in normal flow; the iframe's height
    is set by uptime.js from the embed's height reports, so the page
    grows with the content and scrolling ends at the data end.
*/
.iframe-container {
    flex: 1 0 auto;
    position: relative;
    /* Transparent: the page background (and its purple glow) must be
       the one and only backdrop, including through the embed. */
    background: transparent;
    min-height: 55vh;
}

.iframe-container iframe {
    display: block;
    width: 100%;
    height: 65vh; /* placeholder until the first height report */
    border: none;
    /* Blend the light embed into the dark theme */
    filter:
        invert(1)
        hue-rotate(180deg)
        brightness(0.85)
        contrast(1.1)
        saturate(1.3)
        sepia(0.15);
    /*
        The inverted page's empty areas come out near-black (#000),
        not the site's #0a0a0f-plus-glow. Lighten-blending against the
        page makes every pixel darker than the real backdrop take the
        backdrop's value, so the embed's voids are literally the page
        background - no imitation overlays, no shade seams.
    */
    mix-blend-mode: lighten;
    /* Hidden until native mode is confirmed or fallback engages,
       so the raw page (with its grey bar) never flashes. */
    opacity: 0;
    transition: opacity 0.35s ease;
}

body.embed-native .iframe-container iframe,
body.embed-fallback .iframe-container iframe {
    opacity: 1;
}

/* Loading state */
.loading {
    position: absolute;
    top: min(40vh, 50%);
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
    color: #a1a1aa;
    z-index: 10;
    background: rgba(10, 10, 15, 0.95);
    padding: 48px;
    border-radius: 16px;
    border: 1px solid rgba(255, 255, 255, 0.06);
}

.spinner {
    width: 44px;
    height: 44px;
    border: 3px solid rgba(139, 92, 246, 0.2);
    border-top-color: #8b5cf6;
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

.loading.hidden {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
}

/*
    FALLBACK MODE - no proxy reachable, raw backend embedded.

    Reproduces the previous fixed-viewport layout: the page itself
    cannot scroll, the embed scrolls internally, and the measured
    offsets in :root crop the HetrixTools chrome at the edges.
*/
body.embed-fallback {
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
}

body.embed-fallback .iframe-container {
    flex: 1 1 auto;
    overflow: hidden;
    min-height: 240px;
}

body.embed-fallback .iframe-container iframe {
    position: absolute;
    top: calc(-1 * var(--ht-header-crop));
    left: 0;
    width: calc(100% + var(--ht-scrollbar-crop));
    height: calc(100% + var(--ht-header-crop) + var(--ht-footer-crop));
    transition: none;
}

/*
    DIRECT EMBED MODE - the official Hetrix embed page
    (wl.hetrixtools.com/r/<RUID>/, body.embed-direct set by uptime.js).

    That page is already dark-themed (Hetrix darkmode.css), so the
    invert filter used for the light statusbackend page is disabled.
    What remains of its light chrome - a 25px white band above the
    card, ~28px white page margins beside it, and the inline
    "Powered by" row on white below it (66px) - is clipped away and
    the layout space collapsed, so the page still ends exactly where
    the data ends. The iframe is held +56px wider than its container
    to pin the embed's fluid .container (98% + 15px padding) into a
    regime where those side bands are a constant ~28px.
*/
body.embed-direct .iframe-container {
    overflow: hidden;
    width: 100%;
    max-width: 1280px;
    margin: 0 auto;
}

body.embed-direct .iframe-container iframe {
    /*
        Exact site colours without the proxy: the embed is dark
        (Hetrix darkmode - voids #15202b, cards #223140), and this
        chain pushes both below the page backdrop (#0a0a0f) on every
        channel, so the lighten blend inherited from the base rule
        replaces them with the real page background - purple glow
        included - the same mechanism the proxied invert path uses.
        Pixel-verified against the live embed: void/row deltas 0-1,
        white text lands ~rgb(229), status greens stay clearly green.
    */
    filter: brightness(0.75) contrast(1.6);
    mix-blend-mode: lighten;
    /*
        Clip = white page margins around the dark card plus, on the
        right, the white track of the scrollbar the embed forces
        (html { overflow-y: scroll } inside the page, ~17px). Each
        value carries ~2px slack so display-scaling rounding can't
        leave 1px white slivers; the slack lands on the card's uniform
        dark edge where it is invisible.

        left 30 | top 27 | right 47 (30 margin + 17 scrollbar) | bottom 67
        width grows by left+right so the visible area still spans the
        container exactly.
    */
    width: calc(100% + 77px);
    margin-left: -30px;
    margin-top: -27px;
    margin-bottom: -67px;
    clip-path: inset(27px 47px 67px 30px);
}

@media (max-width: 768px) {
    nav {
        flex-direction: column;
        gap: 16px;
        padding: 16px 5%;
    }

    nav ul {
        gap: 20px;
    }

    .page-header {
        padding: 10px 5%;
    }

    .page-header h1 {
        font-size: 1.05rem;
    }
}
