/*--------------------------------------------------------------
# components.css: the site's shared building blocks (UI_MODERNIZATION_PLAN.md, Phase 1).
#
# Loaded by _Layout right after site.css, so where the two meet, this file decides. Sizes and
# colours come from tokens.css.
#
#   1. Form fields: floating fields and select2, one size and one look everywhere
#   2. A field with its own button beside it (.field-action, .btn-field)
#   3. Buttons in the site's colours (.btn-alma, .btn-alma-secondary, .btn-outline-alma, .btn-outline-serenity)
#   4. The page header (.page-header)
#   5. The grid toolbar (.grid-toolbar), its search box (.grid-search, Views/Shared/_GridSearch.cshtml)
#      and the filter panel (.filter-offcanvas)
#   6. Grid cards: the grid below md (.grid-cards, .grid-card)
#   7. Form pages: the card, its sections and its actions (.form-card, .form-section, .form-actions)
#   8. Details pages: the record card and its sections (.detail-card, .detail-section)
--------------------------------------------------------------*/


/*--------------------------------------------------------------
# 1. Form fields
#
# Every floating field (.form-floating: the label inside the box, over the value) is --field-h
# tall (52px) with a 12px label over a 15px value, whether it is an input, a date, a native
# select, a textarea or a select2. The label and the value start at the same inset
# (--field-px), the value is centred in the space under the label, and the label always sits at
# the top: there is no "label as placeholder" state for some fields and not others.
#
# Why about 50px: Bootstrap's floating field is 58px. Dense business forms in the common design
# systems use 32-40px controls with the label above them (IBM Carbon 32/40px, Atlassian 32/40px,
# Ant Design 32px, Salesforce 32px), which with the label comes to about 52-60px a field. A
# floating field of 48-52px fits the same label and value in no more height, and stays above the
# 44px touch target the forms need on the warehouse's phones. 48px was tried first; 52px was
# chosen for a little more room.
--------------------------------------------------------------*/

/* The box. The padding is repeated for every state Bootstrap gives its own (focused, filled,
   autofilled), which it writes with higher specificity than the plain selector. */
.form-floating > .form-control,
.form-floating > .form-control-plaintext,
.form-floating > .form-select {
    height: var(--field-h);
    min-height: var(--field-h);
    font-size: var(--field-font);
    line-height: 1.25;
}

.form-floating > .form-control,
.form-floating > .form-control:focus,
.form-floating > .form-control:not(:placeholder-shown),
.form-floating > .form-control:-webkit-autofill,
.form-floating > .form-control-plaintext,
.form-floating > .form-control-plaintext:focus,
.form-floating > .form-control-plaintext:not(:placeholder-shown),
.form-floating > .form-select {
    padding: var(--field-value-top) var(--field-px) var(--field-value-bottom);
}

/* Firefox's name for :placeholder-shown, in a rule of its own: an unknown selector in a list
   would drop the whole list in other browsers. */
.form-floating > .form-control:not(:-moz-placeholder-shown) {
    padding: var(--field-value-top) var(--field-px) var(--field-value-bottom);
}

.form-floating > .form-select {
    padding-right: 2.25rem;
    background-position: right var(--field-px) center;
}

/* A textarea starts one field high (it lines up with the fields beside it) and can be dragged
   taller. */
.form-floating > textarea.form-control {
    resize: vertical;
}

    /* An input centres its value in the space under the label, so the value sits a few pixels
       below the label; a textarea's text starts at the top of that space, touching the label. Its
       first line starts where an input's value does (the space's height less one line, halved). */
    .form-floating > textarea.form-control,
    .form-floating > textarea.form-control:focus,
    .form-floating > textarea.form-control:not(:placeholder-shown) {
        padding-top: calc(var(--field-value-top) + (var(--field-h) - 2px - var(--field-value-top) - var(--field-value-bottom) - 1.25em) / 2);
    }

/* A field that can't be changed here (a derived total, a date set by a filed invoice). */
.form-floating > .form-control[readonly] {
    background-color: var(--field-readonly-bg);
}

/* Bootstrap 5.2 squares the corners of any floating field with a sibling after or before it; the
   rule was meant for input groups only (5.3 scopes it to them). Rounded everywhere else. */
.form-floating:not(:last-child) > .form-control,
.form-floating:not(:last-child) > .form-select,
.form-floating:not(:first-child) > .form-control,
.form-floating:not(:first-child) > .form-select {
    border-radius: var(--bs-border-radius);
}

