/* ============================================================================
   Bootstrap 4 -> 5 compatibility shim
   ----------------------------------------------------------------------------
   Loaded ONLY on pages running Bootstrap 5 (body.ht-bs5, set by header.php when
   a controller passes ui_bs5). It re-implements the BS4 utilities and component
   classes that BS5 dropped, so existing markup keeps working unchanged.

   WHY a shim instead of renaming the markup: the app has ~110 BS4-only classes
   in the Invest surface alone and several hundred more site-wide, a third of
   them inside PHP string concatenation in controllers where a typo fails
   silently. Shimming makes a controller-by-controller migration a one-line
   switch; markup can be modernised later, at leisure, file by file.

   Everything here is deliberately scoped to body.ht-bs5 so it can never leak
   onto a page still running Bootstrap 4 (where these classes already exist).
   ========================================================================== */

/* ---- Spacing utilities: BS5 renamed left/right to start/end --------------- */
/* $spacer scale: 0, .25rem, .5rem, 1rem, 1.5rem, 3rem */
body.ht-bs5 .ml-0 { margin-left: 0 !important; }
body.ht-bs5 .ml-1 { margin-left: .25rem !important; }
body.ht-bs5 .ml-2 { margin-left: .5rem !important; }
body.ht-bs5 .ml-3 { margin-left: 1rem !important; }
body.ht-bs5 .ml-4 { margin-left: 1.5rem !important; }
body.ht-bs5 .ml-5 { margin-left: 3rem !important; }
body.ht-bs5 .ml-auto { margin-left: auto !important; }
body.ht-bs5 .mr-0 { margin-right: 0 !important; }
body.ht-bs5 .mr-1 { margin-right: .25rem !important; }
body.ht-bs5 .mr-2 { margin-right: .5rem !important; }
body.ht-bs5 .mr-3 { margin-right: 1rem !important; }
body.ht-bs5 .mr-4 { margin-right: 1.5rem !important; }
body.ht-bs5 .mr-5 { margin-right: 3rem !important; }
body.ht-bs5 .mr-auto { margin-right: auto !important; }
body.ht-bs5 .pl-0 { padding-left: 0 !important; }
body.ht-bs5 .pl-1 { padding-left: .25rem !important; }
body.ht-bs5 .pl-2 { padding-left: .5rem !important; }
body.ht-bs5 .pl-3 { padding-left: 1rem !important; }
body.ht-bs5 .pl-4 { padding-left: 1.5rem !important; }
body.ht-bs5 .pl-5 { padding-left: 3rem !important; }
body.ht-bs5 .pr-0 { padding-right: 0 !important; }
body.ht-bs5 .pr-1 { padding-right: .25rem !important; }
body.ht-bs5 .pr-2 { padding-right: .5rem !important; }
body.ht-bs5 .pr-3 { padding-right: 1rem !important; }
body.ht-bs5 .pr-4 { padding-right: 1.5rem !important; }
body.ht-bs5 .pr-5 { padding-right: 3rem !important; }

