:root {
    /* Height of the fixed MudAppBar — used to keep modal/darkening backdrops from
       covering the header (matches MudBlazor: 64px desktop, 56px on mobile). */
    --app-header-h: 64px;
    /* Width of the docked desktop task-detail side panel. */
    --side-panel-w: 460px;

    /* ===== theme tokens (light) =====
       All page/component styles draw from these; html.dark swaps the values below.
       The dark palette is the night version of the UniConnect identity: desaturated
       navy-slate surfaces (kin to the brand navy #152f4f), not neutral black. */

    /* surfaces */
    --c-bg: #f7f7f9;            /* page background */
    --c-surface: #ffffff;       /* cards, panels, modals */
    --c-surface-2: #f5f6f8;     /* columns, inset areas on a surface */
    --c-surface-3: #e9ecf0;     /* deeper panel (board rail) */
    --c-inset: #dbe0e6;         /* sunken fields (rail search) */
    --c-hover: #f5f7fa;         /* hover fill on surface */

    /* lines */
    --c-border: #e3e6ea;
    --c-border-soft: #eceef1;   /* hairline dividers */
    --c-border-strong: #c9cfd8; /* grips, outlines that must read */

    /* text */
    --c-text: #1f2d3d;
    --c-text-2: #5b6b7d;        /* secondary */
    --c-muted: #8a94a6;         /* meta, captions */
    --c-faint: #aab2bf;         /* placeholders, disabled */

    /* brand */
    --c-brand: #152f4f;         /* UniConnect navy (appbar, headings) */
    --c-primary: #e84e1b;       /* UniConnect orange */
    --c-primary-soft: #ee5a36;  /* unsaved markers, softer orange accents */
    --c-accent: #4a90d9;        /* selection blue */
    --c-accent-tint: #eaf2fb;   /* selected-row/card tint */
    --c-link: #1b75d1;
    --c-link-strong: #14457a;

    /* status */
    --c-warn-bg: #fde8c8;  --c-warn-text: #9a5b00;   /* afventer */
    --c-info-bg: #cfe3ff;  --c-info-text: #14457a;   /* igang */
    --c-ok-bg: #cdeccd;    --c-ok-text: #1f6a1f;     /* afsluttet */
    --c-ok: #2e7d32;
    --c-danger: #d32f2f;
    --c-danger-bg: #fbe9e2;
    --c-star: #ecc889;          /* favorite star */
    --c-primary-tint: #fff3ef;  /* warm drop-target / create tint */
    --c-today-tint: #fff8f6;    /* calendar today cell */
    --c-heading: #152f4f;       /* brand-navy headings */
    --c-on-color: #ffffff;      /* text on colored chips/bars (stays light in dark) */

    color-scheme: light;
}

/* Dark: applied as a class on <html> by the boot script in index.html (before Blazor
   loads, so there is no light flash) and toggled by ThemeService. */
html.dark {
    --c-bg: #12161d;
    --c-surface: #1a212b;
    --c-surface-2: #202834;
    --c-surface-3: #171d26;
    --c-inset: #10151c;
    --c-hover: #232c39;

    --c-border: #2b3442;
    --c-border-soft: #242d3a;
    --c-border-strong: #3d4859;

    --c-text: #d7dde6;
    --c-text-2: #a7b1bf;
    --c-muted: #8a94a6;
    --c-faint: #5f6b7c;

    --c-brand: #152f4f;
    --c-primary: #ef5f2f;
    --c-primary-soft: #f06a3e;
    --c-accent: #5a9be0;
    --c-accent-tint: #1d2c40;
    --c-link: #6aaae8;
    --c-link-strong: #8fb8e4;

    --c-warn-bg: #3b2f1a;  --c-warn-text: #e6c088;
    --c-info-bg: #1c2d42;  --c-info-text: #9dc3ee;
    --c-ok-bg: #1e3322;    --c-ok-text: #9ed3a4;
    --c-ok: #7cc283;
    --c-danger: #ef6b6b;
    --c-danger-bg: #3a2226;
    --c-star: #d9b874;
    --c-primary-tint: #33221b;
    --c-today-tint: #201a17;
    --c-heading: #d7dde6;
    --c-on-color: #f2f5f9;

    color-scheme: dark;
}

@media (max-width: 599.98px) {
    :root {
        --app-header-h: 56px;
    }
}

html {
    font-family: 'Roboto', sans-serif;
    background-color: var(--c-bg);
}

body {
    font-family: 'Roboto', sans-serif;
    background-color: var(--c-bg);
    min-height: 100vh;
}

/* Remove 300ms touch delay on all interactive elements */
button,
a,
[role="button"],
.mud-button-root,
.mud-icon-button,
.clickable,
input,
select,
textarea {
    touch-action: manipulation;
}

/* Disable MudBlazor dialog animations for instant appearance */
.mud-dialog-container {
    animation: none !important;
}

.mud-dialog {
    animation: none !important;
}

.mud-overlay {
    animation: none !important;
}

#blazor-error-ui {
    background: lightyellow;
    color: var(--c-text);
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

#blazor-error-ui a {
    color: var(--c-text);
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

/* Boot splash (index.html #app-splash) — shown while Blazor WASM downloads and boots.
   The bar fill tracks Blazor's --blazor-load-percentage; the fade-out class is added by
   the MutationObserver in index.html once the app has rendered. */
#app-splash {
    position: fixed;
    inset: 0;
    /* Below the MudBlazor app bar (1300) so the header — same navy as the curtain —
       paints on top of the splash from first render, letting its icons drop in while
       the curtain recedes. Above everything else (side-nav is 1250, content unpositioned). */
    z-index: 1299;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 28px;
    transition: opacity 0.3s ease;
}

