﻿/* Small, deliberate overrides on top of the vendored tabler-theme.css (which must stay a
   byte-for-byte copy of -NEWUI's compiled stylesheet - see _Layout.cshtml's own comment).
   Loaded after it, so plain same-specificity rules here win. */

/* Task (2026-07-31) - Brad: "Client & Staff are an autocomplete dropdown list" (BannedEmployees'
   filters, same bmsInitAutocomplete helper - wwwroot/js/bms-list-common.js - reused across every
   other Client/Staff type-to-search filter). Dropdown sits inside the field's .input-icon wrapper
   (position:relative already, from tabler-theme.css) so it lines up under the input regardless of
   column width.

   Fix (2026-07-31, live-tested on /bannedemployees): text was unreadable, overlapping the grid
   rows underneath - tabler-theme.css's .list-group sets --tblr-list-group-bg: inherit and
   .list-group-item itself is background-color: inherit (see its "list-group-header" block), which
   is correct for a list-group sitting inside an opaque card but leaves this one - a
   position:absolute overlay with no opaque ancestor of its own - fully see-through. Setting an
   explicit opaque background + border directly on the dropdown container fixes it for every
   .list-group-item inside via that same inherit chain, no per-item override needed. */
.bms-autocomplete-dropdown {
    top: 100%;
    left: 0;
    z-index: 1000;
    margin-top: 2px;
    max-height: 240px;
    overflow-y: auto;
    background-color: var(--tblr-bg-surface, #fff);
    border: 1px solid var(--tblr-border-color, #e6e7e9);
    border-radius: var(--tblr-border-radius, 4px);
}

.bms-autocomplete-item.active {
    background-color: var(--tblr-list-group-action-hover-bg, #f4f6fb);
}

/* Task #73 - Brad (2026-07-29): "Don't need the red cross in the field, just the red border and
   small text below". Bootstrap/Tabler's .is-invalid paints an inline error icon (a red cross
   background-image) inside the control and pads the text away from it - drop the icon and restore
   normal padding; the red border + .invalid-feedback text remain. */
.form-control.is-invalid,
.form-select.is-invalid,
textarea.form-control.is-invalid {
    background-image: none;
    padding-right: 0.75rem;
}

/* Task (2026-07-30): System Settings Primary/Secondary colours. --bms-primary-color/
   --bms-secondary-color are set inline in _Layout.cshtml's <head> from
   SystemSetting.PrimaryColor/SecondaryColor - the var() fallback below (tabler-theme.css's
   original hardcoded values) keeps every existing install's look unchanged until an admin
   actually picks colours on the System Settings screen. Primary drives the sidebar (plus its
   mobile-collapsed equivalent, .bms-topbar, so the two don't visually disagree); Secondary
   drives the "soft" card header used across list/grid screens.

   Deliberately NOT touched: the many other places tabler-theme.css reuses the same #0f1e3f as a
   general brand-navy accent (page heading/breadcrumb text, .bms-card-header-tint's top border,
   .bms-field-group-label, the .bms-info-popover) - Brad's ask was specifically "Primary drives
   the side menu", not a full site-wide brand recolour, and those other spots weren't designed
   with variable text/icon contrast in mind (a light Primary would make some of that text
   unreadable). Revisit as its own task if a fuller reskin is wanted later. */
.bms-sidebar,
.bms-topbar {
    background: var(--bms-primary-color, #0f1e3f);
}

/* Dark-mode fix (2026-07-30): when Brad hasn't actually picked a Secondary Colour on System
   Settings, this used to fall back to a hardcoded #ffffff - fixed light regardless of theme. Now
   it falls back to Tabler's own theme-aware surface token instead, so an unconfigured install
   correctly inverts under data-bs-theme=dark. Once a tenant picks a real Secondary Colour, that
   fixed value still wins in both light and dark mode, same as before - this only changes the
   "nothing configured yet" default. */
.bms-card-header-soft {
    background: var(--bms-secondary-color, var(--tblr-bg-surface, #ffffff));
}

/* Dark-mode fix (2026-07-30, take 2, live-inspected on /systemsettings): Brad HAS actually picked
   a Secondary Colour (#ffffff - confirmed via devtools, --bms-secondary-color computes to
   #ffffff), so the var() fallback above never even runs - #ffffff is a validly-set value, not an
   empty one, and it was winning in both themes exactly as designed above. The bug is that
   "Secondary Colour" was clearly chosen as a LIGHT-mode brand choice with no dark equivalent yet,
   so it shouldn't carry into dark mode and paint every section header solid white. Until System
   Settings grows a separate dark-mode colour picker, dark mode always wins here regardless of
   what's configured - qualifying with [data-bs-theme="dark"] gives this higher specificity than
   the plain .bms-card-header-soft rule above, so it overrides regardless of source order. */
[data-bs-theme="dark"] .bms-card-header-soft {
    background: var(--tblr-bg-surface, #1f2937);
}

/* Dark-mode fix (2026-07-30, take 2, live-inspected on /staff): grid rows were still wrong in
   dark mode after the tabler-theme.css pass - turns out that pass only touched
   ".card table.dataTable tr.odd/even TD" backgrounds. The actual paint is the vendored DataTables
   plugin stylesheet (wwwroot/lib/datatables/css/jquery.dataTables.css), which every grid page
   links directly in its own @section Styles - loaded AFTER this file, right before </head> - and
   which hardcodes the colour directly on the <tr> itself:
     table.dataTable tr.odd { background-color: #E2E4FF; }
     table.dataTable tr.even { background-color: white; }
   Our earlier <td>-level fix made the td transparent, which let this <tr> colour keep showing
   through underneath - so visually nothing changed. Qualifying with .card here (specificity
   0,3,2) beats the vendor file's plain "table.dataTable tr.odd" (0,2,2) regardless of which loads
   last, because higher specificity always wins over load order. Matches the "fully vanilla, no
   tint" experiment Brad asked for - both rows now render with no fill at all, letting the card's
   own (already theme-aware) background show. */
.card table.dataTable tr.odd,
.card table.dataTable tr.even {
    background-color: transparent;
}

/* Task (2026-07-31) - Brad: "Left Main menu should automatically collapse and
   expand out on mouse over." Desktop rail rests at a narrow icon-only width
   and expands to tabler-theme.css's original 240px on hover. .bms-sidebar is
   already position:fixed there, so widening it on hover overlays the page
   instead of reflowing it - only .bms-main-col's resting margin-left needs to
   match the new narrow width. Mobile keeps its existing off-canvas
   .mobile-open toggle untouched (hover has no meaning on touch, and
   tabler-theme.css's own max-width:992px block already owns that behaviour). */
@media (min-width: 992px) {
    :root {
        --bms-sidebar-collapsed-width: 64px;
    }

    .bms-sidebar {
        width: var(--bms-sidebar-collapsed-width);
        overflow: hidden;
        transition: width .15s ease;
    }
    .bms-sidebar:hover {
        width: 240px;
    }

    .bms-sidebar-nav {
        overflow-x: hidden;
    }

    .bms-main-col {
        margin-left: var(--bms-sidebar-collapsed-width);
    }

    /* Labels/secondary text disappear while collapsed. flex:none + width:0
       (rather than just opacity) so the invisible text can't keep claiming
       its flex-grow share of the row and throw off icon centering. */
    .bms-nav-link span,
    .bms-user-btn .bms-user-name,
    .bms-version-tag {
        flex: none;
        width: 0;
        opacity: 0;
        overflow: hidden;
        white-space: nowrap;
        transition: opacity .1s ease;
    }
    .bms-sidebar:hover .bms-nav-link span,
    .bms-sidebar:hover .bms-user-btn .bms-user-name,
    .bms-sidebar:hover .bms-version-tag {
        flex: 1;
        width: auto;
        opacity: 1;
    }

    /* The chevron is a fixed 13x13 SVG icon (tabler-theme.css), not text - it
       only needs its opacity toggled, never its width/flex. Overriding its
       width to "auto" here (as the labels above legitimately need to) would
       replace that fixed 13px with the SVG's own intrinsic auto-sizing
       instead, which is dramatically larger and was eating all the flex row's
       free space, starving the label span next to it down to 0 width. */
    .bms-nav-chevron {
        opacity: 0;
        transition: opacity .1s ease;
    }
    .bms-sidebar:hover .bms-nav-chevron {
        opacity: 1;
    }

    /* Submenus only ever show once the rail itself is hovered/expanded (or locked open - see
       below) - the existing .open accordion state (incl. bms-sidebar.js's auto-open of the
       current page's section) still drives which section shows once expanded. Excluding
       .bms-sidebar-locked here (rather than adding a separate counter-rule) lets tabler-theme.css's
       own display:none/.open>display:flex pair keep working unmodified once locked - a `display:
       revert !important` counter-rule would reset to the *user-agent* default and skip that
       author-level pair entirely, which is not what "locked = permanently expanded" means. */
    .bms-sidebar:not(:hover):not(.bms-sidebar-locked) .bms-sidebar-submenu {
        display: none !important;
    }

    /* Task (2026-07-31) - Brad: "option to lock the side menu, like a toggle in the top right of
       the side menu". #bmsSidebarLockToggle (bms-sidebar.js) adds/removes .bms-sidebar-locked on
       #bmsSidebar and flips --bms-sidebar-collapsed-width to 240px so .bms-main-col's margin
       matches without a separate rule (both already read that one variable, see above). These two
       rules repeat the :hover-expanded look (labels/chevron visible) under .bms-sidebar-locked
       instead, so the rail reads as permanently "hovered". */
    .bms-sidebar.bms-sidebar-locked .bms-nav-link span,
    .bms-sidebar.bms-sidebar-locked .bms-user-btn .bms-user-name,
    .bms-sidebar.bms-sidebar-locked .bms-version-tag {
        flex: 1;
        width: auto;
        opacity: 1;
    }
    .bms-sidebar.bms-sidebar-locked .bms-nav-chevron {
        opacity: 1;
    }
}

/* Actions-column placeholder (Brad, 2026-09-02, Attachment Types: "The ones with system type
   equal to Yes need a blank active/inactive placeholder"). When a row legitimately has no
   toggle (system attachment types, the default site requirements) the remaining icons used to
   slide right and the column read as misaligned. Render this in the icon's place instead: the
   same box a btn-link p-1 + fs-2 icon occupies, so the Edit/History icons stay in their columns. */
.bms-action-placeholder {
    display: inline-block;
    width: 40px;
    height: 40px;
    flex: none;
}

/* Empty validation summaries take no space (Brad, 2026-09-02, Lookup List New/Edit: "the left
   menu and the right area don't align at the top"). <div asp-validation-summary="All"
   class="... mb-3"> renders even with no errors - as .validation-summary-valid wrapping an empty
   <ul> - so its margin pushed the form card 13px below the section menu's card. With errors the
   tag helper emits .validation-summary-errors instead, which this rule leaves alone. */
.validation-summary-valid {
    display: none;
}

/* Sidebar header row (logo + lock toggle) - .bms-sidebar-brand keeps tabler-theme.css's own
   padding/sizing, so only the wrapper and the new button need rules here. */

/* Layout-stable brand row (Brad, 2026-09-02: the menu "jumps" because the logo arrives after
   first paint and pushes everything down). tabler-theme.css sizes the image with max-height only,
   so an unloaded image is 0px tall and the row is 30px shorter until the request completes -
   on every navigation, because the custom logo is served by a controller action. Fix the row
   and image heights so the space exists before the bytes do. 58px = 30px image + 14px padding
   top and bottom, exactly what the loaded row measured before. */
.bms-sidebar-brand {
    min-height: 58px;
    box-sizing: border-box;
}
.bms-sidebar-brand img {
    height: 30px;
    max-height: 30px;
    width: auto;
}

.bms-sidebar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.bms-sidebar-header .bms-sidebar-brand {
    min-width: 0;
    flex: 1;
}

.bms-sidebar-lock-toggle {
    flex: none;
    width: 28px;
    height: 28px;
    margin-right: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    border-radius: 6px;
    color: rgba(255, 255, 255, 0.65);
    cursor: pointer;
}

.bms-sidebar-lock-toggle:hover {
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
}

.bms-sidebar-lock-toggle .icon {
    width: 16px;
    height: 16px;
}

.bms-sidebar-lock-toggle .bms-lock-icon-locked {
    display: none;
}

.bms-sidebar-lock-toggle[aria-pressed="true"] {
    color: #fff;
}

.bms-sidebar-lock-toggle[aria-pressed="true"] .bms-lock-icon-open {
    display: none;
}

.bms-sidebar-lock-toggle[aria-pressed="true"] .bms-lock-icon-locked {
    display: inline-block;
}

@media (min-width: 992px) {
    /* Collapsed rail: only visible once the rail is hovered/expanded or locked open, same
       show/hide treatment as the nav-link labels above - avoids a cramped icon-only header at
       64px. Locking is a desktop-only concept (mobile's off-canvas sidebar already shows full
       width whenever it's open), so the toggle stays plainly visible below 992px instead. */
    .bms-sidebar-lock-toggle {
        opacity: 0;
        pointer-events: none;
        transition: opacity .1s ease;
    }
    .bms-sidebar:hover .bms-sidebar-lock-toggle,
    .bms-sidebar.bms-sidebar-locked .bms-sidebar-lock-toggle {
        opacity: 1;
        pointer-events: auto;
    }

    /* First paint of a locked-open sidebar (Brad, 2026-09-02: "still appears to start small and
       moves to locked"). _Layout's <head> script adds this class when localStorage says locked;
       while it is present the locked look applies with NO transitions, so the rail, its labels,
       the logo and the lock toggle are drawn straight into their final positions instead of
       animating there. bms-sidebar.js removes the class after the first frame, which hands
       control back to the normal hover/lock transitions above. */
    html.bms-sidebar-locked-init .bms-sidebar,
    html.bms-sidebar-locked-init .bms-sidebar *,
    html.bms-sidebar-locked-init .bms-main-col {
        transition: none !important;
    }
    html.bms-sidebar-locked-init .bms-sidebar {
        width: 240px;
    }
    html.bms-sidebar-locked-init .bms-sidebar .bms-nav-link span,
    html.bms-sidebar-locked-init .bms-sidebar .bms-user-btn .bms-user-name,
    html.bms-sidebar-locked-init .bms-sidebar .bms-version-tag {
        flex: 1;
        width: auto;
        opacity: 1;
    }
    html.bms-sidebar-locked-init .bms-sidebar .bms-nav-chevron,
    html.bms-sidebar-locked-init .bms-sidebar .bms-sidebar-lock-toggle {
        opacity: 1;
    }
    html.bms-sidebar-locked-init .bms-sidebar .bms-sidebar-lock-toggle {
        pointer-events: auto;
    }
}

/*
    Follow-up (2026-08-03) - Brad: "On All datagrids with Actions, client and staff, the heading
    needs to be centered and the column width fix for just the two icons and a little bit of
    padding."

    One class instead of a width and an alignment repeated across ~30 views. Applied to the header
    cell AND the body cell, because there is no way in CSS to say "the cells under this heading" -
    and the Actions column is not always last (the client grids put the responsive disclosure
    toggle after it).

    92px is measured, not guessed: two btn-link p-1 buttons at Tabler's fs-2 come to ~28px each,
    the gap-2 between them is 8px, and the card-table's own cell padding adds ~16px. Fixed rather
    than auto so the column does not grow with the heading text or shuffle between grids, and
    !important because DataTables writes its sWidth straight onto the element's style attribute.
*/
th.bms-actions-col,
td.bms-actions-col {
    width: 92px !important;
    min-width: 92px;
    text-align: center !important;
    white-space: nowrap;
}

/*
    Three-icon actions column (Brad, 2026-08-13: View History alongside Edit and
    Activate/Deactivate). 92px fits two icons; a third overflows a nowrap cell.

    A modifier class rather than widening the base rule, because most grids still have two icons
    and should not all grow. It has to be a CLASS and not a DataTables sWidth: the base rule above
    is !important precisely to beat the inline width DataTables writes, so sWidth alone loses. Same
    specificity as the base rule, declared after it, so it wins.
*/
th.bms-actions-col-wide,
td.bms-actions-col-wide {
    width: 128px !important;
    min-width: 128px;
}

/*
    Fixed grid column widths (Brad, 2026-08-11, on Attachments and Leave Dates: "Fixed width for
    Type, Expiry Date, File, Status and Action columns" / "Comments Wrap text if required").

    Sized buckets rather than a class per column, because the same handful of widths covers every
    grid in the record - a date is a date whether the heading says Expiry Date, Start or Test Date.

    HOW THE WRAP COLUMN WORKS. These tables are table-layout: auto. Giving every column but one a
    fixed width is not enough on its own - a long unbroken comment simply makes the table wider and
    the container scrolls. .bms-col-flex sets width: 100%, which in an auto-layout table means "take
    whatever is left after the fixed columns", and the fixed columns are nowrap so they cannot give
    ground. The result is that the free column absorbs the remainder and its text wraps inside it.

    Applied to BOTH the <th> and every matching <td>, same as .bms-actions-col above: CSS has no way
    to say "the cells under this heading", and bms-staff-grid.js's syncSecondaryCells only copies
    the .bms-rt-secondary flag down, not these.

    !important on the widths because DataTables writes its own sWidth onto the style attribute on
    grids that run with bAutoWidth true (the client record's). The staff grids set bAutoWidth false,
    so it is belt and braces there.
*/
th.bms-col-w-sm,
td.bms-col-w-sm {
    width: 110px !important;
    min-width: 110px;
    white-space: nowrap;
}

th.bms-col-w-md,
td.bms-col-w-md {
    width: 140px !important;
    min-width: 140px;
    white-space: nowrap;
}

th.bms-col-w-lg,
td.bms-col-w-lg {
    width: 200px !important;
    min-width: 200px;
    white-space: nowrap;
}

/*  File names in this system are frequently a 36-character GUID plus an extension, so this bucket
    is the one that is allowed to wrap inside its fixed width rather than push the table wider. */
th.bms-col-w-xl,
td.bms-col-w-xl {
    width: 260px !important;
    min-width: 260px;
    white-space: normal;
    overflow-wrap: anywhere;
}

/*  The Active/Inactive pill. Was an inline style="width:110px;" repeated on every staff grid. */
th.bms-status-col,
td.bms-status-col {
    width: 110px !important;
    min-width: 110px;
    text-align: center !important;
    white-space: nowrap;
}

/*  The one column per grid that takes the leftover width and wraps - Notes/Comments. */
th.bms-col-flex,
td.bms-col-flex {
    width: 100%;
    min-width: 180px;
    white-space: normal !important;
    overflow-wrap: anywhere;
}

/*  Below md the responsive-table stylesheet hides the secondary columns and lets what is left wrap,
    so the fixed widths have to stand down or the primary column is squeezed against them. */
@media (max-width: 767.98px) {
    table.bms-rt th.bms-col-w-sm,
    table.bms-rt td.bms-col-w-sm,
    table.bms-rt th.bms-col-w-md,
    table.bms-rt td.bms-col-w-md,
    table.bms-rt th.bms-col-w-lg,
    table.bms-rt td.bms-col-w-lg,
    table.bms-rt th.bms-col-w-xl,
    table.bms-rt td.bms-col-w-xl,
    table.bms-rt th.bms-col-flex,
    table.bms-rt td.bms-col-flex {
        width: auto !important;
        min-width: 0;
    }
}

/*  Mandatory-field marker (Brad, 2026-08-10: "the red * should be inline with the label not
    below it").

    The markup that produced the problem was `<label class="form-label"></label><span
    class="text-danger">*</span>`. Tabler sets `.form-label { display: block }`, so the label
    takes the full row and the span is pushed onto the next line - the asterisk ended up under
    the label instead of after it.

    Fixed with a pseudo-element rather than by making the label inline-block, because a marker
    generated INSIDE the label box cannot be separated from it by any future layout change -
    inline-block would still wrap if the label text ever filled the column.

    Why not just put the * inside the label, the way Clients/Details.cshtml does
    (`<label class="form-label">Location <span class="text-danger">*</span></label>`)? Because
    these labels use asp-for and take their text from the model's [Display] attributes. Writing
    the text inline to host the span would hardcode every label and lose that binding.

    Decorative on purpose: a screen reader announcing "star" adds nothing. The accessible
    signal belongs on the input (aria-required), not on a glyph in the label.
*/
.bms-label-required::after {
    content: " *";
    color: var(--tblr-danger, #d63939);
    font-weight: 600;
}

/*
    Checkbox / radio border (Brad, 2026-08-21: "the checkboxes have a slightly darker border, they
    are hard to see in light mode").

    Tabler's light palette gives form controls --tblr-border-color: #e5e7eb, which is gray-200 - on
    a white card an unticked box is very nearly invisible. This steps it to gray-400 (#9ca3af),
    which is two stops darker and reads clearly without looking like a heavy outline or an error
    state. The theme's own token is used rather than a hand-picked hex so it still tracks the
    palette.

    LIGHT MODE ONLY. This app has a real dark theme (the ThemePreference session value drives
    data-bs-theme on <html>), where --tblr-border-color is #2e3c51 against a dark card and already
    has plenty of contrast - forcing a light grey there would make the borders glare.

    Radios are included deliberately even though the request was about checkboxes: they share
    .form-check-input and sit next to each other on the same forms, so darkening only one would
    read as a bug rather than a fix.

    :checked is NOT touched - tabler-theme.css already sets `border: none` on the checked state,
    which is fine because a ticked box is filled with the primary colour and needs no outline.
    Switches are excluded for the same reason: the track carries its own fill and border treatment.
*/
[data-bs-theme="light"] .form-check-input:not(:checked) {
    border-color: var(--tblr-gray-400, #9ca3af);
}

/* The switch track keeps the lighter border - it is a filled pill, not an empty box. */
[data-bs-theme="light"] .form-switch .form-check-input:not(:checked) {
    border-color: var(--tblr-border-color, #e5e7eb);
}

/* Bootstrap Icons sweep (Brad, 2026-08-27): every icon moved from the Tabler svg sprite
   (<svg class="icon"><use .../></svg>) to Bootstrap Icons (<i class="icon bi bi-...">). Tabler's
   own .icon class already carries the box size and font-size for font icons; these rules add the
   flex centring an <i> needs to sit in that box the way the svg did. */
i.icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.bms-card-header-icon i.icon {
    font-size: 1.1rem;
}

/*  Custom Reports > Columns: the colour-band editor that opens under a numeric column's row
    (Brad, 2026-09-04). Narrow on purpose - three small inputs per band, in a panel that spans the
    full width of a table that may have a dozen columns, would otherwise stretch them across the
    page and make the panel harder to read than the grid it sits in. */
.bms-colour-bands {
    max-width: 34rem;
}

/*  Custom Reports run grid: a column heading that has been given a width must be allowed to WRAP
    inside it (Brad, 2026-09-04) - that is the entire reason for setting a width in the first place.
    Several table styles in this app set white-space: nowrap on header cells, which would leave the
    caption overflowing its column instead, so this says so explicitly rather than relying on the
    cascade landing the right way round. Applied to every heading on that grid, not only the ones
    with a width, so a heading never behaves differently depending on whether a width happens to be
    set; vertical-align keeps a one-line heading level with a wrapped neighbour. */
th.bms-report-heading {
    white-space: normal;
    overflow-wrap: anywhere;
    vertical-align: bottom;
}

/*  System alert banner (Brad, 2026-09-23): the red bar _Layout renders between the top bar and
    <main> for users holding 'Get Alerts', one line per active email / finance-integration alert
    (Views/Shared/_SystemAlertBanner.cshtml). Deliberately NOT Tabler's .alert - that is a boxed,
    in-page component; this is a full-width strip that has to read as "the system is telling
    you something" before the page below it, so it uses the danger colour as a solid background
    with light text and light outline buttons. Lines are separated by a faint rule rather than
    stacked boxes so three alerts still read as one bar. */
.bms-system-alerts {
    background: var(--tblr-danger, #d63939);
    color: #fff;
    padding: .25rem 1.5rem;
}

.bms-system-alert {
    padding: .5rem 0;
}

.bms-system-alert + .bms-system-alert {
    border-top: 1px solid rgba(255, 255, 255, .35);
}

.bms-system-alert .bi-exclamation-octagon-fill {
    font-size: 1.15rem;
}

.bms-system-alert .btn-outline-light:hover {
    color: var(--tblr-danger, #d63939);
}

/*  Client-portal client picker (Brad, 2026-09-24: "Move the Client dropdown from the Home Page and
    move it to the top right of all pages"; then "just as simple dropdown in the top right probably
    2/12 maybe 3/12 wide in line with the breadcrumbs"). _Layout renders it as the first thing in
    <main> on every client-portal page, taken out of the flow and pinned top right, level with the
    breadcrumb, so it adds no height. A quarter of the content width (3/12), never narrower than
    200px so a client name stays readable. top 1rem keeps it clear of the heading row below the
    breadcrumb, where page buttons such as Export / Approve sit. On a phone there is no room beside
    the breadcrumb, so it sits right-aligned just above it at half width instead. */
.bms-has-client-picker {
    position: relative;
}

.bms-client-picker {
    position: absolute;
    top: 1rem;
    right: 1.5rem;
    width: 25%;
    min-width: 200px;
    z-index: 5;
}

.bms-client-picker .form-select {
    width: 100%;
}

@media (max-width: 767.98px) {
    .bms-client-picker {
        position: static;
        width: 50%;
        margin: 0 0 .5rem auto;
    }
}