.input-group > .form-floating:not(:last-child) > .form-control,
.input-group > .form-floating:not(:last-child) > .form-select {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

.input-group > .form-floating:not(:first-child) > .form-control,
.input-group > .form-floating:not(:first-child) > .form-select {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}

/* In an input group the field's wrapper is exactly the field (site.css pads every .form-floating
   below; here that would stretch the group's other parts taller than the field), and the group
   keeps that 10px under it instead. */
.input-group > .form-floating {
    padding-bottom: 0;
}

.input-group:has(> .form-floating) {
    margin-bottom: 10px;
}

/* The label's box: from the wrapper's top-left corner, as wide as the wrapper. (Kept apart from
   the rule below, so the two column rules further down can move it.) */
.form-floating > label {
    top: 0;
    left: 0;
    right: 0;
    width: auto;
    height: auto;
}

/* The label: always at the top, over the value, in one size and weight whatever class the view
   gave it (control-label, form-label, small-bold-text). Colour utilities (text-success on Date In,
   text-danger on Date Out) still apply, and fw-bold still wins. Every state Bootstrap floats the
   label in is listed so this wins over its transform. */
.form-floating > label,
.form-floating > .form-control:focus ~ label,
.form-floating > .form-control:not(:placeholder-shown) ~ label,
.form-floating > .form-control:-webkit-autofill ~ label,
.form-floating > .form-control-plaintext ~ label,
.form-floating > .form-select ~ label {
    padding: var(--field-label-top) var(--field-px) 0;
    font-size: var(--field-label-font);
    font-weight: 500;
    line-height: 1.25;
    color: var(--field-label-color);
    opacity: 1;
    transform: none;
}

.form-floating > .form-control:not(:-moz-placeholder-shown) ~ label {
    opacity: 1;
    transform: none;
}

/* A floating field that is also its grid column (class="col-md-4 form-floating"): the control
   sits inside the column's padding, but the label is placed from the column's edge. Moving the
   label in by the same padding lines it up with the value; the gutter variable resolves on the
   label exactly as it does on its column. */
.row > .form-floating > label {
    left: calc(var(--bs-gutter-x) * .5);
    right: calc(var(--bs-gutter-x) * .5);
}

/* The same for a wrapper padded with p-1 (the Orders forms): 4px on every side, the top too. */
.form-floating.p-1 > label {
    top: .25rem;
    left: .25rem;
    right: .25rem;
}

/*---------------------------------------------------------- select2: every select2 on the site
   One look with the native .form-select: the same border, radius, chevron and focus colour.
   The clear button (×) and the chevron share the box's middle; open, the list joins the box
   with no gap. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
    border: 1px solid var(--field-border);
    border-radius: var(--bs-border-radius);
    background-color: #fff;
}

.select2-container--default .select2-selection--single {
    height: calc(1.5em + .75rem + 2px);        /* a .form-select's 38px */
    background: #fff var(--field-chevron) no-repeat right .75rem center / 16px 12px;
}

    .select2-container--default .select2-selection--single .select2-selection__rendered {
        padding: .375rem 2.25rem .375rem .75rem;
        color: #212529;
        line-height: 1.5;
        text-align: left;
    }

    .select2-container--default .select2-selection--single .select2-selection__placeholder {
        color: #212529;
    }

    /* The chevron is the box's background, as on a native select. */
    .select2-container--default .select2-selection--single .select2-selection__arrow {
        display: none;
    }

    /* The clear button: in the middle of the box, left of the chevron. */
    .select2-container--default .select2-selection--single .select2-selection__clear {
        position: absolute;
        top: 50%;
        right: 2.25rem;
        z-index: 1;
        float: none;
        height: auto;
        margin: 0;
        padding: 0 .25rem;
        color: #6c757d;
        font-size: 1.1rem;
        font-weight: 400;
        line-height: 1;
        transform: translateY(-50%);
    }

        .select2-container--default .select2-selection--single .select2-selection__clear:hover {
            color: #212529;
        }

    .select2-container--default .select2-selection--single.select2-selection--clearable .select2-selection__rendered {
        padding-right: 3.75rem;
    }

.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--focus .select2-selection--multiple,
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
    border-color: var(--field-focus);
    outline: 0;
}

.select2-container--default.select2-container--disabled .select2-selection--single,
.select2-container--default.select2-container--disabled .select2-selection--multiple {
    background-color: #e9ecef;
}

/* Open: the list and the box share one border, joined without a seam (select2 squares the
   touching corners; a rounded corner left there is what showed the gap). */
.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,
.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple {
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
}

.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,
.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple {
    border-top-left-radius: 0;
    border-top-right-radius: 0;
}

.select2-dropdown {
    border-color: var(--field-focus);
    border-radius: var(--bs-border-radius);
    font-size: var(--field-font);
    overflow: hidden;
}

.select2-search--dropdown {
    padding: .375rem;
}

.select2-container--default .select2-search--dropdown .select2-search__field {
    padding: .25rem .5rem;
    border: 1px solid var(--field-border);
    border-radius: calc(var(--bs-border-radius) - 2px);
    font-size: var(--field-font);
    outline: 0;
}

    .select2-container--default .select2-search--dropdown .select2-search__field:focus {
        border-color: var(--field-focus);
    }

.select2-results__option {
    padding: .375rem var(--field-px);
}

.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
    background-color: var(--alma-blue);
}

.select2-container--default .select2-results__option--selected {
    background-color: #e9ecef;
}

/* Several values (select2 multiple): chips in the site's quiet style. */
.select2-container--default .select2-selection--multiple .select2-selection__choice {
    border-color: var(--field-border);
    border-radius: calc(var(--bs-border-radius) - 2px);
    background-color: #eef1f5;
}

/* Width: a select2 fills its field (select2 sizes itself from the <select> otherwise). */
.select2-container,
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple,
.select2-container--default .select2-selection {
    width: 100% !important;
    max-width: 100% !important;
    box-sizing: border-box !important;
    min-width: 0 !important;
}

/*---------------------------------------------------------- select2 as a floating field
   The same box, label and value inset as the inputs beside it. */
.form-floating > .select2-container .select2-selection--single {
    height: var(--field-h);
}

    /* An input centres its value in the space under the label; select2's text is ordinary block
       text, so it is given a line as tall as that space, which centres it the same way at any
       --field-h (the 2px are the box's top and bottom borders). */
    .form-floating > .select2-container .select2-selection--single .select2-selection__rendered {
        padding: var(--field-value-top) 2.25rem var(--field-value-bottom) var(--field-px);
        font-size: var(--field-font);
        line-height: calc(var(--field-h) - 2px - var(--field-value-top) - var(--field-value-bottom));
    }

    .form-floating > .select2-container .select2-selection--single.select2-selection--clearable .select2-selection__rendered {
        padding-right: 3.75rem;
    }

