/* ==========================================================================
   Launcher controls
   --------------------------------------------------------------------------
   Toggles, sliders, fields, colour swatches, key pickers and the drawn
   dropdown, in the launcher's own idiom rather than the browser's. Used by the
   mod and plugin config editor, where a real install has 2,344 settings across
   119 files - a screen of raw text boxes for values that are actually booleans,
   bounded numbers and closed lists would be unusable.

   Every control here degrades to a working native input if its script does not
   load: the toggle IS a checkbox, the slider IS a range beside a number box
   that carries the field name, and a dropdown IS the <select> it was drawn
   from. Nothing is a div pretending to be a form field.

   Loaded LAST on admin.php, after assets/admin.css, so a tie on specificity
   falls this way. The defaults below are deliberately kept at (0,1,0) so the
   (0,2,0) rules in admin.css - .admin-field, .ed-toolbar - still win where a
   control has to take the shape of the form around it.

   Scrollbars are NOT styled here. home-style.css defines them globally for the
   whole launcher; a second definition scoped to one area is exactly how they
   came to differ once already.
   ========================================================================== */

:root {
    /* One definition of "this has keyboard focus", used by every control below.
       Chromium's own ring on Windows is a black-and-white double line over
       whatever the OS accent is - the combination that belongs to nothing here. */
    --oasis-focus-outline: 2px solid var(--tarkov-gold);
    --oasis-focus-offset: 2px;
    --oasis-field-bg: #080808;
    --oasis-field-glow: 0 0 10px rgba(180, 160, 114, 0.28);
}

/* Where the focus rings are: at the FOOT of this file, under "keyboard focus",
   one rule per control. They were a single blanket rule here at the top and it did
   not work - `.oasis-slider :focus-visible` and `.oasis-slider-value:focus` are
   both (0,2,0), and on a tie the later rule wins, so every `outline: none` written
   below to keep a mouse click from ringing a box was also erasing the ring a
   keyboard user needs. The mirrored rules at the end win by coming last. */

/* ---------------------------------------------------------------- toggle ---
   A checkbox drawn as a switch. The input stays in the DOM and stays the thing
   that submits; :checked on it drives everything below, so no script is
   involved in it working. */
.oasis-toggle {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    user-select: none;
}
.oasis-toggle input[type="checkbox"] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}
.oasis-toggle-track {
    position: relative;
    width: 44px;
    height: 22px;
    flex: 0 0 auto;
    background: #0a0a0a;
    border: 1px solid var(--panel-border);
    /* Named properties, not the `0.22s` shorthand that means `all`. outline is animatable,
       so `all` made every focus ring in this file fade in from the browser's grey one over
       the whole duration rather than appear - a ring that arrives late is not a ring. */
    transition: background-color 0.22s, border-color 0.22s, box-shadow 0.22s;
}
.oasis-toggle-track::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 16px;
    height: 16px;
    background: var(--text-muted);
    transition: left 0.22s, background-color 0.22s, box-shadow 0.22s;
}
.oasis-toggle:hover .oasis-toggle-track { border-color: var(--tarkov-gold); }
.oasis-toggle input:checked + .oasis-toggle-track {
    background: rgba(180, 160, 114, 0.18);
    border-color: var(--tarkov-gold);
    box-shadow: inset 0 0 10px rgba(180, 160, 114, 0.25);
}
.oasis-toggle input:checked + .oasis-toggle-track::after {
    left: 24px;
    background: var(--tarkov-gold);
    box-shadow: 0 0 8px rgba(180, 160, 114, 0.8);
}
/* Keyboard focus has to be drawn on the track, because the input it belongs to is
   the invisible one and an outline on a 0x0 box is nothing. */
.oasis-toggle input:focus-visible + .oasis-toggle-track {
    outline: var(--oasis-focus-outline);
    outline-offset: var(--oasis-focus-offset);
}
/* cursor on the track rather than on the label, because the track is where the pointer
   is when someone tries a switch that is off limits, and reaching the label from here
   would need :has() for the sake of a cursor. */
.oasis-toggle input:disabled + .oasis-toggle-track { opacity: 0.45; cursor: default; }

.oasis-toggle-label {
    font-size: 11px;
    letter-spacing: 1px;
    color: var(--text-muted);
    min-width: 34px;
}
.oasis-toggle input:checked ~ .oasis-toggle-label { color: var(--tarkov-gold); }

/* ---------------------------------------------------------------- slider ---
   A range and a number box, each editing the same value. The range is for
   finding a value; the box is for typing an exact one, which a range cannot do
   at any useful width. Only the box carries the field name, so what is submitted
   is what was read - with or without the script. */
