/* ==============================================================================
   OPTIONS & CONTENT
   ==============================================================================
   Options list, groups, checkbox, option content, icons, text, and states
*/

/* ==============================================================================
   OPTIONS CONTAINER
   ==============================================================================
*/

/* Options container */
.ms__options {
  padding: var(--ms-options-padding);

  /* Scrollbar styling */
  scrollbar-width: thin;  /* Firefox */
  scrollbar-color: var(--ms-scrollbar-thumb-bg) var(--ms-scrollbar-track-bg);
}

.ms__options::-webkit-scrollbar {
  width: var(--ms-scrollbar-width);
}

.ms__options::-webkit-scrollbar-track {
  background: var(--ms-scrollbar-track-bg);
}

.ms__options::-webkit-scrollbar-thumb {
  background: var(--ms-scrollbar-thumb-bg);
  border-radius: var(--ms-scrollbar-thumb-border-radius);
}

.ms__options::-webkit-scrollbar-thumb:hover {
  background: var(--ms-scrollbar-thumb-bg-hover);
}

/* Virtual scroll - enforce consistent heights */
.ms__options--virtual .ms__option {
  height: var(--ms-option-height, 50px);
  min-height: var(--ms-option-height, 50px);
  max-height: var(--ms-option-height, 50px);
  overflow: hidden;
  box-sizing: border-box;
}

/* Non-virtual rendering while virtual scroll is *enabled* (result count is below
   the threshold): pin rows to the same fixed --ms-option-height so the row height
   doesn't jump as filtering crosses the virtualization threshold. Mirrors the
   rule above; applied only when the consumer opted into virtual scroll, so plain
   non-virtual lists keep their natural content height. */
.ms__options--fixed-height .ms__option {
  height: var(--ms-option-height, 50px);
  min-height: var(--ms-option-height, 50px);
  max-height: var(--ms-option-height, 50px);
  overflow: hidden;
  box-sizing: border-box;
}

/* ==============================================================================
   GROUPS
   ==============================================================================
*/

/* Group - consecutive groups */
.ms__group + .ms__group {
  border-top: var(--ms-group-border-top);
  margin-top: var(--ms-group-margin-top);
  padding-top: var(--ms-group-padding-top);
}

/* Group label */
.ms__group-label {
  padding: var(--ms-group-label-padding);
  font-size: var(--ms-group-label-font-size);
  font-weight: var(--ms-group-label-font-weight);
  color: var(--ms-group-label-color);
  text-transform: var(--ms-group-label-transform);
  letter-spacing: var(--ms-group-label-letter-spacing);
}

/* ==============================================================================
   INDIVIDUAL OPTION
   ==============================================================================
*/

/* Individual option */
.ms__option {
  display: flex;
  align-items: var(--ms-checkbox-align, center); /* Support checkbox alignment */
  gap: var(--ms-option-gap);
  padding: var(--ms-option-padding);
  position: relative; /* anchor for the matched leading-accent overlay (::before) */
  min-height: var(--ms-option-min-height, auto);
  color: var(--ms-option-text-color);
  background: var(--ms-option-bg);
  cursor: pointer;
  /* A click on a row (or a click-drag across the list) is a selection gesture,
     not a text-selection one — stop the browser from highlighting the label. */
  user-select: none;
  -webkit-user-select: none;
  /* Tap-highlight flash is suppressed once for the whole component on :host (base.css) —
     an inherited property, so it reaches this row without a per-element declaration. */
}

/* Hover states are gated to real pointing devices. On touch, `:hover` "sticks"
   after a tap until the next tap elsewhere, so a tapped row (or a tap on its info
   affordance) would stay highlighted as if selected. `@media (hover: hover)` keeps
   hover on mouse/trackpad and drops it on touch (phones, the fullscreen overlay). */
@media (hover: hover) {
  .ms__option:hover {
    background: var(--ms-option-bg-hover);
    color: var(--ms-option-color-hover, inherit);
  }
}

.ms__option--focused {
  background: var(--ms-option-bg-focused);
  color: var(--ms-option-color-focused, inherit);
  outline: var(--ms-option-outline-focused);
  outline-offset: var(--ms-option-focus-outline-offset);
}

.ms__option--matched {
  background: var(--ms-option-bg-matched);
  color: var(--ms-option-color-matched, inherit);
}