.form-floating > .select2-container .select2-selection--multiple {
    min-height: var(--field-h);
    padding: var(--field-value-top) 2rem var(--field-value-bottom) calc(var(--field-px) - 5px);
    font-size: var(--field-font);
}


/*--------------------------------------------------------------
# 2. A field with its own button beside it
#
# .field-action: an export's order or package with its Remove button, a note with Add Package.
# The field and the button are separate controls with a gap between them, each with its own
# rounded corners. (An .input-group joins its children into one control and squares the corners
# where they meet, which is wrong for a button set apart.)
#
#   <div class="field-action mb-2"><input class="form-control" …><button class="btn …">…</button></div>
#
# A child can itself be an .input-group (fields that are joined), and .field-fixed keeps a child
# to a quarter of the row, between 3.5rem and 10rem (a package's type beside its measurements).
#
# .btn-field: a button as tall as the floating field in the column next to it (Expenses' New
# Type / New Vendor).
--------------------------------------------------------------*/
.field-action {
    display: flex;
    align-items: center;
    gap: .5rem;
}

    .field-action > .form-control,
    .field-action > .form-select,
    .field-action > .input-group {
        flex: 1 1 0;
        width: auto;
        min-width: 0;
    }

    .field-action > .btn {
        flex: none;
        margin: 0;
    }

    .field-action > .field-fixed {
        flex: 0 0 25%;
        min-width: 3.5rem;
        max-width: 10rem;
    }

    /* A floating field in the row (a package's type and notes) sizes like a plain one. */
    .field-action > .form-floating {
        flex: 1 1 0;
        min-width: 0;
    }

    .field-action > .form-floating.field-fixed {
        flex: 0 0 25%;
    }

/* Joined floating measurements (a package's length, width, height, weight): narrow boxes, so
   their label and value sit closer to the edge; both still fit, the label over the value. */
.field-action > .input-group > .form-floating {
    --field-px: .5rem;
}

/* The row spaces its fields; the 10px §1 puts under an input group of floating fields would
   lift the group off the row's line. */
.field-action > .input-group:has(> .form-floating) {
    margin-bottom: 0;
}

/* A package, saved or being entered, is a small bordered box of its own. */
.form-item {
    margin-bottom: .5rem;
    padding: .5rem;
    border: 1px solid var(--field-border);
    border-radius: var(--alma-radius);
    background-color: #fff;
}

    .form-item.is-new {
        border-style: dashed;
    }

/* A choice in a list (an in-stock order): its checkbox and text in a small bordered tile, the
   whole tile clickable through its label. */
.form-option {
    margin: 0 0 .375rem;
    padding: .375rem .625rem .375rem 2.125rem;
    border: 1px solid var(--field-border);
    border-radius: var(--alma-radius);
    background-color: #fff;
}

    .form-option:last-child {
        margin-bottom: 0;
    }

    /* Ticked: pale green with a green tick (the orders card around it is pale blue). */
    .form-option:has(.form-check-input:checked) {
        border-color: var(--field-chosen-border);
        background-color: var(--field-chosen-bg);
    }

        .form-option .form-check-input:checked {
            border-color: var(--field-chosen-check);
            background-color: var(--field-chosen-check);
        }

    /* The fields' value size, not the page's 16px. */
    .form-option .form-check-label {
        display: block;
        font-size: var(--field-font);
        cursor: pointer;
    }

/* An item already chosen (an order on the export, in Edit): the ticked tile's pale green. */
.form-control.is-chosen,
.form-control.is-chosen[readonly] {
    border-color: var(--field-chosen-border);
    background-color: var(--field-chosen-bg);
}

/* On a phone a package being entered has its type (a select, whose chevron takes room) and its
   measurements on a row each: side by side, neither has room for its text. A saved package's
   read-only type box fits beside its values and stays on one row. */
@media (max-width: 575.98px) {
    .field-action:has(> .field-fixed > select) {
        flex-wrap: wrap;
    }

        .field-action > .form-floating.field-fixed:has(> select),
        .field-action > .form-floating.field-fixed:has(> select) + .input-group {
            flex: 1 1 100%;
            max-width: none;
        }

    /* The measurements' labels in short (L / W / H / KG) from data-short: at a phone's width four
       full names don't fit their boxes. The full name stays for screen readers. */
    .field-action > .input-group > .form-floating > label[data-short] {
        font-size: 0;
    }

        .field-action > .input-group > .form-floating > label[data-short]::after {
            content: attr(data-short);
            font-size: var(--field-label-font);
        }
}
.btn.btn-field {
    height: var(--field-h);
    margin: 0;
}

/* Remove (×) beside a field: a small square in the middle of the room a full-height button took
   (its margins keep that width), so the field beside it keeps its size.
     <button class="btn btn-outline-danger btn-remove" aria-label="Remove"><i class="bi bi-x-lg"></i></button> */
.btn.btn-remove {
    --bs-btn-padding-x: 0;
    --bs-btn-padding-y: 0;
    --bs-btn-font-size: .875rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.875rem;
    height: 1.875rem;
    margin: 0 .375rem;
    line-height: 1;
}

/* A button in a row of plain (38px) controls, at the small button's size but the row's height
   (Edit's Add beside the orders list). */
.field-action > .btn.btn-sm {
    align-self: stretch;
}


