/* ============================================================================
   VigilAI form field component  —  <vg-field>
   ----------------------------------------------------------------------------
   Self-contained and NOT scoped to the auth pages, so it can be dropped into
   any dashboard view. Owns the .vg-field* namespace.

   Layout: the bordered box (.vg-field__box) is a FLEX ROW and the icon, input
   and toggle are real siblings inside it. Nothing is absolutely positioned, so
   text and the caret can never slide underneath an adornment, and there is no
   z-index contest with the admin template (which gives
   .input-group > .form-control `position: relative; z-index: 3`).

   The visual "input" is the box: it carries the background, border, radius and
   focus ring via :focus-within. The <input> itself is transparent and borderless.

   Structure
     .vg-field
       label.vg-field__label
       .vg-field__control        plain block — injected siblings land here
         .vg-field__box          flex row: [icon] [control] [toggle]
       span.vg-field__error

   States: rest · hover · focus · filled · invalid · disabled · readonly · RTL.
   ========================================================================= */

:root {
  --vgf-primary:   #0090e7;
  --vgf-ring:      rgba(0, 144, 231, .16);
  --vgf-surface:   #171b21;
  --vgf-surface-2: #10161d;
  --vgf-line:      #262b33;
  --vgf-line-hi:   #33404f;
  --vgf-text:      #eef2f6;
  --vgf-muted:     #9aa7b4;
  --vgf-faint:     #6b7783;
  --vgf-danger:    #fc424a;
  --vgf-success:   #00d25b;
  --vgf-radius:    10px;
  --vgf-height:    48px;
  --vgf-pad-x:     14px;
  --vgf-gap:       10px;
}

.vg-field {
  display: block;
  margin-bottom: 18px;
  min-width: 0;
}

/* ---- label --------------------------------------------------------------- */

.vg-field__label {
  display: block;
  margin-bottom: 7px;
  font-size: .84rem;
  font-weight: 600;
  color: var(--vgf-muted);
}

.vg-field__req {
  color: var(--vgf-danger);
  margin-inline-start: 4px;
  font-weight: 700;
}

/* ---- control + box ------------------------------------------------------- */

/* Plain block. Anything a third-party script injects after the input (e.g.
   password-strength.js) is relocated here by vg-forms.js, outside the box. */
.vg-field__control {
  display: block;
  width: 100%;
}

.vg-field__box {
  display: flex;
  align-items: center;
  gap: var(--vgf-gap);
  width: 100%;
  min-height: var(--vgf-height);
  padding: 0 var(--vgf-pad-x);
  background: var(--vgf-surface);
  border: 1px solid var(--vgf-line);
  border-radius: var(--vgf-radius);
  transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}

/* icon is a real flex item: it occupies layout space, so nothing overlaps it */
.vg-field__icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  color: var(--vgf-faint);
  font-size: .92rem;
  pointer-events: none;
  transition: color .16s ease;
}

/* The icon is now an inline sprite <svg>, and this file must size it itself: the sign-in
   and sign-up pages load vg-forms.css but NOT vg-ui.css, so the .vg-icon sizing rules do
   not exist there. Without this the SVG has no intrinsic height, stretches to fill the
   flex line, and drags the whole field box to ~150px tall — on the login form. */
.vg-field__icon svg {
  inline-size: 16px;
  block-size: 16px;
  flex: 0 0 auto;
}

.vg-field__input {
  flex: 1 1 auto;
  min-width: 0;              /* lets the input shrink rather than overflow the row */
  width: 100%;
  height: calc(var(--vgf-height) - 2px);
  margin: 0;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  color: var(--vgf-text);
  font-family: inherit;
  font-size: .95rem;
  line-height: normal;
  appearance: none;
  outline: none;
  box-shadow: none;
}

.vg-field__input::placeholder { color: var(--vgf-faint); opacity: 1; }

