/* Only the pre-Blazor boot screen and the framework error banner live here.
   MudBlazor isn't loaded yet at this point, so these styles are standalone
   and follow the OS color scheme rather than the app theme. */

html {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

:root {
    /* Must match MainLayout's FontStack so nothing shifts when Blazor takes over.
       Includes CJK faces — the Latin-only default fell back to SimSun for Chinese. */
    --app-font: 'Segoe UI Variable Text', 'Segoe UI', -apple-system, BlinkMacSystemFont,
                'Microsoft YaHei UI', 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB',
                'Noto Sans CJK SC', 'Helvetica Neue', Arial, sans-serif;

    --boot-bg: #f6f7fb;
    --boot-bg-accent: rgba(124, 108, 255, 0.16);
    --boot-bg-accent-2: rgba(255, 64, 129, 0.13);
    --boot-fg: #16161f;
    --boot-muted: #5c5c72;
    --boot-track: rgba(22, 22, 31, 0.09);
    --boot-glow: rgba(124, 108, 255, 0.45);
}

@media (prefers-color-scheme: dark) {
    :root {
        --boot-bg: #101019;
        --boot-bg-accent: rgba(124, 108, 255, 0.26);
        --boot-bg-accent-2: rgba(255, 64, 129, 0.2);
        --boot-fg: #f2f2f7;
        --boot-muted: #9c9cb4;
        --boot-track: rgba(255, 255, 255, 0.1);
        --boot-glow: rgba(124, 108, 255, 0.6);
    }
}

/* ---------- Boot screen ---------- */

.boot {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1.75rem;
    background: var(--boot-bg);
    color: var(--boot-fg);
    font-family: var(--app-font);
    overflow: hidden;
}

/* Two slowly drifting colour blobs behind the ring. */
.boot-aurora {
    position: absolute;
    inset: -25%;
    background:
        radial-gradient(38% 42% at 28% 32%, var(--boot-bg-accent) 0%, transparent 65%),
        radial-gradient(34% 38% at 72% 68%, var(--boot-bg-accent-2) 0%, transparent 65%);
    filter: blur(28px);
    animation: boot-drift 14s ease-in-out infinite alternate;
}

.boot-ring {
    position: relative;
    width: 9rem;
    height: 9rem;
    display: grid;
    place-items: center;
}

/* Rotating conic halo — the "alive" part of the loader. */
.boot-halo {
    position: absolute;
    inset: -12%;
    border-radius: 50%;
    background: conic-gradient(from 0deg, transparent 0deg, var(--boot-glow) 90deg, transparent 200deg);
    filter: blur(14px);
    opacity: 0.7;
    animation: boot-spin 2.6s linear infinite;
}

.loading-progress {
    position: absolute;
    inset: 0;
    width: 9rem;
    height: 9rem;
}

    .loading-progress circle {
        fill: none;
        stroke: var(--boot-track);
        stroke-width: 0.4rem;
        stroke-linecap: round;
        transform-origin: 50% 50%;
        transform: rotate(-90deg);
    }

        /* Blazor updates --blazor-load-percentage on <html> as assets download.
           r="40%" makes the circumference 2.513 x the SVG width, which is what
           the 3.141 * P * 0.8 term below reproduces. */
        .loading-progress circle:last-child {
            stroke: url(#boot-gradient);
            stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
            transition: stroke-dasharray 0.15s ease-out;
            filter: drop-shadow(0 0 6px var(--boot-glow));
        }

.loading-progress-text {
    position: relative;
    font-size: 1.5rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.02em;
    color: var(--boot-fg);
}

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

.boot-title {
    position: relative;
    font-size: 1.6rem;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    background: linear-gradient(100deg, var(--boot-fg) 0%, var(--boot-fg) 35%, #7c6cff 50%, var(--boot-fg) 65%, var(--boot-fg) 100%);
    background-size: 260% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    animation: boot-shimmer 3.2s linear infinite;
}

.boot-subtitle {
    position: relative;
    margin-top: -1.1rem;
    font-size: 0.8rem;
    letter-spacing: 0.06em;
    color: var(--boot-muted);
}

    /* Three equal-width dots, so stepping the clip in thirds lands exactly
       on a dot boundary each time. */
    .boot-subtitle:after {
        content: "...";
        display: inline-block;
        animation: boot-ellipsis 1.5s steps(3, end) infinite;
    }

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

@keyframes boot-drift {
    from { transform: translate3d(-3%, -2%, 0) scale(1); }
    to   { transform: translate3d(3%, 2%, 0) scale(1.12); }
}

@keyframes boot-shimmer {
    from { background-position: 130% 0; }
    to   { background-position: -130% 0; }
}

@keyframes boot-ellipsis {
    from { clip-path: inset(0 100% 0 0); }
    to   { clip-path: inset(0 0 0 0); }
}

@media (prefers-reduced-motion: reduce) {
    .boot-aurora,
    .boot-halo,
    .boot-title,
    .boot-subtitle:after {
        animation: none;
    }

    .boot-title {
        background: none;
        -webkit-background-clip: border-box;
        background-clip: border-box;
        color: var(--boot-fg);
    }
}

/* ---------- Unhandled error banner ---------- */

/* Blazor toggles this element's inline display between none and block, so the
   container stays block-level and the card inside does the layout.
   MudBlazor.min.css also styles #blazor-error-ui (full-width red strip), so the
   background/padding/box-shadow it sets have to be explicitly reset here. */
#blazor-error-ui {
    display: none;
    position: fixed;
    bottom: 1.25rem;
    left: 50%;
    transform: translateX(-50%);
    z-index: 9999;
    width: min(34rem, calc(100vw - 2rem));
    padding: 0;
    background: none;
    box-shadow: none;
    font-family: var(--app-font);
}

.error-card {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.85rem 0.9rem 0.85rem 1rem;
    border-radius: 0.9rem;
    border: 1px solid rgba(255, 255, 255, 0.09);
    background: #1b1b26;
    box-shadow: 0 18px 45px rgba(0, 0, 0, 0.42);
    color: #f2f2f7;
    animation: error-rise 0.28s ease-out;
}

.error-icon {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 1.9rem;
    height: 1.9rem;
    border-radius: 50%;
    background: linear-gradient(135deg, #ff4d6d, #ff8a3d);
    color: #fff;
    font-weight: 800;
    font-size: 1.05rem;
    line-height: 1;
}

.error-text {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
    flex: 1 1 auto;
}

    .error-text strong {
        font-size: 0.9rem;
        font-weight: 600;
    }

    .error-text span {
        font-size: 0.78rem;
        color: #b9b9cc;
    }

#blazor-error-ui .reload {
    flex: 0 0 auto;
    padding: 0.4rem 0.85rem;
    border-radius: 0.5rem;
    background: #594ae2;
    color: #fff;
    font-size: 0.82rem;
    font-weight: 600;
    text-decoration: none;
    transition: background 0.15s ease;
}

    #blazor-error-ui .reload:hover {
        background: #6d5ff0;
    }

#blazor-error-ui .dismiss {
    flex: 0 0 auto;
    position: static; /* MudBlazor.min.css absolutely positions this */
    width: 1.6rem;
    height: 1.6rem;
    padding: 0;
    border: 0;
    border-radius: 0.4rem;
    background: transparent;
    color: #9c9cb4;
    font-size: 0.8rem;
    line-height: 1;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}

    #blazor-error-ui .dismiss:hover {
        background: rgba(255, 255, 255, 0.1);
        color: #f2f2f7;
    }

#blazor-error-ui .reload:focus-visible,
#blazor-error-ui .dismiss:focus-visible {
    outline: 2px solid #9d92ff;
    outline-offset: 2px;
}

@keyframes error-rise {
    from { opacity: 0; transform: translateY(0.75rem); }
    to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
    .error-card { animation: none; }
}

/* ---------- Blazor error boundary fallback ---------- */

.blazor-error-boundary {
    padding: 1rem 1.25rem;
    border-radius: 0.75rem;
    background: linear-gradient(135deg, #b32121, #d94848);
    color: #fff;
}

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