/*--------------------------------------------------------------
# 3. Buttons in the site's colours
#
# Built on Bootstrap 5.2's button variables, so the site's colours come with Bootstrap's own
# hover, pressed, focus and disabled states, and work at every size (btn-sm, btn-lg).
#
#   Primary action (Save, Add New)   btn-alma
#   Secondary / Cancel               btn-outline-secondary (btn-alma-secondary on older pages)
#   Destructive                      btn-outline-danger, or btn-danger inside a confirm dialog
#   Excel / PDF export               btn-outline-success / btn-outline-danger
--------------------------------------------------------------*/
.btn-alma {
    --bs-btn-color: #fff;
    --bs-btn-bg: var(--alma-blue);
    --bs-btn-border-color: var(--alma-blue);
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: var(--alma-blue-hover);
    --bs-btn-hover-border-color: var(--alma-blue-hover);
    --bs-btn-focus-shadow-rgb: 48, 79, 127;
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: #29446d;
    --bs-btn-active-border-color: #29446d;
    --bs-btn-disabled-color: #fff;
    --bs-btn-disabled-bg: var(--alma-blue);
    --bs-btn-disabled-border-color: var(--alma-blue);
}

.btn-alma-secondary {
    --bs-btn-color: #fff;
    --bs-btn-bg: var(--alma-steel);
    --bs-btn-border-color: var(--alma-steel);
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: #878d93;
    --bs-btn-hover-border-color: #878d93;
    --bs-btn-focus-shadow-rgb: 139, 158, 176;
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: #767c82;
    --bs-btn-active-border-color: #767c82;
    --bs-btn-disabled-color: #fff;
    --bs-btn-disabled-bg: var(--alma-steel);
    --bs-btn-disabled-border-color: var(--alma-steel);
}

.btn-outline-alma {
    --bs-btn-color: var(--alma-blue);
    --bs-btn-border-color: var(--alma-blue);
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: var(--alma-blue);
    --bs-btn-hover-border-color: var(--alma-blue);
    --bs-btn-focus-shadow-rgb: 48, 79, 127;
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: #29446d;
    --bs-btn-active-border-color: #29446d;
    --bs-btn-disabled-color: var(--alma-blue);
    --bs-btn-disabled-bg: transparent;
    --bs-btn-disabled-border-color: var(--alma-blue);
}

/* Serenity blue (#306AC0): the 1804 index's bulk Sent-date button. */
.btn-outline-serenity {
    --bs-btn-color: #306ac0;
    --bs-btn-border-color: #306ac0;
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: #306ac0;
    --bs-btn-hover-border-color: #306ac0;
    --bs-btn-focus-shadow-rgb: 48, 106, 192;
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: #24508f;
    --bs-btn-active-border-color: #24508f;
    --bs-btn-disabled-color: #306ac0;
    --bs-btn-disabled-bg: transparent;
    --bs-btn-disabled-border-color: #306ac0;
}

/* A button whose request is under way (.is-busy, with aria-busy): a spinner in its middle, in the
   button's own colour, its text and icon hidden so the button keeps its size, and no second click. */
.btn.is-busy {
    position: relative;
    color: transparent !important;
    pointer-events: none;
    transition: none;   /* at once: Bootstrap's 0.15s colour fade would show the text under the spinner */
}

    .btn.is-busy::after {
        content: "";
        position: absolute;
        top: 50%;
        left: 50%;
        width: 1rem;
        height: 1rem;
        margin: -.5rem 0 0 -.5rem;
        border: .15rem solid var(--bs-btn-color);
        border-right-color: transparent;
        border-radius: 50%;
        animation: spinner-border .75s linear infinite;
    }

    .btn.btn-remove.is-busy::after {
        width: .875rem;
        height: .875rem;
        margin: -.4375rem 0 0 -.4375rem;
        border-width: .125rem;
    }


/*--------------------------------------------------------------
# 4. The page header
#
# The page's title (icon and name in the site's blue) on the left, and on the right whatever the
# page puts there: a status line (Orders' "In Stock & Pending"), or buttons. One markup for every
# width: it wraps as the window narrows, and centres on a phone.
#
#   <div class="page-header">
#       <h3 class="page-header-title"><i class="bi bi-…"></i>Title</h3>
#       <div class="page-header-aside">…</div>          (optional)
#   </div>
--------------------------------------------------------------*/
.page-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .25rem 1rem;
    margin-bottom: 1rem;
}

.page-header-title {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin: 0;
    color: var(--alma-blue);
    font-size: 2rem;
}

.page-header-aside {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .375rem;
    margin-left: auto;
}

.page-header-status {
    margin: 0;
    font-size: 1.5rem;
}

@media (max-width: 1200px) {
    .page-header-title {
        font-size: 1.75rem;
    }
}

@media (max-width: 991.98px) {
    .page-header-title {
        font-size: 1.5rem;
    }

    .page-header-status {
        font-size: 1.25rem;
    }
}

@media (max-width: 767.98px) {
    .page-header {
        flex-direction: column;
        justify-content: center;
        text-align: center;
    }

    .page-header-aside {
        justify-content: center;
        margin-left: 0;
    }
}


/*--------------------------------------------------------------
# 5. The grid toolbar and its search box
#
# Above a grid: the actions (Add New, Filters), the search box, and the tools (the column
# picker). One row at every width, one gap between them all, every control 31px high (a btn-sm).
# The buttons keep their size and the search box takes what is left.
#
# As the window narrows, first the buttons lose their labels (below 992px: icons only; the label
# is kept for screen readers and in the site tooltip), then the column picker goes where the
# grid becomes cards (below 768px: d-none d-md-flex on .grid-toolbar-tools). A button's text goes
# in <span class="btn-label">, and every button keeps an aria-label, since site.js turns titles
# into its own tooltips.
#
# A grid with more buttons than fit (Orders, 1804, Jobs) puts them in one "Menu" dropdown in
# .grid-toolbar-actions, so the row still fits; which buttons stay outside it is decided per grid.
#
#   <div class="grid-toolbar">
#       <div class="grid-toolbar-actions">…buttons…</div>
#       <partial name="_GridSearch" model="…" />         (renders .grid-toolbar-search)
#       <div class="grid-toolbar-tools d-none d-md-flex">…column picker…</div>
#   </div>
--------------------------------------------------------------*/
.grid-toolbar {
    display: flex;
    align-items: center;
    gap: .25rem;
    margin-bottom: .5rem;
}

    .grid-toolbar .btn {
        margin: 0;          /* site.css gives every .btn 5px under it */
    }

    .grid-toolbar .btn > i + .btn-label {
        margin-left: .35rem;
    }

