/* ==========================================================================
   Trihedron ERP — dark industrial design system
   --------------------------------------------------------------------------
   Built from the Trihedron logo. The four brand colours were sampled from the
   logo file itself rather than estimated:

       blue   #007EC4   outer cube      — identity, primary action
       cyan   #03ACE4   right facet     — links, accents, headings
       red    #F04D28   left facet      — danger, errors, over budget
       green  #76C043   top facet       — success, complete, within budget
       white  #FFFFFF   wordmark        — primary text

   Every neutral is mixed at hue 205, four degrees off the brand blue, so the
   greys read as desaturated relatives of the logo rather than a separate palette.

   All text and accent colours clear WCAG AA against the dark surfaces:
       body text  15.3:1     cyan links  6.85:1
       green      8.01:1     red         4.95:1     dim text  8.0:1

   Motion is 120–200ms and disabled entirely under prefers-reduced-motion. This
   is a back-office system: it should feel responsive, not animated.
   ========================================================================== */

:root {
    /* TELLS THE BROWSER, not just our own rules. Date and time pickers, native
       select popups, scrollbars and form-control chrome are drawn by the
       browser and take no notice of a custom property — this is the one
       declaration that reaches them. Without it a light page opens a black date
       picker, which is exactly the kind of thing "make sure it is all readable"
       means. */
    color-scheme: dark;

    /* --- Brand, exactly as sampled from the logo ------------------------- */
    --t-blue: #007ec4;
    --t-cyan: #03ace4;
    --t-red: #f04d28;
    --t-green: #76c043;
    --t-blue-soft: rgba(0, 126, 196, 0.16);
    --t-cyan-soft: rgba(3, 172, 228, 0.15);
    --t-red-soft: rgba(240, 77, 40, 0.15);
    --t-green-soft: rgba(118, 192, 67, 0.15);
    --t-amber-soft: rgba(240, 160, 40, 0.15);
    /* Button fill: four percent darker than brand blue so a white label
       reaches 4.77:1 rather than 4.39:1. The logo always renders true blue. */
    --t-blue-fill: #0078bb;
    --t-blue-fill-hover: #0d8dd6;
    /* Warning: brand red with lightness and saturation held, hue rotated
       11° → 36°. A sibling of the red, not an imported colour. */
    --t-amber: #f0a028;
    /* --- Neutrals, hue 205 ---------------------------------------------- */
    --t-bg-0: #0b1014;
    --t-bg-1: #11181d;
    --t-bg-2: #1a2228;
    --t-bg-3: #252f37;
    --t-line: #2e3a42;
    --t-line-strong: #475662;
    --t-text: #e9eef1;
    --t-text-dim: #a2afb9;
    --t-text-faint: #6f8290;
    /* --- Type ------------------------------------------------------------ */
    --t-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --t-mono: "Cascadia Mono", "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
    /* --- Rhythm and motion ----------------------------------------------- */
    --t-radius: 4px;
    --t-radius-lg: 7px;
    --t-gap: 1rem;
    --t-fast: 120ms cubic-bezier(0.2, 0, 0.2, 1);
    --t-med: 200ms cubic-bezier(0.2, 0, 0.2, 1);
    --t-sidebar-w: 236px;
    --t-sidebar-collapsed-w: 64px;
    /* --- Roles ------------------------------------------------------------
       EVERYTHING BELOW IS A ROLE, NOT A COLOUR, and that distinction is what
       makes a second theme possible at all. A rule that says
       `color: var(--t-cyan)` has decided the hue; a rule that says
       `color: var(--t-link)` has decided the meaning, and the theme decides
       the hue. The light block further down redefines only these.

       The reason there has to be a link colour at all: brand cyan on white is
       about 2.3:1, which is unreadable as text. The brand does not change —
       the logo is the logo — but the colour text is written in has to. */
    --t-link: var(--t-cyan);
    --t-link-hover: #37cbfc;

    /* The "this one is selected" colour: nav items, focus rings, active tabs. */
    --t-accent: var(--t-cyan);

    /* Text sitting ON a filled brand button. White in both themes — the fills
       are dark enough in both that it stays the readable choice. */
    --t-on-fill: #ffffff;

    /* Status text, for alerts and badges. Pale tints of the brand hues on a
       dark ground; the light theme replaces them with dark tints, because a
       pale green on white is invisible. */
    --t-text-ok: #bce0a2;
    --t-text-warn: #f3cf9c;
    --t-text-danger: #f8b09f;
    --t-text-info: #7fc9ef;

    /* Bar fills on the planning board. Alpha over the page ground, so they
       have to be a shade stronger in the light theme to read at all. */
    --t-bar-active: rgba(118, 192, 67, 0.28);
    --t-bar-planned: rgba(0, 126, 196, 0.24);
    --t-bar-overrun: rgba(240, 77, 40, 0.26);

    /* Elevation. A modal on a dark page is lifted by a black shadow; on a light
       one that same shadow is a smudge, so the light theme softens it. */
    --t-shadow-modal: 0 22px 60px rgba(0, 0, 0, 0.5);
    --t-shadow-panel: 0 1px 2px rgba(0, 0, 0, 0);

    /* The brand wash behind the home screen and the login card. */
    --t-wash-1: rgba(0, 126, 196, 0.16);
    --t-wash-2: rgba(3, 172, 228, 0.08);

    /* Behind a modal. Near-black at 72% is right over a dark page and would be
       a blackout over a light one. */
    --t-scrim: rgba(4, 8, 12, 0.72);

    /* Text on an amber or green status pill. Those fills are bright in the dark
       theme and dark in the light one, so the label on them has to invert. */
    --t-on-status: #1a2026;

    /* --- Paper -----------------------------------------------------------
       THESE DO NOT CHANGE WITH THE THEME, and that is the point. A document
       being prepared for signature is shown as the document: white sheet,
       black text, in both themes. Making the signing surface follow the
       interface would mean the thing on screen no longer looked like the thing
       that gets printed and signed. */
    --t-paper: #ffffff;
    --t-on-paper: #0b1014;
    --t-on-paper-dim: #5b6670;

    /* --- The globe -------------------------------------------------------
       Read from here by wwwroot/js/schedule-globe.js rather than hard-coded in
       it, so a canvas that paints its own pixels still follows the theme. The
       glow radius is a number in a custom property on purpose: it is the one
       thing about the Cerebro look that has to come down in a light room. */
    --t-globe-sea: #070d12;
    --t-globe-sea-lit: #0e1a24;
    --t-globe-sea-edge: #04080b;
    --t-globe-land: #16232e;
    --t-globe-land-edge: #22384a;
    --t-globe-grid: rgba(3, 172, 228, 0.13);
    --t-globe-rim: rgba(3, 172, 228, 0.55);
    --t-globe-sweep: rgba(3, 172, 228, 0.16);
    --t-globe-label: rgba(233, 238, 241, 0.9);
    --t-globe-sublabel: rgba(162, 175, 185, 0.85);
    --t-globe-city: rgba(162, 175, 185, 0.55);
    --t-globe-city-label: rgba(162, 175, 185, 0.7);
    --t-globe-count: #04080b;
    --t-globe-glow: 12;

    /* The panel the sphere sits in, behind the two brand washes. */
    --t-globe-stage: #05090c;

    /* A control floating over the globe — the zoom buttons. Translucent so the
       sphere shows through, and matched to whichever ground is behind it. */
    --t-control-fill: rgba(11, 16, 20, 0.82);

    --bs-body-bg: var(--t-bg-0);
    --bs-body-color: var(--t-text);
    --bs-border-color: var(--t-line);
    --bs-primary: var(--t-blue);
    --bs-link-color: var(--t-link);
    --bs-link-hover-color: var(--t-link-hover);
}