/* Chrome's autofill paints its own background; keep the box's instead. */
.vg-field__input:-webkit-autofill,
.vg-field__input:-webkit-autofill:hover,
.vg-field__input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--vgf-text);
  -webkit-box-shadow: 0 0 0 1000px var(--vgf-surface) inset;
  transition: background-color 9999s ease-in-out 0s;
}

textarea.vg-field__input {
  height: auto;
  min-height: 96px;
  padding: 13px 0;
  resize: vertical;
}

.vg-field__box:has(textarea) { align-items: flex-start; }
.vg-field__box:has(textarea) .vg-field__icon { margin-top: 15px; }

/* ---- states (all on the box) --------------------------------------------- */

.vg-field__box:hover { border-color: var(--vgf-line-hi); }

.vg-field__box:focus-within {
  background: var(--vgf-surface-2);
  border-color: var(--vgf-primary);
  box-shadow: 0 0 0 4px var(--vgf-ring);
}

.vg-field__box:focus-within .vg-field__icon { color: var(--vgf-primary); }

/* filled — class set by vg-forms.js. Not :placeholder-shown, which only matches
   when a placeholder attribute exists and so reported every placeholder-less
   field as filled. */
.vg-field__box.is-filled:not(:focus-within) { border-color: #2f3a46; }

.vg-field__box.is-disabled,
.vg-field__box.is-readonly {
  background: #12151a;
  border-color: var(--vgf-line);
}

.vg-field__box.is-disabled { cursor: not-allowed; }
.vg-field__box.is-disabled .vg-field__icon,
.vg-field__box.is-readonly .vg-field__icon { opacity: .5; }
.vg-field__input:disabled { color: var(--vgf-muted); cursor: not-allowed; }
.vg-field__input[readonly] { color: var(--vgf-muted); }

/* invalid */
.vg-field__box.is-invalid { border-color: var(--vgf-danger); }
.vg-field__box.is-invalid:focus-within { box-shadow: 0 0 0 4px rgba(252, 66, 74, .15); }
.vg-field__box.is-invalid .vg-field__icon { color: var(--vgf-danger); }

/* ---- select -------------------------------------------------------------- */

select.vg-field__input {
  cursor: pointer;
  padding-inline-end: 22px;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%239aa7b4' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right center;
}

[dir="rtl"] select.vg-field__input { background-position: left center; }

select.vg-field__input option {
  background: var(--vgf-surface);
  color: var(--vgf-text);
}

/* ---- password toggle ----------------------------------------------------- */

.vg-field__toggle {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--vgf-faint);
  cursor: pointer;
  transition: color .16s ease, background .16s ease;
}

.vg-field__toggle:hover { color: var(--vgf-text); background: rgba(255, 255, 255, .06); }
.vg-field__toggle:focus-visible { outline: 2px solid var(--vgf-primary); outline-offset: 1px; }
.vg-field__toggle[aria-pressed="true"] { color: var(--vgf-primary); }

.vg-field__eye { display: block; }

/* ---- hint + error -------------------------------------------------------- */

.vg-field__hint {
  margin: 6px 0 0;
  font-size: .78rem;
  line-height: 1.5;
  color: var(--vgf-faint);
}

.vg-field__error {
  display: block;
  margin-top: 6px;
  font-size: .8rem;
  color: var(--vgf-danger);
}

.vg-field__error:empty { display: none; }

/* ---- third-party injections ---------------------------------------------- */

/* password-strength.js inserts its policy list after the input; vg-forms.js
   relocates it out of the box so it sits under the field, not inside the border. */
.vg-field__control > .pw-policy {
  margin-top: 10px;
  padding: 0;
  list-style: none;
  font-size: .78rem;
  line-height: 1.7;
  color: var(--vgf-faint);
}

.vg-field__control > .pw-policy .ok,
.vg-field__control > .pw-policy .valid,
.vg-field__control > .pw-policy .is-valid { color: var(--vgf-success); }