.grid-toolbar-actions,
.grid-toolbar-tools {
    display: flex;
    flex: none;
    align-items: center;
    gap: .25rem;
}

.grid-toolbar-search {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    min-width: 0;
}

@media (max-width: 991.98px) {
    .grid-toolbar .btn-label {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        white-space: nowrap;
    }
}

/* The search box: the active filters as pills (the search text is one of them), the search text,
   then apply / clear everything. The pills scroll sideways rather than squeeze the text, which
   always keeps 8rem. */
.grid-search {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    min-width: 0;
    height: var(--grid-control-h);
    border: 1px solid #6c757d;
    border-radius: var(--bs-border-radius);
    background-color: #fff;
    overflow: hidden;
}

    .grid-search:focus-within {
        border-color: var(--field-focus);
    }

.grid-search-pills {
    display: flex;
    flex: 0 1 auto;
    align-items: center;
    gap: .25rem;
    min-width: 0;
    padding-left: .3rem;
    overflow-x: auto;
    scrollbar-width: none;
}

    .grid-search-pills:empty {
        display: none;
    }

    .grid-search-pills::-webkit-scrollbar {
        display: none;
    }

    /* More pills than room: their right edge fades until the row is scrolled to its end
       (index-grid.js sets the class). */
    .grid-search-pills.is-overflowing {
        -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 1.5rem), transparent);
        mask-image: linear-gradient(to right, #000 calc(100% - 1.5rem), transparent);
    }

.grid-search-pill {
    display: inline-flex;
    flex: none;
    align-items: center;
    gap: .25rem;
    padding: 1px 6px;
    border: 1px solid var(--alma-blue);
    border-radius: 5px;
    background-color: var(--alma-blue);
    color: #fff;
    font-size: .7rem;
    line-height: 1.6;
    white-space: nowrap;
}

    .grid-search-pill:hover,
    .grid-search-pill:focus-visible {
        border-color: #dee2e6;
        background-color: #dee2e6;
        color: var(--alma-accent);
    }

.grid-search-pill-value {
    max-width: 16ch;
    overflow: hidden;
    text-overflow: ellipsis;
}

.grid-search-input {
    flex: 1 1 auto;
    min-width: 8rem;
    height: 100%;
    padding: 0 .5rem;
    border: 0;
    background: transparent;
    font-size: .875rem;
    outline: 0;
}

.grid-search-btn {
    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 100%;
    padding: 0;
    border: 0;
    background: #f8f9fa;
    color: #212529;
    text-decoration: none;
}

    .grid-search-btn:hover,
    .grid-search-btn:focus-visible {
        background: #e2e6ea;
        color: #212529;
    }

    .grid-search-btn.is-reset {
        border-left: 1px solid #dee2e6;
    }

    /* The ✓ and the × drawn the same size. At one font size bi-check-lg's ink is 11×8px and
       bi-x-lg's 13×12px (measured at 16px), so the ✓ is set larger and the × smaller: about
       11×8 and 10×10 here, 13×9 and 12×11 at the touch size below. */
    .grid-search-btn {
        font-size: .875rem;
    }

        .grid-search-btn > i {
            line-height: 1;
        }

        .grid-search-btn > .bi-check-lg {
            font-size: 1.15em;
        }

        .grid-search-btn > .bi-x-lg {
            font-size: .9em;
        }

@media (max-width: 575.98px) {
    .grid-search-pill-value {
        max-width: 11ch;
    }
}

/* Touch: where the grid is cards (below 768px) the toolbar's controls are 40px, large enough to
   hit with a finger. The search text is 16px there, so phones don't zoom in when it is focused. */
@media (max-width: 767.98px) {
    .grid-toolbar {
        --grid-control-h: 40px;
    }

        .grid-toolbar .btn {
            min-width: var(--grid-control-h);
            height: var(--grid-control-h);
            display: inline-flex;
            align-items: center;
            justify-content: center;
            font-size: 1rem;
        }

    .grid-search-input {
        font-size: 1rem;
    }

    .grid-search-btn {
        width: 2.5rem;
        font-size: 1rem;
    }

    .grid-search-pill {
        padding: 3px 8px;
        font-size: .75rem;
    }
}

/*---------------------------------------------------------- The filter panel (.filter-offcanvas)
   The toolbar's Filters button opens it. The same on every grid:

     <div class="offcanvas offcanvas-end filter-offcanvas" id="filtersOffcanvas" tabindex="-1" aria-labelledby="…Title">
         <div class="offcanvas-header">
             <h2 class="offcanvas-title" id="…Title"><i class="bi bi-funnel"></i>Filters</h2>
             <button class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
         </div>
         <div class="offcanvas-body">   one .form-floating select per filter  </div>
         <div class="offcanvas-footer"> <a class="btn btn-outline-secondary"><i class="bi bi-x-lg"></i>Reset All Filters</a> </div>
     </div>
*/
.filter-offcanvas .offcanvas-header {
    border-bottom: 1px solid var(--alma-line);
}