/* ---- Text / float / type utilities --------------------------------------- */
body.ht-bs5 .text-left  { text-align: left !important; }
body.ht-bs5 .text-right { text-align: right !important; }
body.ht-bs5 .float-left  { float: left !important; }
body.ht-bs5 .float-right { float: right !important; }
body.ht-bs5 .font-weight-light   { font-weight: 300 !important; }
body.ht-bs5 .font-weight-normal  { font-weight: 400 !important; }
body.ht-bs5 .font-weight-bold    { font-weight: 700 !important; }
body.ht-bs5 .font-weight-bolder  { font-weight: bolder !important; }
body.ht-bs5 .text-monospace { font-family: var(--bs-font-monospace) !important; }
body.ht-bs5 .sr-only {
    position: absolute !important; width: 1px; height: 1px; padding: 0;
    margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* ---- Grid / layout ------------------------------------------------------- */
/* .form-row was a .row with tighter gutters. */
body.ht-bs5 .form-row { display: flex; flex-wrap: wrap; margin-right: -5px; margin-left: -5px; }
body.ht-bs5 .form-row > [class*="col-"], body.ht-bs5 .form-row > .col { padding-right: 5px; padding-left: 5px; }
body.ht-bs5 .no-gutters { margin-right: 0; margin-left: 0; }
body.ht-bs5 .no-gutters > [class*="col-"] { padding-right: 0; padding-left: 0; }
/* BS5 dropped .form-group entirely in favour of explicit margin utilities. */
body.ht-bs5 .form-group { margin-bottom: 1rem; }
/* BS5 replaced .btn-block with a .d-grid wrapper. */
body.ht-bs5 .btn-block { display: block; width: 100%; }
body.ht-bs5 .btn-block + .btn-block { margin-top: .5rem; }

/* ---- Input groups -------------------------------------------------------- */
/* BS5 removed the prepend/append wrappers and styles .input-group's children
   directly. display:contents dissolves the wrapper for layout so the addon
   becomes a real flex item; the radius rules below replace what BS5 would have
   applied via :first-child / :last-child (which the wrapper still blocks). */
body.ht-bs5 .input-group-prepend,
body.ht-bs5 .input-group-append { display: contents; }

/* Size variants. BS5 applies these with a DIRECT-child selector
   (.input-group-lg > .input-group-text), which the BS4 wrapper blocks — so the
   control got 1.25rem text while the addon and button beside it stayed at 1rem.
   Silent, because the control still drives the row height, so it reads as a font
   mismatch rather than a broken layout. 169 groups in 41 views use -lg, 30 in 8
   use -sm. Deliberately placed BEFORE the radius rules below so those still win
   on the group's inner corners. */
body.ht-bs5 .input-group-lg > .input-group-prepend > .input-group-text,
body.ht-bs5 .input-group-lg > .input-group-append > .input-group-text,
body.ht-bs5 .input-group-lg > .input-group-prepend > .btn,
body.ht-bs5 .input-group-lg > .input-group-append > .btn,
body.ht-bs5 .input-group-lg > .custom-select {
    padding: .5rem 1rem; font-size: 1.25rem; border-radius: .5rem;
}
body.ht-bs5 .input-group-sm > .input-group-prepend > .input-group-text,
body.ht-bs5 .input-group-sm > .input-group-append > .input-group-text,
body.ht-bs5 .input-group-sm > .input-group-prepend > .btn,
body.ht-bs5 .input-group-sm > .input-group-append > .btn,
body.ht-bs5 .input-group-sm > .custom-select {
    padding: .25rem .5rem; font-size: .875rem; border-radius: .25rem;
}

body.ht-bs5 .input-group > .input-group-prepend > .input-group-text {
    border-top-right-radius: 0; border-bottom-right-radius: 0;
}
body.ht-bs5 .input-group > .input-group-append > .input-group-text,
body.ht-bs5 .input-group > .input-group-append > .btn {
    border-top-left-radius: 0; border-bottom-left-radius: 0;
}
body.ht-bs5 .input-group > .input-group-prepend ~ .form-control,
body.ht-bs5 .input-group > .input-group-prepend ~ .custom-select,
body.ht-bs5 .input-group > .input-group-prepend ~ .custom-file .custom-file-label {
    border-top-left-radius: 0; border-bottom-left-radius: 0;
}
body.ht-bs5 .input-group > .form-control:has(~ .input-group-append),
body.ht-bs5 .input-group > .custom-select:has(~ .input-group-append),
body.ht-bs5 .input-group > .custom-file:has(~ .input-group-append) .custom-file-label,
body.ht-bs5 .input-group > .custom-file:has(~ .input-group-append) .custom-file-label::after {
    border-top-right-radius: 0; border-bottom-right-radius: 0;
}

/* BS4 shipped a SECOND set of rules for these components for when they sit inside
   an .input-group, overriding their standalone width:100% so they behave as flex
   items. Porting only the standalone rules (as this file first did) left the 100%
   width in force, which fills the flex line and wraps every sibling addon onto its
   own row — .custom-select + .btn-block on edit_unit's "Add Pet:" group, and
   .custom-file on edit_property's document upload. BS5's own rescue rules don't
   apply because they key off .form-select / .form-control, not the BS4 class names.
   In use: custom-file in 47 views, btn-block in 53, custom-select in 19. */
body.ht-bs5 .input-group > .custom-select,
body.ht-bs5 .input-group > .input-group-prepend > .custom-select,
body.ht-bs5 .input-group > .input-group-append > .custom-select {
    flex: 1 1 auto; width: 1%; min-width: 0;
}
body.ht-bs5 .input-group > .custom-file {
    display: flex; align-items: center; flex: 1 1 auto; width: 1%; min-width: 0;
    /* height:auto lets the box stretch to the group. The standalone rule's
       calc(1.5em + ...) is derived from the INHERITED font size (14.5px under ht-ui),
       while the addons size from their own 1rem — which left the file control 3px
       short of the addon beside it. The input keeps a rem-based intrinsic height so a
       custom-file that is alone in its group still has a floor. */
    height: auto;
}
body.ht-bs5 .input-group > .custom-file .custom-file-input { height: calc(1.5rem + .75rem + 2px); }
body.ht-bs5 .input-group > .custom-file .custom-file-label,
body.ht-bs5 .input-group > .custom-file .custom-file-label::after {
    height: auto; display: flex; align-items: center;
}
body.ht-bs5 .input-group > .custom-file .custom-file-label { inset: 0; }
body.ht-bs5 .input-group > .custom-file .custom-file-label::after { inset: 0 0 0 auto; }
/* .btn-block inside a group was previously constrained by the append wrapper's own
   flex context; display:contents removed that, so neutralise it explicitly. */
body.ht-bs5 .input-group .btn-block { display: inline-block; width: auto; }
/* bootstrap-select renders a .dropdown wrapper that also defaults to full width. */
body.ht-bs5 .input-group > .bootstrap-select,
body.ht-bs5 .input-group > .input-group-prepend > .bootstrap-select,
body.ht-bs5 .input-group > .input-group-append > .bootstrap-select {
    flex: 1 1 auto; width: 1% !important; min-width: 0;
}

/* ---- Form controls ------------------------------------------------------- */
/* .custom-select -> .form-select */
body.ht-bs5 select.custom-select {
    display: block; width: 100%;
    padding: .375rem 2.25rem .375rem .75rem;
    font-size: 1rem; line-height: 1.5; color: var(--bs-body-color);
    background-color: #fff;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
    background-repeat: no-repeat; background-position: right .75rem center; background-size: 16px 12px;
    border: 1px solid #ced4da; border-radius: .375rem; appearance: none;
}
body.ht-bs5 select.custom-select-sm { padding-top: .25rem; padding-bottom: .25rem; font-size: .875rem; }
/* -lg was missed on the first pass: 20 selects carry it, several beside a .btn-lg
   addon, so without it the group's two halves are different heights. */
body.ht-bs5 select.custom-select-lg {
    padding-top: .5rem; padding-bottom: .5rem; padding-left: 1rem; font-size: 1.25rem;
}
/* .custom-control / .custom-checkbox / .custom-radio -> .form-check */
body.ht-bs5 .custom-control {
    display: block; min-height: 1.5rem; padding-left: 1.75rem; position: relative; margin-bottom: .125rem;
}
body.ht-bs5 .custom-control-inline { display: inline-flex; margin-right: 1rem; }
body.ht-bs5 .custom-control-input {
    position: absolute; left: 0; top: .2rem; width: 1rem; height: 1rem; margin: 0;
    vertical-align: top; background-color: #fff; background-repeat: no-repeat;
    background-position: center; background-size: contain;
    border: 1px solid rgba(0,0,0,.25); appearance: none; print-color-adjust: exact;
}
body.ht-bs5 .custom-checkbox .custom-control-input { border-radius: .25em; }
body.ht-bs5 .custom-radio .custom-control-input { border-radius: 50%; }
body.ht-bs5 .custom-control-input:checked {
    background-color: #0d6efd; border-color: #0d6efd;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e");
}
body.ht-bs5 .custom-control-input:focus { outline: 0; box-shadow: 0 0 0 .25rem rgba(13,110,253,.25); }
body.ht-bs5 .custom-control-label { cursor: pointer; margin-bottom: 0; }
body.ht-bs5 .custom-control-label::before,
body.ht-bs5 .custom-control-label::after { content: none; }   /* BS4 drew the box in pseudo-elements */

/* .custom-switch — BS5's equivalent is .form-switch. Without this the switch inherits the checkbox
   styling above and renders as a square box (used on condo bill approval, the condo map and the
   daily-digest report). */
body.ht-bs5 .custom-switch { padding-left: 2.5rem; }
body.ht-bs5 .custom-switch .custom-control-input {
    width: 2rem; border-radius: 2em;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");
    background-position: left center; background-repeat: no-repeat;
    transition: background-position .15s ease-in-out;
}
body.ht-bs5 .custom-switch .custom-control-input:checked {
    background-position: right center;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e");
}

/* .custom-range — BS5's equivalent is .form-range (bed/bath sliders on edit_unit, pricing tool). */
body.ht-bs5 .custom-range {
    width: 100%; height: 1.5rem; padding: 0; background: transparent; appearance: none;
}
body.ht-bs5 .custom-range:focus { outline: 0; }
body.ht-bs5 .custom-range::-webkit-slider-thumb {
    width: 1rem; height: 1rem; margin-top: -.25rem; appearance: none;
    background-color: #0d6efd; border: 0; border-radius: 1rem;
}
body.ht-bs5 .custom-range::-webkit-slider-runnable-track {
    width: 100%; height: .5rem; color: transparent; cursor: pointer;
    background-color: #dee2e6; border-color: transparent; border-radius: 1rem;
}
body.ht-bs5 .custom-range::-moz-range-thumb {
    width: 1rem; height: 1rem; background-color: #0d6efd; border: 0; border-radius: 1rem;
}
body.ht-bs5 .custom-range::-moz-range-track {
    width: 100%; height: .5rem; background-color: #dee2e6; border-radius: 1rem;
}

/* ---- Components ---------------------------------------------------------- */
/* BS5 replaced .close (with a × glyph) by .btn-close (a background image). The
   markup still carries the glyph, so style .close rather than swap it out. */
body.ht-bs5 .close {
    padding: 0; background: transparent; border: 0;
    font-size: 1.5rem; font-weight: 700; line-height: 1;
    color: #000; text-shadow: 0 1px 0 #fff; opacity: .5; cursor: pointer;
}
body.ht-bs5 .close:hover { color: #000; opacity: .85; }
body.ht-bs5 .modal-header .close { margin: -.5rem -.5rem -.5rem auto; }
body.ht-bs5 .thead-light th { background-color: #f8f9fa; }
body.ht-bs5 .thead-dark th { background-color: #212529; color: #fff; }
body.ht-bs5 .badge-pill { border-radius: 999px; }

/* ---- Components BS5 deleted outright ------------------------------------- */
/* These don't appear in Invest but are used heavily across the rest of the app:
   custom-file 271x, jumbotron 455x, btn-group-toggle 23x, card-columns 10x,
   card-deck 7x, media 12x, form-inline 11x. Ports of the BS4 rules. */

/* .custom-file — BS4 layered a styled label over a transparent file input. */
body.ht-bs5 .custom-file {
    position: relative; display: inline-block; width: 100%;
    height: calc(1.5em + .75rem + 2px); margin-bottom: 0;
}
body.ht-bs5 .custom-file-input {
    position: relative; z-index: 2; width: 100%;
    height: calc(1.5em + .75rem + 2px); margin: 0; opacity: 0;
}
body.ht-bs5 .custom-file-input:disabled ~ .custom-file-label { background-color: #e9ecef; }
body.ht-bs5 .custom-file-label {
    position: absolute; inset: 0 0 auto 0; z-index: 1;
    height: calc(1.5em + .75rem + 2px); padding: .375rem .75rem;
    overflow: hidden; font-weight: 400; line-height: 1.5; color: #495057;
    background-color: #fff; border: 1px solid #ced4da; border-radius: .25rem;
}
body.ht-bs5 .custom-file-label::after {
    position: absolute; inset: 0 0 0 auto; z-index: 3; display: block;
    height: calc(1.5em + .75rem); padding: .375rem .75rem; line-height: 1.5;
    color: #495057; content: "Browse"; background-color: #e9ecef;
    border-left: inherit; border-radius: 0 .25rem .25rem 0;
}
body.ht-bs5 .custom-file-input:focus ~ .custom-file-label {
    border-color: #86b7fe; box-shadow: 0 0 0 .25rem rgba(13,110,253,.25);
}

/* .jumbotron */
body.ht-bs5 .jumbotron {
    padding: 2rem 1rem; margin-bottom: 2rem;
    background-color: #e9ecef; border-radius: .3rem;
}
@media (min-width: 576px) { body.ht-bs5 .jumbotron { padding: 4rem 2rem; } }
body.ht-bs5 .jumbotron-fluid { padding-right: 0; padding-left: 0; border-radius: 0; }

/* .btn-group-toggle — BS4 hid the real radio/checkbox inside the button. */
body.ht-bs5 .btn-group-toggle > .btn input[type="radio"],
body.ht-bs5 .btn-group-toggle > .btn input[type="checkbox"],
body.ht-bs5 .btn-group-toggle > .btn-group > .btn input[type="radio"],
body.ht-bs5 .btn-group-toggle > .btn-group > .btn input[type="checkbox"] {
    position: absolute; clip: rect(0,0,0,0); pointer-events: none;
}

/* .card-columns (masonry) and .card-deck (equal-width row) */
body.ht-bs5 .card-columns { column-count: 1; column-gap: 1.25rem; orphans: 1; widows: 1; }
body.ht-bs5 .card-columns .card { display: inline-block; width: 100%; margin-bottom: .75rem; }
@media (min-width: 576px) { body.ht-bs5 .card-columns { column-count: 2; } }
@media (min-width: 992px) { body.ht-bs5 .card-columns { column-count: 3; } }
body.ht-bs5 .card-deck { display: flex; flex-flow: row wrap; margin-right: -15px; margin-left: -15px; }
body.ht-bs5 .card-deck .card { flex: 1 0 0%; margin-right: 15px; margin-left: 15px; }

/* .media */
body.ht-bs5 .media { display: flex; align-items: flex-start; }
body.ht-bs5 .media-body { flex: 1 1 0%; }

/* .form-inline */
body.ht-bs5 .form-inline { display: flex; flex-flow: row wrap; align-items: center; }
body.ht-bs5 .form-inline .form-control { display: inline-block; width: auto; vertical-align: middle; }
/* Same omission as the input-group set: BS4 also un-stretched these inside a
   .form-inline, and only .form-control was ported on the first pass. */
body.ht-bs5 .form-inline .custom-select { width: auto; }
body.ht-bs5 .form-inline .input-group { width: auto; }
body.ht-bs5 .form-inline label { display: flex; align-items: center; margin-bottom: 0; }
body.ht-bs5 .form-inline .custom-control { align-items: center; justify-content: center; }
/* BS5 badges have no default colour; the Hometime layer defines .badge-* itself
   (see ht-ui.css) so no bg-* rename is needed anywhere in the markup. */
