/* ==========================================================================
   FAAC Analytics — design tokens and theme.

   This file is the single source of truth for colour, type, spacing and radius across the
   whole app. Everything else (dashboard.css, the page stylesheets, the charts) reads these
   custom properties instead of hard-coding values, so switching theme is one attribute on
   the root element:

       <html data-bs-theme="light">   (default)
       <html data-bs-theme="dark">

   `data-bs-theme` is Bootstrap 5.3's own colour-mode hook, so Bootstrap components follow the
   same switch for free. js/theme.js sets it (and remembers the choice in localStorage); an
   inline snippet in App.razor applies it before first paint, so there is no flash.

   Light is the default and adopts the brand tokens of the landing page (landing.css):
   Inter Tight, the navy / blue / sky palette, ink text on a near-white page, hairline
   #dfe2e8 borders. Dark is the counterpart: the same brand hues over deep navy surfaces.
   ========================================================================== */

:root {
    /* ---------- brand primitives (from the landing page) ---------- */
    --brand-navy: #011a3c;
    --brand-navy-2: #011f45;
    --brand-blue: #0a4d9f;
    --brand-blue-hover: #0d5cbb;
    --brand-blue-text: #0b429c;
    --brand-sky: #2b8ad3;
    --brand-sky-soft: #7fc3ef;
    --brand-ink: #161b26;
    --brand-ink-strong: #0a1f44;
    --brand-muted: #4a5568;
    --brand-line: #dfe2e8;
    --brand-page: #f9fafb;

    /* ---------- typography ---------- */
    --font-sans: "Inter Tight", "Inter", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --ease: cubic-bezier(0.22, 0.8, 0.3, 1);
    /* Floor for the dashboard's small captions. Their rem sizes were tuned for a wide
       desktop; on smaller screens the floor keeps them legible instead of shrinking to 8px. */
    --fs-floor: 10.5px;

    /* ---------- spacing scale (rem, follows the fluid root size) ---------- */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;

    /* ---------- radius & elevation ---------- */
    --radius-sm: 6px;
    --radius-md: 10px;
    --radius-lg: 14px;
    --shadow-1: 0 1px 2px rgba(10, 31, 68, 0.06), 0 1px 1px rgba(10, 31, 68, 0.04);
    --shadow-2: 0 6px 20px -8px rgba(10, 31, 68, 0.22);

    /* ---------- semantic colour: LIGHT (default) ---------- */
    color-scheme: light;

    --bg: #f9fafb;
    --page-bg: #f9fafb;
    --page-bg-image: none;
    --surface: #ffffff;
    --surface-2: #f1f6fd;          /* soft blue tint: chips, stat tiles, empty states */
    --surface-sunken: #eef1f6;

    --text: #161b26;
    --text-strong: #0a1f44;
    --text-2: #26324a;
    --text-3: #3a4658;
    --text-muted: #4a5568;
    --text-faint: #66717f;

    --border: #dfe2e8;
    --border-soft: #eaedf2;
    --border-strong: #c3cddb;
    --tint: rgba(10, 31, 68, 0.035);        /* card-in-card fill */
    --zebra: rgba(20, 41, 92, 0.022);       /* alternate table rows */
    --divider: rgba(10, 31, 68, 0.08);      /* list separators */
    --outline-soft: rgba(10, 31, 68, 0.12); /* hairline on coloured tiles */

    --heading-accent: #0b429c;              /* page sub-title, section eyebrows */
    --gold-line: rgba(138, 97, 0, 0.32);
    --panel-shadow: var(--card-shadow);

    --accent: #0a4d9f;
    --accent-hover: #0d5cbb;
    --accent-soft: rgba(10, 77, 159, 0.08);
    --accent-text: #0b429c;
    --focus: #2b8ad3;
    --on-accent: #ffffff;

    /* tables: a pale header band with navy text, hairline rules, a tinted total row */
    --th-bg: #f2f5fb;
    --th-text: #14295c;
    --th-border: #dfe6f2;
    --tfoot-bg: #eaf1fc;
    --card-shadow: 0 1px 2px rgba(16, 42, 90, 0.05), 0 6px 16px -8px rgba(16, 42, 90, 0.14);
    --kpi-blue: #2563eb;
    --kpi-green: #0f9d6b;
    --kpi-purple: #7c4ddb;
    --kpi-orange: #ef7d16;
    --kpi-teal: #0a93ae;
    --kpi-pink: #d6336c;
    --row-hover: rgba(10, 77, 159, 0.07);

    --control-bg: #ffffff;
    --control-border: #d3dcec;
    --control-text: #161b26;
    --control-placeholder: #7a8494;
    --control-hover: #f1f6fd;
    --seg-bg: #eef1f6;
    --seg-hover: #e4e9f1;
    --seg-text: #3a4658;

    /* status */
    --c-gold: #8a6100;
    --c-gold-soft: #7a5b00;
    --c-green: #0b6b3a;
    --c-green-strong: #0a7d3b;
    --c-amber: #7a4b00;
    --c-amber-soft: #6b5326;
    --c-blue: #0b429c;
    --c-red: #b3261e;
    --good-bg: rgba(10, 125, 59, 0.08);
    --good-border: rgba(10, 125, 59, 0.35);
    --bad-bg: rgba(179, 38, 30, 0.07);
    --bad-border: rgba(179, 38, 30, 0.35);
    --info-bg: rgba(10, 77, 159, 0.07);
    --info-border: rgba(10, 77, 159, 0.3);
    --warn-bg: rgba(200, 130, 0, 0.1);
    --warn-border: rgba(200, 130, 0, 0.4);
    --chip-green-bg: rgba(10, 125, 59, 0.1);
    --chip-green-border: rgba(10, 125, 59, 0.3);
    --chip-gold-bg: rgba(200, 140, 0, 0.12);
    --chip-blue-bg: rgba(10, 77, 159, 0.08);
    --scroll-thumb: rgba(10, 31, 68, 0.28);
    --scroll-thumb-hover: rgba(10, 31, 68, 0.45);

    /* charts (read by the SVG builders in Charts/*.cs) */
    --chart-axis: #66717f;
    --chart-text: #26324a;
    --chart-text-strong: #0a1f44;
    --chart-text-soft: #3a4658;
    --chart-grid: rgba(10, 31, 68, 0.09);
    --chart-baseline: rgba(10, 31, 68, 0.22);
    --chart-surface: #ffffff;
    --chart-track: #e8edf4;
    --chart-halo: rgba(255, 255, 255, 0.9);
}

