/* ==============================================================================
   FLOATING — Floating-UI-anchored panels
   ==============================================================================
   Search hint, dropdown panel, badge tooltips, and the selected-items popover.
   All use `position: fixed` so they escape `overflow: hidden|auto|scroll`
   containers, and all are positioned by Floating UI from JS. The CSS here
   defines visual chrome only — positioning is dynamic.
*/

/* ==============================================================================
   FLOATING SEARCH HINT
   ============================================================================== */

.ms__hint {
  display: none;
  position: fixed;
  z-index: var(--ms-z-index-popover);
  padding: var(--ms-hint-padding);
  background: var(--ms-hint-bg);
  border: var(--ms-hint-border);
  border-radius: var(--ms-hint-border-radius);
  box-shadow: var(--ms-hint-box-shadow);
  font-size: var(--ms-hint-font-size);
  color: var(--ms-hint-color);
  line-height: var(--ms-line-height-relaxed);
  max-width: 100%;
}

.ms__hint--visible {
  display: block;
}

/* ==============================================================================
   DROPDOWN PANEL
   ============================================================================== */

.ms__dropdown {
  display: none;
  position: fixed;
  /* --ms-dropdown-width is the input wrapper's offsetWidth (a border-box measurement), so this
     surface must be border-box too — otherwise its own 1px border is added on top and the panel
     renders 2px wider than the input it's anchored to. */
  box-sizing: border-box;
  font-family: inherit; /* Ensure font inherits from container */
  z-index: var(--ms-z-index-dropdown);
  background: var(--ms-dropdown-bg);
  border: var(--ms-dropdown-border);
  border-radius: var(--ms-dropdown-border-radius);
  box-shadow: var(--ms-dropdown-box-shadow);
  width: var(--ms-dropdown-width); /* defaults to the live input width; themeable/attribute-overridable */
  max-height: var(--ms-options-max-height);
  overflow: hidden; /* Clips content to border-radius, inner container handles scrolling */
  color: var(--ms-dropdown-text-color);
}

.ms__dropdown--visible {
  display: flex;
  flex-direction: column;
}

/* ------------------------------------------------------------------------------
   FULLSCREEN OVERLAY — phone / touch presentation
   Set by JS (setPresentation('fullscreen'), driven by the element's
   environmentChanged hook) INSTEAD of anchoring the panel. The panel becomes a
   fixed, full-viewport sheet with its own search + close header, so the input it
   would otherwise float beneath is fully covered. `dvh` tracks the mobile URL bar.
   ------------------------------------------------------------------------------ */
/* Phone-view scaling. Every size is calc(N × --ms-rem), but a custom property bakes
   its var(--ms-rem) at its DECLARATION site — the semantic vars are declared at :host
   (10px), so overriding --ms-rem on the panel alone does NOT re-scale them. So we both
   (a) set the panel's --ms-rem to --ms-fullscreen-rem, and (b) RE-DECLARE the shared
   option/checkbox/group vars here in the panel scope, with the same formulas as
   variables.css, so their var(--ms-rem) now resolves to the enlarged value. Overlay-
   only --ms-fullscreen-* vars already derive from --ms-fullscreen-rem at :host, and
   JS-driven row heights (virtual/fixed) are scaled to match in code. */
.ms__dropdown--fullscreen,
.ms__selected-popover--fullscreen {
  --ms-rem: var(--ms-fullscreen-rem);
  --ms-option-padding: calc(0.8 * var(--ms-rem)) calc(1.2 * var(--ms-rem));
  --ms-option-gap: calc(0.8 * var(--ms-rem));
  --ms-option-title-font-size: calc(var(--base-font-size-sm, 1.4) * var(--ms-rem));
  --ms-option-subtitle-font-size: calc(var(--base-font-size-xs, 1.2) * var(--ms-rem));
  --ms-option-icon-font-size: calc(var(--base-font-size-base, 1.6) * var(--ms-rem));
  --ms-checkbox-size: calc(1.6 * var(--ms-rem));
  --ms-group-label-font-size: calc(var(--base-font-size-xs, 1.2) * var(--ms-rem));
  --ms-group-label-padding: calc(0.4 * var(--ms-rem)) calc(1.2 * var(--ms-rem));
  /* Reclaim horizontal space for labels: tighter indent than the floating default
     (--ms-tree-base-indent 0.75rem / --ms-tree-indent 1.25rem in tree.css). */
  --ms-tree-base-indent: var(--ms-fullscreen-tree-base-indent);
  --ms-tree-indent: var(--ms-fullscreen-tree-indent);
}

