/*
 * Application-wide combobox skin (TomSelect v2.6.2).
 *
 * Companion to public/assets/js/aiz-combobox.js, which upgrades every <select>
 * in the app into an editable combobox with list autocomplete.
 *
 * This file carries TomSelect's structural rules as well as the theme, on
 * purpose. The build shipped with the Virtual Office template is the Bootstrap
 * 5 one and resolves against --bs-* custom properties, which do not exist in
 * the admin and seller panels. Owning the structure keeps the control looking
 * and behaving identically in every portal regardless of which Bootstrap the
 * page is on.
 *
 * Colours are driven by tokens so dark mode is a token swap. Portals signal
 * dark differently — `body.dark` (Virtual Office / Cork), `html.dark`, and
 * `[data-theme="dark"]` — so all three are honoured.
 */

:root {
    --cbx-accent: #6366f1;
    --cbx-accent-strong: #4f46e5;
    --cbx-accent-soft: rgba(99, 102, 241, 0.12);
    --cbx-ring: rgba(99, 102, 241, 0.22);

    --cbx-field: #ffffff;
    --cbx-field-hover: #ffffff;
    --cbx-border: rgba(100, 116, 139, 0.3);
    --cbx-border-strong: rgba(99, 102, 241, 0.65);
    --cbx-text: #0f172a;
    --cbx-muted: #64748b;

    --cbx-pop: #ffffff;
    --cbx-pop-border: rgba(100, 116, 139, 0.18);
    --cbx-hover: rgba(99, 102, 241, 0.1);
    --cbx-selected: rgba(99, 102, 241, 0.16);
    --cbx-shadow: 0 20px 44px -16px rgba(15, 23, 42, 0.32), 0 0 0 1px rgba(15, 23, 42, 0.04);

    /*
     * The card colour sitting behind a field. Only used to notch a floating
     * label out of the field's border. A screen whose cards are a different
     * colour retunes this token for its own scope rather than restating the
     * rule.
     */
    --cbx-surface: #ffffff;

    --cbx-radius: 10px;
    --cbx-height: 44px;
}

body.dark,
html.dark,
html.dark body,
[data-theme="dark"] {
    --cbx-field: rgba(15, 23, 42, 0.6);
    --cbx-field-hover: rgba(15, 23, 42, 0.78);
    --cbx-border: rgba(148, 163, 184, 0.26);
    --cbx-border-strong: rgba(129, 140, 248, 0.8);
    --cbx-text: #e2e8f0;
    --cbx-muted: rgba(226, 232, 240, 0.55);

    --cbx-pop: #131c2f;
    --cbx-pop-border: rgba(148, 163, 184, 0.2);
    --cbx-hover: rgba(99, 102, 241, 0.2);
    --cbx-selected: rgba(99, 102, 241, 0.28);
    --cbx-shadow: 0 22px 48px -14px rgba(0, 0, 0, 0.75), 0 0 0 1px rgba(148, 163, 184, 0.08);

    /* The Virtual Office dark card colour. */
    --cbx-surface: #1b1d25;
}

/* ------------------------------------------------------------------ */
/* Structure                                                           */
/* ------------------------------------------------------------------ */

/*
 * TomSelect moves the original <select> aside and marks it with this class.
 * Without a rule for it the native control stays on screen next to the new
 * one, so this is load-bearing rather than cosmetic.
 *
 * Deliberately visually-hidden rather than display:none. 107 selects in this
 * app are `required`, and a required control that is not rendered cannot be
 * focused, which makes the browser refuse to submit the form with no visible
 * explanation. It also keeps its static position inside the wrapper so the
 * native validation bubble still points at the field.
 */
.ts-hidden-accessible {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0 0 0 0) !important;
    clip-path: inset(50%) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

.ts-wrapper {
    position: relative;
    display: block;
    width: 100%;
    /* The app has Bootstrap 4 and 5 pages; neither should size this. */
    padding: 0 !important;
    border: 0 !important;
    background: none !important;
    background-image: none !important;
    box-shadow: none !important;
    height: auto !important;
}