/* ---------- semantic colour: DARK ---------- */
[data-bs-theme="dark"] {
    color-scheme: dark;

    --bg: #010e2f;
    --page-bg: #010e2f;
    --page-bg-image:
        radial-gradient(120% 80% at 50% 0%, rgba(6, 32, 86, 0.5) 0%, rgba(1, 7, 33, 0) 70%),
        linear-gradient(180deg, #020b28 0%, #010e2f 55%, #010423 100%);
    --surface: #011140;
    --surface-2: #0b2358;
    --surface-sunken: #010a26;

    --text: #e8eaf0;
    --text-strong: #ffffff;
    --text-2: #dfe6f0;
    --text-3: #bcc7d8;
    --text-muted: #9fb4d4;
    --text-faint: #7f93b5;

    --border: rgba(120, 165, 235, 0.2);
    --border-soft: rgba(120, 165, 235, 0.12);
    --border-strong: rgba(120, 165, 235, 0.45);
    --tint: rgba(255, 255, 255, 0.04);
    --zebra: rgba(255, 255, 255, 0.022);
    --divider: rgba(255, 255, 255, 0.055);
    --outline-soft: rgba(255, 255, 255, 0.14);

    --heading-accent: #35d17a;
    --gold-line: rgba(245, 200, 66, 0.28);
    --panel-shadow: none;

    --accent: #0421c6;
    --accent-hover: #021fb8;
    --accent-soft: rgba(74, 159, 224, 0.14);
    --accent-text: #9fc8ff;
    --focus: #4a9fe0;
    --on-accent: #ffffff;

    /* solid: this sits under a sticky (position: sticky, top: 0) table header, which must fully
       hide the rows scrolling underneath it rather than let them show through */
    --th-bg: #12245a;
    --th-text: #dbe6fb;
    --th-border: rgba(120, 165, 235, 0.22);
    /* solid, not a tint over --accent: this sits under a sticky footer, which must fully hide
       the row scrolling behind it rather than let it show through */
    --tfoot-bg: #132a5e;
    --card-shadow: none;
    --kpi-blue: #5b8def;
    --kpi-green: #2fc98f;
    --kpi-purple: #a58bf0;
    --kpi-orange: #f59b3d;
    --kpi-teal: #34c0d8;
    --kpi-pink: #f472a6;
    --row-hover: rgba(74, 159, 224, 0.14);

    --control-bg: rgba(255, 255, 255, 0.06);
    --control-border: rgba(120, 165, 235, 0.38);
    --control-text: #e8eaf0;
    --control-placeholder: #7f93b5;
    --control-hover: rgba(255, 255, 255, 0.1);
    --seg-bg: rgba(255, 255, 255, 0.06);
    --seg-hover: rgba(255, 255, 255, 0.12);
    --seg-text: #bcc7d8;

    --c-gold: #f5c842;
    --c-gold-soft: #f5d98a;
    --c-green: #8ee4ab;
    --c-green-strong: #4bd47a;
    --c-amber: #ffd79a;
    --c-amber-soft: #cfb894;
    --c-blue: #9fc8ff;
    --c-red: #ff8a80;
    --good-bg: rgba(75, 212, 122, 0.1);
    --good-border: rgba(75, 212, 122, 0.4);
    --bad-bg: rgba(255, 138, 128, 0.1);
    --bad-border: rgba(255, 138, 128, 0.4);
    --info-bg: rgba(120, 165, 235, 0.1);
    --info-border: rgba(120, 165, 235, 0.4);
    --warn-bg: rgba(240, 160, 32, 0.12);
    --warn-border: rgba(240, 172, 60, 0.45);
    --chip-green-bg: rgba(47, 168, 90, 0.18);
    --chip-green-border: rgba(47, 168, 90, 0.34);
    --chip-gold-bg: rgba(245, 200, 66, 0.16);
    --chip-blue-bg: rgba(120, 165, 235, 0.16);
    --scroll-thumb: rgba(120, 165, 235, 0.45);
    --scroll-thumb-hover: rgba(120, 165, 235, 0.7);

    --chart-axis: #8794ac;
    --chart-text: #dfe6f0;
    --chart-text-strong: #ffffff;
    --chart-text-soft: #c2cbdb;
    --chart-grid: rgba(255, 255, 255, 0.07);
    --chart-baseline: rgba(255, 255, 255, 0.16);
    --chart-surface: #011140;
    --chart-track: #0d1b3f;
    --chart-halo: rgba(4, 10, 28, 0.82);

    --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.35);
    --shadow-2: 0 6px 20px -8px rgba(0, 0, 0, 0.6);
}