/* Bigger, dropdown-like selected-item rows in the phone overlay. The badge sizing
   vars are declared at :host against the base --ms-rem (baked at 10px), so without
   this they'd keep base-size text/padding inside the enlarged sheet and read as
   cramped. Re-declaring them here — where --ms-rem is --ms-fullscreen-rem — scales
   the pill height, text, padding and remove button up with the rest of the overlay.
   The row height is also mirrored in JS (scaledBadgeHeight → --ms-badge-height-virtual)
   for the virtual list, so both paths agree. */
.ms__selected-popover--fullscreen {
  --ms-badge-gap: calc(0.8 * var(--ms-rem));
  --ms-badge-height: calc(4.2 * var(--ms-rem));
  --ms-badge-font-size: calc(var(--base-font-size-sm, 1.4) * var(--ms-rem));
  --ms-badge-text-padding: 0 calc(1.2 * var(--ms-rem));
  --ms-badge-remove-width: calc(3.6 * var(--ms-rem));
  --ms-badge-remove-icon-size: calc(1.2 * var(--ms-rem));
  --ms-badge-remove-font-size: calc(var(--base-font-size-sm, 1.4) * var(--ms-rem));
}

/* Action buttons (Select All / Clear All / custom) scale up in the overlay too — their
   sizing vars are baked at :host against the base --ms-rem, so re-declare them here
   (where --ms-rem is --ms-fullscreen-rem) for a comfortable touch target. Dropdown-only:
   the selected-items popover has no actions row. */
.ms__dropdown--fullscreen {
  --ms-actions-gap: calc(0.4 * var(--ms-rem));
  /* Horizontal padding matches the header (--ms-fullscreen-header-padding-h) and the
     option rows (--ms-option-padding-h), both 1.2rem, so the action buttons' outer edges
     line up with the search field and the option checkboxes instead of starting ~0.4rem
     further out. Vertical stays 0.8rem for the row's own rhythm. */
  --ms-actions-padding: calc(0.8 * var(--ms-rem)) calc(1.2 * var(--ms-rem));
  --ms-action-btn-padding: calc(0.6 * var(--ms-rem)) calc(1.2 * var(--ms-rem));
  --ms-action-btn-font-size: calc(var(--base-font-size-sm, 1.4) * var(--ms-rem));
}

.ms__dropdown--fullscreen {
  position: fixed;
  /* top/left only — NOT `inset: 0`. `inset` also sets `bottom: 0`, and a fixed box with
     both `top` and `bottom` constrained ignores its `height`. observeKeyboardInset()
     shrinks the sheet above the soft keyboard by writing `height` (+ `top`), so a pinned
     `bottom` would silently defeat it — the list and bottom actions would stay behind the
     keyboard. With only top/left pinned, height governs and the keyboard reflow works. */
  top: 0;
  inset-inline-start: 0;
  width: 100vw;
  max-width: 100vw;
  height: 100dvh;
  max-height: 100dvh;
  border: none;
  border-radius: 0;
  /* The sheet is a squared full-viewport overlay, so the inner content must not
     round its corners — zero the inner clip radius here (the base var derives from
     --ms-dropdown-border-radius, which isn't 0 in this scope). */
  --ms-dropdown-inner-border-radius: 0;
  background: var(--ms-fullscreen-bg);
  color: var(--ms-fullscreen-text-color);
  z-index: var(--ms-z-index-fullscreen);

  /* Keep the sheet's CONTENT inside the display's safe area — the biggest offender is
     LANDSCAPE, where the Android nav bar sits on one side and a camera cutout / rounded
     corner on the other, so a plain `width: 100vw` sheet runs its rows and search box
     UNDER those system bars (left/right edges clipped, the field looks "too wide for the
     screen"). `box-sizing: border-box` keeps the outer box a full-bleed 100vw × 100dvh
     (so the BACKGROUND still paints edge-to-edge with no gaps at the corners), while the
     safe-area padding pulls the flex column (header · list · actions) into the visible
     region. `env(safe-area-inset-*)` is 0 unless the host page opts into edge-to-edge
     with `<meta name="viewport" content="… viewport-fit=cover">`, so this is a no-op on
     non-cutout / letterboxed pages — never a regression, only a fix where it's needed. */
  box-sizing: border-box;
  padding-top: env(safe-area-inset-top);
  padding-right: env(safe-area-inset-right);
  padding-bottom: env(safe-area-inset-bottom);
  padding-left: env(safe-area-inset-left);
}

.ms__dropdown--fullscreen .ms__dropdown-inner {
  /* The panel is a full-height flex column; the list fills the space under the header. */
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  max-height: none;
  /* The .ms__options child is the sole scroller in fullscreen (flex-fill + overflow-y
     below). The base rule makes THIS element scroll too; two nested scrollers let the
     last row get trapped in the outer one (partially visible, unreachable). Clip here so
     scrolling happens in exactly one place. */
  overflow: hidden;
}

