/*
 * Styling for the searchable dropdown built by core/select_search.js
 * (components/select.html with searchable=True).
 *
 * Plain CSS, not Tailwind, on purpose: the `@source` globs at the bottom of
 * theme/static_src/src/styles.css only reach .html files under a templates
 * directory, so any utility class that exists solely inside a .js file is never
 * generated. The collapsed control is the one exception — the trigger <input>
 * reuses the <select>'s own className, which IS written in the template, so
 * those utilities do get generated (the same trick core/date_field.js relies on
 * for flatpickr's altInput).
 *
 * Never write a glob pattern into a comment in this file. A doubled asterisk
 * followed by a slash ends with the same two characters that close a CSS
 * comment, so the parser leaves the comment early, reads the rest of the
 * paragraph as a selector, and drops every rule up to the next opening brace.
 * That is exactly how this file once shipped with none of its styling applied.
 *
 * Colors come from the @theme custom properties in styles.css (--color-border,
 * --color-info, ...), with literal fallbacks so the popover still looks right if
 * this file is ever loaded before the Tailwind bundle.
 *
 * These rules are unlayered, so they win over Tailwind v4's layered utilities
 * regardless of specificity — which is what lets `select.select-search-native`
 * below shrink a <select> that still carries `w-full`.
 */

/*
 * Anchors the 1px <select> below. Without it the absolutely-positioned select
 * escapes to the initial containing block, and a `required` field's validation
 * bubble would pop up at the top-left corner of the page instead of next to the
 * control the user has to fix.
 */
[data-select-search] {
    position: relative;
}

/*
 * The native <select> is kept in the DOM (it posts the value, page JS reads and
 * writes .value, and its inline onchange still runs) but taken out of sight.
 * Deliberately NOT display:none / visibility:hidden: a `required` select that is
 * fully hidden makes the browser abort submit with "not focusable" instead of
 * showing its validation bubble. opacity:0 on a 1px box stays focusable and
 * validatable, and the bubble points at the right spot.
 */
select.select-search-native {
    position: absolute;
    left: 0;
    top: 0;
    /* !important, not specificity: the `min_width` param puts its value in an
       inline style attribute, which no selector can outrank. Left at its full
       width this 1px-tall box would still widen the scrollWidth of an
       overflow-auto ancestor and hand a toolbar a phantom horizontal scrollbar. */
    width: 1px !important;
    height: 1px !important;
    min-width: 0 !important;
    margin: 0;
    padding: 0;
    border: 0;
    opacity: 0;
    pointer-events: none;
}

/* --- collapsed control ------------------------------------------------- */

/*
 * The collapsed control is a real <input>: the user types the filter straight
 * into it, so it must keep looking like the <select> it replaced. It inherits
 * every Tailwind class the caller put on that <select> (border, radius, bg, h-8,
 * disabled: variants...); only the chevron the native control used to draw for
 * itself is added back here. That chevron is a background-image, not an ::after
 * — the copied `truncate` class puts overflow:hidden + ellipsis on this element,
 * which would clip a real child but leaves a background alone (and an <input>
 * cannot host pseudo-element children at all).
 */
.select-search-trigger {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%23666' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 8px center;
    background-size: 10px 7px;
}

.select-search-trigger:disabled {
    cursor: not-allowed;
}