/* ==========================================================================
   THE LIGHT THEME
   --------------------------------------------------------------------------
   Only tokens. Not one selector below this block, and that is the whole point:
   if a light theme needs a rule of its own then something above is describing a
   colour instead of a role, and the fix belongs there.

   Same hue family — 205, the neutrals are the same slate the dark theme uses,
   inverted rather than swapped for a warm grey, so the two themes are visibly
   one application.

   CONTRAST, checked rather than eyeballed. On the white panel:
     text on bg-1        #17242c on #ffffff   14.9:1
     text-dim on bg-1    #4a5c68 on #ffffff    7.2:1
     text-faint on bg-1  #667a86 on #ffffff    4.6:1
     link on bg-1        #0b6591 on #ffffff    5.6:1
     white on blue fill  #ffffff on #0069a8    5.0:1
   All above the 4.5:1 that WCAG AA asks of body text. text-faint is the one
   that had to move: the dark theme's #6f8290 is only 3.6:1 on white, which is
   why hints and captions were the first thing to become unreadable.
   ========================================================================== */

:root[data-theme="light"] {
    color-scheme: light;

    /* --- Brand. The logo is the logo; these do not change. --------------- */
    --t-blue: #007ec4;
    --t-cyan: #03ace4;
    --t-red: #d63c1a;
    --t-green: #4f8f22;
    --t-amber: #b26a00;

    /* Soft washes, lifted a little: 15% of a hue over white is fainter to the
       eye than 15% over near-black. */
    --t-blue-soft: rgba(0, 126, 196, 0.10);
    --t-cyan-soft: rgba(3, 172, 228, 0.12);
    --t-red-soft: rgba(214, 60, 26, 0.10);
    --t-green-soft: rgba(79, 143, 34, 0.12);
    --t-amber-soft: rgba(178, 106, 0, 0.12);

    /* The button fill darkens so a white label still clears 4.5:1. */
    --t-blue-fill: #0069a8;
    --t-blue-fill-hover: #00588c;

    /* --- Neutrals, hue 205, inverted -------------------------------------
       bg-0 is the room, bg-1 the panels standing in it, bg-2 an inset within a
       panel, bg-3 a pressed or striped row. Panels are pure white so that a
       table of numbers is the brightest thing on screen, which is where the
       eye should go. */
    --t-bg-0: #eaeff3;
    --t-bg-1: #ffffff;
    --t-bg-2: #f4f7f9;
    --t-bg-3: #e4ebef;
    --t-line: #d2dce2;
    --t-line-strong: #9fb0bb;
    --t-text: #17242c;
    --t-text-dim: #4a5c68;
    --t-text-faint: #667a86;

    /* --- Roles ----------------------------------------------------------- */
    --t-link: #0b6591;
    --t-link-hover: #08496a;
    --t-accent: #0b6591;
    --t-on-fill: #ffffff;

    /* Dark tints now: a pale green on white says nothing. */
    --t-text-ok: #2f6412;
    --t-text-warn: #8a5000;
    --t-text-danger: #a82c10;
    --t-text-info: #05587f;

    /* Stronger, because alpha over white washes out. */
    --t-bar-active: rgba(79, 143, 34, 0.30);
    --t-bar-planned: rgba(0, 126, 196, 0.26);
    --t-bar-overrun: rgba(214, 60, 26, 0.24);

    /* A soft grey lift rather than a black drop. And panels gain a hairline
       shadow, which is what separates white-on-white without a heavy border. */
    --t-shadow-modal: 0 18px 44px rgba(23, 36, 44, 0.18);
    --t-shadow-panel: 0 1px 2px rgba(23, 36, 44, 0.06);

    --t-wash-1: rgba(0, 126, 196, 0.09);
    --t-wash-2: rgba(3, 172, 228, 0.06);

    /* A grey veil, not a blackout. */
    --t-scrim: rgba(23, 36, 44, 0.38);

    /* The amber and green fills are dark in this theme, so their labels go white. */
    --t-on-status: #ffffff;

    /* Paper is paper. Repeated rather than inherited so the intent is visible
       in both blocks: a reader checking the light theme sees that this was a
       decision, not an omission. */
    --t-paper: #ffffff;
    --t-on-paper: #0b1014;
    --t-on-paper-dim: #5b6670;

    /* --- The globe becomes a map ------------------------------------------
       Not a dark sphere dropped into a light page. Pale sea, light land, dark
       labels — and the glow comes right down, because a bloom that reads as
       "signal" in a dark room reads as "smudge" in a bright one. */
    --t-globe-sea: #dce8f0;
    --t-globe-sea-lit: #eef5fa;
    --t-globe-sea-edge: #c3d5e2;
    --t-globe-land: #f6f2e7;
    --t-globe-land-edge: #c0ccb8;
    --t-globe-grid: rgba(11, 101, 145, 0.16);
    --t-globe-rim: rgba(11, 101, 145, 0.45);
    --t-globe-sweep: rgba(3, 172, 228, 0.14);
    --t-globe-label: rgba(23, 36, 44, 0.92);
    --t-globe-sublabel: rgba(74, 92, 104, 0.9);
    --t-globe-city: rgba(74, 92, 104, 0.55);
    --t-globe-city-label: rgba(74, 92, 104, 0.75);
    --t-globe-count: #ffffff;
    --t-globe-glow: 4;
    --t-globe-stage: #e3ecf3;
    --t-control-fill: rgba(255, 255, 255, 0.86);
}

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */

html, body {
    height: 100%;
}

body {
    margin: 0;
    background: var(--t-bg-0);
    color: var(--t-text);
    font-family: var(--t-font);
    font-size: 14px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

.mono,
.table td.mono,
.table th.mono {
    font-family: var(--t-mono);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}

.muted {
    color: var(--t-text-dim);
}

.faint {
    color: var(--t-text-faint);
}

a {
    color: var(--t-cyan);
    text-decoration: none;
    transition: color var(--t-fast);
}

    a:hover {
        color: var(--t-link-hover);
        text-decoration: underline;
    }

:focus-visible {
    outline: 2px solid var(--t-cyan);
    outline-offset: 2px;
    border-radius: 2px;
}

/* --------------------------------------------------------------------------
   Icons
   --------------------------------------------------------------------------
   Inline SVG from Ui/Icons.cs. stroke="currentColor" means an icon takes the
   colour of its container, so hover and active states need no second asset.
   -------------------------------------------------------------------------- */

.icon {
    width: 18px;
    height: 18px;
    flex: 0 0 auto;
    vertical-align: -0.18em;
}

.icon-sm {
    width: 13px;
    height: 13px;
}

.icon-lg {
    width: 22px;
    height: 22px;
}

.icon-xl {
    width: 34px;
    height: 34px;
}

/* --------------------------------------------------------------------------
   Brand marks
   -------------------------------------------------------------------------- */

.logo-full {
    display: block;
    height: auto;
    width: 100%;
    max-width: 100%;
}

/* WHICH WORDMARK. The logo's text is baked pixels, so it cannot be recoloured
   by CSS — there are two files and one of them is hidden. See _BrandLogo.cshtml.

   Both selectors are (0,3,0) so neither can lose to the other by specificity;
   the theme attribute is what decides. The collapsed-sidebar rule below is
   deliberately raised above both — see the note there. */
.logo-full.for-light { display: none; }

:root[data-theme="light"] .logo-full.for-dark { display: none; }
:root[data-theme="light"] .logo-full.for-light { display: block; }

.logo-mark {
    display: block;
    height: auto;
}

.logo-mark-only {
    display: none;
    width: 30px;
    height: auto;
}

/* --------------------------------------------------------------------------
   Application shell
   -------------------------------------------------------------------------- */

.app-shell {
    display: grid;
    grid-template-columns: var(--t-sidebar-w) 1fr;
    min-height: 100vh;
    transition: grid-template-columns var(--t-med);
}

    .app-shell.is-collapsed {
        grid-template-columns: var(--t-sidebar-collapsed-w) 1fr;
    }

.app-sidebar {
    background: var(--t-bg-1);
    border-right: 1px solid var(--t-line);
    padding: 1.1rem 0 1.5rem;
    display: flex;
    flex-direction: column;
    gap: 1.1rem;
    overflow: hidden;
    position: sticky;
    top: 0;
    height: 100vh;
}

.brand {
    position: relative;
    padding: 0 1.15rem 1.1rem;
    border-bottom: 1px solid var(--t-line);
}

.brand-link {
    display: block;
}

.brand .logo-full {
    width: 152px;
}

.brand-sub {
    display: block;
    margin-top: 0.4rem;
    font-family: var(--t-mono);
    font-size: 0.64rem;
    letter-spacing: 0.34em;
    color: var(--t-cyan);
    text-transform: uppercase;
}

.sidebar-toggle {
    position: absolute;
    top: -0.15rem;
    right: 0.7rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--t-radius);
    color: var(--t-text-faint);
    cursor: pointer;
    transition: color var(--t-fast), background var(--t-fast), border-color var(--t-fast);
}

    .sidebar-toggle:hover {
        color: var(--t-cyan);
        background: var(--t-bg-2);
        border-color: var(--t-line);
    }