/* The options list fills the sheet between the header and any actions row, scrolling
   within the panel instead of at a fixed height — for BOTH the virtual list (its
   inline maxHeight is dropped in fullscreen, see renderDropdownVirtual) and the plain
   non-virtual list (small selections). Without flex-fill, a short non-virtual list
   sits content-height at the top and a bottom actions row floats mid-sheet with empty
   space beneath it. */
.ms__dropdown--fullscreen .ms__options {
  flex: 1 1 0;
  min-height: 0;
  height: auto;
  max-height: none;
  overflow-y: auto;
  /* Breathing room so the last row always clears the sheet's (or keyboard's) bottom edge
     instead of sitting flush against it, half-cut. */
  padding-bottom: var(--ms-option-gap);
}

/* Pin the action row (Select All / Clear / custom) so it never shrinks and stays docked
   at the bottom of the sheet. Once observeKeyboardInset() shrinks the panel above the
   soft keyboard, only .ms__options scrolls — the actions stay reachable above the keys. */
.ms__dropdown--fullscreen .ms__actions {
  flex: 0 0 auto;
}

/* Shared fullscreen header bar — ONE treatment for both the dropdown (search
   field) and the selected-items popover (title). Same padding, height, border, and
   close button, so the two mobile overlays are visually identical. The popover's
   header/close reuse their own class names but adopt these rules under
   `--fullscreen`, and the selectors are listed together so there's one source of
   truth (no drift between the two headers). */
.ms__fullscreen-header,
.ms__selected-popover--fullscreen .ms__selected-popover-header {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  /* Wrap lets the navigate-mode match navigator (flex-basis 100%) drop onto its own
     row under the search box while search + close stay on the first row. */
  flex-wrap: wrap;
  gap: var(--ms-fullscreen-header-gap);
  min-height: var(--ms-fullscreen-header-min-height);
  padding: var(--ms-fullscreen-header-padding);
  background: var(--ms-fullscreen-header-bg);
  border-bottom: var(--ms-fullscreen-header-border);
}

/* Keep the search field's top padding constant whether or not the navigate-mode nav row
   is showing. The dropdown header wraps the nav onto a second line; with the default
   `align-content` a single line is re-centered inside the header's min-height, so when the
   nav appears the freed slack snapped the search field up a few px. Top-anchor the wrapped
   lines instead, and give the first-row search wrapper the bar's min-height (minus the
   header's vertical padding) so single-row mode still fills the bar with no bottom gap. */
.ms__fullscreen-header {
  align-content: flex-start;
}

.ms__fullscreen-header > .ms__fullscreen-search-wrapper {
  min-height: var(--ms-fullscreen-header-min-height);
}

/* Match navigator (navigate searchMode only): result count on the lead edge, round
   prev/next buttons on the trailing edge, forced onto its own full-width row. Hidden
   inline (display:none) by JS until there's a search term. */
.ms__fullscreen-nav {
  flex: 0 0 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ms-fullscreen-nav-gap);
  padding-top: var(--ms-fullscreen-nav-padding-top);
}

.ms__fullscreen-nav-count {
  font-size: var(--ms-fullscreen-nav-count-font-size);
  color: var(--ms-fullscreen-nav-count-color);
}

.ms__fullscreen-nav-controls {
  display: flex;
  align-items: center;
  gap: var(--ms-fullscreen-nav-gap);
}

.ms__fullscreen-nav-btn {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--ms-fullscreen-nav-btn-size);
  height: var(--ms-fullscreen-nav-btn-size);
  padding: 0;
  color: var(--ms-fullscreen-nav-btn-color);
  background: var(--ms-fullscreen-nav-btn-bg);
  border: none;
  border-radius: 50%;
  cursor: pointer;
}

.ms__fullscreen-nav-btn:hover:not(:disabled) {
  background: var(--ms-fullscreen-nav-btn-bg-hover);
}

.ms__fullscreen-nav-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

.ms__fullscreen-nav-btn::before {
  content: "";
  display: block;
  width: var(--ms-fullscreen-nav-btn-icon-size);
  height: var(--ms-fullscreen-nav-btn-icon-size);
  background-color: currentColor;
  -webkit-mask: var(--ms-fullscreen-nav-btn-icon) center / contain no-repeat;
          mask: var(--ms-fullscreen-nav-btn-icon) center / contain no-repeat;
  /* --ms-fullscreen-nav-btn-icon points RIGHT (defaults to the base chevron); rotate it to
     point up for "prev". Its own token so a pre-oriented toggle glyph can't leak in here. */
  transform: rotate(-90deg);
}