/* intl-tel-input builds its own wrapper around the input */
.vg-field__box .iti { flex: 1 1 auto; min-width: 0; display: block; }
.vg-field__box .iti input { width: 100%; }
.vg-field__box .iti__country-list {
  background: var(--vgf-surface);
  border: 1px solid var(--vgf-line);
  border-radius: var(--vgf-radius);
  color: var(--vgf-text);
}
.vg-field__box .iti__country.iti__highlight { background: rgba(0, 144, 231, .18); }

/* ---- layout helper ------------------------------------------------------- */

.vg-field-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 0 16px;
}

@media (prefers-reduced-motion: reduce) {
  .vg-field__box,
  .vg-field__icon,
  .vg-field__toggle { transition: none; }
}

/* ============================================================================
   Searchable select  —  Tom Select integration
   ----------------------------------------------------------------------------
   Two ways in, one theme:

     <vg-field searchable="true" …/>        inside a form
     <div class="vg-select">                anywhere else — a toolbar filter, say
       <select data-vg-select>…</select>
     </div>

   Tom Select v2 replaces the <select> with:
     .ts-wrapper            outer element, carries state classes
                            (.focus .disabled .invalid .dropdown-active …)
       .ts-control          the visible control
       .ts-dropdown         the popup
         .ts-dropdown-content > .option

   The theming was originally scoped to .vg-field__box only, so a searchable
   select outside a form field fell back to Tom Select's own light theme on a
   dark page. Both hosts are matched now; the wrapper supplies the border,
   background and focus ring, and the Tom Select control is stripped back to
   transparent so it simply fills the row.
   ========================================================================= */

/* Standalone host. Mirrors .vg-field__box, minus the label/validation plumbing.
   --vg-select-h lets a caller match the height of the inputs beside it. */
.vg-select {
  /* Consumed by the Tom Select control below, so it matches whatever height the
     caller asked for instead of the 48px form field. In a form field the leading
     icon supplies the text inset; there is no icon here, so the control has to
     provide it or the text sits flush against the border. */
  --vg-ts-h: calc(var(--vg-select-h, 36px) - 2px);
  --vg-ts-fs: .8125rem;
  --vg-ts-pad-s: var(--vgf-pad-x);

  display: flex;
  align-items: center;
  block-size: var(--vg-select-h, 36px);
  inline-size: 100%;
  border: 1px solid var(--vgf-line);
  border-radius: var(--vgf-radius);
  background: var(--vgf-surface-2);
  transition: border-color .15s ease, box-shadow .15s ease;
}

.vg-select:focus-within {
  border-color: var(--vgf-primary);
  box-shadow: 0 0 0 3px var(--vgf-ring);
}

/* Before the enhancement runs — or if it never does, because the library failed
   to load — the native <select> still has to look right rather than showing an
   unstyled control for a beat. */
.vg-select > select {
  inline-size: 100%;
  block-size: 100%;
  padding-inline: var(--vgf-pad-x);
  border: 0;
  background: transparent;
  color: var(--vgf-text);
  font-family: inherit;
  font-size: .8125rem;
  cursor: pointer;
  color-scheme: dark;
}

.vg-select > select:focus { outline: none; }

:is(.vg-field__box, .vg-select) .ts-wrapper {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
}

:is(.vg-field__box, .vg-select) .ts-wrapper.single .ts-control,
:is(.vg-field__box, .vg-select) .ts-control {
  /* Fill the row and centre the item. Previously min-height:0 here collapsed the
     control to the text's 15px and pinned it to the top of the 48px field.

     The height and type size follow the HOST rather than being hardcoded:
     --vgf-height is the form field's 48px, but a toolbar select is 36px or 28px,
     and a 46px control inside a 36px box overflows it — which is what made the
     selected text sit visibly off-centre. */
  display: flex;
  align-items: center;
  height: 100%;
  min-height: var(--vg-ts-h, calc(var(--vgf-height) - 2px));
  /* Start inset is a variable, not a separate override rule: this selector list
     also contains `… .ts-wrapper.single .ts-control` at (0,4,0), and per-selector
     specificity means any `.vg-select .ts-control` rule (0,2,0) loses to it no
     matter how late it appears. 22px at the end reserves room for the chevron. */
  padding-inline: var(--vg-ts-pad-s, 0) 22px;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: var(--vgf-text);
  font-family: inherit;
  font-size: var(--vg-ts-fs, .95rem);
  line-height: 1;
  cursor: pointer;
}

