/* ══════════════════════════════════════════════════════════════
 * select-upgrade.css
 *
 * The list drawn in the page, so the stylesheet decides how it looks rather
 * than the operating system.
 *
 * Every colour is a token. Nothing here is a hex except the shadows, which
 * are the same in both themes.
 * ══════════════════════════════════════════════════════════════ */

/* ── One set of tokens, whichever page this is on ───────────
 *
 * Three interfaces, two token families:
 *
 *   admin panel     --a-bg-2, --a-fg …   switch on [data-admin-theme]
 *   portal & site   --bg-2,   --fg   …   switch on [data-theme]
 *
 * The first version read only the --a-* family. On the portal and the public
 * site those never switch — theme.css defines them under
 * [data-admin-theme="light"] and nothing else — so a dark page kept the :root
 * values and the widget came out with the wrong surface against the right
 * text. That is the dark-theme bug.
 *
 * These four locals resolve to whichever family the page actually defines:
 * the portal's token first where it exists, the admin's second, a literal
 * last. A page that defines neither still gets something readable rather than
 * white on white.
 */
/*
 * The RAISED surface, not the page surface.
 *
 * This is the actual dark-theme bug. I used --bg-2 / --a-bg-2, which in dark
 * are #0A0A0A and #0A0C0F against a page of #000000 — so the list painted
 * itself almost exactly the colour of what is behind it, with a border at 16%
 * white, and the options appeared to float over the page with no panel.
 *
 * In light it happened to read, because #EFF1F4 on #F7F8FA is enough
 * separation when both are bright. In dark it was not.
 *
 * --bg-card is the token both families use for something that sits ABOVE the
 * page: #111111 on the portal, #151A21 in the admin panel. That is what a
 * dropdown is.
 */