/* The "next" (down) button rotates the same right-pointing chevron the other way. */
.ms__fullscreen-nav-btn--next::before {
  transform: rotate(90deg);
}

/* The leading element (search field's wrapper or the title) fills the bar, pushing
   the close button to the trailing edge in both overlays.

   flex-basis MUST be 0, not auto. The header is `flex-wrap: wrap` (so the navigate
   nav row can drop below), and flex decides which items share a line using each
   item's flex-basis BEFORE applying flex-shrink. With `auto`, this element's
   hypothetical size is its CONTENT width (toggle + input + placeholder + clear
   gutter); once that + gap + the close button overflows the line by even a
   sub-pixel, the close wraps onto its own row — even though this element is fully
   shrinkable and could have made room. That's the "close on a second line, but only
   on some (narrower) phones" bug. Basis 0 keeps its hypothetical size at 0 so it
   never forces the close to wrap; flex-grow still fills the bar. */
.ms__fullscreen-header > .ms__fullscreen-search-wrapper,
.ms__selected-popover--fullscreen .ms__selected-popover-header > span {
  flex: 1 1 0;
  min-width: 0;
}

/* Positioned context for the inline clear (✕); the input fills it fully. Center the
   cross axis so the optional leading mode toggle (shorter than the padded input) sits
   on the input's vertical center rather than at the top of the field. */
.ms__fullscreen-search-wrapper {
  position: relative;
  display: flex;
  align-items: center;
}

/* Popover title typography in fullscreen (matches a header title, not the small
   floating-popover label). */
.ms__selected-popover--fullscreen .ms__selected-popover-header {
  font-size: var(--ms-fullscreen-title-font-size);
  font-weight: var(--ms-fullscreen-title-font-weight);
  color: var(--ms-fullscreen-text-color);
}

.ms__fullscreen-search {
  flex: 1 1 auto;
  min-width: 0;
  font-family: inherit;
  font-size: var(--ms-fullscreen-search-font-size);
  color: inherit;
  background: transparent;
  border: var(--ms-fullscreen-search-border);
  border-radius: var(--ms-fullscreen-search-border-radius);
  padding: var(--ms-fullscreen-search-padding);
  /* Reserve trailing room so typed text never slides under the clear (✕). */
  padding-inline-end: var(--ms-fullscreen-search-clear-gutter);
}

.ms__fullscreen-search:focus {
  outline: none;
  border: var(--ms-input-border-focus);
}

/* Inline clear pinned to the trailing edge of the search field. Small, round,
   mask-icon glyph — a distinct Lucide search-x (see --ms-icon-search-clear), NOT the
   overlay's bare ✕. JS toggles display so it appears only while the field has text. */
.ms__fullscreen-search-clear {
  position: absolute;
  inset-inline-end: var(--ms-fullscreen-search-clear-inset);
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--ms-fullscreen-search-clear-size);
  height: var(--ms-fullscreen-search-clear-size);
  padding: 0;
  color: var(--ms-fullscreen-search-clear-color);
  background: transparent;
  border: none;
  border-radius: 50%;
  cursor: pointer;
}

.ms__fullscreen-search-clear:hover {
  background: var(--ms-fullscreen-search-clear-bg-hover);
}

.ms__fullscreen-search-clear::before {
  content: "";
  display: block;
  width: var(--ms-fullscreen-search-clear-icon-size);
  height: var(--ms-fullscreen-search-clear-icon-size);
  background-color: currentColor;
  /* Lucide search-x (magnifier + x), not the bare ✕ — see --ms-icon-search-clear. */
  -webkit-mask: var(--ms-icon-search-clear) center / contain no-repeat;
          mask: var(--ms-icon-search-clear) center / contain no-repeat;
}

/* Leading search-mode toggle (opt-in: show-search-mode-toggle). In-flow at the field's
   leading edge — [toggle][input …clear] — so it pushes the input rather than overlaying
   it (unlike the absolutely-pinned clear). The icon reflects the current mode and swaps
   via the [data-mode] rules below; JS flips the mode in place on click. */