/* the wrapper is a flex child of the box; stretch it so the control can fill it */
:is(.vg-field__box, .vg-select) .ts-wrapper { align-self: stretch; display: flex; }

/* Tom Select draws its own caret; use the component's chevron instead */
:is(.vg-field__box, .vg-select) .ts-wrapper.single .ts-control:after { display: none; }

:is(.vg-field__box, .vg-select) .ts-control::before { display: none; }

:is(.vg-field__box, .vg-select) .ts-wrapper::after {
  content: "";
  position: absolute;
  inset-inline-end: 0;
  top: 50%;
  width: 12px;
  height: 8px;
  margin-top: -4px;
  pointer-events: none;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%239aa7b4' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center;
  transition: transform .18s ease;
}

:is(.vg-field__box, .vg-select) .ts-wrapper { position: relative; }
:is(.vg-field__box, .vg-select) .ts-wrapper.dropdown-active::after { transform: rotate(180deg); }

/* the field's own focus ring — Tom Select's input is inside the box, but the
   library also toggles .focus on the wrapper, so mirror both */
.vg-field__box.is-ts-focus {
  background: var(--vgf-surface-2);
  border-color: var(--vgf-primary);
  box-shadow: 0 0 0 4px var(--vgf-ring);
}

.vg-field__box.is-ts-focus .vg-field__icon { color: var(--vgf-primary); }

:is(.vg-field__box, .vg-select) .ts-control > input {
  color: var(--vgf-text);
  font-size: var(--vg-ts-fs, .95rem);
  margin: 0;
}

:is(.vg-field__box, .vg-select) .ts-control > input::placeholder { color: var(--vgf-faint); }

/* The typed query has to be able to fill the control. Tom Select ships the input
   at size="1" and grows it to fit its value, which clips the placeholder once the
   item beside it is hidden. */
:is(.vg-field__box, .vg-select) .ts-wrapper.single .ts-control > input {
  flex: 1 1 auto;
  min-width: 0;
}

/* ---- selected item ------------------------------------------------------- */

:is(.vg-field__box, .vg-select) .ts-control .item { color: var(--vgf-text); }

/* The empty first option ("All cameras", "All types") is the resting placeholder,
   so it stays visible — just muted — while the control is idle. It cannot be
   swapped for the input's own placeholder attribute: Tom Select parks that input
   off-screen (left:-10000px) until the control is active, so hiding the item
   leaves the field looking blank. */
:is(.vg-field__box, .vg-select) .ts-control > .item[data-value=""] { color: var(--vgf-faint); }

/* The moment the list opens, the current value steps aside so the field is ready
   to be typed into — the input's own placeholder takes over until you type.

   Keyed on .dropdown-active ("the list is open"), NOT .input-active ("the control
   has focus"): the latter stays on after a selection, so the field looked empty
   until you clicked away, and it also left the old value sitting next to whatever
   you were typing. With closeAfterSelect the list shuts on pick, which brings the
   chosen value straight back. */
:is(.vg-field__box, .vg-select) .ts-wrapper.single.dropdown-active .ts-control > .item { display: none; }

/* ---- dropdown ------------------------------------------------------------ */

:is(.vg-field__box, .vg-select) .ts-dropdown {
  margin: 8px 0 0;
  border: 1px solid var(--vgf-line);
  border-radius: var(--vgf-radius);
  background: #12171e;
  box-shadow: 0 18px 44px rgba(0, 0, 0, .55);
  overflow: hidden;
  z-index: 60;
}

:is(.vg-field__box, .vg-select) .ts-dropdown .ts-dropdown-content {
  max-height: 260px;
  padding: 6px;
  /* A long list (the camera picker runs to 60 entries in ~2350px of content)
     otherwise draws the platform's light scrollbar down a dark panel. */
  scrollbar-width: thin;
  scrollbar-color: var(--vgf-line-hi) transparent;
}

