/* ============================================================
   components/select.css — .dd-select (accessible custom listbox)
   Progressive enhancement over a native <select>:
     • No JS / before enhance → the native <select> shows (it carries
       the .dd-field__input look + the .dd-field__chevron from
       field.css), fully usable + accessible.
     • components.js adds .is-enhanced, hides the native select (kept
       for submission), and renders a combobox trigger + listbox panel.
   The chevron rotates on open; the selected option carries a coral dot.
   ============================================================ */

.dd-select {
  position: relative;
}

/* The native select is the source of truth + the no-JS fallback. */
.dd-select__native {
  display: block;
  width: 100%;
}

/* Once enhanced, keep the native select in the DOM for form submission
   but remove it from view + the a11y tree (JS also sets aria-hidden +
   tabindex=-1). The custom combobox below becomes the interface. */
.dd-select.is-enhanced .dd-select__native {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  border: 0;
}
/* hide the fallback chevron once the trigger provides its own */
.dd-select.is-enhanced > .dd-field__chevron { display: none; }

/* ---- trigger (role=combobox) -------------------------------------- */
.dd-select__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  width: 100%;
  text-align: left;
  cursor: pointer;
  /* shares the .dd-field__input face (set in markup) for a seamless look */
}
.dd-select__value {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dd-select__value--placeholder { color: var(--text-muted); }

.dd-select__caret {
  color: var(--accent);
  flex-shrink: 0;
  transition: transform var(--dur-base) var(--ease-dreamy);
}
.dd-select.is-open .dd-select__caret { transform: rotate(180deg); }

/* ---- panel (role=listbox) ----------------------------------------- */
/* No scroll fade (#201): this is a surface with its own edge — a
   gradient inside it reads as a rendering fault rather than a cue. */
.dd-select__panel {
  position: absolute;
  z-index: var(--z-dropdown);
  left: 0;
  right: 0;
  top: calc(100% + var(--space-2));
  margin: 0;
  padding: var(--space-2);
  list-style: none;
  max-height: 16rem;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  /* hidden state */
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity var(--dur-base) var(--ease-soft),
              visibility var(--dur-base) var(--ease-soft),
              transform var(--dur-base) var(--ease-dreamy);
}
.dd-select.is-open .dd-select__panel {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

/* a faint grain wash on the panel for the dreamy material */
.dd-select__panel::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: var(--grain);
  opacity: 0.03;
  border-radius: inherit;
}

.dd-select__option {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-3) var(--space-3) var(--space-7);
  border-radius: var(--radius-md);
  font-size: var(--fs-body);
  color: var(--text);
  cursor: pointer;
  user-select: none;
}
/* `display: flex` above is an author rule, and an author rule beats the UA
   `[hidden]` one whatever its specificity — so without this line every option
   the panel hides stays on screen. That is both halves of the panel's own
   filtering: the query in the search box (#56) and the out-of-context options
   folded away behind it (#195) are each expressed by setting `hidden` on the
   <li>, and neither one was reaching the screen. Found in a browser, where it
   is the only place it is visible: the attribute was always correct, the count
   in `.dd-select__more` always right, and the rows underneath it painted
   anyway. Its three siblings here — `__search`, `__empty`, `__more` — each
   carry the same line for the same reason. */
.dd-select__option[hidden] { display: none; }
/* the coral dot marker — shown only on the selected option */
.dd-select__option::before {
  content: "";
  position: absolute;
  left: var(--space-3);
  top: 50%;
  transform: translateY(-50%) scale(0);
  width: 0.5em;
  height: 0.5em;
  border-radius: var(--radius-pill);
  background: var(--accent);
  transition: transform var(--dur-fast) var(--ease-dreamy);
}
.dd-select__option[aria-selected="true"] {
  font-weight: 600;
}
.dd-select__option[aria-selected="true"]::before {
  transform: translateY(-50%) scale(1);
}
/* keyboard / pointer highlight (active descendant) */
.dd-select__option.is-active,
.dd-select__option:hover {
  background: var(--coral-50);
}