#app-splash.app-splash-hide {
    opacity: 0;
    pointer-events: none;
}

/* The navy backdrop is its own layer so the fly-out can shrink it into the app bar
   (same navy) without disturbing the flex-centered logo/bar. */
.app-splash-bg {
    position: absolute;
    inset: 0;
    background: #152f4f;
    transform-origin: top;
    transition: transform 0.45s cubic-bezier(0.4, 0, 0.2, 1);
    will-change: transform;
}

/* Fly-to-app-bar dismissal: the bar fades, the navy layer recedes into the header, and
   the logo (kept fully opaque) is transformed to the app-bar logo's rect — both
   transforms are set by the index.html script. */
#app-splash.app-splash-fly {
    pointer-events: none;
}

#app-splash.app-splash-fly .app-splash-bar {
    opacity: 0;
}

.app-splash-logo {
    position: relative;   /* paint above the absolutely-positioned backdrop */
    width: min(220px, 55vw);
    height: auto;
    transition: transform 0.45s cubic-bezier(0.4, 0, 0.2, 1);
    will-change: transform;
}

.app-splash-bar {
    position: relative;   /* paint above the absolutely-positioned backdrop */
    width: min(220px, 55vw);
    height: 4px;
    border-radius: 2px;
    background: rgba(255, 255, 255, 0.15);
    overflow: hidden;
    transition: opacity 0.2s ease;
}

/* Header intro after the splash: the other app-bar elements drop in from the top while
   the logo flies to its spot. The class is added (and later removed) by the splash
   script in index.html; the logo button is excluded so the flight's landing spot
   stays put. */
/* The real app-bar logo stays hidden during the intro (the splash logo flies to its spot
   and "becomes" it) — without this it flashes at the destination for the frames between
   first render and the flight starting. The splash script reveals it when the flight lands. */
body.app-intro .mud-appbar .app-logo {
    visibility: hidden;
}

/* No elevation shadow while the curtain recedes: the app bar paints above the splash, so
   its bottom shadow would draw a line across the (same-navy) curtain mid-animation. The
   transition on .mud-appbar below eases the shadow back in once the intro class is removed. */
body.app-intro .mud-appbar {
    box-shadow: none;
}

.mud-appbar {
    transition: box-shadow 0.3s ease;
    /* The app bar is brand navy in BOTH themes, so it is excluded from theming: icons and
       text stay white regardless of palette (the dark palette would otherwise dim them so
       they no longer match the white logo). The scoped palette vars catch Mud components
       that don't inherit color (Default-colored buttons, chips, progress). */
    color: #ffffff;
    --mud-palette-action-default: #ffffff;
    --mud-palette-text-primary: #ffffff;
}

/* The app bar paints above the splash, so the drop-in is visible immediately — it runs
   simultaneously with the logo flight and receding curtain. body.app-intro is set in the
   static markup and removed by the splash script after the intro. */
body.app-intro .mud-appbar .mud-toolbar > *:not(.app-logo-button) {
    animation: appHeaderDropIn 0.4s cubic-bezier(0.4, 0, 0.2, 1) 0.1s backwards;
}

/* MudChip sits inside a display:contents wrapper (no box → transforms are a no-op),
   so animate the chip element itself instead. */
body.app-intro .mud-appbar .mud-toolbar > .mud-chip-container > .mud-chip {
    animation: appHeaderDropIn 0.4s cubic-bezier(0.4, 0, 0.2, 1) 0.1s backwards;
}

@keyframes appHeaderDropIn {
    from {
        /* Fixed offset (≈ header height) rather than a percentage: percentages are of each
           element's own height, which made short elements (the company chip) fall a shorter
           distance — and thus visibly slower — than the taller icon buttons. */
        transform: translateY(-64px);
        opacity: 0;
    }

    to {
        transform: translateY(0);
        opacity: 1;
    }
}

.app-splash-bar-fill {
    height: 100%;
    width: var(--blazor-load-percentage, 0%);
    border-radius: inherit;
    background: var(--c-primary);
    transition: width 0.05s ease-in-out;
}

/* MudBlazor 9's ripple starts on pointerdown (good — instant feedback) but expands and fades
   faster than v8 did (.5s/.4s vs .6s/1s). Keep the instant start, restore the old unhurried
   pace. Same-specificity override works because app.css loads after MudBlazor.min.css. */
.mud-ripple-effect-expanding {
    transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.1s linear;
}

.mud-ripple-effect-fading {
    transition: opacity 1s linear;
}

/* MudBlazor types input/select VALUE text as subtitle1 (1rem) via the mud-typography-subtitle1
   class on the .mud-input wrapper, which looks oversized next to the app's 0.875rem default
   text. Normalize it app-wide — components must not re-shrink values locally (the old .tdp /
   .asg-dialog overrides), or they defeat the touch-device zoom guard below. */
.mud-input.mud-typography-subtitle1 {
    font-size: 0.875rem;
}

/* iOS Safari zooms the whole page when an input with font-size < 16px gets focus, so touch
   devices get a 16px floor on every input. Scoped to coarse pointers so desktop keeps the
   intended sizes.
   Don't fight this with per-component !important overrides: winning the specificity battle
   re-enables the zoom on that component (CommentThread's .ct-input shows the same pattern for
   a custom input). */
@media (pointer: coarse) {
    input,
    select,
    textarea,
    .mud-input-slot input,
    .mud-input-slot textarea,
    .mud-select-input {
        font-size: 16px !important;
    }
}
