h1:focus {
    outline: none;
}

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

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.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."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.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;
}

/* ===== Theme =====
   Matches the login page's palette (Components/Pages/Login.razor): navy shell, blue accent. */
:root {
    --brand-primary: #1769aa;
    --brand-primary-dark: #124e80;
    --brand-navy: #102a43;
    --sidebar-bg: #102a43;
    --sidebar-bg-active: #1c3f5f;
    --sidebar-text: #9fb3c8;
    --sidebar-text-active: #f8fafc;

    /* Bootstrap's own tokens - .btn-primary/.btn-outline-primary compile to literal hex per
       component and need their own overrides below, but bg-primary/text-primary/border-primary,
       badges, links, and focus rings all read these two at runtime, so retheming them here is
       enough to carry the brand blue through every Bootstrap utility that uses "primary". */
    --bs-primary: var(--brand-primary);
    --bs-primary-rgb: 23, 105, 170;
    --bs-link-color: var(--brand-primary);
    --bs-link-color-rgb: 23, 105, 170;
    --bs-link-hover-color: var(--brand-primary-dark);
    --bs-link-hover-color-rgb: 18, 78, 128;
}

body {
    background-color: #f4f6fb;
}

.btn-primary {
    background-color: var(--brand-primary);
    border-color: var(--brand-primary);
}

.btn-primary:hover, .btn-primary:focus, .btn-primary:active {
    background-color: var(--brand-primary-dark) !important;
    border-color: var(--brand-primary-dark) !important;
}

.btn-outline-primary {
    --bs-btn-color: var(--brand-primary);
    --bs-btn-border-color: var(--brand-primary);
    --bs-btn-hover-bg: var(--brand-primary);
    --bs-btn-hover-border-color: var(--brand-primary);
    --bs-btn-active-bg: var(--brand-primary-dark);
    --bs-btn-active-border-color: var(--brand-primary-dark);
    --bs-btn-disabled-color: var(--brand-primary);
    --bs-btn-disabled-border-color: var(--brand-primary);
}

.text-primary-brand { color: var(--brand-primary) !important; }
.bg-primary-brand { background-color: var(--brand-primary) !important; }

/* ===== Cards =====
   Echoes the login card's white-to-navy-tinted header (Login.razor's .login-card-top). */
.card {
    border-color: rgba(16, 42, 67, 0.09);
}