:is(.vg-field__box, .vg-select) .ts-dropdown .ts-dropdown-content::-webkit-scrollbar {
  inline-size: 8px;
}

:is(.vg-field__box, .vg-select) .ts-dropdown .ts-dropdown-content::-webkit-scrollbar-track {
  background: transparent;
}

:is(.vg-field__box, .vg-select) .ts-dropdown .ts-dropdown-content::-webkit-scrollbar-thumb {
  border: 2px solid transparent;
  border-radius: 8px;
  background: var(--vgf-line-hi);
  background-clip: content-box;
}

:is(.vg-field__box, .vg-select) .ts-dropdown .ts-dropdown-content::-webkit-scrollbar-thumb:hover {
  background: var(--vgf-muted);
  background-clip: content-box;
}

:is(.vg-field__box, .vg-select) .ts-dropdown .option {
  padding: 9px 12px;
  border-radius: 8px;
  color: var(--vgf-muted);
  font-size: .9rem;
  cursor: pointer;
}

:is(.vg-field__box, .vg-select) .ts-dropdown .option.active {
  background: rgba(0, 144, 231, .16);
  color: var(--vgf-text);
}

:is(.vg-field__box, .vg-select) .ts-dropdown .option[aria-selected="true"],
:is(.vg-field__box, .vg-select) .ts-dropdown .option.selected {
  background: var(--vgf-primary);
  color: #fff;
}

/* Tom Select ships `.optgroup-header { background: #fff }` and the rules here
   only ever restyled its typography, so a grouped list drew white bars across
   a dark dropdown. It went unnoticed because no page paired data-vg-select
   with <optgroup> until Camera/SimulateStreamRegular grouped its cameras by
   location — nothing else renders this element, so setting the background is
   inert everywhere else. */
:is(.vg-field__box, .vg-select) .ts-dropdown .optgroup-header {
  padding: 10px 12px 4px;
  background: transparent;
  color: var(--vgf-faint);
  font-size: .72rem;
  cursor: default;
}

/* Hairline above every group but the first, so the headers separate the list
   instead of sitting on filled blocks. */
:is(.vg-field__box, .vg-select) .ts-dropdown .optgroup + .optgroup .optgroup-header {
  margin-block-start: 4px;
  border-block-start: 1px solid var(--vgf-line);
}

/* An empty result is a state, not a list row — it was inheriting the
   optgroup-header treatment and read as a heading with no items under it.
   Centred, with the query echoed back on its own line so it is obvious WHAT
   found nothing. */
:is(.vg-field__box, .vg-select) .ts-dropdown .no-results {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 18px 12px;
  text-align: center;
}

:is(.vg-field__box, .vg-select) .ts-dropdown .no-results__msg {
  color: var(--vgf-muted);
  font-size: .8rem;
  font-weight: 500;
}

:is(.vg-field__box, .vg-select) .ts-dropdown .no-results__q {
  max-inline-size: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 2px 8px;
  border-radius: 5px;
  background: rgba(255, 255, 255, .05);
  color: var(--vgf-faint);
  font-family: var(--vg-font-mono, ui-monospace, monospace);
  font-size: .72rem;
}

:is(.vg-field__box, .vg-select) .ts-dropdown .optgroup-header {
  text-transform: uppercase;
  letter-spacing: .06em;
  font-weight: 700;
}

/* Arabic is a joining script: tracking pulls the letterforms apart and there is
   no uppercase to apply. Same escape vg-shell.css gives .vg-eyebrow. Camera
   locations are user data and are routinely Arabic. */
[dir="rtl"] :is(.vg-field__box, .vg-select) .ts-dropdown .optgroup-header {
  text-transform: none;
  letter-spacing: normal;
  font-weight: 600;
}

/* keep the dropdown usable inside RTL layouts */
/* The control's padding is logical now, so RTL needs no mirror rule for it. */

