/* WookiVerse Status.
   Chrome copied from the app itself (MainLayout.razor.css): a #f7f7f7 top bar with a #d6d5d5
   hairline, and #111/#222 as the dark brand tone from the docked sidebar. The navy-to-purple
   gradient belongs to the sign-in screen and is deliberately absent here.
   States are Bootstrap semantics and nothing else uses colour.
   Type: Tilt Neon and Fira Code are both already in the app's font import. */

@import url('https://fonts.googleapis.com/css2?family=Tilt+Neon&family=Fira+Code:wght@400;500&display=swap');

:root {
    /* App chrome */
    --bar: #f7f7f7;
    --bar-line: #d6d5d5;
    --dark: #212529;
    --darker: #111;

    /* Bootstrap semantics — states only */
    --success: #198754;
    --warning: #ffc107;
    --danger: #dc3545;
    --secondary: #6c757d;

    --page: #eeeeee;
    --surface: #ffffff;
    --border: #dee2e6;
    --ink: #212529;
    --ink-soft: #6c757d;
    --track: #e9ecef;

    --radius: 6px;
    --mono: 'Fira Code', ui-monospace, SFMono-Regular, Menlo, monospace;
    --display: 'Tilt Neon', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--page);
    color: var(--ink);
    font-family: var(--display);
    font-size: 15px;
    line-height: 1.55;
}

/* --- Top bar: the app's brand header ------------------------------------------------------
   The app's brand block (NavMenu.razor) is white-on-dark: the sidebar's #111-to-#222 gradient
   under a rgba(0,0,0,.4) tint, carrying the blinking-eyes logo and Wooki<b>Verse</b>. Its
   #f7f7f7 .top-row only reads as chrome because that dark sidebar sits beside it; on a page
   with no sidebar the same grey is invisible. So the brand header IS the top bar here. */