.card-header {
    background: linear-gradient(135deg, #ffffff, #f3f7fa);
    color: var(--brand-navy);
    font-weight: 600;
}

/* ===== Search clear button =====
   A small transparent "x" that sits inside the text field itself (Bootstrap's .input-group is
   already position:relative, so this just needs to float over the input's right edge - no extra
   wrapper markup needed). */
.input-group:has(.search-clear-btn) > .form-control {
    padding-right: 2rem;
}

.search-clear-btn {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    z-index: 5;
    width: 22px;
    height: 22px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: #8091a0;
    font-size: 0.75rem;
    line-height: 1;
}

.search-clear-btn:hover {
    color: #495057;
    background: rgba(0, 0, 0, 0.06);
}

[data-bs-theme="dark"] body {
    background-color: #0f1117;
}

[data-bs-theme="dark"] .topbar {
    background: #171a24;
    border-bottom-color: #262a3d;
}

[data-bs-theme="dark"] .sidebar-backdrop {
    background: rgba(0, 0, 0, 0.6);
}

/* Bootstrap's .bg-white/.bg-light utilities only set a background - they never set text
   color, so in dark mode the text falls back to the theme's light inherited body color,
   clashing with the explicit light background (card headers, search icons, etc.). */
[data-bs-theme="dark"] .bg-white,
[data-bs-theme="dark"] .bg-light {
    color: #212529 !important;
}

/* ===== Login page ===== */
.login-page {
    background: linear-gradient(135deg, #1a1d29 0%, #4f46e5 100%);
    padding: 1.5rem;
}

.login-card {
    width: 100%;
    max-width: 420px;
    border-radius: 1rem;
}

.login-icon {
    width: 64px;
    height: 64px;
    line-height: 64px;
    border-radius: 50%;
    background: rgba(79, 70, 229, 0.1);
    color: var(--brand-primary);
    font-size: 1.75rem;
    margin: 0 auto;
}

/* ===== App shell ===== */
.app-shell {
    height: 100vh;
    overflow: hidden;
}

.sidebar {
    width: 260px;
    min-width: 260px;
    height: 100vh;
    background: var(--sidebar-bg);
    color: var(--sidebar-text);
    display: flex;
    flex-direction: column;
    flex-shrink: 0;
    transition: width 0.2s ease, min-width 0.2s ease;
}

.sidebar .brand {
    height: 60px;
    padding: 0 1.5rem;
    color: #fff;
    font-weight: 700;
    font-size: 1.15rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    display: flex;
    align-items: center;
    flex-shrink: 0;
}

.sidebar .brand i {
    color: var(--brand-primary);
}

.sidebar-search {
    padding-top: 0.75rem;
}

.sidebar-search .input-group-text {
    background: var(--sidebar-bg-active);
    border-color: transparent;
    color: var(--sidebar-text);
}

.sidebar-search .form-control {
    background: var(--sidebar-bg-active);
    border-color: transparent;
    color: var(--sidebar-text-active);
}

.sidebar-search .form-control::placeholder {
    color: var(--sidebar-text);
}

.sidebar-search .form-control:focus {
    background: var(--sidebar-bg-active);
    color: var(--sidebar-text-active);
    box-shadow: 0 0 0 2px var(--brand-primary);
}

.sidebar-nav {
    flex: 1;
    /* Flex items default to min-height: auto, which lets content grow past this element's
       allotted space instead of shrinking to trigger overflow-y - this is what actually
       makes the scrollbar kick in once the expanded submenus (Procurement, Reports, etc.)
       exceed the sidebar's height. */
    min-height: 0;
    overflow-y: auto;
    padding: 1rem 0.75rem;
}

.sidebar-nav .nav-link {
    color: var(--sidebar-text);
    border-radius: 0.5rem;
    padding: 0.65rem 1rem;
    margin-bottom: 0.25rem;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    font-size: 0.925rem;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.sidebar-nav .nav-link i {
    font-size: 1.05rem;
    width: 1.25rem;
    text-align: center;
}

.sidebar-nav .nav-link:hover {
    background: var(--sidebar-bg-active);
    color: var(--sidebar-text-active);
}

.sidebar-nav .nav-link.active {
    background: var(--brand-primary);
    color: #fff;
}

.sidebar-nav .submenu-link {
    padding-left: 2.75rem;
    font-size: 0.85rem;
}

/* Long submenus (Procurement especially, 13 items) get their own bounded, independently
   scrollable area instead of just stretching the whole sidebar - this is what actually
   shows a visible scrollbar right inside the expanded section. */
.sidebar-nav .collapse.show {
    max-height: 320px;
    overflow-y: auto;
}

.sidebar-nav .collapse.show {
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.35) transparent;
}

.sidebar-nav .collapse.show::-webkit-scrollbar {
    width: 7px;
}

.sidebar-nav .collapse.show::-webkit-scrollbar-track {
    background: transparent;
}

.sidebar-nav .collapse.show::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.35);
    border-radius: 4px;
}

.sidebar-nav .collapse.show::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.55);
}

.sidebar-nav .submenu-caret {
    transition: transform 0.2s ease;
}

.sidebar-nav [aria-expanded="true"] .submenu-caret {
    transform: rotate(180deg);
}

.sidebar-footer {
    padding: 1rem 1.5rem;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    font-size: 0.75rem;
    color: var(--sidebar-text);
}