.ms__fullscreen-mode-toggle {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--ms-fullscreen-mode-toggle-size);
  height: var(--ms-fullscreen-mode-toggle-size);
  margin-inline-end: var(--ms-fullscreen-mode-toggle-gap);
  /* Mirror the close (✕) so both icons read as symmetric across the bar. The close is
     pulled toward the trailing edge by --ms-fullscreen-close-edge-nudge, landing its
     GLYPH centre at `header-padding-h - edge-nudge + close-size/2` from that edge. This
     nudge lands the toggle's glyph centre the same distance from the LEADING edge — the
     `(close-size - toggle-size)/2` term compensates for the toggle being a smaller chip
     than the close, so it's the drawn glyphs (not just the button boxes) that align. */
  margin-inline-start: calc(
    (var(--ms-fullscreen-close-size) - var(--ms-fullscreen-mode-toggle-size)) / 2
    - var(--ms-fullscreen-close-edge-nudge)
  );
  padding: 0;
  color: var(--ms-fullscreen-mode-toggle-color);
  background: var(--ms-fullscreen-mode-toggle-bg);
  border: none;
  border-radius: 50%;
  cursor: pointer;
}

.ms__fullscreen-mode-toggle:hover {
  background: var(--ms-fullscreen-mode-toggle-bg-hover);
}

.ms__fullscreen-mode-toggle::before {
  content: "";
  display: block;
  width: var(--ms-fullscreen-mode-toggle-icon-size);
  height: var(--ms-fullscreen-mode-toggle-icon-size);
  background-color: currentColor;
  -webkit-mask: var(--ms-fullscreen-mode-toggle-icon, var(--ms-icon-search)) center / contain no-repeat;
          mask: var(--ms-fullscreen-mode-toggle-icon, var(--ms-icon-search)) center / contain no-repeat;
}

/* Current mode → glyph: magnifier for navigate, funnel for filter. */
.ms__fullscreen-mode-toggle[data-mode="navigate"] {
  --ms-fullscreen-mode-toggle-icon: var(--ms-icon-search);
}

.ms__fullscreen-mode-toggle[data-mode="filter"] {
  --ms-fullscreen-mode-toggle-icon: var(--ms-icon-filter);
}

/* Shared close button — a fixed-size chip in both overlays: mask-icon ✕ centered in a
   --close-size box that's round and borderless by default, but fully themeable into a
   bordered "button" (see the --ms-fullscreen-close-bg / -border / -border-radius vars,
   e.g. a light border + small radius like a command-palette close). The visible box is
   a contained square so a border reads as a button, NOT a full-height strip; a separate
   transparent ::after (below) keeps the tap target large and corner-reaching. A small
   negative inline-end margin slides the button (and glyph) closer to the edge. */
.ms__fullscreen-close,
.ms__selected-popover--fullscreen .ms__selected-popover-close {
  flex: 0 0 auto;
  position: relative;                 /* anchor for the ::after hit-area extension */
  box-sizing: border-box;             /* a border must not grow the --close-size box */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--ms-fullscreen-close-size);
  height: var(--ms-fullscreen-close-size);
  margin-inline-end: calc(-1 * var(--ms-fullscreen-close-edge-nudge));  /* slide toward the edge */
  padding: 0;
  color: var(--ms-fullscreen-close-color);
  background: var(--ms-fullscreen-close-bg);
  border: var(--ms-fullscreen-close-border);
  border-radius: var(--ms-fullscreen-close-border-radius);
  cursor: pointer;
}

/* Invisible hit-area extension — grows the tap target well beyond the visible chip so
   the whole top-trailing corner (the easiest place to tap, and the old dead padding
   around a centered button) dismisses the sheet, without changing the chip's look. It
   overshoots UP past the button (harmless — that's off the top of the sheet) and past
   the trailing edge (clipped), and reaches a bounded amount below and into the leading
   gap (kept short so it never covers the first option row or the search field). */
.ms__fullscreen-close::after,
.ms__selected-popover--fullscreen .ms__selected-popover-close::after {
  content: "";
  position: absolute;
  inset-block-start: calc(-1 * var(--ms-fullscreen-close-size));
  inset-block-end: calc(-1 * var(--ms-fullscreen-header-padding-v));
  inset-inline-end: calc(-1 * var(--ms-fullscreen-header-padding-h));
  inset-inline-start: calc(-1 * var(--ms-fullscreen-header-gap));
}

.ms__fullscreen-close:hover,
.ms__selected-popover--fullscreen .ms__selected-popover-close:hover {
  background: var(--ms-fullscreen-close-bg-hover);
  color: var(--ms-fullscreen-close-color);
}

.ms__fullscreen-close::before,
.ms__selected-popover--fullscreen .ms__selected-popover-close::before {
  content: "";
  display: block;
  width: var(--ms-fullscreen-close-icon-size);
  height: var(--ms-fullscreen-close-icon-size);
  background-color: currentColor;
  -webkit-mask: var(--ms-icon-remove) center / contain no-repeat;
          mask: var(--ms-icon-remove) center / contain no-repeat;
}

