/* ═══════════════════════════════════════════════════════════════════════
   Portal select — Tom Select in the portal's clothes.

   Replaces the bootstrap-select theming that used to live in
   portal-components.css. Loaded globally by base.twig, AFTER the vendored
   tom-select.bootstrap5.min.css it overrides.

   Tom Select's Bootstrap 5 theme is already driven by --bs-* variables, so
   most of the light-mode treatment arrives for free from data-bs-theme. What
   is written here is the portal layer the vendor cannot know about: the
   --portal-c-* token palette, the liquid-glass overlay treatment on the
   dropdown, and the accent tint on the selected row.

   Selector convention matches the rest of portal-components.css:
   `body:has(.portal-page-themed[data-bs-theme="…"])`. The dropdown is
   included by descent from body, which matters because a select carrying
   data-container="body" renders its dropdown outside .portal-page-themed —
   scoping to the page wrapper would leave exactly those unstyled.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Control (the closed dropdown) ──────────────────────────────────── */

.portal-page-themed .ts-control,
body:has(.portal-page-themed) .ts-wrapper .ts-control {
    background-color: var(--portal-c-surface);
    border-color: var(--portal-c-edge-control);
    color: var(--portal-c-text);
}

/* Height. A select spends its life on a filter bar between a search field and
   a button, so it has to be exactly as tall as they are: --portal-control-h,
   the shared control height, rather than the 2.375rem/38px this carried —
   Bootstrap's full-size field height, which was the right thing to match
   before the fields themselves came to the token (portal-components.css).

   BOTH boxes, because Tom Select is two nested elements: the vendor stands
   .ts-wrapper up with `display:flex; min-height:calc(1.5em + .75rem + 2px)`
   and the control stretches to fill it, so a min-height on the control alone
   is a no-op — as is the padding, since the vendor's 6px against a 24px line
   box already reaches 38 on its own. 5px is what puts it on 36.

   The wrapper's padding is zeroed on purpose. Tom Select copies the original
   <select>'s classes onto the wrapper, so a `form-select-sm` select hands the
   WRAPPER the small-field padding meant for a field's own text — which here
   would inset the control inside it instead. */
.portal-page-themed .ts-wrapper,
body:has(.portal-page-themed) .ts-wrapper {
    min-height: var(--portal-control-h);
    padding-top: 0;
    padding-bottom: 0;
}

.portal-page-themed .ts-control,
body:has(.portal-page-themed) .ts-wrapper .ts-control {
    min-height: var(--portal-control-h);
    padding-top: 0.3125rem;
    padding-bottom: 0.3125rem;
}

/* Same 44px touch floor the buttons and fields take on a coarse pointer. */
@media (pointer: coarse) {
    .portal-page-themed .ts-wrapper,
    body:has(.portal-page-themed) .ts-wrapper,
    .portal-page-themed .ts-control,
    body:has(.portal-page-themed) .ts-wrapper .ts-control {
        min-height: 2.75rem;
    }
}

body:has(.portal-page-themed) .ts-wrapper:not(.disabled) .ts-control:hover {
    background-color: var(--portal-c-btn-outline-hover-bg);
    border-color: var(--portal-c-btn-outline-hover-border, var(--portal-c-border));
}

/* focus-within, not :focus — the focusable node is the inner input, so a
   :focus rule on .ts-control never fires on a searchable select. */
body:has(.portal-page-themed) .ts-wrapper.focus .ts-control,
body:has(.portal-page-themed) .ts-control:focus-within {
    outline: none;
    box-shadow: var(--portal-c-focus-ring);
    border-color: var(--portal-c-accent-border);
}

body:has(.portal-page-themed) .ts-control > input,
body:has(.portal-page-themed) .ts-control > .item {
    color: var(--portal-c-text);
}

body:has(.portal-page-themed) .ts-control > input::placeholder {
    color: var(--portal-c-text-muted);
}

/* The caret. Tom Select draws it as a bordered triangle, same as Bootstrap. */
body:has(.portal-page-themed) .ts-wrapper.single .ts-control:after {
    border-top-color: var(--portal-c-text-muted);
}

/* ── Dropdown (the open menu) — glass, like every other portal overlay ─ */

body:has(.portal-page-themed) .ts-dropdown {
    background-color: var(--portal-c-overlay);
    border-color: var(--portal-c-border);
    /* A menu, so it takes the menu tier — Tom Select ships its own radius and
       was landing on the 6px CONTROL tier next to .dropdown-menu's 10px.
       Found by auditing every overlay's computed radius against the scale
       after the same bug turned up on .card. */
    border-radius: var(--bs-border-radius-lg);
    box-shadow: var(--portal-c-edge-card), var(--portal-c-elev-overlay);
    backdrop-filter: var(--portal-blur-overlay);
    -webkit-backdrop-filter: var(--portal-blur-overlay);
    color: var(--portal-c-text);
    margin-top: 0.25rem;
}