.filter-offcanvas .offcanvas-title {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin: 0;
    color: var(--alma-blue);
    font-size: 1.1rem;
    font-weight: 700;
}

.filter-offcanvas .offcanvas-body {
    display: flex;
    flex-direction: column;
    gap: .75rem;
}

    /* The body spaces the fields; site.css's 10px under every floating field would double it. */
    .filter-offcanvas .offcanvas-body .form-floating {
        padding-bottom: 0;
    }

.filter-offcanvas .offcanvas-footer {
    display: flex;
    justify-content: flex-end;
    gap: .5rem;
    padding: .75rem 1rem;
    border-top: 1px solid var(--alma-line);
    background-color: var(--alma-surface);
}

    .filter-offcanvas .offcanvas-footer .btn {
        display: inline-flex;
        align-items: center;
        gap: .375rem;
        margin: 0;
    }


/*--------------------------------------------------------------
# 6. Grid cards: the grid below md (768px), one card a record
#
# Three rows at most, each a main part on the left (truncated with … when it runs out of room)
# and an aside on the right (a date, a client, the chips). The first row's main part is the
# record's link to its Details.
#
#   <div class="grid-cards d-md-none">
#       <div class="grid-card">
#           <div class="grid-card-row">
#               <a class="grid-card-title" …>MRN</a><span class="grid-card-aside">date</span>
#           </div>
#           <div class="grid-card-row">
#               <span class="grid-card-main"><a class="grid-card-icon">…</a><a class="grid-card-text">…</a></span>
#               <span class="grid-card-chips"><button class="grid-card-chip is-primary">…</button></span>
#           </div>
#       </div>
#   </div>
#
# Not a Bootstrap .card: site.css stretches every .card to its container's height.
--------------------------------------------------------------*/
.grid-cards {
    display: flex;
    flex-direction: column;
    gap: .375rem;
    margin-bottom: .75rem;
}

.grid-card {
    display: flex;
    flex-direction: column;
    gap: .125rem;
    padding: .4rem .6rem;
    border: 1px solid var(--alma-line);
    border-left: 3px solid var(--alma-blue);
    border-radius: var(--alma-radius);
    background-color: #fff;
    box-shadow: 0 1px 2px rgba(23, 43, 69, .08);
    color: #212529;
    font-size: .8rem;
    line-height: 1.35;
    -webkit-touch-callout: none;
}

.grid-card-empty {
    padding: 1rem;
    border-left-color: #dc3545;
    color: #dc3545;
    font-size: 1rem;
    font-weight: 600;
    text-align: center;
}

.grid-card-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    min-width: 0;
    min-height: 1.375rem;
}

.grid-card-title,
.grid-card-main,
.grid-card-text {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.grid-card-title {
    color: var(--alma-blue);
    font-size: .875rem;
    font-weight: 600;
    text-decoration: none;
}

.grid-card-main {
    display: flex;
    align-items: center;
    gap: .375rem;
}

.grid-card a.grid-card-text,
.grid-card a.grid-card-aside {
    color: var(--alma-blue);
    text-decoration: none;
}

/* A link in the card's own text colour (the client before its vessel); short of room, it gives
   way before the part after it. */
.grid-card a.grid-card-text.is-quiet {
    flex: 0 3 auto;
    color: #212529;
    font-weight: 400;
}

/* A middle dot between two parts of one line. */
.grid-card-sep {
    flex: none;
    color: var(--alma-muted);
}

.grid-card-aside {
    flex: none;
    max-width: 45%;
    overflow: hidden;
    color: var(--alma-muted);
    text-overflow: ellipsis;
    white-space: nowrap;
}

.grid-card-label {
    color: var(--alma-muted);
    font-size: .7rem;
    font-weight: 600;
    text-transform: uppercase;
}

.grid-card-icon {
    display: inline-flex;
    flex: none;
    align-items: center;
    color: var(--alma-blue);
    font-size: 1rem;
    line-height: 1;
    text-decoration: none;
}

    .grid-card-icon .flag img {
        width: 16px !important;     /* site.css sizes the flag 20px, with a 5px lift */
        height: 16px !important;
        margin: 0;
    }

.grid-card-chips {
    display: flex;
    flex: none;
    gap: .25rem;
}

.grid-card-chip {
    padding: 1px 7px;
    border: 1px solid #adb5bd;
    border-radius: 999px;
    background-color: #fff;
    color: #212529;
    font-size: .68rem;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
}

    button.grid-card-chip:hover,
    button.grid-card-chip:focus-visible {
        border-color: var(--alma-blue);
        background-color: var(--alma-blue);
        color: #fff;
    }

    .grid-card-chip.is-primary {
        border-color: var(--alma-blue);
        color: var(--alma-blue);
    }

    .grid-card-chip.is-static {
        background-color: #f6f6f6;
        color: var(--alma-muted);
    }

/* The table's row-number column (#): as narrow as its numbers. */
.grid-col-no {
    width: .5%;
}

/* A table badge that opens something (Exports' Orders / Packages): a real button, looking as the
   block badge it replaces, the cell's width less its 2px margins. */
.grid-badge-button {
    display: block;
    width: calc(100% - 4px);
    cursor: pointer;
}


/*--------------------------------------------------------------
# 7. Form pages: the card, its sections and its actions
#
# A Create or Edit page is a .page-header, then one .form-card holding the fields and, last,
# the .form-actions: Save, then Cancel, then Delete where the page has one.
#
#   <div class="page-header"><h3 class="page-header-title"><i class="bi bi-…"></i>Title</h3></div>
#   <form …>
#       <div class="form-card">                          (.form-card-narrow: 800px, centred)
#           <div class="row g-3">
#               <div class="col-md-4">
#                   <div class="row g-2">                (the field grid: one 8px gap all round)
#                       <div class="col-sm-8 form-floating">…</div>
#                       <div class="col-12"><div class="form-section">…</div></div>
#                   </div>
#               </div>
#           </div>
#           <div class="form-actions">
#               <span class="form-actions-note">…</span>   (optional: why Save is disabled)
#               <button class="btn btn-alma">Save</button>
#               <a class="btn btn-outline-secondary">Cancel</a>
#           </div>
#       </div>
#   </form>
#
# A .form-section is a panel inside the form (Orders, Packages, Invoices): a quiet title over its
# content. It replaces Bootstrap .cards in forms, which site.css stretches to their column.
#
# The old wms-form-shadow / wms-centerdiv / boxshadowdiv keep working until the last form moves.
--------------------------------------------------------------*/
.form-card {
    padding: 1rem 1.25rem;
    border: 1px solid var(--alma-line);
    border-radius: var(--alma-radius-panel);
    background-color: #fff;
    box-shadow: 0 1px 3px rgba(23, 43, 69, .08);
}

.form-card-narrow {
    max-width: 800px;
    margin-inline: auto;
}

    /* The field grid spaces the fields; site.css's 10px under every floating field would double it. */
    .form-card .form-floating {
        padding-bottom: 0;
    }

    .form-card .btn {
        margin-bottom: 0;   /* site.css gives every .btn 5px under it */
    }

/* A floating textarea several lines high (an agent's name and address). */
.form-floating > textarea.form-control.field-tall {
    height: 12.5rem;
}

.form-section {
    padding: .625rem .75rem .75rem;
    border: 1px solid var(--alma-line);
    border-radius: var(--alma-radius);
    background-color: var(--alma-surface);
}

.form-section-title {
    margin: 0 0 .5rem;
    color: var(--alma-muted);
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .03em;
    text-transform: uppercase;
}

    .form-section > :last-child {
        margin-bottom: 0;
    }

/* A section's "nothing here" line, at the fields' value size. */
.form-section-empty {
    margin: 0 0 .5rem;
    color: var(--alma-muted);
    font-size: var(--field-font);
}

/* A choice's link (an invoice's number) at the text's weight, in the site's blue. */
.form-option .form-check-label a {
    font-weight: 500;
}

/* A row of small buttons under a field (the agent's Edit / Save / Cancel / Remove). */
.form-inline-actions {
    display: flex;
    flex-wrap: wrap;
    gap: .375rem;
}

.form-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: .5rem;
    margin-top: 1rem;
    padding-top: .75rem;
    border-top: 1px solid var(--alma-line);
}