.main-content {
    flex: 1;
    min-width: 0;
    height: 100vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.topbar {
    background: var(--sidebar-bg);
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
    padding: 0.375rem 1.5rem;
    gap: 0.75rem;
    flex-shrink: 0;
    height: 60px;
    overflow: visible;
    color: #fff;
}

.topbar .text-dark {
    color: #fff !important;
}

.topbar-heading h2 {
    line-height: 1.2;
    color: #fff;
}

.topbar-heading .text-muted {
    color: rgba(255, 255, 255, 0.65) !important;
}

.topbar .btn-light {
    background: rgba(255, 255, 255, 0.12);
    border-color: transparent;
    color: #fff;
}

.topbar .btn-light:hover {
    background: rgba(255, 255, 255, 0.2);
    color: #fff;
}

.notification-list {
    max-height: 320px;
    overflow-y: auto;
}

.notification-list .dropdown-item {
    white-space: normal;
    overflow-wrap: anywhere;
}

.btn-icon {
    width: 38px;
    height: 38px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

/* Floating "go to top" button (MainLayout). Translucent brand blue so it does not hide what is behind it,
   solid on hover; below dialogs (z-index 1055+) and the sticky top bar's dropdowns. */
.go-top {
    position: fixed;
    right: 1.25rem;
    bottom: 1.25rem;
    z-index: 1030;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(23, 105, 170, 0.55);
    color: #fff;
    font-size: 1rem;
    box-shadow: 0 2px 8px rgba(16, 42, 67, 0.25);
    cursor: pointer;
    opacity: 0;
    visibility: hidden;
    transform: translateY(8px);
    transition: opacity .2s ease, transform .2s ease, visibility .2s, background-color .15s ease;
}

.go-top.show {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.go-top:hover,
.go-top:focus-visible {
    background: rgba(23, 105, 170, 0.92);
}

.go-top:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
    box-shadow: 0 0 0 4px rgba(23, 105, 170, 0.6);
}

.page-body {
    padding: 1.5rem;
    flex: 1;
    overflow-y: auto;
}

    /* Report pages (SwfReport) use the whole page - just a thin edge around them. */
    .page-body:has(> .swf-report) {
        padding: 6px;
    }

.avatar-circle {
    width: 38px;
    height: 38px;
    border-radius: 50%;
    background: var(--brand-primary);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 600;
    font-size: 0.9rem;
}

.stat-card {
    border: none;
    border-radius: 0.75rem;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
}

/* Dashboard summary cards that jump to their list (see dashScrollTo in site.js). */
.stat-link {
    cursor: pointer;
    transition: box-shadow .15s ease, transform .15s ease;
}

.stat-link:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
    transform: translateY(-1px);
}

.stat-link:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
}

/* The list a summary card scrolled to blinks once, and stops short of the very top edge. */
[id^="dash-"] {
    scroll-margin-top: 8px;
}

.flash-target {
    animation: dash-flash 1.4s ease-out;
}

@keyframes dash-flash {
    from { box-shadow: 0 0 0 4px rgba(23, 105, 170, 0.55); }
    to { box-shadow: 0 0 0 4px rgba(23, 105, 170, 0); }
}

.stat-icon {
    width: 48px;
    height: 48px;
    border-radius: 0.6rem;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.3rem;
}

/* Bootstrap rounds a card's header/footer (and a table or image at its edge) with
   --bs-card-inner-border-radius, derived from --bs-card-border-radius. Raising only border-radius
   left those at Bootstrap's default (~5px), so the tinted header kept near-square corners inside a
   rounded card and its top-left/right corners looked cut off. Set the variables with it. */
.card {
    --bs-card-border-radius: 0.5rem;
    --bs-card-inner-border-radius: calc(0.5rem - var(--bs-card-border-width));
    border-radius: 0.5rem;
}

/* swfBlazor's control.css sets ".table { table-layout: fixed; }" for its own DataGridComponent
   grids, but that selector is Bootstrap's own base table class, so it hijacks every plain
   Bootstrap <table class="table"> in the app too - fixed layout then ignores a column's
   min-width and squeezes it to whatever sliver is left, wrapping text one character per line.
   control.css loads after this file, so normal cascade order can't win here - !important is
   required to actually override it. */
.table {
    table-layout: auto !important;
}

/* Without this, a wide table with plenty of columns doesn't grow past its container and
   trigger .table-responsive's horizontal scrollbar - Bootstrap's default cells wrap text
   instead, so every column just keeps shrinking until the table looks broken (multi-line
   company names, single-character-per-line text, etc.) instead of scrolling. Forcing cells
   to their natural single-line width is what makes the table actually overflow and scroll.
   A column that's meant to wrap (long descriptions/remarks/notes) can opt back in with
   Bootstrap's own .text-wrap utility class on that cell (it carries !important, so it wins
   over this plain rule without needing one here too). */
.table-responsive .table th,
.table-responsive .table td {
    white-space: nowrap;
}

/* Compare: the first column (item names, descriptions, budget names) is 400px and wraps - long
   item names on one line made it 500px+ and pushed the vendors off to the right. Held at 400px:
   the table is wider than the page, so a merely wrapping column got squeezed to its minimum.
   The vendor columns keep the one-line rule above. Rows spanning the whole table are left alone. */
.table-responsive .compare-table tr > :first-child:not([colspan]) {
    white-space: normal;
    width: 400px;
    min-width: 400px;
    max-width: 400px;
}

/* Bootstrap's .table-responsive already sets overflow-x: auto, but the default browser
   scrollbar is thin enough (or auto-hidden entirely on some platforms) that a wide table's
   horizontal scroll goes unnoticed. Give it the same visible treatment as the sidebar. */