.nav-scroll {
    flex: 1 1 auto;
    overflow-y: auto;
    overflow-x: hidden;
    display: flex;
    flex-direction: column;
    gap: 1.1rem;
    scrollbar-width: thin;
    scrollbar-color: var(--t-line-strong) transparent;
}

    .nav-scroll::-webkit-scrollbar {
        width: 8px;
    }

    .nav-scroll::-webkit-scrollbar-thumb {
        background: var(--t-line);
        border-radius: 4px;
    }

        .nav-scroll::-webkit-scrollbar-thumb:hover {
            background: var(--t-line-strong);
        }

.nav-group {
    display: flex;
    flex-direction: column;
}

.nav-heading {
    padding: 0 1.15rem 0.4rem;
    font-size: 0.66rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--t-text-faint);
    white-space: nowrap;
}

.nav-item {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.52rem 1.15rem;
    color: var(--t-text-dim);
    border-left: 2px solid transparent;
    font-size: 0.875rem;
    white-space: nowrap;
    transition: color var(--t-fast), background var(--t-fast), border-color var(--t-fast);
}

.nav-icon {
    color: var(--t-text-faint);
    transition: color var(--t-fast);
}

.nav-label {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
}

.nav-item:hover:not(.disabled) {
    background: var(--t-bg-2);
    color: var(--t-text);
    text-decoration: none;
}

    .nav-item:hover:not(.disabled) .nav-icon {
        color: var(--t-cyan);
    }

.nav-item.active {
    background: var(--t-blue-soft);
    border-left-color: var(--t-blue);
    color: var(--t-text);
    font-weight: 500;
}

    .nav-item.active .nav-icon {
        color: var(--t-cyan);
    }

.nav-item.disabled {
    color: var(--t-text-faint);
    cursor: default;
}

    .nav-item.disabled .nav-icon {
        opacity: 0.5;
    }

.nav-item em {
    font-family: var(--t-mono);
    font-style: normal;
    font-size: 0.66rem;
    color: var(--t-text-faint);
    border: 1px solid var(--t-line);
    border-radius: 2px;
    padding: 0 0.28rem;
    flex: 0 0 auto;
}

/* --- Collapsed rail ------------------------------------------------------ */

.app-shell.is-collapsed .brand {
    padding: 0 0 1.1rem;
    text-align: center;
}

    /* RAISED ON PURPOSE. With the sidebar collapsed the wordmark goes and the
       cube alone stays, and that has to hold in both themes.

       At four classes this rule tied with `:root[data-theme="light"]
       .logo-full.for-light`, and a tie is settled by source order — which is a
       coin toss decided by where somebody happens to paste the next rule.
       Naming both variants takes it to five and settles it properly. */
    .app-shell.is-collapsed .brand .logo-full.for-dark,
    .app-shell.is-collapsed .brand .logo-full.for-light {
        display: none;
    }