.oasis-slider {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-width: 0;
}
.oasis-slider input[type="range"] {
    flex: 1 1 auto;
    min-width: 0;
    height: 22px;
    background: transparent;
    -webkit-appearance: none;
    appearance: none;
    cursor: pointer;
}
/* The two engines need the track and thumb declared separately - a combined
   selector list is dropped whole by both if either half is unknown. */
.oasis-slider input[type="range"]::-webkit-slider-runnable-track {
    height: 4px;
    background: linear-gradient(90deg, var(--tarkov-gold) 0%, var(--tarkov-gold) var(--fill, 0%),
                #1a1a1a var(--fill, 0%), #1a1a1a 100%);
    border: 1px solid var(--panel-border);
}
.oasis-slider input[type="range"]::-moz-range-track {
    height: 4px;
    background: #1a1a1a;
    border: 1px solid var(--panel-border);
}
.oasis-slider input[type="range"]::-moz-range-progress {
    height: 4px;
    background: var(--tarkov-gold);
}
.oasis-slider input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 12px;
    height: 18px;
    margin-top: -8px;
    background: var(--tarkov-gold);
    border: 1px solid #000;
    box-shadow: 0 0 8px rgba(180, 160, 114, 0.6);
    cursor: grab;
}
.oasis-slider input[type="range"]::-moz-range-thumb {
    width: 12px;
    height: 18px;
    border-radius: 0;
    background: var(--tarkov-gold);
    border: 1px solid #000;
    box-shadow: 0 0 8px rgba(180, 160, 114, 0.6);
    cursor: grab;
}
.oasis-slider input[type="range"]:active::-webkit-slider-thumb { cursor: grabbing; }
/* The range is a tab stop and the arrow keys move it, so it needs a ring of its
   own - the thumb's glow is not a focus state, it is there all the time. */
.oasis-slider input[type="range"]:focus-visible {
    outline: var(--oasis-focus-outline);
    outline-offset: var(--oasis-focus-offset);
}