.form-actions-note {
    margin-right: auto;
    color: #dc3545;
    font-size: .875rem;
}

@media (max-width: 575.98px) {
    .form-card {
        padding: .75rem;
    }

    /* On a phone the actions share the row, each wide enough to hit with a thumb. */
    .form-actions > .btn {
        flex: 1 1 0;
        min-height: 44px;
    }

    .form-actions-note {
        flex-basis: 100%;
        margin-right: 0;
        text-align: center;
    }
}


/*--------------------------------------------------------------
# 8. Details pages: the record card and its sections
#
# A record's page reads as its quick view at page size, in the same pieces (modal-modern.css:
# chips, facts, notes, tables, totals), under .mm-scope for their values:
#
#   <div class="page-header">…title…<div class="page-header-aside">Documents, Photos, Edit, Delete, Back</div></div>
#   <div class="mm-scope detail-page">
#       <div class="detail-card">
#           <div class="detail-head">
#               <div class="detail-head-main"><h2 class="detail-title">MRN</h2><span class="mm-title-aside">B/L …</span></div>
#               <div class="mm-meta detail-head-meta">chips, <span class="detail-date">date</span></div>
#           </div>
#           <div class="detail-body">                        (three panels of one height)
#               <div class="detail-block">the party, as addressed</div>
#               <dl class="detail-block detail-pairs">label, value, label, value…</dl>
#               <dl class="detail-block detail-pairs">…</dl>
#           </div>
#           <p class="mm-note detail-note">…</p>
#       </div>
#       <div class="detail-section"><h3 class="mm-group-title">Orders</h3><table class="mm-table is-rows">…</table><div class="mm-totals">…</div></div>
#       <div class="detail-audit">Admin: ids, created, modified</div>
#   </div>
#
# The header's buttons carry an icon and a .btn-label; below 576px only the icons show.
--------------------------------------------------------------*/
.page-header-aside .btn {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    margin: 0;
}

    .page-header-aside .btn .badge {
        margin: 0;
    }

/* Every label from xl up; below xl only the main action's (.btn-label.is-kept, Edit). */
@media (max-width: 1199.98px) {
    .page-header-aside .btn-label:not(.is-kept) {
        display: none;
    }
}

/* .page-header-row: the title and the actions stay one row at every width (a plain .page-header
   stacks and centres them below md). Below sm the actions are one Menu dropdown
   (.page-header-menu), since the title and five buttons don't fit a phone's width. */
.page-header-row .page-header-title {
    min-width: 0;
}

.page-header-row .page-header-aside {
    flex-wrap: nowrap;
}

.page-header-menu {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    margin: 0;
}

.page-header-row .dropdown-item {
    display: flex;
    align-items: center;
    gap: .5rem;
}

@media (max-width: 767.98px) {
    .page-header.page-header-row {
        flex-direction: row;
        flex-wrap: nowrap;
        justify-content: space-between;
        text-align: left;
    }

        .page-header.page-header-row .page-header-aside {
            justify-content: flex-end;
            margin-left: auto;
        }
}