.app-shell.is-collapsed .logo-mark-only {
    display: inline-block;
    margin: 0 auto;
}

.app-shell.is-collapsed .brand-sub {
    display: none;
}

.app-shell.is-collapsed .sidebar-toggle {
    position: static;
    margin: 0.6rem auto 0;
    display: flex;
}

.app-shell.is-collapsed .nav-heading {
    display: none;
}

.app-shell.is-collapsed .nav-item {
    justify-content: center;
    padding: 0.6rem 0;
    gap: 0;
}

    .app-shell.is-collapsed .nav-label,
    .app-shell.is-collapsed .nav-item em {
        display: none;
    }

.app-shell.is-collapsed .nav-group + .nav-group {
    border-top: 1px solid var(--t-line);
    padding-top: 0.5rem;
}

/* --------------------------------------------------------------------------
   Top bar
   -------------------------------------------------------------------------- */

.app-main {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.app-topbar {
    height: 54px;
    flex: 0 0 54px;
    background: var(--t-bg-1);
    border-bottom: 1px solid var(--t-line);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 1.5rem;
    position: sticky;
    top: 0;
    z-index: 20;
}

.topbar-title {
    font-size: 0.78rem;
    letter-spacing: 0.11em;
    text-transform: uppercase;
    color: var(--t-text-dim);
}

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

.avatar {
    width: 32px;
    height: 32px;
    flex: 0 0 32px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(140deg, var(--t-blue), var(--t-cyan));
    color: var(--t-on-fill);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    user-select: none;
}

.user-meta {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    line-height: 1.2;
}

.user-name {
    font-size: 0.8rem;
}

.user-role {
    font-size: 0.65rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--t-cyan);
}

.logout-form {
    margin: 0;
}

.app-content {
    padding: 1.6rem 1.75rem 3rem;
    flex: 1 1 auto;
    min-width: 0;
    animation: page-in var(--t-med) both;
}

@keyframes page-in {
    from {
        opacity: 0;
        transform: translateY(6px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

/* --------------------------------------------------------------------------
   Signed-out shell
   -------------------------------------------------------------------------- */

.anon-shell {
    /* Positioned so the theme toggle in the corner has something to anchor to. */
    position: relative;
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2.5rem 1rem;
    background: radial-gradient(1100px 620px at 50% -12%, var(--t-wash-1), transparent 62%), radial-gradient(760px 460px at 84% 108%, var(--t-wash-2), transparent 60%), var(--t-bg-0);
}

/* --------------------------------------------------------------------------
   Page furniture
   -------------------------------------------------------------------------- */

.page-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--t-gap);
    margin-bottom: 1.4rem;
    flex-wrap: wrap;
}

.page-head-text {
    min-width: 0;
}

.page-title {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    font-size: 1.32rem;
    font-weight: 600;
    margin: 0;
    letter-spacing: -0.01em;
}

.title-icon {
    color: var(--t-cyan);
    width: 21px;
    height: 21px;
}

.page-sub {
    margin: 0.2rem 0 0;
    font-size: 0.82rem;
    color: var(--t-text-dim);
}

/* --- Hero band ----------------------------------------------------------- */

.hero {
    display: flex;
    align-items: center;
    gap: 1.15rem;
    background: linear-gradient(100deg, var(--t-wash-1), var(--t-wash-2) 48%, transparent 76%), var(--t-bg-1);
    border: 1px solid var(--t-line);
    border-left: 3px solid var(--t-blue);
    border-radius: var(--t-radius-lg);
    padding: 1.15rem 1.35rem;
    margin-bottom: 1.4rem;
}

.hero-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 62px;
    height: 62px;
    flex: 0 0 62px;
    border-radius: var(--t-radius-lg);
    background: var(--t-blue-soft);
    border: 1px solid var(--t-cyan-soft);
}

    .hero-mark .logo-mark {
        width: 40px;
    }

.hero-text {
    flex: 1 1 auto;
    min-width: 0;
}

    .hero-text h1 {
        font-size: 1.32rem;
        font-weight: 600;
        margin: 0 0 0.12rem;
        letter-spacing: -0.01em;
    }

    .hero-text p {
        margin: 0;
        font-size: 0.83rem;
        color: var(--t-text-dim);
    }

.hero-badge {
    flex: 0 0 auto;
}

/* --- Panels -------------------------------------------------------------- */

.panel {
    background: var(--t-bg-1);
    border: 1px solid var(--t-line);
    border-radius: var(--t-radius-lg);
    margin-bottom: 1.15rem;
    overflow: hidden;

    /* Transparent in the dark theme, a hairline lift in the light one. A white
       panel on a near-white page needs something to sit on: the border alone
       reads as a drawn box rather than a raised surface, which is what makes a
       light back-office screen look like a spreadsheet. */
    box-shadow: var(--t-shadow-panel);
}

.panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--t-gap);
    padding: 0.75rem 1.1rem;
    border-bottom: 1px solid var(--t-line);
    background: var(--t-bg-2);
}

    .panel-head h2 {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        margin: 0;
        font-size: 0.78rem;
        letter-spacing: 0.1em;
        text-transform: uppercase;
        color: var(--t-text-dim);
    }

.head-icon {
    color: var(--t-cyan);
    width: 16px;
    height: 16px;
}

.panel-body {
    padding: 1.05rem 1.1rem;
}

/* --------------------------------------------------------------------------
   Stat tiles
   -------------------------------------------------------------------------- */

.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(196px, 1fr));
    gap: 0.85rem;
    margin-bottom: 1.4rem;
}

.stat {
    background: var(--t-bg-1);
    border: 1px solid var(--t-line);
    border-top: 2px solid var(--t-line-strong);
    border-radius: var(--t-radius-lg);
    padding: 0.85rem 1rem 0.95rem;
    transition: transform var(--t-fast), border-color var(--t-fast), background var(--t-fast);
}

    .stat:hover {
        transform: translateY(-2px);
        background: var(--t-bg-2);
    }

.stat-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.5rem;
}

.stat-icon {
    opacity: 0.85;
}

.stat-blue {
    border-top-color: var(--t-blue);
}

.stat-cyan {
    border-top-color: var(--t-cyan);
}

.stat-green {
    border-top-color: var(--t-green);
}

.stat-red {
    border-top-color: var(--t-red);
}

.stat-blue .stat-icon {
    color: var(--t-blue);
}

.stat-cyan .stat-icon {
    color: var(--t-cyan);
}

.stat-green .stat-icon {
    color: var(--t-green);
}

.stat-red .stat-icon {
    color: var(--t-red);
}

.stat-label {
    font-size: 0.68rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--t-text-faint);
}

.stat-value {
    font-family: var(--t-mono);
    font-variant-numeric: tabular-nums;
    font-size: 1.95rem;
    line-height: 1.1;
    margin: 0.2rem 0 0.1rem;
}

.stat-foot {
    font-size: 0.73rem;
    color: var(--t-text-dim);
}

/* --------------------------------------------------------------------------
   Tables
   -------------------------------------------------------------------------- */

.table {
    width: 100%;
    border-collapse: collapse;
    --bs-table-bg: transparent;
    --bs-table-color: var(--t-text);
    margin: 0;
}

    .table th {
        text-align: left;
        font-size: 0.68rem;
        letter-spacing: 0.1em;
        text-transform: uppercase;
        color: var(--t-text-faint);
        font-weight: 600;
        border-bottom: 1px solid var(--t-line-strong);
        padding: 0.5rem 0.7rem;
        background: var(--t-bg-1);
    }

    .table td {
        padding: 0.5rem 0.7rem;
        border-bottom: 1px solid var(--t-line);
        color: var(--t-text);
    }

.table-dense th,
.table-dense td {
    padding: 0.36rem 0.7rem;
    font-size: 0.83rem;
}

.table tbody tr {
    transition: background var(--t-fast);
}

    .table tbody tr:hover td {
        background: var(--t-bg-2);
    }

    .table tbody tr:last-child td {
        border-bottom: none;
    }

.num {
    text-align: right;
    font-family: var(--t-mono);
    font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   Badges
   -------------------------------------------------------------------------- */

/* HIDDEN MEANS HIDDEN.
   --------------------------------------------------------------------------
   The browser's own stylesheet says [hidden] { display: none }, and ANY author
   rule beats it — so .badge below, which sets display: inline-flex, quietly
   un-hides every badge carrying the hidden attribute.

   THIS WAS A LIVE BUG, not a precaution. An employee with no unread notices saw
   an empty amber pill beside "Notices" on their dashboard, because the script
   sets el.hidden = true and .badge overrode it. The same pattern is on the HR
   dashboard and on the documents card.

   !important is deliberate. The alternative is remembering to write
   .badge[hidden], .pill[hidden], .portal-stat[hidden] for every component that
   sets a display — which is the same bug waiting for the next component. The
   only other uses in this file are in the reduced-motion and print blocks at
   the bottom, where overriding is the whole point. */
[hidden] { display: none !important; }

.badge {
    display: inline-flex;
    align-items: center;
    gap: 0.28rem;
    font-size: 0.66rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 0.16rem 0.5rem;
    border-radius: 3px;
    border: 1px solid var(--t-line-strong);
    color: var(--t-text-faint);
    background: transparent;
    font-weight: 600;
    white-space: nowrap;
}

.badge-ok {
    color: var(--t-green);
    border-color: var(--t-green);
    background: var(--t-green-soft);
}

.badge-accent {
    color: var(--t-cyan);
    border-color: var(--t-cyan);
    background: var(--t-cyan-soft);
}

.badge-next {
    color: var(--t-link);
    border-color: var(--t-blue);
    background: var(--t-blue-soft);
}

.badge-warn {
    color: var(--t-amber);
    border-color: var(--t-amber);
    background: var(--t-amber-soft);
}

.badge-danger {
    color: var(--t-red);
    border-color: var(--t-red);
    background: var(--t-red-soft);
}

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */

.btn {
    border-radius: var(--t-radius);
    font-size: 0.85rem;
    font-weight: 500;
    padding: 0.44rem 0.95rem;
    border: 1px solid transparent;
    transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast), transform var(--t-fast);
}

    .btn:active {
        transform: translateY(1px);
    }