:is(.vg-field__box, .vg-select) .ts-wrapper.disabled .ts-control { opacity: .6; cursor: not-allowed; }

/* .ts-control is a focusable div (tabindex="0"), so the browser paints its default
   focus ring — a light rectangle inside our box. Focus is already communicated by
   the box's own ring (.is-ts-focus), so suppress the native one. */
:is(.vg-field__box, .vg-select) .ts-control,
:is(.vg-field__box, .vg-select) .ts-control:focus,
:is(.vg-field__box, .vg-select) .ts-control:focus-visible,
:is(.vg-field__box, .vg-select) .ts-wrapper:focus,
:is(.vg-field__box, .vg-select) .ts-wrapper:focus-visible { outline: none; box-shadow: none; }

/* The blank first <option> is the placeholder; keep it as the resting label but
   don't offer it as a choice in the list. */
:is(.vg-field__box, .vg-select) .ts-dropdown .option[data-value=""] { display: none; }

/* muted placeholder text while nothing is chosen */
:is(.vg-field__box, .vg-select) .ts-control .item[data-value=""] { color: var(--vgf-faint); }

/* Tom Select positions .ts-dropdown against the nearest positioned ancestor. With
   .ts-wrapper relative that is the area AFTER the icon, so the popup sat inset from
   the field. Anchor it to the box instead, and move the chevron there too.

   .vg-select needs the same treatment for the same reason — without it the wrapper
   is static, nothing above it is positioned either, and the popup escapes to the
   page origin (full width, far below the fold) instead of hanging off the control. */
.vg-field__box:has(.ts-wrapper),
.vg-select { position: relative; }
:is(.vg-field__box, .vg-select) .ts-wrapper { position: static; }

:is(.vg-field__box, .vg-select) .ts-wrapper::after { content: none; }

.vg-field__box:has(.ts-wrapper)::after {
  content: "";
  position: absolute;
  inset-inline-end: var(--vgf-pad-x);
  top: 50%;
  width: 12px;
  height: 8px;
  margin-top: -4px;
  pointer-events: none;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%239aa7b4' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center;
  transition: transform .18s ease;
}

.vg-field__box:has(.ts-wrapper.dropdown-active)::after { transform: rotate(180deg); }

:is(.vg-field__box, .vg-select) .ts-dropdown { left: 0; right: 0; width: auto; }


:is(.vg-field__box, .vg-select) .ts-control > .item,
:is(.vg-field__box, .vg-select) .ts-control > input {
  display: flex;
  align-items: center;
  height: 100%;
  line-height: 1;
  padding: 0;
  margin: 0;
}

/* If a search input is present (long lists), it must look like the field, not like
   a nested control — Tom Select ships its own border/background for it. */
:is(.vg-field__box, .vg-select) .ts-control > input {
  border: 0 !important;
  outline: none !important;
  background: transparent !important;
  box-shadow: none !important;
  color: var(--vgf-text);
  min-width: 4px;
}

/* ---- multi-select ---------------------------------------------------------
   Everything above is written for .ts-wrapper.single — one value, one row, a
   fixed height. A <select multiple> breaks all three assumptions: it holds N
   chips that wrap onto more rows and grow the control. Without these rules it
   fell through to Tom Select's own stylesheet, i.e. a light-theme control on a
   dark page.

   Specificity note, same trap as the .single rules document above: the shared
   `:is(.vg-field__box, .vg-select) .ts-control` block is (0,2,0) and the
   `.ts-control > .item` block is (0,3,0). `.ts-wrapper.multi` adds a class, so
   these land at (0,3,0)/(0,5,0) and win regardless of source order.
   ------------------------------------------------------------------------- */

/* The host is a fixed-height flex row; let it grow with the chips instead. */
.vg-select:has(.ts-wrapper.multi),
.vg-field__box:has(.ts-wrapper.multi) {
  block-size: auto;
  min-block-size: var(--vg-select-h, 36px);
  align-items: stretch;
}