:root {
  --xs-surface: var(--bg-card, var(--a-bg-card, #ffffff));
  /* The closed control is a form field and must match the inputs beside it.
     Those use --a-bg / --bg, the page colour — a button painted with the
     raised panel colour reads as a card sitting in the middle of a form. */
  --xs-field:   var(--bg, var(--a-bg, #ffffff));
  --xs-fg:      var(--fg,   var(--a-fg,   #12161B));
  --xs-muted:   var(--fg-muted, var(--a-fg-3, #5A6472));
  --xs-line:    var(--border-2, var(--a-border-2, rgba(18,22,27,.14)));
  --xs-accent:  var(--accent,   var(--a-accent,   #C98E1F));
}

/*
 * The admin panel defines --bg-2 nowhere, so the fallback chain above already
 * lands on --a-bg-2 there. But portal.css is loaded on the admin panel too
 * for a handful of shared components — so pin the admin family explicitly
 * where the admin attribute is present, and the chain cannot be hijacked by a
 * token that happens to exist for another reason.
 */
[data-admin-theme] {
  /* theme.css sets --a-bg-card to the same value as --a-bg-2 in dark, so this
     one names --a-bg-3 instead: #12161B against a #000000 page, which is the
     separation a floating panel needs. */
  --xs-surface: var(--a-bg-3, #12161B);
  --xs-field:   var(--a-bg, #000000);
  --xs-fg:      var(--a-fg, #E8EBEF);
  --xs-muted:   var(--a-fg-3, #78808F);
  --xs-line:    var(--a-border-2, rgba(255,255,255,.14));
  --xs-accent:  var(--a-accent, #E5A833);
}

/*
 * The wrapper carries the select's classes, so it has to ignore what they
 * would paint.
 *
 * `.a-select` sets a border, padding and a caret background image. On the
 * wrapper those would draw a second box around the button and a second arrow
 * behind it — which is the duplicate arrow, moved rather than fixed.
 *
 * Everything that draws is flattened here; everything that lays out —
 * width, max-width, flex-grow — is left alone, because that is why the classes
 * are on the wrapper at all.
 *
 * select-upgrade.css loads after select.css, so at equal specificity this
 * wins. No !important needed.
 */
.xs-wrap {
  position: relative;
  display: block;
  width: 100%;

  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  background-image: none;
  box-shadow: none;
  min-height: 0;
  /* The caret image lives in the background shorthand; appearance and outline
     are what a browser might add on its own. */
  appearance: none;
  outline: none;
}

/*
 * And the button refuses a caret from anywhere but this file.
 *
 * Belt as well as braces: if some future rule targets a select's class and
 * that class ever lands back on the button, this still leaves one arrow.
 */
.xs-btn { background-image: none }

/* ── The closed control ────────────────────────────────────── */
.xs-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  width: 100%;
  /* 44px, so it is a real target on a tablet. */
  min-height: 44px;
  padding: .55rem .85rem;
  font: inherit;
  /* start, so Arabic sits against the right edge and English the left,
     without a second rule for each. */
  text-align: start;
  color: var(--xs-fg);
  background: var(--xs-field);
  border: 1px solid var(--xs-line);
  border-radius: 8px;
  cursor: pointer;
}
.xs-btn:hover:not(:disabled) { border-color: var(--xs-accent) }
.xs-btn:disabled { opacity: .55; cursor: not-allowed }

.xs-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.xs-caret {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  fill: none;
  /* currentColor works here and not on a native select, because this one is
     an element in the page rather than a background image. */
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: .6;
  transition: transform .15s ease;
}
.xs-wrap.is-open .xs-caret { transform: rotate(180deg) }

/* ── The open list ─────────────────────────────────────────── */
.xs-list {
  /*
   * Positioned entirely by the script, which moves this to <body> while it is
   * open and sets fixed coordinates from the button.
   *
   * No inset-inline here: it would fight the inline left/width the script
   * sets, and the list would stretch to the window edge. Position is the
   * script's job now; this file keeps the appearance.
   */
  position: fixed;
  /* On <body> it competes only with modals and toasts, so it sits just above
     the escalation dialog (10000) and below nothing that matters. */
  z-index: 10050;
  overflow-y: auto;
  padding: .25rem;
  background: var(--xs-surface);
  border: 1px solid var(--xs-line);
  outline: 1px solid rgba(0,0,0,.35);
  outline-offset: -1px;
  border-radius: 10px;
  box-shadow: 0 16px 44px rgba(0,0,0,.5);
}

/* The upward flip is the script's, because it needs the button's live
   coordinates and the space actually left below it — neither of which a
   stylesheet can see. */

.xs-opt {
  padding: .5rem .7rem;
  border-radius: 6px;
  font-size: .85rem;
  color: var(--xs-fg);
  cursor: pointer;
  text-align: start;
}
.xs-opt.is-active { background: var(--xs-line) }
.xs-opt.is-sel    { color: var(--xs-accent); font-weight: 600 }
.xs-opt[aria-disabled="true"] { opacity: .45; cursor: not-allowed }

.xs-group {
  padding: .5rem .7rem .25rem;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--xs-muted);
  text-align: start;
}

/* ── The real select, still in the form ────────────────────── *
 *
 * `select.xs-native`, not `.xs-native`.
 *
 * select.css styles every dropdown with
 * `select:not([multiple]):not([size])`, and `:not()` takes the specificity of
 * its argument — so that selector weighs (0,2,1) while a bare `.xs-native`
 * weighs (0,1,0). It won. The hidden select kept its caret background image
 * and its 2.4rem padding and painted them over the button, which is the mark
 * on the closed control that the open list never had.
 *
 * `select.xs-native` is (0,1,1) — still short. `select.xs-native.xs-native`
 * is (0,2,1), matching it, and later in the cascade, so it wins outright.
 * Repeating a class to raise specificity is ugly and it is the honest way to
 * beat a selector you do not want to weaken for everything else.
 */
select.xs-native.xs-native {
  /*
   * A one-pixel box at the start of the control, not a full overlay.
   *
   * The overlay was the other half of the problem: anything the browser
   * insisted on painting had the whole button to paint on. One pixel behind
   * the button has nowhere to go.
   *
   * Still a rendered box with a size, so it stays focusable — which is what
   * `required` needs. A display:none or visibility:hidden select makes the
   * browser refuse the submit with "An invalid form control is not focusable"
   * and nothing on screen.
   */
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0;
  width: 1px;
  height: 1px;
  min-height: 0;
  padding: 0;
  margin: 0;
  border: 0;
  opacity: 0;
  pointer-events: none;
  z-index: 0;

  /* Every paintable property select.css sets, cancelled explicitly. Belt as
     well as braces: a future rule cannot bring the caret back. */
  appearance: none;
  background: none;
  background-image: none;
  box-shadow: none;
  outline: none;
}

.xs-btn { position: relative; z-index: 1 }

@media (prefers-reduced-motion: reduce) {
  .xs-caret { transition: none }
}

/* Drop 808: the open list reads clearly — one line per option, comfortable rows, long names end with … and show in full on hover */
.xs-list { min-width: 11rem; max-width: min(30rem, calc(100vw - 16px)); padding: .35rem; }
.xs-opt { padding: .58rem .8rem; line-height: 1.35; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.xs-opt + .xs-opt { margin-top: 1px; }
.xs-list [role="group"] > .xs-group, .xs-group { padding: .45rem .8rem .25rem; font-size: .72rem; font-weight: 700; color: var(--xs-muted, inherit); opacity: .75; white-space: nowrap; }