/* Truncated-label reveal — a circled "i" at the trailing edge of a fullscreen row
   whose label is clipped. Fullscreen-only markup (the renderer emits it only for the
   overlay), and CSS keeps it hidden until JS tags the row .ms__option--truncated
   (measured per render). Tapping it reveals the full label — the touch-friendly
   substitute for the hover option tooltip, which never fires on touch. */
.ms__dropdown--fullscreen .ms__option-info {
  flex: 0 0 auto;
  display: none;
  align-items: center;
  justify-content: center;
  width: var(--ms-fullscreen-info-size);
  height: var(--ms-fullscreen-info-size);
  margin-inline-start: var(--ms-option-gap);
  padding: 0;
  color: var(--ms-fullscreen-info-color);
  background: transparent;
  border: none;
  border-radius: 50%;
  cursor: pointer;
}

.ms__dropdown--fullscreen .ms__option--truncated .ms__option-info {
  display: inline-flex;
}

@media (hover: hover) {
  .ms__dropdown--fullscreen .ms__option-info:hover {
    background: var(--ms-fullscreen-info-bg-hover);
  }
}

.ms__dropdown--fullscreen .ms__option-info::before {
  content: "";
  display: block;
  width: var(--ms-fullscreen-info-icon-size);
  height: var(--ms-fullscreen-info-icon-size);
  background-color: currentColor;
  -webkit-mask: var(--ms-icon-info) center / contain no-repeat;
          mask: var(--ms-icon-info) center / contain no-repeat;
}

/* Inner scrolling container — the single content clip for the panel (holds the
   actions bar + options in every render mode). Rounding it to the inner radius makes
   whatever sits in a corner (the sticky actions bar, the first/last option, or —
   because it's the scroll box, not a specific row — whatever row is at the scrolled
   edge) follow the panel's rounded corners, instead of a square background bleeding
   past the rounded 1px border. Also rounds the scrollbar into the corners. */
.ms__dropdown-inner {
  flex: 1;
  overflow-y: auto;
  border-radius: var(--ms-dropdown-inner-border-radius);
  overscroll-behavior: contain;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;

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

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

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

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

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

.ms__dropdown--virtual {
  /* In virtual scroll mode, let the options container handle scrolling */
  max-height: none;
}

.ms__dropdown--virtual .ms__dropdown-inner {
  /* Virtual mode: .ms__options--virtual owns the scroll, so the inner must NOT
     scroll too (two nested scrollers strand the last row). Clip (not `visible`) so
     it still bounds content to its rounded corners — same one-scroller pattern the
     fullscreen inner uses — otherwise the corner artifact returns for virtual lists. */
  overflow: hidden;
}

/* ==============================================================================
   BADGE TOOLTIPS
   ============================================================================== */

.ms__badge-tooltip {
  position: fixed;
  z-index: var(--ms-tooltip-z-index);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--ms-transition-normal) ease, visibility var(--ms-transition-normal) ease;

  background: var(--ms-tooltip-bg);
  color: var(--ms-tooltip-text-color);
  padding: var(--ms-tooltip-padding);
  border-radius: var(--ms-tooltip-border-radius);
  font-size: var(--ms-tooltip-font-size);
  line-height: var(--ms-line-height-relaxed);
  max-width: var(--ms-tooltip-max-width);
  word-wrap: break-word;
  white-space: pre-wrap;
  box-shadow: var(--ms-tooltip-shadow);
  pointer-events: none; /* Prevent tooltip from interfering with mouse events */
}

.ms__badge-tooltip--visible {
  opacity: 1;
  visibility: visible;
}

/* Option (dropdown row) tooltip. Same shape as the badge tooltip but reads its own
   --ms-option-tooltip-* hooks (which default to the shared --ms-tooltip-* surface), so it can be
   themed independently and targeted separately in custom CSS. */
.ms__option-tooltip {
  position: fixed;
  z-index: var(--ms-option-tooltip-z-index);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--ms-transition-normal) ease, visibility var(--ms-transition-normal) ease;

  background: var(--ms-option-tooltip-bg);
  color: var(--ms-option-tooltip-text-color);
  padding: var(--ms-option-tooltip-padding);
  border-radius: var(--ms-option-tooltip-border-radius);
  font-size: var(--ms-option-tooltip-font-size);
  line-height: var(--ms-line-height-relaxed);
  max-width: var(--ms-option-tooltip-max-width);
  word-wrap: break-word;
  white-space: pre-wrap;
  box-shadow: var(--ms-option-tooltip-shadow);
  pointer-events: none; /* Prevent tooltip from interfering with mouse events */
}