:is(.vg-field__box, .vg-select) .ts-wrapper.multi .ts-control {
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  height: auto;
  padding-block: 4px;
}

/* Chips. height:100% from the single-value rule would stretch each one to the
   full (now variable) control height.

   No block padding: the remove_button plugin forces `padding-right:0` on the item
   so its × can sit flush, and any vertical padding here would inset the ×'s
   divider from the chip's edges — it drew an 18px rule down the middle of a 24px
   chip instead of dividing it. The height comes from min-block-size and the label
   is centred by the flex rule the single-value chips already use. */
:is(.vg-field__box, .vg-select) .ts-wrapper.multi .ts-control > .item {
  height: auto;
  min-block-size: 22px;
  padding: 0;
  padding-inline-start: 8px;
  border-radius: 6px;
  border: 1px solid var(--vgf-line-hi);
  background: rgba(255, 255, 255, .05);
  color: var(--vgf-text);
  font-size: var(--vg-ts-fs, .8125rem);
  line-height: 1.4;
}

:is(.vg-field__box, .vg-select) .ts-wrapper.multi .ts-control > .item.active {
  border-color: var(--vgf-primary);
  background: var(--vgf-ring);
}

/* remove_button's ×. align-self:stretch is what makes the divider span the chip
   rather than float in it, and the flex centring puts the glyph on the label's
   optical centre. Logical properties so it sits on the trailing edge under
   dir="rtl" too, where Tom Select's own rule would keep it left. */
:is(.vg-field__box, .vg-select) .ts-wrapper.multi .ts-control > .item > .remove {
  display: flex;
  align-items: center;
  align-self: stretch;
  margin: 0;
  margin-inline-start: 7px;
  padding: 0 6px;
  border: 0;
  border-inline-start: 1px solid var(--vgf-line-hi);
  border-radius: 0;
  color: var(--vgf-muted);
  font-size: 1rem;
  line-height: 1;
  text-decoration: none;
}

:is(.vg-field__box, .vg-select) .ts-wrapper.multi .ts-control > .item > .remove:hover {
  background: transparent;
  color: var(--vgf-text);
}

/* Narrow basis so the caret tucks in beside the last chip instead of claiming a
   row of its own; it still grows to fit whatever is typed. */
:is(.vg-field__box, .vg-select) .ts-wrapper.multi .ts-control > input {
  height: auto;
  flex: 1 1 auto;
  min-width: 4px;
}

/* ============================================================================
   Toast  —  window.vgToast(message, type)
   Non-blocking replacement for alert(). Unscoped so any dashboard page can use it.
   ========================================================================= */

.vg-toast-host {
  position: fixed;
  top: 20px;
  inset-inline-end: 20px;
  z-index: 2000;
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: min(400px, calc(100vw - 40px));
  pointer-events: none;
}

.vg-toast {
  position: relative;
  pointer-events: auto;
  padding: 13px 42px 13px 15px;
  border-radius: var(--vgf-radius);
  border: 1px solid var(--vgf-line);
  background: var(--vgf-surface);
  color: var(--vgf-text);
  font-size: .9rem;
  line-height: 1.45;
  box-shadow: 0 18px 44px rgba(0, 0, 0, .5);
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity .2s ease, transform .2s ease;
}

[dir="rtl"] .vg-toast { padding: 13px 15px 13px 42px; }

.vg-toast.is-in { opacity: 1; transform: translateY(0); }

.vg-toast--error   { border-color: rgba(252, 66, 74, .45); background: #22151a; }
.vg-toast--success { border-color: rgba(0, 210, 91, .45);  background: #10201a; }
.vg-toast--warning { border-color: rgba(255, 171, 0, .45); background: #221c10; }

.vg-toast__close {
  position: absolute;
  top: 8px;
  inset-inline-end: 8px;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--vgf-muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

.vg-toast__close:hover { color: var(--vgf-text); background: rgba(255, 255, 255, .07); }

@media (prefers-reduced-motion: reduce) {
  .vg-toast { transition: none; }
}