/* Leading-edge accent bar for the current match. Painted as an absolutely-positioned
   overlay rather than a real `border-inline-start` on the row: a border eats into the
   row's inline size only in the matched state, so the checkbox/label jumped ~3px inward
   as focus stepped between matches (navigate mode). The overlay is out of flow, so it
   never shifts content; it still uses the same --ms-option-border-matched shorthand and
   flips in RTL via the logical inset/border. Covers selected+matched too (same class). */
.ms__option--matched::before {
  content: '';
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  border-inline-start: var(--ms-option-border-matched);
  pointer-events: none;
}

.ms__option--selected {
  background: var(--ms-option-bg-selected);
}

@media (hover: hover) {
  .ms__option--selected:hover {
    background: var(--ms-option-bg-selected-hover, var(--ms-option-bg-selected));
  }
}

.ms__option--disabled {
  opacity: var(--ms-disabled-opacity);
  cursor: not-allowed;
  background: var(--ms-option-disabled-bg);
}

.ms__option--disabled:hover {
  background: var(--ms-option-disabled-bg);
}

/* Focused + Hover */
@media (hover: hover) {
  .ms__option--focused:hover {
    background: var(--ms-option-bg-focused-hover);
    color: var(--ms-option-color-focused-hover, var(--ms-option-color-focused, var(--ms-option-text-color)));
  }
}

/* Matched + Hover */
.ms__option--matched:hover {
  background: var(--ms-option-bg-matched-hover);
  color: var(--ms-option-color-matched-hover, var(--ms-option-color-matched, var(--ms-option-text-color)));
}

/* Selected + Focused */
.ms__option--selected.ms__option--focused {
  background: var(--ms-option-bg-selected-focused);
  outline: var(--ms-option-outline-focused);
  outline-offset: var(--ms-option-focus-outline-offset);
}

/* Selected + Matched (the accent bar is drawn by .ms__option--matched::before above) */
.ms__option--selected.ms__option--matched {
  background: var(--ms-option-bg-selected-matched);
}

/* Disabled + Selected */
.ms__option--disabled.ms__option--selected {
  background: var(--ms-option-bg-disabled-selected);
}

/* Disabled + Focused (prevents focus outline on disabled items) */
.ms__option--disabled.ms__option--focused {
  outline: none;
}

/* Checkbox alignment variants (center is default, defined in variables.css) */
.ms__option[data-checkbox-align="top"] {
  --ms-checkbox-align: flex-start;
  /* Nudge the top-aligned checkbox down to sit on the label's first text line
     (line-height leaves the glyph inset from the line-box top). Only meaningful
     for top alignment — center/bottom keep the 0 default so they stay centered. */
  --ms-checkbox-margin-top: calc(0.2 * var(--ms-rem));
}

.ms__option[data-checkbox-align="bottom"] {
  --ms-checkbox-align: flex-end;
}

/* ==============================================================================
   CHECKBOX (Custom Styled)
   ==============================================================================
   Uses a hidden native checkbox with a custom styled pseudo-element overlay.
   This allows full control over background, border, and checkmark colors.
*/