.oasis-slider-value {
    flex: 0 0 auto;
    width: 82px;
    background: var(--oasis-field-bg);
    border: 1px solid var(--panel-border);
    color: var(--tarkov-gold);
    padding: 6px 8px;
    font-family: inherit;
    font-size: 11px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.oasis-slider-value:hover { border-color: var(--tarkov-gold); }
.oasis-slider-value:focus {
    outline: none;
    border-color: var(--tarkov-gold);
    box-shadow: var(--oasis-field-glow);
}
/* The stated bounds, so the reader knows what the track spans without dragging
   it to each end. */
.oasis-slider-bounds {
    flex: 0 0 auto;
    font-size: 9px;
    letter-spacing: 1px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* --------------------------------------------------- text / number field ---
   The library's plain field, and the box every other control here is measured
   against.

   The second half of this selector is the load-bearing one. A setting row puts
   whatever the value needs into its control column, and a mod's string setting
   is a bare text box while an unbounded number is a bare number box - neither
   carries a class. Unstyled, they are white, oversized, and the only light
   rectangles on a black page. Matched on the DIRECT child so the classed inputs
   nested inside .oasis-slider / .oasis-color / .oasis-keybind keep their own
   widths instead of being stretched to 100% by a more specific selector. */
.oasis-field,
.setting-control > input:not([class]):not([type="hidden"]),
.setting-control > select:not([class]),
.setting-control > textarea:not([class]) {
    width: 100%;
    max-width: 100%;
    background: var(--oasis-field-bg);
    border: 1px solid var(--panel-border);
    color: #ddd;
    padding: 8px 10px;
    font-family: inherit;
    font-size: 12px;
    letter-spacing: 1px;
}
.oasis-field:hover,
.setting-control > input:not([class]):not([type="hidden"]):hover,
.setting-control > select:not([class]):hover,
.setting-control > textarea:not([class]):hover { border-color: var(--tarkov-gold); }

.oasis-field:focus,
.setting-control > input:not([class]):not([type="hidden"]):focus,
.setting-control > select:not([class]):focus,
.setting-control > textarea:not([class]):focus {
    outline: none;
    border-color: var(--tarkov-gold);
    box-shadow: var(--oasis-field-glow);
}
.oasis-field[readonly],
.oasis-field:disabled { opacity: 0.55; cursor: default; }

/* Numbers line up when they are read down a column, which is the only way a page
   of settings is ever read. */
.oasis-field[type="number"],
.setting-control > input[type="number"] { font-variant-numeric: tabular-nums; }

/* The seconds before select.js reaches a dropdown, and the whole of the case where
   it never loads. The same treatment home-ui.css gives .contact-select option, and
   for the same reason: a dropped OS list is drawn on a surface CSS cannot reach, but
   the option colours it starts from are ours to set. A list box - a multiple select,
   which the browser draws inline rather than dropping - can be reached properly, so
   its selected rows get the gold bar and black lettering the drawn list uses. */
.setting-control select option { background: #0c0c0c; color: #ddd; }
.setting-control select option:disabled { color: #666; }
.setting-control select[multiple] option:checked {
    background: var(--tarkov-gold) linear-gradient(var(--tarkov-gold), var(--tarkov-gold));
    color: #000;
}

/* --------------------------------------------------------- colour picker ---
   A native colour input framed like everything else, plus the hex, because the
   swatch alone tells you nothing you can write down or compare. */
.oasis-color { display: flex; align-items: center; gap: 10px; }
.oasis-color input[type="color"] {
    width: 42px;
    height: 30px;
    padding: 0;
    background: var(--oasis-field-bg);
    border: 1px solid var(--panel-border);
    cursor: pointer;
}
.oasis-color input[type="color"]:hover { border-color: var(--tarkov-gold); }
.oasis-color input[type="color"]:focus { outline: none; border-color: var(--tarkov-gold); }
.oasis-color-hex {
    width: 130px;
    background: var(--oasis-field-bg);
    border: 1px solid var(--panel-border);
    color: #ddd;
    padding: 6px 8px;
    font-family: inherit;
    font-size: 11px;
    letter-spacing: 1px;
}
.oasis-color-hex:hover { border-color: var(--tarkov-gold); }
.oasis-color-hex:focus {
    outline: none;
    border-color: var(--tarkov-gold);
    box-shadow: var(--oasis-field-glow);
}
/* Set by controls.js when what is typed is not a colour the swatch can take. A
   red edge rather than a sentence under the box: the value is still allowed
   through - BepInEx colours are frequently RGBA floats - it just cannot be
   previewed, and the swatch going stale silently is what confuses people. */
.oasis-color-hex.is-unpreviewable { border-color: rgba(184, 70, 61, 0.55); }

/* ------------------------------------------------------------ key picker ---
   Reuses the drawn caps from assets/keycaps.css, so a keybind setting shows the
   key rather than the words "LeftControl+K". */
.oasis-keybind {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
.oasis-keybind-preview { display: inline-flex; align-items: center; gap: 3px; min-height: 32px; }
.oasis-keybind-capture {
    padding: 7px 12px;
    border: 1px solid var(--panel-border);
    background: #0f0f0f;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 10px;
    letter-spacing: 2px;
    cursor: pointer;
    transition: color 0.2s, background-color 0.2s, border-color 0.2s, box-shadow 0.2s;
}
.oasis-keybind-capture:hover {
    color: #000;
    background: var(--tarkov-gold);
    border-color: var(--tarkov-gold);
}
.oasis-keybind-capture:focus-visible {
    outline: var(--oasis-focus-outline);
    outline-offset: var(--oasis-focus-offset);
}
.oasis-keybind-capture.is-listening {
    color: #000;
    background: var(--tarkov-gold);
    border-color: var(--tarkov-gold);
    box-shadow: 0 0 14px rgba(180, 160, 114, 0.55);
}
.oasis-keybind-raw {
    flex: 1 1 160px;
    min-width: 0;
    background: var(--oasis-field-bg);
    border: 1px solid var(--panel-border);
    color: #ddd;
    padding: 6px 8px;
    font-family: inherit;
    font-size: 11px;
}
.oasis-keybind-raw:hover { border-color: var(--tarkov-gold); }
.oasis-keybind-raw:focus {
    outline: none;
    border-color: var(--tarkov-gold);
    box-shadow: var(--oasis-field-glow);
}

/* ======================================================== drawn dropdown ===
   assets/select.js replaces the OS option list with one it draws. The shape of
   the trigger and the list lives in assets/home-ui.css, because the contacts
   picker on the launcher's own pages uses it and must not depend on an admin
   stylesheet. What is here is only what that sheet cannot know about.
   ========================================================================== */

/* select.js copies the original <select>'s class list onto the button it draws,
   which is how the contacts picker keeps its own look. A <select> with no class
   left the button with none either, and a bare <button> is a light grey OS
   control in the middle of a dark form - the "white and oversized" that keeps
   coming back. This is the box it falls back to.

   Kept at (0,1,0) on purpose: .admin-field .oasis-select-trigger and
   .ed-toolbar .oasis-select-trigger in admin.css are (0,2,0) and still win, so a
   trigger inside a form field or a toolbar takes that shape rather than this. */
.oasis-select-trigger {
    background: var(--oasis-field-bg);
    border: 1px solid var(--panel-border);
    color: #ddd;
    padding: 8px 10px;
    font-family: inherit;
    font-size: 12px;
    letter-spacing: 1px;
    cursor: pointer;
    transition: border-color 0.2s, box-shadow 0.2s;
}
.oasis-select-trigger:hover { border-color: var(--tarkov-gold); }
.oasis-select-trigger:focus-visible {
    outline: var(--oasis-focus-outline);
    outline-offset: var(--oasis-focus-offset);
}

/* The list is fixed-positioned against the viewport by the script, so nothing
   that scrolls can clip it - which also means it has to clear the sticky editor
   bar and the modals it may open over. */
.oasis-select-list { z-index: 9998; }

/* The enhanced <select> itself, kept in the page as the thing that submits and the
   thing assistive tech reads, and hidden because the trigger is what is on screen.
   home-ui.css hides it with .oasis-select-native, which is (0,1,0) - and
   `.admin-field select` is (0,2,0), so on every admin form it was putting width:100%
   and 10px of padding straight back on. clip-path was still covering for it, which is
   why nothing was visible, but a full-width native select sitting under a clip is one
   changed property away from being on top of the control that replaced it. Restated
   here at (0,2,1), which nothing on an admin form beats. */
.oasis-select > select.oasis-select-native {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip-path: inset(50%);
}

/* An <optgroup> heading. Without this the group labels of a grouped select - the
   key catalogue on the mechanics page is grouped by keyboard region - disappeared
   the moment the list was drawn, leaving 79 codes in one flat run. Sticky, so the
   heading of the group being scrolled through stays legible. */
.oasis-select-group {
    position: sticky;
    top: 0;
    z-index: 1;
    padding: 6px 10px 4px;
    background: #0a0a0a;
    border-top: 1px solid var(--panel-border);
    color: var(--tarkov-gold);
    font-size: 9px;
    font-weight: bold;
    letter-spacing: 2px;
    text-transform: uppercase;
    cursor: default;
}
.oasis-select-group:first-child { border-top: 0; }
.oasis-select-option.in-group { padding-left: 20px; }

/* A select with nothing in it still has to open into something, or the click reads
   as a control that is broken rather than one that is empty. */
.oasis-select-empty {
    padding: 10px;
    font-size: 10px;
    letter-spacing: 1px;
    color: var(--text-muted);
    cursor: default;
}

/* ----------------------------------------------------- multi-select list ---
   Drawn by assets/select.js when the underlying <select> carries `multiple`.
   The trigger reports the count; the list checks items rather than closing on
   the first pick. */
.oasis-select-option.is-multi { display: flex; align-items: center; gap: 9px; }
.oasis-select-check {
    flex: 0 0 auto;
    width: 13px;
    height: 13px;
    border: 1px solid var(--panel-border);
    position: relative;
}
.oasis-select-option.is-checked .oasis-select-check {
    border-color: var(--tarkov-gold);
    background: var(--tarkov-gold);
}
/* The tick is drawn rather than a glyph, so it inherits the row's colour when
   the row is highlighted gold-on-black. */
.oasis-select-option.is-checked .oasis-select-check::after {
    content: "";
    position: absolute;
    left: 4px;
    top: 1px;
    width: 3px;
    height: 7px;
    border: solid #000;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}
.oasis-select-option.is-multi.is-checked { color: var(--tarkov-gold); }
.oasis-select-option.is-multi.is-checked:hover,
.oasis-select-option.is-multi.is-checked.is-active { color: #000; }

/* The actions at the foot of a multi-select list: select all, clear. An <li>
   rather than a <div>, because the list is a <ul> and a div in there is not
   markup - and sticky, because with a long enum, scrolling back to the top to
   clear a selection is worse than the selection itself. */
.oasis-select-actions {
    display: flex;
    gap: 6px;
    padding: 6px 8px;
    border-top: 1px solid var(--panel-border);
    background: #0a0a0a;
    position: sticky;
    bottom: 0;
    z-index: 2;
    list-style: none;
}
.oasis-select-actions button {
    flex: 1 1 auto;
    padding: 5px 8px;
    background: #141414;
    border: 1px solid var(--panel-border);
    color: var(--text-muted);
    font-family: inherit;
    font-size: 9px;
    letter-spacing: 1px;
    cursor: pointer;
}
.oasis-select-actions button:hover {
    color: #000;
    background: var(--tarkov-gold);
    border-color: var(--tarkov-gold);
}
/* Inset, because the button sits hard against the list's own gold border and an
   outward ring would land on top of it. */
.oasis-select-actions button:focus-visible {
    outline: var(--oasis-focus-outline);
    outline-offset: -3px;
}

/* ---------------------------------------------------------- setting rows ---
   One row per setting in the config editor: what it is on the left, the control
   on the right. */
.setting-row {
    display: grid;
    grid-template-columns: minmax(200px, 320px) minmax(0, 1fr);
    gap: 18px;
    align-items: start;
    padding: 12px 0;
    border-bottom: 1px solid rgba(180, 160, 114, 0.1);
}
.setting-row:last-child { border-bottom: 0; }
.setting-row.is-changed { background: rgba(180, 160, 114, 0.06); }

/* The filter hides rows by setting .hidden, and `display: grid` above would
   quietly beat the browser's own `[hidden] { display: none }` - an author rule
   outranks the user-agent sheet whatever the specificity says. Without this line
   the filter counts down correctly and hides nothing at all. The same trap
   catches anything in this file that is both hideable and given a display. */
.setting-row[hidden],
[data-section-block][hidden] { display: none; }

.setting-name {
    font-size: 12px;
    color: var(--text-primary);
    letter-spacing: 0.5px;
    overflow-wrap: anywhere;
}
.setting-desc {
    font-size: 10px;
    line-height: 1.55;
    color: var(--text-muted);
    margin-top: 4px;
}
.setting-meta {
    font-size: 9px;
    letter-spacing: 1px;
    color: var(--text-muted);
    margin-top: 5px;
    opacity: 0.8;
}
.setting-control { min-width: 0; }

/* Shown against a setting whose value is no longer its default, so an admin can
   see at a glance what has been changed from stock. */
.setting-default-flag {
    display: inline-block;
    margin-left: 8px;
    padding: 1px 6px;
    border: 1px solid var(--tarkov-gold);
    color: var(--tarkov-gold);
    font-size: 8px;
    letter-spacing: 1px;
}
/* Same trap as .setting-row: the display above would win over the UA sheet, and
   the CHANGED flag would never go away once it had been shown. */
.setting-default-flag[hidden] { display: none; }

.setting-reset {
    margin-left: 8px;
    padding: 2px 7px;
    background: transparent;
    border: 1px solid var(--panel-border);
    color: var(--text-muted);
    font-family: inherit;
    font-size: 8px;
    letter-spacing: 1px;
    cursor: pointer;
}
.setting-reset:hover {
    color: #000;
    background: var(--tarkov-gold);
    border-color: var(--tarkov-gold);
}
.setting-reset:focus-visible {
    outline: var(--oasis-focus-outline);
    outline-offset: var(--oasis-focus-offset);
}
/* A row already at its default has nothing to reset. Dimmed rather than removed,
   so the buttons do not jump around the column as values are edited. */
.setting-reset:disabled { opacity: 0.3; cursor: default; }
.setting-reset:disabled:hover {
    color: var(--text-muted);
    background: transparent;
    border-color: var(--panel-border);
}

@media (max-width: 820px) {
    .setting-row { grid-template-columns: 1fr; gap: 8px; }
}

/* ======================================================== keyboard focus ===
   Every ring, last in the file and on purpose.

   Each control above turns the browser's ring off on :focus, because a mouse
   click should light the border and glow rather than draw a line around the box.
   That leaves the keyboard with nothing, and these put it back - one rule per
   control, each written to at least the weight of the `outline: none` it has to
   beat, and placed here so that where the weights tie it is these that win. A
   ring declared before them is a ring that never appears.

   :focus-visible, not :focus, is what keeps the two cases apart: the browser only
   matches it when the focus came from the keyboard.
   ========================================================================== */
.oasis-slider .oasis-slider-value:focus-visible,
.oasis-color .oasis-color-hex:focus-visible,
.oasis-color input[type="color"]:focus-visible,
.oasis-keybind .oasis-keybind-raw:focus-visible,
.oasis-select-trigger:focus-visible,
.oasis-field:focus-visible,
.setting-control > input:not([class]):not([type="hidden"]):focus-visible,
.setting-control > select:not([class]):focus-visible,
.setting-control > textarea:not([class]):focus-visible {
    outline: var(--oasis-focus-outline);
    outline-offset: var(--oasis-focus-offset);
}