.top-row {
    background-color: var(--darker);
    background-image:
        linear-gradient(rgba(0, 0, 0, .4), rgba(0, 0, 0, .4)),
        linear-gradient(180deg, #111 0%, #222 75%);
    color: #fff;
    height: 3.5rem;
    position: sticky;
    top: 0;
    z-index: 6;
}

.top-row-inner {
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; color: #fff; }
.brand img { width: 40px; height: auto; }

.wordmark { font-size: 20px; line-height: 1; }
.wordmark b { font-weight: 400; }

/* Burger — <details> so the menu needs no JavaScript */
.menu { position: relative; }

.menu summary {
    list-style: none;
    cursor: pointer;
    color: #fff;
    padding: 6px 4px 2px;
    border-radius: var(--radius);
}

.menu summary::-webkit-details-marker { display: none; }
.menu summary:hover { color: #c9c7d4; }

.menu ul {
    position: absolute;
    right: 0;
    top: calc(100% + 8px);
    min-width: 220px;
    margin: 0;
    padding: 6px 0;
    list-style: none;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 6px 20px rgba(0, 0, 0, .1);
    z-index: 7;
}

.menu a { display: block; padding: 9px 18px; color: var(--ink); text-decoration: none; font-size: 14px; }
.menu a:hover, .menu a:focus-visible { background: var(--secondary); color: #fff; }
.menu a[aria-current="page"] { font-weight: 500; }
.menu .sep { border-top: 1px solid var(--border); margin-top: 6px; padding-top: 6px; }
.menu .sep a { color: var(--ink-soft); font-family: var(--mono); font-size: 12px; }

.container { width: 100%; margin: 0 auto; padding-left: 2rem; padding-right: 1.5rem; }
@media (min-width: 576px)  { .container { max-width: 540px; } }
@media (min-width: 768px)  { .container { max-width: 720px; } }
@media (min-width: 992px)  { .container { max-width: 960px; } }
@media (min-width: 1200px) { .container { max-width: 1140px; } }

.page { padding-top: 30px; padding-bottom: 64px; }

/* --- Banner ------------------------------------------------------------------------------ */

.banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px 18px;
    /* Bootstrap mb-3. The stamp used to carry this gap; it moved into the banner. */
    margin-bottom: 1rem;
    padding: 15px 20px;
    border-radius: var(--radius);
    color: #fff;
}

.banner-main { display: flex; flex-direction: column; gap: 3px; }
.banner-text { font-size: 21px; line-height: 1.25; }

/* The stamp lives in the banner now: the state and how fresh it is are one claim, and
   splitting them let a reader take the state on trust without seeing its age. */
.banner-stamp { font-family: var(--mono); font-size: 11px; opacity: .82; }

.banner-affected { display: flex; flex-wrap: wrap; gap: 6px; }
.banner-badge img { width: 22px; height: 22px; object-fit: contain; }

/* Translucent white rather than a semantic colour — a red badge on a red banner disappears. */
.banner-badge {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: .3em .75em .3em .45em;
    border-radius: .375rem;
    background: rgba(255, 255, 255, .22);
    font-size: 12px;
    font-weight: 500;
    line-height: 1.2;
    white-space: nowrap;
}

.banner.up { background: var(--success); }
.banner.down { background: var(--danger); }
.banner.maintenance { background: var(--secondary); }
.banner.unknown { background: var(--secondary); }

/* Still used by the incidents and uptime pages. */
.stamp { color: var(--ink-soft); font-family: var(--mono); font-size: 12px; margin: 12px 0 28px; }

/* --- Components -------------------------------------------------------------------------- */

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 16px 18px;
}

/* Two up on desktop — Bootstrap's col-6. The strips still give each day about 7px at the xxl
   container, which is what Statuspage runs at full width. */
/* The platform-wide strip: full width above the per-component grid, so the first thing under
   the banner is one line about the whole estate rather than twelve about its parts. */
.overall { margin-bottom: 10px; overflow: visible; }
.overall .bars { height: 40px; }
.overall .bar { border-right-width: 2px; }

.components { display: grid; grid-template-columns: 1fr; gap: 10px; }
@media (min-width: 992px) { .components { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.component { overflow: visible; }
/* 40px square, matching the module icons in the app nav — not circles: these are pictograms,
   not avatars, and cropping them to a circle clips the artwork. */
.component-icon { width: 40px; height: 40px; object-fit: contain; }
.name { display: flex; align-items: center; gap: 9px; font-weight: 500; }

.component-head {
    display: flex;
    justify-content: space-between;
    /* Centred, not baseline: the 40px icon makes the name side tall, and a baseline-aligned
       badge hangs at the bottom of it. */
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
}


/* Bootstrap badges. Solid fill for a state we are asserting; a quiet outline for Unknown,
   because "we cannot see" is not a claim about the service and should not shout like one. */
.state {
    display: inline-block;
    padding: .35em .7em;
    font-size: 12px;
    font-weight: 500;
    line-height: 1.2;
    border-radius: .375rem;
    white-space: nowrap;
    color: #fff;
}

.state.up { background: var(--success); }
.state.down { background: var(--danger); }
.state.maintenance { background: var(--secondary); }
.state.degraded { background: var(--warning); color: #000; }
.state.unknown { background: transparent; color: var(--ink-soft); box-shadow: inset 0 0 0 1px var(--border); }

.bars { display: flex; gap: 0; height: 32px; }

/* A popover, not a tooltip: a real element carrying a badge and figures, rather than the
   browser's title attribute, which is one string, slow to appear and unstyleable.
   Deliberately not focusable — 90 bars across 12 components would be 1,080 tab stops, and the
   same figures are in the legend below and day-by-day on the Uptime page. */
.bar { position: relative; }

.pop {
    display: none;
    position: absolute;
    bottom: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%);
    z-index: 8;
    min-width: 320px;
    padding: 0;
    background: var(--surface);
    color: var(--ink);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .16);
    text-align: left;
    font-size: 12px;
    line-height: 1.45;
    cursor: default;
}

/* Popovers at either end would overflow the panel, so the outermost bars anchor to their own
   edge instead of centring. Driven by index at render time, so nothing has to be measured. */
.bar.pop-start .pop { left: 0; transform: none; }
.bar.pop-end .pop { left: auto; right: 0; transform: none; }

/* Two triangles: the border colour behind, the surface in front, so the arrow keeps the
   popover's outline instead of showing a seam where it meets the card. */
.pop::before, .pop::after {
    content: "";
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    border: 7px solid transparent;
}

.pop::before { top: 100%; border-top-color: var(--border); }
.pop::after { top: calc(100% - 1px); border-top-color: var(--surface); }

.pop-start .pop::before, .pop-start .pop::after { left: 16px; transform: none; }
.pop-end .pop::before, .pop-end .pop::after { left: auto; right: 16px; transform: none; }

/* The title names which component the day belongs to — on a page of twelve strips, the row a
   popover came from stops being obvious the moment the pointer leaves it. */
/* Rows, not a stack: the day, what happened and how long it lasted belong on one line, and the
   platform strip then adds a line per component underneath in the same three columns. */
.pop-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 13px;
}

.pop-row + .pop-row { border-top: 1px solid var(--border); }
.pop-head { background: var(--bar); border-radius: var(--radius) var(--radius) 0 0; }
.pop-head { font-size: 13px; font-weight: 500; }
.pop-day { flex: 1; }
.pop-pct { font-family: var(--mono); font-size: 12px; font-weight: 400; color: var(--ink-soft); }

/* A component's own rows: the window stacked on the left, what it was on the right. */
.pop-window {
    flex: none;
    font-family: var(--mono);
    font-size: 11px;
    line-height: 1.35;
    color: var(--ink-soft);
    white-space: nowrap;
}

.pop-window b { display: block; font-size: 12px; font-weight: 500; color: var(--ink); }
.pop-what { margin-left: auto; text-align: right; font-size: 12px; }

/* Two lines: who and what above, when and how long below. */
.pop-stack { display: block; }
.pop-top { display: flex; align-items: center; gap: 9px; }
.pop-name { flex: 1; font-size: 13px; }
.pop-sub {
    display: block;
    margin-top: 4px;
    padding-left: 29px;
    font-family: var(--mono);
    font-size: 11px;
    color: var(--ink-soft);
}
.pop-when {
    display: flex;
    align-items: center;
    gap: 7px;
    flex: 1;
    font-family: var(--mono);
    font-size: 12px;
    white-space: nowrap;
}

.pop-icon { width: 20px; height: 20px; object-fit: contain; flex: none; }
.pop-len { margin-left: auto; font-family: var(--mono); font-size: 11px; color: var(--ink-soft); white-space: nowrap; }

.pop-figure { font-family: var(--mono); }
.pop-note { color: var(--ink-soft); font-size: 12px; }
.pop .state { flex: none; }

.bar.has-pop:hover { box-shadow: inset 0 0 0 999px rgba(0, 0, 0, .18); }
.bar.has-pop:hover .pop { display: block; }

/* The popover escapes its row, so nothing on the path may clip it. */
.component, .bars { overflow: visible; }
.bar {
    flex: 1 1 0;
    min-width: 0;
    box-sizing: border-box;
    border-right: 1px solid var(--surface);
    background: var(--track);
    background-clip: padding-box;
}

.bar:last-child { border-right: 0; }
.bar.up { background: var(--success); }
.bar.down { background: var(--danger); }
.bar.maintenance { background: var(--secondary); }
.bar.unknown { background: var(--track); }

.legend {
    display: flex;
    justify-content: space-between;
    margin-top: 9px;
    color: var(--ink-soft);
    font-family: var(--mono);
    font-size: 11px;
}

/* --- Incidents --------------------------------------------------------------------------- */

h2 {
    font-size: 21px;
    font-weight: 400;
    margin: 30px 0 10px;
}

h2:first-child { margin-top: 0; }

.open { margin-bottom: 22px; }

.incident { margin-bottom: 12px; }
.incident h3 { font-size: 19px; font-weight: 500; margin: 0 0 3px; max-width: 60ch; color: var(--ink); }

.incident-when { margin: 0; color: var(--ink-soft); font-family: var(--mono); font-size: 11px; }

/* Chips ride the title row rather than sitting under it: they answer "what does this touch",
   which belongs beside the headline, not stacked between it and the story. */
.incident-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px 16px;
    margin-bottom: 14px;
}

/* The order of an incident's updates IS the information, so the shape carries it: one rail
   down the side, a dot per update, newest at the top. */
.timeline { position: relative; margin: 0; padding: 2px 0 0 24px; list-style: none; }

.timeline::before {
    content: "";
    position: absolute;
    left: 5px;
    top: 8px;
    bottom: 8px;
    width: 2px;
    background: var(--border);
}

.update { position: relative; margin: 0 0 14px; font-size: 14px; max-width: 72ch; }
.update:last-child { margin-bottom: 2px; }

.update .dot {
    position: absolute;
    left: -24px;
    top: 6px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--surface);
    box-shadow: inset 0 0 0 2px var(--secondary);
}