.ts-wrapper .ts-control {
    position: relative;
    z-index: 1;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    box-sizing: border-box;
    width: 100%;
    min-height: var(--cbx-height);
    padding: 0.5rem 2.25rem 0.5rem 0.85rem;
    border: 1px solid var(--cbx-border);
    border-radius: var(--cbx-radius);
    background: var(--cbx-field);
    color: var(--cbx-text);
    font-size: 0.9rem;
    line-height: 1.4;
    cursor: text;
    transition: border-color 0.18s ease, box-shadow 0.18s ease, background-color 0.18s ease;
}

.ts-wrapper.single .ts-control,
.ts-wrapper.single .ts-control input {
    cursor: pointer;
}

.ts-wrapper .ts-control > input {
    flex: 1 1 auto;
    min-width: 7ch;
    max-width: 100%;
    margin: 0 !important;
    padding: 0 !important;
    border: 0 !important;
    outline: none !important;
    background: none !important;
    box-shadow: none !important;
    color: inherit;
    font: inherit;
    line-height: inherit;
}

.ts-wrapper .ts-control > input::placeholder {
    color: var(--cbx-muted);
}

.ts-wrapper .ts-control > input:disabled {
    background: none !important;
}

/*
 * A single-value combobox keeps its typing input in the control alongside the
 * chosen item, and TomSelect expects the theme to take that input out of view
 * once something is selected — it only toggles `input-hidden` on the wrapper
 * and leaves the placeholder attribute in place.
 *
 * Without this rule the placeholder is painted straight over the selected
 * value: "Select Account Type" on top of "Bronze (Trial)". It reads as an
 * empty field, which is how the Edit Membership Pack dropdowns still looked
 * after they were correctly filled.
 *
 * Kept off-canvas rather than display:none so the control stays focusable and
 * typing to search still works.
 */
.ts-wrapper.input-hidden .ts-control > input {
    position: absolute;
    left: -10000px;
    width: 1px;
    opacity: 0;
}

/* The caret. Drawn here so it survives Bootstrap's own .form-select chevron
   being stripped off the wrapper above. */
.ts-wrapper::after {
    content: "";
    position: absolute;
    top: 50%;
    right: 0.9rem;
    width: 9px;
    height: 9px;
    margin-top: -6px;
    border-right: 2px solid var(--cbx-muted);
    border-bottom: 2px solid var(--cbx-muted);
    transform: rotate(45deg);
    transform-origin: center;
    pointer-events: none;
    transition: transform 0.2s ease, border-color 0.2s ease;
}

.ts-wrapper.dropdown-active::after {
    margin-top: -2px;
    border-color: var(--cbx-accent);
    transform: rotate(-135deg);
}

/* ------------------------------------------------------------------ */
/* States                                                              */
/* ------------------------------------------------------------------ */

.ts-wrapper:not(.disabled) .ts-control:hover {
    border-color: rgba(99, 102, 241, 0.45);
    background: var(--cbx-field-hover);
}

.ts-wrapper.focus .ts-control,
.ts-wrapper.dropdown-active .ts-control {
    border-color: var(--cbx-border-strong);
    box-shadow: 0 0 0 0.2rem var(--cbx-ring);
}

.ts-wrapper.disabled .ts-control,
.ts-wrapper.disabled .ts-control * {
    cursor: not-allowed !important;
}

.ts-wrapper.disabled .ts-control {
    opacity: 0.55;
}

/* `invalid` is TomSelect's own state class; `is-invalid` comes from Bootstrap
   server-side validation classes copied onto the wrapper from the select. */
.ts-wrapper.invalid .ts-control,
.ts-wrapper.is-invalid .ts-control {
    border-color: #ef4444;
}

.ts-wrapper.invalid.focus .ts-control,
.ts-wrapper.is-invalid.focus .ts-control {
    box-shadow: 0 0 0 0.2rem rgba(239, 68, 68, 0.22);
}

/* ------------------------------------------------------------------ */
/* Selected values                                                     */
/* ------------------------------------------------------------------ */

.ts-wrapper.single .ts-control > .item {
    color: var(--cbx-text);
}

.ts-wrapper.multi .ts-control > .item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    padding: 3px 9px;
    border: 1px solid rgba(99, 102, 241, 0.35);
    border-radius: 999px;
    background: var(--cbx-accent-soft);
    color: var(--cbx-text);
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.5;
}