.table-responsive {
    scrollbar-width: thin;
    scrollbar-color: rgba(0, 0, 0, 0.25) transparent;
}

.table-responsive::-webkit-scrollbar {
    height: 8px;
}

.table-responsive::-webkit-scrollbar-track {
    background: transparent;
}

.table-responsive::-webkit-scrollbar-thumb {
    background: rgba(0, 0, 0, 0.25);
    border-radius: 4px;
}

.table-responsive::-webkit-scrollbar-thumb:hover {
    background: rgba(0, 0, 0, 0.4);
}

@media (min-width: 992px) {
    .app-shell.sidebar-collapsed .sidebar {
        width: 0;
        min-width: 0;
        overflow: hidden;
        border: none;
    }
}

@media (max-width: 991.98px) {
    .sidebar {
        position: fixed;
        left: -260px;
        top: 0;
        bottom: 0;
        height: auto;
        z-index: 1040;
        transition: left 0.2s ease;
    }

    .sidebar.show {
        left: 0;
    }

    .sidebar-backdrop {
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.4);
        z-index: 1030;
    }
}

@media print {
    .sidebar, .topbar, .page-toolbar, .btn:not(.change-info-btn), .dropdown {
        display: none !important;
    }

    /* Vendor deviations (item name/spec/dimensions changed from what was requested) matter on the
       printed comparison too, so this one stays visible while every other action button is hidden. */
    .change-info-btn {
        display: inline-block !important;
        color: #0dcaf0 !important;
        border-color: #0dcaf0 !important;
    }

    /* The app shell clips everything to a single 100vh viewport with hidden overflow
       for the normal scrolling SPA layout - printing needs that lifted so content can
       flow across as many pages as it takes instead of being cut off after one screen. */
    .app-shell, .main-content, .page-body {
        height: auto !important;
        overflow: visible !important;
    }

    .main-content, .page-body {
        width: 100% !important;
        padding: 0 !important;
    }

    .card {
        border: none !important;
        box-shadow: none !important;
    }
}
/* Chat rich-text editor (Procurement.UI FormattedTextArea + chatEditor in site.js) */
.chat-editor {
    min-height: 3.4rem;
    max-height: 12rem;
    overflow-y: auto;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    cursor: text;
}

.chat-editor:empty::before {
    content: attr(data-placeholder);
    color: var(--bs-secondary-color);
    pointer-events: none;
}

.chat-editor[contenteditable="false"] {
    background-color: var(--bs-secondary-bg);
}

.chat-editor ul, .chat-editor ol {
    margin-bottom: 0;
    padding-left: 1.25rem;
}

/* Email template HTML editor (Procurement.UI HtmlEditor + htmlEditor in site.js) */
.html-editor {
    min-height: 14rem;
    max-height: 50vh;
    overflow-y: auto;
    overflow-wrap: anywhere;
    cursor: text;
}

.html-editor:empty::before {
    content: attr(data-placeholder);
    color: var(--bs-secondary-color);
    pointer-events: none;
}

.html-editor p {
    margin-bottom: 0.5rem;
}

.html-editor ul, .html-editor ol {
    margin-bottom: 0.5rem;
    padding-left: 1.5rem;
}

/* List tables whose rows scroll inside the card instead of the whole page (e.g. Purchase Orders).
   Header and footer rows stay pinned. The exact height is set by tableAutoHeight (site.js) to
   fill the window below the table; this calc() is only the fallback until that script runs. */
.table-scroll-body {
    max-height: calc(100vh - 230px);
    overflow: auto;
}

.table-scroll-body thead th {
    position: sticky;
    top: 0;
    z-index: 2;
}

.table-scroll-body tfoot td {
    position: sticky;
    bottom: 0;
    z-index: 2;
    /* Sticky cells lose their collapsed border, so draw the top line as a shadow. */
    box-shadow: inset 0 1px 0 var(--bs-border-color);
}

/* Spend Analytics chart - full view (SpendChart) */
.spend-chart-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1060;
    background: rgba(0, 0, 0, .45);
}

.spend-chart-full {
    position: fixed;
    inset: 4vh 4vw;
    z-index: 1061;
    display: flex;
    flex-direction: column;
    padding: 12px 16px 16px;
    background: var(--bs-body-bg, #fff);
    border-radius: 8px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, .3);
    outline: none;
}

.spend-chart-full-body {
    position: relative;
    flex: 1;
    min-height: 0;
}