/* The dot's colour is the update's own state, so the rail reads as a progression: red while it
   is being worked out, amber once a fix is being watched, green when it is done. */
.update.bad .dot { background: var(--danger); box-shadow: inset 0 0 0 2px var(--danger); }
.update.watching .dot { background: var(--warning); box-shadow: inset 0 0 0 2px var(--warning); }
.update.good .dot { background: var(--success); box-shadow: inset 0 0 0 2px var(--success); }
.update.neutral .dot { background: var(--secondary); box-shadow: inset 0 0 0 2px var(--secondary); }

.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-left: auto; }

.chip {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    background: var(--secondary);
    border: 1px solid var(--secondary);
    border-radius: .375rem;
    padding: 6px 14px 6px 8px;
    font-size: 13px;
    color: #fff;
}

/* 24px, not the nav's 40px: the app uses 40 for icons in LIST ROWS, and a 40px icon inside an
   inline pill makes a 46px chip that outweighs the incident title it sits beside. */
.chip img { width: 24px; height: 24px; object-fit: contain; }

.update { margin: 8px 0; font-size: 14px; max-width: 72ch; }
.update b { color: var(--dark); }
.update time { border-bottom: 1px dotted var(--border); cursor: help; }
.update .at { display: block; margin-top: 3px; color: var(--ink-soft); font-family: var(--mono); font-size: 11px; }