.ms__option-tooltip--visible {
  opacity: 1;
  visibility: visible;
}

/* Truncated-label reveal fired from inside the fullscreen overlay — lift it above
   the overlay (10001), which the plain option tooltip (10000) would sit behind. */
.ms__option-tooltip--fullscreen {
  z-index: var(--ms-z-index-fullscreen-tooltip);
}

/* ==============================================================================
   TRANSIENT MESSAGE / TOAST (showMessage)
   ==============================================================================
   Rendered above the panel so a veto reason (or any consumer feedback) is visible
   in BOTH presentations: anchored under the control when floating (position set by
   floating-ui), pinned to the bottom-centre of the viewport — above the sheet — when
   fullscreen. One shows at a time; tap to dismiss. */
.ms__message {
  position: fixed;
  z-index: var(--ms-message-z-index);
  box-sizing: border-box;
  max-width: var(--ms-message-max-width);
  padding: var(--ms-message-padding);
  font-family: inherit;
  font-size: var(--ms-message-font-size);
  font-weight: var(--ms-message-font-weight);
  line-height: var(--ms-line-height-normal);
  color: var(--ms-message-color);
  background: var(--ms-message-bg);
  border: var(--ms-message-border);
  border-radius: var(--ms-message-border-radius);
  box-shadow: var(--ms-message-shadow);
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--ms-transition-normal) ease;
  /* The one tap-highlight declaration NOT covered by :host (base.css): the message can
     be reparented to document.body, outside the shadow subtree, so it sets its own. */
  -webkit-tap-highlight-color: transparent;
}

.ms__message--visible {
  opacity: 1;
}

.ms__message--info    { background: var(--ms-message-info-bg);    color: var(--ms-message-info-color); }
.ms__message--warning { background: var(--ms-message-warning-bg); color: var(--ms-message-warning-color); }
.ms__message--error   { background: var(--ms-message-error-bg);   color: var(--ms-message-error-color); }
.ms__message--success { background: var(--ms-message-success-bg); color: var(--ms-message-success-color); }

/* Fullscreen: bottom-centre of the viewport, above the overlay. Its sizing vars are
   --ms-rem-based (baked at :host), so rescale the key ones here against
   --ms-fullscreen-rem to match the enlarged phone view. */
.ms__message--fullscreen {
  left: 50%;
  right: auto;
  /* Lift above the bottom safe area (gesture pill / nav bar) so the toast isn't tucked
     under it — env() is 0 on non-edge-to-edge pages, degrading to the plain offset. */
  bottom: calc(var(--ms-message-fullscreen-offset) + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  max-width: min(var(--ms-message-max-width), calc(100vw - 4 * var(--ms-fullscreen-rem)));
  padding: calc(1.0 * var(--ms-fullscreen-rem)) calc(1.4 * var(--ms-fullscreen-rem));
  font-size: calc(var(--base-font-size-sm, 1.4) * var(--ms-fullscreen-rem));
}

/* ==============================================================================
   SELECTED-ITEMS POPOVER
   ==============================================================================
   Opens from the count-display / compact / "+X more" interactions to show
   every selected item. Contains its own scrollable body.
*/

.ms__selected-popover {
  display: none;
  position: fixed;
  /* Border-box so the 1px border sits inside --ms-selected-popover-width (the input's border-box
     offsetWidth) rather than adding to it — otherwise the popover renders 2px wider than the input
     and overhangs it. Matches .ms__dropdown. */
  box-sizing: border-box;
  z-index: var(--ms-z-index-popover);
  background: var(--ms-selected-popover-bg);
  border: var(--ms-selected-popover-border);
  border-radius: var(--ms-selected-popover-border-radius);
  box-shadow: var(--ms-selected-popover-box-shadow);
  width: var(--ms-selected-popover-width);
  max-height: var(--ms-selected-popover-max-height);
  overflow: hidden;
}

.ms__selected-popover--visible {
  display: flex;
  flex-direction: column;
}

.ms__selected-popover--virtual {
  /* In virtual scroll mode, let the body container handle scrolling (matches dropdown pattern) */
  display: block;        /* Change from flex to block (like dropdown) */
  overflow: visible;
  max-height: none;
}

/* ------------------------------------------------------------------------------
   FULLSCREEN OVERLAY — phone / touch presentation (mirrors the dropdown overlay).
   Set by JS (setPresentation('fullscreen')) instead of anchoring. The popover
   already renders its own header + close button, so it just becomes a fixed,
   full-viewport sheet. Declared AFTER --virtual so its `display:flex` wins the
   large-selection (virtual) case; the virtual body flexes to fill (its inline
   height is dropped in fullscreen — see renderSelectedPopoverVirtual).
   ------------------------------------------------------------------------------ */
.ms__selected-popover--fullscreen {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  width: 100vw;
  max-width: 100vw;
  height: 100dvh;
  max-height: 100dvh;
  border: none;
  border-radius: 0;
  overflow: hidden;
  background: var(--ms-fullscreen-bg);
  color: var(--ms-fullscreen-text-color);
  z-index: var(--ms-z-index-fullscreen);

  /* Same safe-area contract as the dropdown sheet above — full-bleed background,
     content inset out from under the landscape side bars / cutout. See that note. */
  box-sizing: border-box;
  padding-top: env(safe-area-inset-top);
  padding-right: env(safe-area-inset-right);
  padding-bottom: env(safe-area-inset-bottom);
  padding-left: env(safe-area-inset-left);
}

.ms__selected-popover--fullscreen .ms__selected-popover-body {
  flex: 1 1 0;
  min-height: 0;
  max-height: none;
}

.ms__selected-popover-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--ms-selected-popover-header-padding);
  background: var(--ms-selected-popover-header-bg);
  border-bottom: var(--ms-selected-popover-header-border-bottom);
  font-size: var(--ms-selected-popover-header-font-size);
  font-weight: var(--ms-selected-popover-header-font-weight);
  color: var(--ms-selected-popover-header-color);
}