/* ---- search variant: filtering input + selected cards (issue #56) --
   The long relation pickers become a text field that filters the listbox;
   the current value(s) sit inside it as removable cards. The .dd-select__box
   wears the .dd-field__input face, so it inherits the field border/focus. */
.dd-select--search .dd-select__box {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  cursor: text;
  /* the caret rides at the trailing edge; keep text clear of it */
  padding-right: var(--space-8);
}
.dd-select--search .dd-select__box:focus-within {
  outline: none;
  border-color: var(--focus-ring);
  background: var(--paper);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus-ring) 22%, transparent);
}
.dd-select--search.has-error .dd-select__box:focus-within {
  border-color: var(--danger);
}

/* the caret flows as the last flex child (un-absolute the reused chevron) */
.dd-select--search .dd-select__caret {
  position: static;
  margin-left: auto;
}

/* the search input is chromeless — the box is the field face */
.dd-select__search {
  flex: 1 1 6rem;
  min-width: 4rem;
  border: 0;
  padding: 0;
  background: transparent;
  font: inherit;
  color: var(--text);
  line-height: var(--lh-snug);
}
.dd-select__search:focus { outline: none; }
.dd-select__search::placeholder { color: transparent; }
.dd-select__search[hidden] { display: none; }

/* selected value(s) as cards */
.dd-select__cards {
  display: contents;
}
.dd-select__card {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  max-width: 100%;
  padding: var(--space-1) var(--space-1) var(--space-1) var(--space-3);
  background: var(--coral-50);
  border: 1px solid var(--coral-200);
  border-radius: var(--radius-pill);
  font-size: var(--fs-body-sm, var(--fs-body));
  line-height: var(--lh-snug);
}
.dd-select__card-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dd-select__card-x {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 1.25em;
  height: 1.25em;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--accent-strong, var(--accent));
  font-size: 1.15em;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-soft);
}
.dd-select__card-x:hover {
  background: color-mix(in srgb, var(--accent) 22%, transparent);
}
.dd-select__card-x:focus-visible {
  outline: var(--focus-outline);
  outline-offset: 1px;
}

/* Select or add (#321): the "add “…”" row a picker with `data-dd-create`
   offers for a name nothing in the list is, and the card that name becomes —
   marked new, so a new client is never mistaken for one the site has. */
.dd-select__option--create {
  color: var(--link);
  font-weight: 600;
}
.dd-select__card-tag {
  flex-shrink: 0;
  font-size: var(--fs-label);
  color: var(--text-muted);
}

/* the "no matches" note when a query filters everything out */
.dd-select__empty {
  padding: var(--space-3);
  color: var(--text-muted);
  font-size: var(--fs-body-sm, var(--fs-body));
  text-align: center;
}
.dd-select__empty[hidden] { display: none; }

/* The count of options still folded away behind the picker's own context
   (issue #195) — how many rows a longer query would reach, and the only thing
   on screen saying they exist. Reads as a note, never as a pickable row: it
   carries no `role=option`, so the keyboard walks straight past it. */
.dd-select__more {
  padding: var(--space-2) var(--space-3);
  border-top: 1px solid var(--border-subtle, var(--border));
  color: var(--text-muted);
  font-size: var(--fs-body-sm, var(--fs-body));
  text-align: center;
}
.dd-select__more[hidden] { display: none; }

/* Where the picker's own context ends and the rest of the studio begins —
   set on the first out-of-context option showing under a query that reached
   past it. A hairline only: what is below it is every bit as pickable as what
   is above, and dimming it would say otherwise. */
.dd-select__option--fold-start {
  border-top: 1px solid var(--border-subtle, var(--border));
}

@media (prefers-reduced-motion: reduce) {
  .dd-select__caret,
  .dd-select__panel,
  .dd-select__option::before,
  .dd-select__card-x { transition: none; }
}