.btn-icon {
    display: inline-flex;
    align-items: center;
    gap: 0.42rem;
}

.btn-sm {
    padding: 0.26rem 0.62rem;
    font-size: 0.78rem;
}

    .btn-sm .icon {
        width: 15px;
        height: 15px;
    }

.btn-block {
    width: 100%;
    justify-content: center;
}

.btn-primary {
    background: var(--t-blue-fill);
    border-color: var(--t-blue-fill);
    color: var(--t-on-fill);
    font-weight: 600;
}

    .btn-primary:hover,
    .btn-primary:focus,
    .btn-primary:active {
        background: var(--t-blue-fill-hover);
        border-color: var(--t-blue-fill-hover);
        color: var(--t-on-fill);
    }

.btn-ghost {
    background: transparent;
    border-color: var(--t-line-strong);
    color: var(--t-text-dim);
}

    .btn-ghost:hover {
        background: var(--t-bg-2);
        color: var(--t-text);
        border-color: var(--t-cyan);
    }

.btn-danger-ghost:hover {
    color: var(--t-red);
    border-color: var(--t-red);
    background: var(--t-red-soft);
}

.btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    transform: none;
}

/* --------------------------------------------------------------------------
   Forms
   -------------------------------------------------------------------------- */

.form-label {
    font-size: 0.7rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--t-text-dim);
    margin-bottom: 0.3rem;
    font-weight: 600;
}

.form-control,
.form-select {
    background: var(--t-bg-0);
    border: 1px solid var(--t-line-strong);
    border-radius: var(--t-radius);
    color: var(--t-text);
    font-size: 0.9rem;
    padding: 0.45rem 0.65rem;
    transition: border-color var(--t-fast), box-shadow var(--t-fast);
}

    .form-control:focus,
    .form-select:focus {
        background: var(--t-bg-0);
        color: var(--t-text);
        border-color: var(--t-cyan);
        box-shadow: 0 0 0 3px var(--t-cyan-soft);
    }

    .form-control::placeholder {
        color: var(--t-text-faint);
    }

.form-check-input:checked {
    background-color: var(--t-blue-fill);
    border-color: var(--t-blue-fill);
}

.form-check-input:focus {
    border-color: var(--t-cyan);
    box-shadow: 0 0 0 3px var(--t-cyan-soft);
}

.field {
    margin-bottom: 1rem;
}

.field-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.85rem;
}

.field-error {
    display: block;
    color: var(--t-red);
    font-size: 0.78rem;
    margin-top: 0.25rem;
}

.hint {
    margin: 0.3rem 0 0;
    font-size: 0.75rem;
    color: var(--t-text-faint);
}

    .hint.ok {
        color: var(--t-green);
    }

    .hint.bad {
        color: var(--t-red);
    }

/* Alerts */
.alert {
    border-radius: var(--t-radius);
    font-size: 0.85rem;
    padding: 0.65rem 0.85rem;
    border-width: 1px;
    border-style: solid;
}

.alert-danger {
    background: var(--t-red-soft);
    border-color: var(--t-red);
    color: var(--t-text-danger);
}

.alert-success {
    background: var(--t-green-soft);
    border-color: var(--t-green);
    color: var(--t-text-ok);
}

.alert-info {
    background: var(--t-blue-soft);
    border-color: var(--t-blue);
    color: var(--t-text-info);
}

/* COMPLETING THE SET. danger, success and info were overridden here and warning
   was not, so any .alert-warning on a page fell through to Bootstrap's own —
   dark text on a pale yellow panel, which is unreadable on the dark theme and
   belongs to a palette this file otherwise replaces entirely. The amber tokens
   are the same ones the compliance bar and the expiry pills use. */
.alert-warning {
    background: var(--t-amber-soft);
    border-color: var(--t-amber);
    color: var(--t-text-warn);
}

.alert:empty {
    display: none;
}

/* --------------------------------------------------------------------------
   Centred card — sign-in and first-run setup
   -------------------------------------------------------------------------- */

.auth-shell {
    width: 100%;
    max-width: 420px;
}

.setup-shell {
    width: 100%;
    max-width: 660px;
}

.auth-card,
.setup-card {
    background: var(--t-bg-1);
    border: 1px solid var(--t-line);
    border-top: 2px solid var(--t-blue);
    border-radius: var(--t-radius-lg);
    padding: 1.75rem;
    box-shadow: var(--t-shadow-modal);
    animation: page-in var(--t-med) both;
}