.ms__selected-popover-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--ms-popover-close-size);
  height: var(--ms-popover-close-size);
  padding: 0;
  border: none;
  background: var(--ms-selected-popover-close-bg);
  color: var(--ms-selected-popover-close-color);
  font-size: var(--ms-selected-popover-close-font-size);
  line-height: var(--ms-line-height-none);
  cursor: pointer;
  border-radius: var(--ms-selected-popover-close-border-radius);
  transition: all var(--ms-transition-fast) var(--ms-easing-snappy);
}

.ms__selected-popover-close:hover {
  background: var(--ms-selected-popover-close-bg-hover);
  color: var(--ms-selected-popover-close-color-hover);
}

.ms__selected-popover-close::before {
  content: "";
  display: block;
  width: var(--ms-selected-popover-close-icon-size);
  height: var(--ms-selected-popover-close-icon-size);
  background-color: currentColor;
  -webkit-mask: var(--ms-icon-remove) center / contain no-repeat;
          mask: var(--ms-icon-remove) center / contain no-repeat;
}

.ms__selected-popover-body {
  display: flex;
  flex-direction: column;
  gap: var(--ms-selected-popover-body-gap);
  padding: var(--ms-selected-popover-body-padding);
  overflow-y: auto;
  max-height: var(--ms-selected-popover-body-max-height);

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

.ms__selected-popover-body::-webkit-scrollbar {
  width: var(--ms-scrollbar-width);
}

.ms__selected-popover-body::-webkit-scrollbar-track {
  background: var(--ms-scrollbar-track-bg);
}

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

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

/* Badges inside popover (non-virtual mode) */
.ms__selected-popover-body .ms__badge {
  width: 100%;
  min-height: fit-content; /* Allow badges to expand based on content */
  line-height: var(--ms-line-height-relaxed); /* Override line-height: 1 to allow multi-line content */
  /* The body is a flex column; without this, badges shrink (flex-shrink defaults to 1)
     toward their min-content height once the list overflows — so rows visibly get
     shorter as you select more. Pin the height and let the body scroll instead. */
  flex-shrink: 0;
}

.ms__selected-popover-body .ms__badge-text {
  flex: 1;
  min-width: 0; /* Allow proper flex sizing */
  white-space: normal; /* Explicitly allow wrapping */
  word-wrap: break-word; /* Break long words */
}

/* Virtual scroll mode */
.ms__selected-popover-body--virtual {
  /* Let inline styles control overflow-y: auto (like dropdown does) */
  display: block;        /* Override flex display for virtual scroll */
  max-height: none;      /* Remove max-height constraint */
  padding: 0;            /* Remove padding as virtual scroll has its own spacing */
}

.ms__selected-popover-body--virtual .ms__badge {
  /* Fixed height for virtual scroll (default: 36px, configurable via badge-height attribute) */
  height: var(--ms-badge-height-virtual, 36px);
  min-height: var(--ms-badge-height-virtual, 36px);
  max-height: var(--ms-badge-height-virtual, 36px);
  margin-bottom: var(--ms-selected-popover-body-gap); /* Add gap between badges */
  overflow: hidden;
  box-sizing: border-box;
}

.ms__selected-popover-body--virtual .ms__badge-text {
  /* Enforce single-line truncation for virtual scroll fixed heights */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
