body {
    --body-font: "Segoe UI Variable", "Segoe UI", sans-serif;
    font-family: var(--body-font);
    font-size: var(--type-ramp-base-font-size);
    line-height: var(--type-ramp-base-line-height);
    margin: 0;
}

.navmenu-icon {
    display: none;
}

.main {
    min-height: calc(100dvh - 50px);
    color: var(--neutral-foreground-rest);
    align-items: stretch !important;
}

.body-content {
    align-self: stretch;
    height: calc(100dvh - 50px) !important;
    display: flex;
}

.content {
    padding: 0.5rem 1.5rem;
    align-self: stretch !important;
    width: 100%;
}

.manage {
    width: 100dvw;
}

footer {
    background: var(--neutral-layer-4);
    color: var(--neutral-foreground-rest);
    align-items: center;
    padding: 10px 10px;
}

    footer a {
        color: var(--neutral-foreground-rest);
        text-decoration: none;
    }

        footer a:focus {
            outline: 1px dashed;
            outline-offset: 3px;
        }

        footer a:hover {
            text-decoration: underline;
        }

.alert {
    border: 1px dashed var(--accent-fill-rest);
    padding: 5px;
}

.pwa-update-banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.75rem 1rem;
    background: var(--neutral-layer-4);
    color: var(--neutral-foreground-rest);
    border-bottom: 1px solid var(--neutral-stroke-rest);
    font-size: 0.95rem;
}

.pwa-update-actions {
    display: flex;
    gap: 0.5rem;
}

.pwa-update-banner button {
    border: 1px solid var(--neutral-stroke-rest);
    border-radius: 0.5rem;
    background: transparent;
    color: inherit;
    padding: 0.35rem 0.75rem;
    cursor: pointer;
}

.pwa-update-apply {
    background: var(--accent-fill-rest) !important;
    color: var(--neutral-foreground-rest) !important;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid red;
}

.validation-message {
    color: red;
}

#blazor-error-ui {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.loading-progress {
    position: absolute;
    display: block;
    width: 8rem;
    height: 8rem;
    inset: 20vh 0 auto 0;
    margin: 0 auto 0 auto;
}

    .loading-progress circle {
        fill: none;
        stroke: #e0e0e0;
        stroke-width: 0.6rem;
        transform-origin: 50% 50%;
        transform: rotate(-90deg);
    }

        .loading-progress circle:last-child {
            stroke: #1b6ec2;
            stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
            transition: stroke-dasharray 0.05s ease-in-out;
        }

.loading-progress-text {
    position: absolute;
    text-align: center;
    font-weight: bold;
    inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
}

    .loading-progress-text:after {
        content: var(--blazor-load-percentage-text, "Loading");
    }

code {
    color: #c02d76;
}

.rich-text-editor .ql-toolbar {
    background-color: white;
}

.top-row {
    display: flex;
    justify-content: flex-end;
    padding: 0.5rem 0;
}

/*
    Mobile toggle behaviour for the NavMenu component (Ysailon.Wasm/Layout/NavMenu.razor),
    ported from the legacy Blazor Server app's wwwroot/app.css so the sidebar collapses behind
    a hamburger icon on narrow screens instead of always taking up the full width.
*/
.navmenu-icon {
    display: none;
}

@media (max-width: 600px) {
    .main {
        flex-direction: column !important;
        row-gap: 0 !important;
    }

    nav.sitenav {
        width: 100%;
        height: 100%;
    }

    #main-menu {
        width: 100% !important;
    }

        #main-menu > div:first-child:is(.expander) {
            display: none;
        }

    .navmenu {
        width: 100%;
    }

    #navmenu-toggle {
        appearance: none;
    }

        #navmenu-toggle ~ nav {
            display: none;
        }

        #navmenu-toggle:checked ~ nav {
            display: block;
        }

    .navmenu-icon {
        cursor: pointer;
        z-index: 10;
        display: block;
        position: absolute;
        top: 15px;
        left: unset;
        right: 20px;
        width: 20px;
        height: 20px;
        border: none;
    }

    [dir="rtl"] .navmenu-icon {
        left: 20px;
        right: unset;
    }
}

.login-display {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

/*
    Shared list-page primitives (character list, campaign list).
    Shape rule for the app: surfaces use an 8px corner radius, FluentUI controls keep their own
    --control-corner-radius token. Colour comes from Fluent design tokens only, so the pages
    follow the single dark theme configured in App.razor.
*/
.page-shell {
    max-width: 1100px;
    margin: 0 auto;
    padding-block: 2rem 4rem;
}

.page-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 2rem;
}

.page-title {
    margin: 0;
    font-size: clamp(1.9rem, 4vw, 2.5rem);
    line-height: 1.15;
    letter-spacing: -0.02em;
    font-weight: 600;
}

/*
    App.razor uses <FocusOnNavigate Selector="h1" />, which moves focus to the page heading after
    every navigation. That is the behaviour screen-reader users need, but it also paints the
    browser's default focus ring for pointer users. Hide the ring only when the focus did not come
    from the keyboard, so keyboard users keep theirs.
*/
h1:focus:not(:focus-visible) {
    outline: none;
}

.page-sub {
    margin: 0.4rem 0 0;
    max-width: 60ch;
    color: var(--neutral-foreground-hint);
}

.section-title {
    margin: 0 0 1rem;
    font-size: var(--type-ramp-plus-3-font-size);
    line-height: 1.2;
    font-weight: 600;
}

.empty-state {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 1.75rem;
    border: 1px dashed var(--neutral-stroke-rest);
    border-radius: 8px;
    background: var(--neutral-layer-2);
}

.empty-state p {
    margin: 0;
    max-width: 50ch;
    color: var(--neutral-foreground-hint);
}

.notice {
    margin-bottom: 2rem;
}

.skeleton-grid {
    display: grid;
    gap: 1.25rem;
}

.skeleton-card {
    height: 148px;
    border-radius: 8px;
    background: linear-gradient(90deg, var(--neutral-layer-2) 25%, var(--neutral-layer-3) 50%, var(--neutral-layer-2) 75%);
    background-size: 400% 100%;
    animation: skeleton-shimmer 1.4s ease-in-out infinite;
}

@keyframes skeleton-shimmer {
    from {
        background-position: 100% 0;
    }

    to {
        background-position: 0 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .skeleton-card {
        animation: none;
        background: var(--neutral-layer-2);
    }
}

@media (max-width: 767px) {
    .page-shell {
        padding-block: 1.25rem 2.5rem;
    }

    .page-head {
        align-items: flex-start;
    }
}

.login-display-name {
    font-weight: 500;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}