/* ---------- bridge: let Bootstrap components read the same tokens ---------- */
:root,
[data-bs-theme] {
    --bs-body-font-family: var(--font-sans);
    --bs-body-bg: var(--bg);
    --bs-body-color: var(--text);
    --bs-border-color: var(--border);
    --bs-link-color-rgb: 11, 66, 156;
    --bs-link-hover-color-rgb: 13, 92, 187;
}

[data-bs-theme="dark"] {
    --bs-link-color-rgb: 159, 200, 255;
    --bs-link-hover-color-rgb: 191, 218, 255;
}

/* ==========================================================================
   Base — applies to every page that is not the landing page (the landing page re-declares
   its own root rules under `.landing`; see landing.css).
   ========================================================================== */

/* Fluid root size, for the landing page only. Every measurement there is in rem, so this
   one line scales it: 16px on phones and tablets, growing to 20px at 1280px and 22px on wide
   monitors. The dashboard pages were drawn against a 16px root and their own stylesheets set
   their surface and type, so the match on .landing keeps this off them — unscoped, it grew
   every dashboard page by up to 37% and repainted it. */
html:has(.landing) {
    font-size: clamp(16px, 9px + 0.859375vw, 22px);
    -webkit-text-size-adjust: 100%;
}

body:has(.landing) {
    margin: 0;
    font-family: var(--font-sans);
    background-color: var(--bg);
    color: var(--text);
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

@media (max-width: 640.98px) {
    :root {
        --fs-floor: 11px;
    }
}

.landing h1, .landing h2, .landing h3,
.landing h4, .landing h5, .landing h6 {
    font-family: var(--font-sans);
}

:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 2px;
}