.ms__checkbox {
  /* Hide native checkbox but keep it accessible */
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  flex-shrink: 0;
  position: relative;
  margin-top: var(--ms-checkbox-margin-top);
  margin-inline-end: var(--ms-checkbox-margin-right);
  margin-bottom: var(--ms-checkbox-margin-bottom);
  margin-inline-start: var(--ms-checkbox-margin-left);
  width: var(--ms-checkbox-size);
  height: var(--ms-checkbox-size);
  transform: scale(var(--ms-checkbox-scale));
  transform-origin: top left;
  cursor: pointer;

  /* Custom checkbox appearance */
  background: var(--ms-checkbox-bg);
  border: var(--ms-checkbox-border);
  border-radius: var(--ms-checkbox-border-radius);
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

/* Checkmark using ::after pseudo-element */
.ms__checkbox::after {
  content: '';
  position: absolute;
  display: none;
  /* Checkmark glyph — a currentColor-tinted mask so it follows --ms-icon-check →
     the shared --base-icon-check contract (was a CSS-border checkmark). Sized via
     --ms-icon-check-size, which defaults to the shared --base-icon-check-size (68%) —
     the SAME knob pure-admin's .pa-checkbox reads, so the mark renders identically in
     both and a theme swapping the glyph (e.g. an edge-to-edge star) can shrink it once
     for everyone. Was `contain`, which assumed every glyph carried its own viewBox
     padding. The indeterminate dash below inherits this mask box, so it follows the
     same size. */
  inset: 0;
  background-color: var(--ms-checkbox-checkmark-color);
  -webkit-mask: var(--ms-icon-check) no-repeat center / var(--ms-icon-check-size);
  mask: var(--ms-icon-check) no-repeat center / var(--ms-icon-check-size);
}

/* Hover state */
.ms__checkbox:hover:not(:disabled) {
  border-color: var(--ms-checkbox-hover-border-color);
}

/* Checked state */
.ms__checkbox:checked {
  background: var(--ms-checkbox-checked-bg);
  border: var(--ms-checkbox-checked-border);
}

.ms__checkbox:checked::after {
  display: block;
}

/* Indeterminate (tristate) — cascade checkbox-mode: a partially-selected branch.
   Filled like the checked box but with a dash instead of a checkmark. Rendered
   from a modifier class (not the native :indeterminate property) so it survives
   string re-render + virtual scroll. */
.ms__checkbox--indeterminate {
  background: var(--ms-checkbox-checked-bg);
  border: var(--ms-checkbox-checked-border);
}

.ms__checkbox--indeterminate::after {
  display: block;
  /* Swap the check glyph for the dash — follows --ms-icon-indeterminate →
     --base-icon-indeterminate. Inherits the mask box from .ms__checkbox::after. */
  -webkit-mask-image: var(--ms-icon-indeterminate);
  mask-image: var(--ms-icon-indeterminate);
}

.ms__checkbox--indeterminate:hover:not(:disabled) {
  background: var(--ms-checkbox-checked-bg-hover);
  border-color: var(--ms-checkbox-checked-border-color-hover);
}

/* Checked + Hover */
.ms__checkbox:checked:hover:not(:disabled) {
  background: var(--ms-checkbox-checked-bg-hover);
  border-color: var(--ms-checkbox-checked-border-color-hover);
}

/* Focus state (accessibility) */
.ms__checkbox:focus-visible {
  outline: 2px solid var(--ms-checkbox-checked-bg);
  outline-offset: 2px;
}

/* Disabled state */
.ms__checkbox:disabled {
  cursor: not-allowed;
  background: var(--ms-checkbox-disabled-bg);
  border: var(--ms-checkbox-disabled-border);
  opacity: 0.6;
}

.ms__checkbox:disabled:checked {
  background: var(--ms-checkbox-disabled-bg);
}

.ms__option--disabled .ms__checkbox {
  cursor: not-allowed;
}

/* ==============================================================================
   OPTION CONTENT
   ==============================================================================
*/

/* Option content (rich content wrapper) */
.ms__option-content {
  flex: 1;
  display: flex;
  align-items: center;
  gap: var(--ms-option-content-gap);
  min-width: 0; /* Allow text truncation */
}

/* Option icon/SVG */
.ms__option-icon {
  flex-shrink: 0;
  width: var(--ms-option-icon-size);
  height: var(--ms-option-icon-size);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--ms-option-icon-font-size);
}

.ms__option-icon svg {
  width: 100%;
  height: 100%;
  fill: currentColor;
}

/* Option text container */
.ms__option-text {
  flex: 1;
  min-width: 0;
}

/* Option title/main text. This is the label hook (cf. `.wtv__node-label` /
   `.stv__node-label` in the treeview packages) — flip the white-space/overflow/
   text-overflow variables to truncate long labels; defaults keep them wrapping. */
.ms__option-title {
  font-size: var(--ms-option-title-font-size);
  color: var(--ms-option-title-color);
  line-height: var(--ms-line-height-relaxed);
  white-space: var(--ms-option-title-white-space, normal);
  overflow: var(--ms-option-title-overflow, visible);
  text-overflow: var(--ms-option-title-text-overflow, clip);
}

/* Title color states (for solid background themes) */
@media (hover: hover) {
  .ms__option:hover .ms__option-title {
    color: var(--ms-option-title-color-hover, var(--ms-option-title-color));
  }
}

.ms__option--selected .ms__option-title {
  color: var(--ms-option-title-color-selected, var(--ms-option-title-color));
}

