/* Person picker
 *
 * Search the contact book, pick someone, or add a name that is not in it yet —
 * without leaving the Event you are in the middle of. STORY-015, STORY-016.
 *
 * A <select> cannot do this job. The contact book runs to hundreds of names,
 * it is searched rather than scanned, and "this person is new" is a normal
 * outcome rather than an error. So this is the ARIA combobox pattern: a text
 * input that owns the value, a listbox that offers matches, and a separate
 * button for creating.
 *
 *   <div class="picker">
 *     <input class="field__control" role="combobox" aria-expanded="true"
 *            aria-controls="…-list" aria-autocomplete="list"
 *            aria-activedescendant="…-opt-2" autocomplete="off">
 *     <ul class="picker__list" role="listbox">
 *       <li class="picker__option" role="option" aria-selected="false">…</li>
 *     </ul>
 *   </div>
 *
 * Two rules the markup has to keep, because CSS cannot:
 *
 *  1. Keyboard focus STAYS IN THE INPUT. The active option is pointed at with
 *     `aria-activedescendant`, never with .focus(). Moving real focus into the
 *     list breaks typing, which is the whole interaction.
 *  2. Creating is a <button>, not an option in the list. "Add Jo as a new
 *     person" is a command; announcing it as a choosable value invites picking
 *     it by accident while arrowing past. Same reasoning as `.field__action`.
 */

.picker {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  inline-size: 100%;
}

/* ---- the list ------------------------------------------------------------ */

/* Overlays the content below rather than pushing it down: a list that reflows
 * the page on every keystroke makes the thing you were aiming at move. */
.picker__list {
  position: absolute;
  inset-block-start: 100%;
  inset-inline: 0;
  z-index: var(--z-dropdown);

  margin: var(--space-1) 0 0;
  padding: var(--space-1);
  list-style: none;

  max-block-size: 17rem;
  overflow-y: auto;
  overscroll-behavior: contain;

  background-color: var(--color-surface-raised);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}

/* Anchored under the input when the picker sits inside a form. Where the
 * picker is the page's main control, `.picker--inline` keeps the list in flow
 * so nothing is covered. */
.picker--inline .picker__list {
  position: static;
  max-block-size: none;
  box-shadow: none;
}

.picker__option {
  display: flex;
  align-items: center;
  gap: var(--space-3);

  min-block-size: var(--target-min);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

/* The active option — what Enter would pick. Not `:hover` and not `:focus`:
 * focus is still in the input, so this state is driven by the attribute the
 * screen reader is also reading. Background alone is too weak a signal at low
 * contrast, so it is paired with a marker bar. */
.picker__option[data-active="true"],
.picker__option:hover {
  background-color: var(--color-surface-sunken);
}
.picker__option[data-active="true"] {
  box-shadow: inset var(--border-width-accent) 0 0 var(--color-accent);
}

.picker__main {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-inline-size: 0;
}

.picker__name {
  font-weight: var(--weight-medium);
  line-height: var(--leading-snug);
  overflow-wrap: anywhere;
}

/* Whatever distinguishes two people with similar names — a phone number, a
 * note, how many events they have been to. Never a substitute for the name. */
.picker__note {
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
  color: var(--color-text-muted);
  overflow-wrap: anywhere;
}

/* The matched run of characters. Bold as well as coloured: a highlight that is
 * only a colour disappears in greyscale and says nothing to a screen reader. */
.picker__match {
  font-weight: var(--weight-bold);
  color: var(--color-accent);
}

/* Trailing marker — "already on the guest list", most often. */
.picker__trail {
  margin-inline-start: auto;
  flex: none;
}

/* Already invited. Shown rather than filtered out: hiding the row makes a
 * person look missing from the contact book, and the second attempt to add
 * them is a question ("did that work?"), not a mistake. STORY-016 refuses the
 * duplicate; the UI answers the question instead of raising an error. */
.picker__option[aria-disabled="true"] {
  cursor: default;
}
.picker__option[aria-disabled="true"] .picker__name,
.picker__option[aria-disabled="true"] .picker__note {
  color: var(--color-text-muted);
}
.picker__option[aria-disabled="true"]:hover { background-color: transparent; }

/* ---- create, empty, loading, error --------------------------------------- */

/* Always available, not only when there are no matches: the name you are
 * looking for can be absent while five similar ones match. */
/* Deliberately not a flex row: this is a sentence with the typed name inside
 * it, and `gap` between anonymous text runs would space the quotes off the
 * name — “ an ” instead of “an”. */
.picker__create {
  display: block;
  inline-size: 100%;
  min-block-size: var(--target-min);
  padding: var(--space-2) var(--space-3);

  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  text-align: start;
  color: var(--color-accent);

  background: none;
  border: 0;
  border-block-start: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.picker__create:hover { background-color: var(--color-surface-sunken); }

.picker__create:focus-visible {
  outline: var(--focus-ring-width) solid var(--color-focus-ring);
  outline-offset: calc(var(--focus-ring-offset) * -1);
}

/* The name being created, echoed back so it is obvious what will be saved. */
.picker__create-name { overflow-wrap: anywhere; }

.picker__status {
  padding: var(--space-3);
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
  color: var(--color-text-muted);
}

.picker__status--error {
  color: var(--color-danger);
  font-weight: var(--weight-medium);
}

/* ---- chosen guests ------------------------------------------------------- */

/* What has been picked so far, when the picker adds several in a row. Each
 * chip carries its own remove button — a chip that can only be removed by
 * backspacing is unreachable by touch. */
.picker__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  list-style: none;
  margin: 0;
  padding: 0;
}

.picker__chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding-block: var(--space-1);
  padding-inline: var(--space-3) var(--space-1);
  font-size: var(--text-sm);
  background-color: var(--color-surface-sunken);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
}

.picker__chip-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--target-min);
  block-size: var(--target-min);
  margin-block: calc(var(--space-2) * -1);
  font-family: inherit;
  color: var(--color-text-muted);
  background: none;
  border: 0;
  border-radius: var(--radius-full);
  cursor: pointer;
}

.picker__chip-remove:hover { color: var(--color-text); }

.picker__chip-remove:focus-visible {
  outline: var(--focus-ring-width) solid var(--color-focus-ring);
  outline-offset: var(--focus-ring-offset);
}