.detail-card,
.detail-section {
    padding: 1.25rem 1.5rem;
    border: 1px solid var(--alma-line);
    border-radius: var(--alma-radius-panel);
    background-color: #fff;
    box-shadow: 0 1px 3px rgba(23, 43, 69, .08);
}

.detail-section {
    margin-top: 1rem;
}

/* One row: the record's reference large with its second one beside it (MRN, B/L) on the left; its
   chips and its date on the right, under them when the row runs out of room. A rule under it. */
.detail-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px 24px;
    margin-bottom: 1rem;
    padding-bottom: .875rem;
    border-bottom: 1px solid var(--alma-line);
}

.detail-head-main {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 2px 18px;
    min-width: 0;
}

/* Two classes: modal-modern.css (loaded after this file) sets .mm-meta's margin. */
.detail-card .detail-head-meta {
    justify-content: flex-end;
    margin: 0;
}

/* From lg up the row has three parts: the MRN on the left, the waybill in the middle (its label as
   the panels' labels, its number as large as the MRN), the chips and the date on the right. Below
   lg the waybill is the small B/L beside the MRN. */
/* The label sits over the number, in the space between the card's top edge and the number (as far
   from the one as from the other), so the row is no taller than the MRN makes it. */
.detail-head-waybill {
    position: relative;
    min-width: 0;
}

    .detail-head-waybill > .detail-block-label {
        position: absolute;
        bottom: 100%;
        left: 50%;
        margin-bottom: var(--detail-waybill-label-gap, 2px);
        line-height: 1;
        white-space: nowrap;
        transform: translateX(-50%);
    }

.detail-waybill {
    color: var(--mm-ink);
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: -.01em;
    white-space: nowrap;
}

@media (min-width: 992px) {
    .detail-head {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    }

        .detail-head > .detail-head-waybill {
            justify-self: center;
        }

    .detail-card .detail-head-meta {
        justify-self: end;
    }
}

/* The date as strong as the B/L beside the MRN. */
.detail-date {
    color: var(--mm-ink);
    font-size: .95rem;
    font-weight: 600;
    white-space: nowrap;
}

.detail-title {
    min-width: 0;
    margin: 0;
    color: var(--mm-ink);
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: -.01em;
    overflow-wrap: anywhere;
}

/* Three panels of one height (the tallest sets it): the party as addressed, where it goes, the
   record's own details. The middle one widest, so an agent's address keeps to its lines. Two
   columns between md and lg (the third under them, across), one below md. */
.detail-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) minmax(0, 1.05fr);
    gap: 1rem;
}

    .detail-body > .detail-block {
        margin: 0;
    }

.detail-block {
    padding: 14px 16px;
    border-radius: var(--alma-radius-panel);
    background: var(--alma-surface);
    color: var(--mm-ink);
    font-size: .86rem;
    line-height: 1.5;
}

.detail-block-label,
.detail-contact dt,
.detail-pairs dt,
.detail-line-label {
    margin: 0;
    color: var(--mm-muted);
    font-size: .68rem;
    font-weight: 600;
    letter-spacing: .03em;
    text-transform: uppercase;
}

.detail-block-name {
    margin: 1px 0 2px;
    font-size: .95rem;
    font-weight: 700;
}

.detail-contact {
    display: grid;
    gap: 2px;
    margin: 10px 0 0;
}

    .detail-contact > div {
        display: flex;
        gap: 8px;
        align-items: baseline;
    }

    .detail-contact dt {
        flex: none;
        width: 3.5rem;
    }

    .detail-contact dd {
        min-width: 0;
        margin: 0;
        overflow-wrap: anywhere;
    }

/* Labels beside their values, a row each; a value of several lines keeps its label at its top. */
.detail-pairs {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    align-content: start;
    align-items: baseline;
    gap: 6px 16px;
}

    .detail-pairs dd {
        min-width: 0;
        margin: 0;
        overflow-wrap: anywhere;
    }

.detail-strong {
    font-weight: 700;
}

/* A value over several lines as entered (an agent's name and address). */
.detail-pairs dd.is-lines,
.mm-fact dd.is-lines {
    white-space: pre-line;
}

/* Two classes: modal-modern.css (loaded after this file) gives .mm-facts and .mm-note their
   margins in a modal. */
.detail-card .detail-note {
    margin: 1rem 0 0;
}

.detail-section > .mm-group-title {
    margin-bottom: .5rem;
}

.detail-section > .mm-state {
    min-height: 80px;
}

/* A section's content as one line of text (the packing totals typed in, when no packages were). */
.detail-line {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 10px;
    margin: .25rem 0 0;
    color: var(--mm-ink);
    font-size: .9rem;
    font-weight: 600;
}

.detail-audit {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 2px 16px;
    margin-top: .75rem;
    color: var(--mm-muted);
    font-size: .72rem;
}

@media (max-width: 991.98px) {
    .detail-body {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
    }

        .detail-body > .detail-export {
            grid-column: 1 / -1;
        }
}

@media (max-width: 767.98px) {
    .detail-body {
        grid-template-columns: minmax(0, 1fr);
    }

    .detail-card .detail-head-meta {
        justify-content: flex-start;
    }
}

@media (max-width: 575.98px) {
    .detail-card,
    .detail-section {
        padding: .875rem;
    }

    /* The MRN and the B/L share one line on a phone, as on the quick view. */
    .detail-title {
        font-size: 1rem;
    }

    .detail-head-main {
        flex-wrap: nowrap;
        gap: 10px;
    }

        .detail-head-main .mm-title-aside {
            flex: none;
            font-size: .8rem;
        }

    .detail-date {
        font-size: .8rem;
    }
}
