/**
 * Custom select (ui-select) — shared by every FT tools frontend.
 *
 * Pairs with ui-select.js: the native <select> stays in the DOM as the
 * value source (transparent, pointer-events: none) so existing JS and
 * tests keep working; a styled trigger + popup overlay provide the
 * visible UI, type-ahead, and keyboard navigation.
 *
 * Lives in the shared lib rather than each app's styles.css so the two
 * apps cannot drift into two different-looking dropdowns — which is the
 * whole point of having the widget.
 *
 * Every value here is a design token, so each app keeps its own theme.
 */
/* A flex item's automatic minimum is its max-content width, so without
   these the trigger refuses to shrink and pushes the page sideways — a
   long image tag, or Harbor's error string, measured 479px inside a 322px
   row and overflowed the document by 134px at 390px wide. The value span
   already asks for an ellipsis; this is what lets it engage. */
.ui-select { position: relative; min-width: 0; max-width: 100%; }
.ui-select > select {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    pointer-events: none;
}
/* The disabled VISUAL lives on the trigger; keep the value-holder fully
   hidden even when disabled. Otherwise `.form-group select:disabled`
   (opacity:0.6) out-specifies the rule above and the native control —
   its text + chevron — bleeds through the trigger. */
.ui-select > select:disabled {
    opacity: 0;
}
/* THE ONE PLACE THE METRICS OF A FORM CONTROL LIVE.
 *
 * `--ui-control-pad` / `--ui-control-font` exist because this trigger
 * stands beside an app's own `<input>`s and has to be the same height as
 * them — and it was not. Measured 2026-09-06 in Deployment Manager: an
 * input 34px tall next to a trigger 40.6px, a 6.6px step the eye reads
 * as a misalignment in a row of filters. cicd-manager and env-manager
 * had no such gap, because their inputs are `10px 14px / 0.95rem` — the
 * literals that used to be written here.
 *
 * So the defaults ARE those literals, and nothing changes for an app
 * that does not set them. An app whose controls are smaller sets the two
 * variables once, and its inputs and its dropdowns then agree by
 * construction rather than by two files being edited to match. */
.ui-select-trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    width: 100%;
    padding: var(--ui-control-pad, 10px 14px);
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    background: var(--bg-primary);
    color: var(--text-primary);
    font-family: inherit;
    font-size: var(--ui-control-font, 0.95rem);
    line-height: 1.4;
    cursor: pointer;
    text-align: left;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.ui-select-trigger:hover:not(:disabled) { border-color: var(--border-strong); }
.ui-select.open .ui-select-trigger,
.ui-select-trigger:focus-visible {
    outline: none;
    border-color: var(--accent-primary);
    box-shadow: 0 0 0 3px var(--accent-ring);
}
.ui-select-trigger:disabled {
    background: var(--surface-sunken);
    opacity: 0.6;
    cursor: not-allowed;
}
.ui-select-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-select-trigger.is-placeholder .ui-select-value { color: var(--text-muted); }
.ui-select-caret {
    flex: 0 0 auto;
    display: inline-flex;
    color: var(--text-muted);
    transition: transform var(--transition);
}
.ui-select.open .ui-select-caret { transform: rotate(180deg); }

.ui-select-popup {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    /* The list may be WIDER than the trigger. Pinned to both edges it was
       exactly the trigger's width, which was survivable while the trigger
       sat at its content width and became unreadable once it was allowed to
       shrink — a Harbor tag list rendered as `6.4.10_…`, `6.4.13_…`, one
       ellipsis per row, with nothing to tell the rows apart. Capped against
       the viewport so a long option cannot scroll the page sideways. */
    right: auto;
    min-width: 100%;
    width: max-content;
    max-width: min(26rem, calc(100vw - 2rem));
    z-index: 60;
    display: flex;
    flex-direction: column;
    max-height: 290px;
    padding: 4px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    box-shadow: var(--shadow-hover);
}
.ui-select-popup[hidden] { display: none; }
.ui-select-popup:focus { outline: none; }
.ui-select-group {
    padding: 12px 10px 6px;
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}
.ui-select-group:not(:first-child) {
    margin-top: 6px;
    border-top: 1px solid var(--border-color);
    padding-top: 12px;
}
.ui-select-list { overflow-y: auto; }
.ui-select-option {
    padding: 9px 10px;
    border-radius: 6px;
    font-size: 0.9rem;
    color: var(--text-primary);
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Hover (mouse) and active (keyboard) share a clear highlight */
.ui-select-option:hover,
.ui-select-option.active {
    background: var(--surface-interactive);
    color: var(--text-primary);
}
.ui-select-option[aria-selected="true"] {
    background: var(--accent-tint);
    color: var(--accent-text);
    font-weight: 600;
}
.ui-select-option[aria-selected="true"]:hover,
.ui-select-option[aria-selected="true"].active {
    background: var(--accent-tint-strong);
    color: var(--accent-text);
}
.ui-select-empty {
    padding: 12px;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.9rem;
}

/* The filter box, present only on lists long enough to need one. Sticky so
   it stays reachable while the list scrolls under it. */
.ui-select-search {
    position: sticky;
    top: 0;
    z-index: 1;
    margin: 0 0 4px;
    padding: 8px 10px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    background: var(--bg-input);
    color: var(--text-primary);
    font-family: inherit;
    font-size: 0.9rem;
}
.ui-select-search:focus-visible {
    outline: none;
    border-color: var(--accent-primary);
    box-shadow: 0 0 0 3px var(--accent-ring);
}
.ui-select-option[hidden],
.ui-select-group[hidden],
.ui-select-empty[hidden] { display: none; }
