html, body {
    height: 100%;
}

/* Set the dark background on the root element too, not just <body>. During a
   View Transition crossfade both page snapshots are semi-transparent and
   reveal the root behind them — without this, the browser's default white
   shows through and you get a white blink between pages. */
html {
    background: var(--bg);
}

body {
    background: var(--bg);
    color: var(--text);
    font-family: var(--mono);
    font-size: 12.5px;
    line-height: 1.5;
    height: 100%;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

::-webkit-scrollbar {
    width: 5px;
    height: 5px;
}

::-webkit-scrollbar-track {
    background: var(--bg2);
}

::-webkit-scrollbar-thumb {
    background: var(--bg4);
    border-radius: 3px;
}

::-webkit-scrollbar-thumb:hover {
    background: var(--border3);
}

::-webkit-scrollbar-corner {
    background: var(--bg2);
}

* {
    scrollbar-width: thin;
    scrollbar-color: var(--bg4) var(--bg2);
}

/* Hide native number-input spinners app-wide. The default browser arrows
   don't fit the dark monospace UI and are too small to be useful — keyboard
   input + mouse-wheel scrolling still work without them. */
input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* Smooth page navigation. Opt into the browser's cross-document View
   Transitions API so full page loads crossfade instead of hard-swapping.
   Chrome/Edge 126+ animate this; Firefox/Safari fall back to the instant
   swap (no breakage). Pure CSS, no JS, no build step. */
@view-transition {
    navigation: auto;
}

::view-transition-old(root),
::view-transition-new(root) {
    animation-duration: var(--t-base);
    animation-timing-function: var(--e-out);
}

/* The topbar and breadcrumb are the same on every page, but without a name of
   their own they were snapshotted as part of the root and crossfaded with
   everything else — so the shell appeared to blink on each navigation instead
   of staying put. Naming them takes them out of the root snapshot and morphs
   them between documents, which is what makes navigation read as moving
   within one app rather than swapping pages.

   A name must be unique per document. These elements appear once. */
.topbar {
    view-transition-name: topbar;
}

.topbar-crumb {
    view-transition-name: crumb;
}

/* Content crossfades on its own, slightly slower than the chrome that frames
   it, so the eye settles on the part that actually changed. */
.main {
    view-transition-name: main;
}

::view-transition-old(main),
::view-transition-new(main) {
    animation-duration: var(--t-slow);
    animation-timing-function: var(--e-out);
}

/* Nav progress bar (nav-progress.js). Pinned above everything: it has to be
   visible while the outgoing page is still on screen, which is exactly the
   window the view transition does not cover. The script hides it on pagehide
   and pageshow so it never rides into the next document. */
.nav-progress {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 9999;
}

/* Respect users who ask for less motion. */
@media (prefers-reduced-motion: reduce) {
    @view-transition {
        navigation: none;
    }
}

/* State, not styling — this is what markup uses instead of an inline
   style="display:none", and what JS toggles via element.hidden.
   !important is load-bearing here: a bare [hidden] comes from the UA
   stylesheet with zero specificity, so any component rule that sets display
   (.modal-footer is flex, .rsp-spinner is inline-block) would outrank it and
   the element would stay visible. */
[hidden] {
    display: none !important;
}