.select-search-trigger:focus {
    outline: none;
    border-color: var(--color-info, #185fa5);
    box-shadow: 0 0 0 2px rgba(24, 95, 165, 0.15);
}

/* Reads as a hint, matching the greyed placeholder <option> it stands in for. */
.select-search-trigger::placeholder {
    color: var(--color-text-3, #999);
}

/*
 * Opt-in via components/select.html's `wrap_button` param (data-wrap-button on
 * the wrapper): the trigger core/select_search.js builds for this mode is a
 * <button>, not the <input> above, so it still gets the shared
 * .select-search-trigger rules (chevron, focus ring) but needs its own reset
 * on top — a bare <button> centers text and, via the copied `truncate`
 * utility class (unavoidable: the button's className is the <select>'s own,
 * see build()'s comment on why), clips it to one line with an ellipsis. Both
 * are undone here the same way `.select-search-panel--wrap` above undoes
 * `truncate` on an option row: plain, unlayered CSS beats a layered Tailwind
 * utility regardless of specificity (see this file's header comment).
 */
.select-search-trigger--button {
    display: block;
    width: 100%;
    text-align: left;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    word-break: break-word;
    cursor: pointer;
    appearance: none;
}

/* --- popover ----------------------------------------------------------- */

/*
 * position:fixed and appended to <body>, not absolutely positioned next to the
 * trigger: every screen using this sits inside a clipping ancestor (the item
 * master editor is a `fixed inset-0 z-[999]` overlay with its own overflow-y
 * scroller, the list filters sit in an overflow-auto pane), and an in-flow
 * popover would be cut off by them. z-index clears that 999 overlay.
 * Coordinates are recomputed by the script on open, scroll and resize.
 */
.select-search-panel {
    position: fixed;
    z-index: 1200;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border: 1px solid var(--color-border-2, #ccc);
    border-radius: 6px;
    background: #fff;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
    font-size: 13px;
    color: var(--color-text, #1a1a1a);
}

/* [hidden] alone loses to display:flex above. */
.select-search-panel[hidden] {
    display: none;
}

.select-search-list {
    /* Positioned so it — not the fixed .select-search-panel — is the rows'
       offsetParent: the script scrolls the active row into view from
       li.offsetTop, which has to be measured in the coordinate space of the box
       whose scrollTop it then sets, or every keyboard step lands off by the
       panel's own border and padding. */
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* Declares this element's only native gesture as vertical panning, so the
       browser commits to a scroll on the first touch move instead of holding
       the pointer back to see if a double-tap-zoom/pinch is coming — that
       hesitation is what starved select_search.js's tap/drag split of the
       pointermove frames it needs to tell a scroll from a tap. */
    touch-action: pan-y;
    -webkit-overflow-scrolling: touch;
    margin: 0;
    padding: 4px;
    list-style: none;
}

.select-search-option {
    display: flex;
    align-items: center;
    min-height: 32px;
    padding: 6px 10px;
    border-radius: 4px;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/*
 * Opt-in via components/select.html's `wrap_options` param (data-wrap-options on
 * the wrapper, read by core/select_search.js as a modifier class on the panel):
 * lets a long option label wrap onto multiple lines instead of the single-line
 * ellipsis above. Scoped to this modifier class only — every other searchable
 * dropdown in the project keeps .select-search-option's nowrap/ellipsis look.
 */
.select-search-panel--wrap .select-search-option {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
}

/*
 * Two independent states, so they must stay visually distinct: [data-active] is
 * the keyboard/hover cursor (moves with the arrow keys), aria-selected is the
 * value actually committed to the <select>. The selected row also gets weight +
 * a check mark, so it is never color alone that marks it.
 */
.select-search-option[data-active="1"] {
    background: var(--color-bg-3, #f0efea);
}

.select-search-option[aria-selected="true"] {
    font-weight: 600;
    color: var(--color-info, #185fa5);
}

.select-search-option[aria-selected="true"]::after {
    content: "";
    flex: 0 0 auto;
    width: 12px;
    height: 12px;
    margin-left: auto;
    padding-left: 8px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14' fill='none' stroke='%23185fa5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 7.5 5.5 11 12 3.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right center;
    background-size: 12px 12px;
}

.select-search-option[aria-disabled="true"] {
    color: var(--color-text-3, #999);
    cursor: not-allowed;
}

.select-search-option[aria-disabled="true"][data-active="1"] {
    background: transparent;
}

/* Dead end otherwise: an empty popover reads as "broken", not as "no match". */
.select-search-empty {
    padding: 14px 10px;
    color: var(--color-text-3, #999);
    text-align: center;
}

.select-search-empty[hidden] {
    display: none;
}

/*
 * Touch target floor for the in-store kiosk, mirroring the `coarse:` variant
 * used elsewhere in the project. Only the rows are grown: the control itself
 * keeps whatever height the call site gave the <select>, so it stays aligned
 * with the inputs sitting next to it in the same form row.
 */
@media (pointer: coarse) {
    .select-search-option {
        min-height: 44px;
    }
}

@media (prefers-reduced-motion: no-preference) {
    .select-search-panel {
        animation: select-search-in 120ms ease-out;
    }

    @keyframes select-search-in {
        from {
            opacity: 0;
            transform: translateY(-2px);
        }
    }
}