.auth-brand {
    text-align: center;
    padding-bottom: 1.35rem;
    margin-bottom: 1.35rem;
    border-bottom: 1px solid var(--t-line);
}

    .auth-brand .logo-full {
        width: 210px;
        margin: 0 auto 0.55rem;
    }

/* The invitation screen puts the wordmark straight in the card with no
   .auth-brand wrapper. It carried no width at all before — it now inherits
   .logo-full's 100%, so it is given the same 210px the login card uses rather
   than stretching to the full width of the card. */
.auth-logo {
    width: 210px;
    max-width: 100%;
    margin: 0 auto 1rem;
}

    .auth-brand .brand-sub {
        letter-spacing: 0.4em;
        margin-top: 0;
    }

.auth-card h1 {
    font-size: 1.05rem;
    font-weight: 600;
    margin: 0 0 0.3rem;
    text-align: center;
}

.auth-card .lede {
    font-size: 0.82rem;
    color: var(--t-text-dim);
    text-align: center;
    margin: 0 0 1.35rem;
}

.auth-foot {
    margin-top: 1.35rem;
    padding-top: 1rem;
    border-top: 1px solid var(--t-line);
    text-align: center;
    font-size: 0.78rem;
    color: var(--t-text-faint);
}

.setup-head {
    margin-bottom: 1.5rem;
}

    .setup-head .logo-full {
        width: 200px;
        margin-bottom: 1rem;
    }

    .setup-head h1 {
        font-size: 1.3rem;
        margin: 0 0 0.5rem;
        font-weight: 600;
    }

    .setup-head p {
        margin: 0;
        font-size: 0.85rem;
    }

.setup-section {
    border-top: 1px solid var(--t-line);
    padding-top: 1.1rem;
    margin-bottom: 1.1rem;
}

    .setup-section h2 {
        font-size: 0.72rem;
        letter-spacing: 0.12em;
        text-transform: uppercase;
        color: var(--t-cyan);
        margin: 0 0 0.9rem;
    }

.setup-actions {
    border-top: 1px solid var(--t-line);
    padding-top: 1.1rem;
    display: flex;
    justify-content: flex-end;
}

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 860px) {
    .app-shell,
    .app-shell.is-collapsed {
        grid-template-columns: 1fr;
    }

    .app-sidebar {
        position: static;
        height: auto;
        border-right: none;
        border-bottom: 1px solid var(--t-line);
    }

    .sidebar-toggle {
        display: none;
    }

    .field-row {
        grid-template-columns: 1fr;
    }

    .hero {
        flex-direction: column;
        align-items: flex-start;
    }

    .app-content {
        padding: 1.2rem 1rem 2.5rem;
    }
}

/* --------------------------------------------------------------------------
   Motion preference
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* --------------------------------------------------------------------------
   Print — documents come out on white paper, never in the dark theme
   -------------------------------------------------------------------------- */

@media print {
    .app-sidebar,
    .app-topbar,
    .setup-actions,
    .toast-host,
    .btn {
        display: none !important;
    }

    body,
    .app-content,
    .panel,
    .stat,
    .hero {
        background: #fff !important;
        color: #000 !important;
        border-color: #bbb !important;
    }

    .app-shell {
        display: block;
    }

    .table th, .table td {
        border-color: #bbb !important;
        color: #000 !important;
    }

    a {
        color: #000 !important;
        text-decoration: none !important;
    }
}

/* --------------------------------------------------------------------------
   Section sidebar
   --------------------------------------------------------------------------
   Once you are inside a module, the sidebar lists that module's pages and
   nothing else. Switching modules happens on the home screen's cube.

   Two links plus a way back is a very different object from an eleven-item
   menu, so it gets its own treatment: the return to the cube sits above a
   rule, visually separate from the pages inside the module.
   -------------------------------------------------------------------------- */

.home-return {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    margin: 0 0.75rem;
    padding: 0.45rem 0.5rem;
    border-radius: var(--t-radius);
    color: var(--t-text-dim);
    font-size: 0.83rem;
    white-space: nowrap;
    transition: color var(--t-fast), background var(--t-fast);
}

.home-return:hover {
    background: var(--t-bg-2);
    color: var(--t-text);
    text-decoration: none;
}

.home-return:hover .nav-icon { color: var(--t-cyan); }

.section-title {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0 1.25rem 0.55rem;
    margin-bottom: 0.3rem;
    border-bottom: 1px solid var(--t-line);
    font-size: 0.72rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--t-text-faint);
    white-space: nowrap;
}

.section-icon {
    color: var(--t-cyan);
    width: 16px;
    height: 16px;
    flex: 0 0 auto;
}

/* Collapsed rail: the return arrow centres like a nav item, and the section
   heading disappears with the rest of the labels. */
.app-shell.is-collapsed .home-return {
    justify-content: center;
    margin: 0;
    padding: 0.55rem 0;
    border-radius: 0;
}

.app-shell.is-collapsed .section-title {
    justify-content: center;
    padding: 0 0 0.55rem;
}

.app-shell.is-collapsed .section-title .nav-label { display: none; }