/* data-size rows → dropdown height, set per instance by portal-select.js.
   Falls back to Tom Select's own max-height when the properties are absent. */
body:has(.portal-page-themed) .ts-dropdown .ts-dropdown-content {
    max-height: calc(var(--portal-select-rows, 8) * var(--portal-select-row-h, 2.25rem));
}

body:has(.portal-page-themed) .ts-dropdown .option {
    color: var(--portal-c-text);
}

/* .active is Tom Select's keyboard/hover cursor — the row you are ON. */
body:has(.portal-page-themed) .ts-dropdown .option.active {
    background-color: var(--portal-c-row-hover);
    color: var(--portal-c-text);
}

/* .selected is the row already chosen. Accent treatment, matching the way
   the portal marks a current item everywhere else (toc links, active nav). */
body:has(.portal-page-themed) .ts-dropdown .option.selected {
    background-color: var(--portal-c-accent-muted);
    color: var(--portal-c-accent);
}

body:has(.portal-page-themed) .ts-dropdown .option.selected.active {
    background-color: var(--portal-c-accent-muted);
    color: var(--portal-c-accent);
    filter: brightness(1.15);
}

body:has(.portal-page-themed) .ts-dropdown .no-results,
body:has(.portal-page-themed) .ts-dropdown .optgroup-header {
    background-color: transparent;
    color: var(--portal-c-text-muted);
}

/* ── Search box inside the dropdown ─────────────────────────────────── */

body:has(.portal-page-themed) .ts-dropdown .dropdown-input-wrap {
    padding: 0.5rem;
    border-bottom: 1px solid var(--portal-c-border-subtle);
}

body:has(.portal-page-themed) .ts-dropdown .dropdown-input {
    background-color: var(--portal-c-input-bg);
    border: 1px solid var(--portal-c-border-subtle);
    border-radius: var(--bs-border-radius, 0.375rem);
    color: var(--portal-c-text);
    padding: 0.35rem 0.6rem;
}

body:has(.portal-page-themed) .ts-dropdown .dropdown-input::placeholder {
    color: var(--portal-c-text-muted);
}

/* Focus ring on the search box.
 *
 * Keyed off .focus on the WRAPPER, not :focus on the input — Tom Select moves
 * focus around internally and the input does not reliably match :focus even
 * while the user is typing in it (verified in-browser: activeElement was the
 * input while :focus did not match). The wrapper class is Tom Select's own
 * source of truth, which is why the vendor sheet uses it too; this must
 * out-specify that rule or the ring stays Bootstrap blue. */
body:has(.portal-page-themed) .ts-wrapper.plugin-dropdown_input.focus .ts-dropdown .dropdown-input {
    outline: 0;
    border-color: var(--portal-c-accent-border);
    box-shadow: 0 0 0 0.15rem var(--portal-c-accent-muted);
}

/* ── Multi-select pills ─────────────────────────────────────────────── */

body:has(.portal-page-themed) .ts-wrapper.multi .ts-control > div {
    background-color: var(--portal-c-accent-muted);
    color: var(--portal-c-accent);
    border: 1px solid var(--portal-c-accent-border);
    border-radius: var(--bs-border-radius-sm, 0.25rem);
}

body:has(.portal-page-themed) .ts-wrapper.multi .ts-control > div .remove {
    border-left-color: var(--portal-c-accent-border);
    color: inherit;
}

body:has(.portal-page-themed) .ts-wrapper.multi .ts-control > div .remove:hover {
    background-color: var(--portal-c-accent-muted);
    filter: brightness(1.3);
}

/* ── Select all / Deselect all (portal-select.js addActionsBox) ─────── */

.portal-select-actions {
    display: flex;
    gap: 0.25rem;
    padding: 0.35rem 0.5rem;
    border-bottom: 1px solid var(--portal-c-border-subtle);
}

.portal-select-actions .btn-link {
    padding: 0 0.35rem;
    font-size: var(--portal-text-sm);
    text-decoration: none;
    color: var(--portal-c-accent);
}

.portal-select-actions .btn-link:hover {
    text-decoration: underline;
}

/* ── Disabled ───────────────────────────────────────────────────────── */

body:has(.portal-page-themed) .ts-wrapper.disabled .ts-control {
    background-color: var(--portal-c-surface);
    border-color: var(--portal-c-border-subtle);
    color: var(--portal-c-text-muted);
    opacity: 0.65;
}

/* ── Degrade gate ────────────────────────────────────────────────────
   Same contract as the rest of the kit: where backdrop-filter is missing
   the overlay must go fully opaque rather than render as a translucent
   smear over live content. Mirrors the gates at the end of
   portal-components.css. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    body:has(.portal-page-themed) .ts-dropdown {
        background-color: var(--portal-c-surface);
    }
}