@media (hover: hover) {
  .ms__option--selected:hover .ms__option-title {
    color: var(--ms-option-title-color-selected-hover, var(--ms-option-title-color-selected, var(--ms-option-title-color)));
  }
}

/* Highlight matched text */
.ms__option-title mark {
  background: var(--ms-option-mark-bg);
  color: var(--ms-option-mark-color);
  font-weight: var(--ms-option-mark-font-weight);
}

/* Option subtitle (multiline support) */
.ms__option-subtitle {
  margin-top: var(--ms-option-subtitle-margin-top);
  font-size: var(--ms-option-subtitle-font-size);
  color: var(--ms-option-subtitle-color);
  line-height: var(--ms-option-subtitle-line-height);
}

/* Subtitle color states (for solid background themes) */
@media (hover: hover) {
  .ms__option:hover .ms__option-subtitle {
    color: var(--ms-option-subtitle-color-hover, var(--ms-option-subtitle-color));
  }
}

.ms__option--selected .ms__option-subtitle {
  color: var(--ms-option-subtitle-color-selected, var(--ms-option-subtitle-color));
}

@media (hover: hover) {
  .ms__option--selected:hover .ms__option-subtitle {
    color: var(--ms-option-subtitle-color-selected-hover, var(--ms-option-subtitle-color-selected, var(--ms-option-subtitle-color)));
  }
}

/* ==============================================================================
   STATES
   ==============================================================================
*/

/* Empty state */
.ms__empty {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--ms-state-min-height);
  padding: var(--ms-empty-padding);
  text-align: center;
  font-size: var(--ms-empty-font-size);
  color: var(--ms-empty-color);
}

/* "Add new" prompt — replaces the empty message when isAddNewAllowed is on and the
   user has typed a term with no matches. Clickable (data-action="add-new" → handleAddNew);
   styled like an accent-coloured option row so it reads as an action. */
.ms__add-new {
  display: flex;
  align-items: center;
  gap: var(--ms-add-new-gap);
  /* Size like a normal option row (padding + content) — NOT the tall empty/loading
     footprint. The empty-state min-height is only for the "no results" / spinner swap. */
  padding: var(--ms-add-new-padding);
  font-size: var(--ms-add-new-font-size);
  color: var(--ms-add-new-color);
  cursor: pointer;
  /* Same rationale as .ms__option: a click here is an action gesture, not text selection. */
  user-select: none;
  -webkit-user-select: none;
}

/* Hover gated to real pointing devices (see .ms__option for the touch rationale). */
@media (hover: hover) {
  .ms__add-new:hover {
    background: var(--ms-add-new-bg-hover);
    color: var(--ms-add-new-color-hover);
  }
}

/* Keyboard focus (arrow-navigated) — mirror the hover surface so the prompt reads
   as the active row, matching .ms__option--focused. */
.ms__add-new--focused {
  background: var(--ms-add-new-bg-hover);
  color: var(--ms-add-new-color-hover);
}

/* Pending state — an async addNewCallback is in flight (spinner + "Adding …"). Not
   clickable (no data-action on the row), so drop the pointer cursor. */
.ms__add-new--loading {
  cursor: default;
}

/* Self-contained spinner (no external .pa-loader dependency — it can't cross the
   shadow boundary). Sized to the prompt's icon box; tinted by the row's currentColor. */
.ms__add-new-spinner {
  flex-shrink: 0;
  width: var(--ms-add-new-icon-size);
  height: var(--ms-add-new-icon-size);
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, currentColor 25%, transparent);
  border-top-color: currentColor;
  animation: ms-spin 0.6s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  .ms__add-new-spinner { animation-duration: 1.5s; }
}

.ms__add-new-icon {
  flex-shrink: 0;
  width: var(--ms-add-new-icon-size);
  height: var(--ms-add-new-icon-size);
  background-color: currentColor;
  -webkit-mask: var(--ms-icon-add-new) center / contain no-repeat;
          mask: var(--ms-icon-add-new) center / contain no-repeat;
}

.ms__add-new-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Loading state */
.ms__loader {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: var(--ms-state-min-height);
  padding: var(--ms-loader-padding);
  gap: var(--ms-loader-gap);
}

.ms__loading-text {
  font-size: var(--ms-loading-text-font-size);
  color: var(--ms-loading-color);
}