.ts-wrapper.multi .ts-control > .item.active {
    border-color: var(--cbx-accent);
    background: var(--cbx-selected);
}

.ts-wrapper.plugin-remove_button .item .remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(99, 102, 241, 0.22);
    color: inherit;
    font-size: 12px;
    line-height: 1;
    text-decoration: none;
    opacity: 0.8;
    transition: background-color 0.15s ease, opacity 0.15s ease;
}

.ts-wrapper.plugin-remove_button .item .remove:hover {
    background: #ef4444;
    color: #fff;
    opacity: 1;
}

/* ------------------------------------------------------------------ */
/* Clear affordance                                                    */
/* ------------------------------------------------------------------ */

/*
 * A blank leading <option> is treated as a placeholder rather than a value,
 * so an optional field needs another way back to "nothing selected" — an
 * admin filter that cannot be reset to "All" would be a regression. The
 * combobox layer adds this button to every non-required select; it only
 * earns its space once there is something to clear.
 */
.ts-wrapper .clear-button {
    position: absolute;
    top: 50%;
    right: 2.1rem;
    display: none;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    margin-top: -9px;
    border-radius: 50%;
    background: rgba(148, 163, 184, 0.2);
    color: var(--cbx-muted);
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.ts-wrapper.has-items .clear-button {
    display: flex;
}

.ts-wrapper .clear-button:hover {
    background: #ef4444;
    color: #fff;
}

.ts-wrapper.has-items .ts-control:has(.clear-button) {
    padding-right: 3.5rem;
}

.ts-wrapper.disabled .clear-button {
    display: none;
}

/* ------------------------------------------------------------------ */
/* Dropdown                                                            */
/* ------------------------------------------------------------------ */

.ts-dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 1080;
    box-sizing: border-box;
    width: 100%;
    margin: 6px 0 0;
    padding: 5px;
    border: 1px solid var(--cbx-pop-border);
    border-radius: 12px;
    background: var(--cbx-pop);
    color: var(--cbx-text);
    box-shadow: var(--cbx-shadow);
}

.ts-dropdown .ts-dropdown-content {
    max-height: 260px;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
}

.ts-dropdown .ts-dropdown-content::-webkit-scrollbar {
    width: 8px;
}

.ts-dropdown .ts-dropdown-content::-webkit-scrollbar-thumb {
    border: 2px solid transparent;
    border-radius: 8px;
    background-clip: content-box;
    background-color: rgba(148, 163, 184, 0.5);
}

.ts-dropdown .option {
    padding: 0.5rem 0.65rem;
    border-radius: 8px;
    color: var(--cbx-text);
    font-size: 0.875rem;
    line-height: 1.45;
    cursor: pointer;
    transition: background-color 0.12s ease;
}

.ts-dropdown .option.active {
    background: var(--cbx-hover);
    color: var(--cbx-text);
}

.ts-dropdown .option.selected {
    background: var(--cbx-selected);
    font-weight: 600;
}

.ts-dropdown .option[data-selectable].disabled,
.ts-dropdown .option:not([data-selectable]) {
    opacity: 0.45;
    cursor: default;
}