.landing img, .landing svg {
    max-width: 100%;
}

/* Blazor's unhandled-error bar. One definition for every layout (it used to live in
   MainLayout.razor.css only, which left it permanently visible on the landing page). */
#blazor-error-ui {
    color-scheme: light only;
    background: lightyellow;
    color: #1a1a1a;
    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;
}

/* The .theme-toggle / .tt-* block that used to sit here has been removed along with the
   second theme switch it dressed. The dashboard's switch lives at the foot of the sidebar
   (.faac-theme-* in Components/Layout/NavMenu.razor.css) and is the only one. */

/* ==========================================================================
   Navigation / data-loading indicator (js/nav-loader.js).

   A slim progress bar across the top of every page, shown the instant a navigable link is
   clicked, plus — once the wait passes ~220ms — a centred spinner over a soft backdrop. This is
   what tells a user their click registered while the server works through a slow database query
   (Blazor Server's enhanced navigation renders a page's data fully before any HTML exists to
   send, so the browser's own loading spinner never appears for that wait on its own).

   #nav-loader is rendered once in Components/App.razor with `data-permanent`, so it survives
   enhanced navigation's DOM diff instead of being torn down and rebuilt by the very page change
   it is reporting on. Its default state (no state class) is fully invisible and inert.
   ========================================================================== */
#nav-loader {
    position: fixed;
    inset: 0;
    z-index: 2000;
    pointer-events: none;
    visibility: hidden;
}

#nav-loader.is-active { visibility: visible; }

.nav-loader-bar {
    position: fixed;
    top: 0;
    left: 0;
    height: 3px;
    width: 0%;
    background: linear-gradient(90deg, var(--accent), var(--focus));
    box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 60%, transparent);
    opacity: 0;
    transition: opacity 0.25s ease;
}

#nav-loader.is-active .nav-loader-bar { opacity: 1; }

/* the "creep": eases toward 82% over several seconds, slowing down, so it always looks like
   progress without ever claiming to know how long the request will actually take */
#nav-loader.is-creeping .nav-loader-bar {
    width: 82%;
    transition: width 6s cubic-bezier(0.15, 0.65, 0.25, 1), opacity 0.25s ease;
}

/* the request landed: snap to 100%, then (in JS, after a short pause) fade out */
#nav-loader.is-done .nav-loader-bar { width: 100%; transition: width 0.25s ease; }
#nav-loader.is-hidden .nav-loader-bar { opacity: 0; transition: opacity 0.35s ease; }

.nav-loader-overlay {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: color-mix(in srgb, var(--bg) 55%, transparent);
    backdrop-filter: blur(1.5px);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s ease;
}

/* only for waits past ~220ms — fast navigations never show this, only the bar */
#nav-loader.show-overlay .nav-loader-overlay {
    opacity: 1;
    pointer-events: auto;
    cursor: wait;
}

#nav-loader.is-hidden .nav-loader-overlay { opacity: 0 !important; pointer-events: none; }

.nav-loader-spinner {
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    border: 3px solid var(--border-strong);
    border-top-color: var(--accent);
    box-shadow: var(--shadow-2);
    animation: nav-spin 0.7s linear infinite;
}

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

@media (prefers-reduced-motion: reduce) {
    #nav-loader.is-creeping .nav-loader-bar { width: 100%; transition: opacity 0.25s ease; }
    .nav-loader-spinner { animation-duration: 1.4s; }
}

@media print {
    #nav-loader { display: none; }
}