/* --- Uptime calendar --------------------------------------------------------------------- */

.picker {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    margin-bottom: 20px;
}

.picker-desc { margin: 0; max-width: 60ch; color: var(--ink-soft); font-size: 13px; }
.picker-controls { display: flex; gap: 8px; margin-left: auto; }

.dropdown { position: relative; }

.dropdown .btn {
    display: inline-flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    min-width: 190px;
    padding: 8px 13px;
    font: inherit;
    font-size: 14px;
    background: var(--surface);
    color: var(--ink);
    border: 1px solid #ced4da;
    border-radius: var(--radius);
    cursor: pointer;
    list-style: none;
}

.dropdown .btn::-webkit-details-marker { display: none; }
.dropdown[open] .btn { border-color: var(--ink-soft); }
.dropdown .caret { flex: none; opacity: .7; }

.dropdown .btn > span { flex: 1; text-align: left; }

.dropdown-menu {
    position: absolute;
    right: 0;
    top: calc(100% + 5px);
    z-index: 9;
    min-width: 100%;
    max-height: 340px;
    overflow-y: auto;
    margin: 0;
    padding: 6px 0;
    list-style: none;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 6px 20px rgba(0, 0, 0, .12);
}

.dropdown-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 16px;
    color: var(--ink);
    text-decoration: none;
    font-size: 14px;
    white-space: nowrap;
}

.dropdown-icon { width: 24px; height: 24px; object-fit: contain; flex: none; }

.dropdown-item:hover, .dropdown-item:focus-visible { background: var(--secondary); color: #fff; }
.dropdown-item.active { font-weight: 500; background: var(--bar); }
.dropdown-item.active:hover { background: var(--secondary); color: #fff; }

.months { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 14px; }
.month { overflow: visible; }

.month h3 { display: flex; justify-content: space-between; align-items: baseline; font-size: 15px; font-weight: 500; margin: 0 0 12px; }
.month h3 span { color: var(--ink-soft); font-family: var(--mono); font-size: 12px; font-weight: 400; }

.weekdays {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 3px;
    margin-bottom: 4px;
    color: var(--ink-soft);
    font-size: 11px;
    text-align: center;
}

.weekdays .weekend { color: #a9a9a9; }

.cells { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; overflow: visible; }

.cell {
    position: relative;
    aspect-ratio: 1;
    border-radius: 3px;
    background: var(--track);
    display: flex;
    align-items: center;
    justify-content: center;
}

.cell-num { font-size: 11px; font-family: var(--mono); color: rgba(255, 255, 255, .92); }
.cell.unknown .cell-num { color: var(--ink-soft); }
.cell.blank { background: none; }
.cell.blank .cell-num { display: none; }

.cell.has-pop:hover .pop { display: block; }
.cell.has-pop:hover { box-shadow: inset 0 0 0 999px rgba(0, 0, 0, .18); }
.month { overflow: visible; }
.cell.up { background: var(--success); }
.cell.down { background: var(--danger); }
.cell.maintenance { background: var(--secondary); }
.cell.unknown { background: var(--track); }
.cell.future { background: none; box-shadow: inset 0 0 0 1px var(--track); }

.cell.future .cell-num { color: #bdbdbd; }

.empty { color: var(--ink-soft); }

/* --- Admin ------------------------------------------------------------------------------- */

form { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 4px 20px 18px; margin-bottom: 20px; }
form input, form textarea { font: inherit; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius); }
form button { font: inherit; padding: 9px 18px; border: 0; border-radius: var(--radius); background: var(--dark); color: #fff; cursor: pointer; }
form button:hover { background: var(--darker); }

/* --- Quality floor ------------------------------------------------------------------------ */

a:focus-visible, select:focus-visible, button:focus-visible, input:focus-visible,
textarea:focus-visible, summary:focus-visible {
    outline: 2px solid var(--dark);
    outline-offset: 2px;
}

@media (max-width: 640px) {
    .container { padding-left: 1rem; padding-right: 1rem; }
    .wordmark { font-size: 17px; }
    .brand img { width: 26px; }
    .page { padding-top: 22px; padding-bottom: 48px; }
    .banner { font-size: 18px; padding: 15px 18px; }
    .months { flex-direction: column; }
    .component-head { flex-direction: column; align-items: flex-start; gap: 2px; }
}

@media (prefers-reduced-motion: reduce) {
    * { animation: none !important; transition: none !important; }
}