.ts-dropdown .optgroup-header {
    padding: 0.5rem 0.65rem 0.3rem;
    color: var(--cbx-muted);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.ts-dropdown .optgroup + .optgroup {
    border-top: 1px solid var(--cbx-pop-border);
    margin-top: 4px;
    padding-top: 4px;
}

.ts-dropdown .no-results,
.ts-dropdown .create {
    padding: 0.6rem 0.65rem;
    color: var(--cbx-muted);
    font-size: 0.85rem;
}

.ts-dropdown .create {
    color: var(--cbx-accent);
    cursor: pointer;
}

/* The matched substring, highlighted as you type. */
.ts-dropdown .highlight {
    padding: 0 1px;
    border-radius: 3px;
    background: rgba(250, 204, 21, 0.35);
    color: inherit;
}

body.dark .ts-dropdown .highlight,
html.dark .ts-dropdown .highlight {
    background: rgba(250, 204, 21, 0.28);
}

/* Dropped upward when there is no room below. */
.ts-wrapper.dropdown-active .ts-dropdown.ts-dropdown-above,
.ts-dropdown[style*="bottom"] {
    top: auto;
    bottom: 100%;
    margin: 0 0 6px;
}

/* ------------------------------------------------------------------ */
/* Field titles must stay readable                                     */
/* ------------------------------------------------------------------ */

/*
 * Floating labels straddle the field's top border and rely on painting after
 * the control. TomSelect gives .ts-control `z-index: 1` while the label is
 * `z-index: auto`, so the control won regardless of DOM order — and with an
 * opaque field background it covered the label's lower half, slicing the title
 * text in two.
 *
 * The label is lifted above the control and given the surface colour behind
 * it, which is the notched-outline treatment these themes already use. Only
 * labels that actually sit over a combobox are touched; the ones over plain
 * inputs already paint correctly.
 *
 * Forced, because several screens define their own float label at the same
 * specificity and load after this file — a tie the page would win, putting the
 * sliced title back. The colour stays a token so a screen with differently
 * coloured cards retunes --cbx-surface instead of restating the rule.
 */
.form-float:has(.ts-wrapper) > label,
.form-floating:has(.ts-wrapper) > label,
.floating-label:has(.ts-wrapper) > label {
    z-index: 2 !important;
    padding: 0 6px !important;
    border-radius: 4px;
    background: var(--cbx-surface) !important;
    line-height: 1.55;
}

.form-float:has(.ts-wrapper) > label {
    top: -10px !important;
}

/*
 * Fallback for browsers without :has(). Without it the title would be covered
 * again, so the control is made to yield instead of the label being raised.
 */
@supports not selector(:has(*)) {
    .form-float > label,
    .form-floating > label,
    .floating-label > label {
        z-index: 2;
    }

    .form-float .ts-control,
    .form-floating .ts-control,
    .floating-label .ts-control {
        z-index: 0;
    }
}

/* Labels rendered above the field, which is the admin and seller pattern. */
.form-group > .ts-wrapper,
.form-group > .ts-wrapper + .ts-dropdown {
    margin-top: 0;
}

/* ------------------------------------------------------------------ */
/* Containers that clip                                                */
/* ------------------------------------------------------------------ */

/*
 * Deliberately nothing here.
 *
 * The popup is rendered inside the wrapper, so a scrolling ancestor clips it.
 * The tempting fix — forcing `overflow: visible` on any .modal-body,
 * .offcanvas-body or .table-responsive that contains a combobox — takes the
 * scroll away from the container, and those containers scroll for a reason:
 *
 *   - Bootstrap only sets overflow-y on .modal-body inside a
 *     .modal-dialog-scrollable dialog, so the override does nothing for an
 *     ordinary modal and silently breaks a scrollable one. That is what
 *     stopped the KYC wizard scrolling, since its body carries the ID type
 *     and address selects.
 *   - .offcanvas-body scrolls by default, so the same applies there.
 *   - TomSelect keeps the dropdown element in the DOM while it is closed, so
 *     :has(.ts-dropdown) matches permanently and would have removed the
 *     horizontal scroll from every data table with a filter dropdown.
 *
 * A popup that scrolls with its container is the predictable behaviour, and
 * the list is capped at 260px so there is little to clip.
 */

/* ------------------------------------------------------------------ */
/* Density variants                                                    */
/* ------------------------------------------------------------------ */

/* Filter bars and table toolbars use the small control. */
.form-control-sm + .ts-wrapper .ts-control,
.ts-wrapper.form-control-sm .ts-control,
.ts-wrapper.form-select-sm .ts-control {
    min-height: 36px;
    padding: 0.3rem 2rem 0.3rem 0.65rem;
    font-size: 0.8rem;
}

.ts-wrapper.form-control-lg .ts-control,
.ts-wrapper.form-select-lg .ts-control {
    min-height: 52px;
    font-size: 1rem;
}

/* Inside an input-group the combobox has to square off its joined edge. */
.input-group > .ts-wrapper {
    flex: 1 1 auto;
    width: 1%;
}

.input-group > .ts-wrapper:not(:last-child) .ts-control {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

.input-group > .ts-wrapper:not(:first-child) .ts-control {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}

@media (prefers-reduced-motion: reduce) {
    .ts-wrapper .ts-control,
    .ts-wrapper::after,
    .ts-dropdown .option {
        transition: none;
    }
}
