/**
 * Cross-theme reset for legacy submodule (themes/default/css/main.css) styles
 * that don't match any currently active theme's palette. Loaded by
 * ThemesFacade::onPrepareUserThemes first, so tokens.css / header.css /
 * themes/{ident}.css all win on source order.
 *
 * Scope: only rules that apply to every theme. Per-theme tweaks belong in
 * themes/{ident}.css; structural layout for the shared header.phtml lives
 * in header.css. Owner: ED-7385 modern-as-CSS-override migration.
 */

/* ============ Header — hide-menu button skin ============
   Submodule ships three admin-template skins for the hide-menu button —
   base, :active pressed-state, and the .hidden-menu (sidebar collapsed)
   variant — all hard-coded light/dark grey gradients with inset shadow.
   None of those skins match the themed header, so clear them globally.
   Per-theme files may still set a solid swatch on the same selectors. */
.btn-header > :first-child > a,
.btn-header > :first-child > a:active,
.hidden-menu #hide-menu > :first-child > a {
    background: transparent;
    background-image: none;
    border: none;
    box-shadow: none;
    color: var(--header-fg);
}

/* ============ Header — workspace selector nested in #hide-menu ============
   The workspace selector (.project-context plus its dropdown) is rendered inside
   #hide-menu, so the submodule's broad menu-toggle-button rules leak into it:
     • `#hide-menu i::before { content:"\f0c9" }` turns the angle-down chevron
       into a hamburger glyph below 768px;
     • `#hide-menu i { color:… }` paints the chevron grey instead of matching the
       selector text;
     • `.btn-header a { line-height:38px }` (mobile) inflates the dropdown rows.
   Re-assert the correct values. The #hide-menu prefix plus the extra classes
   outrank the submodule / per-theme rules regardless of CSS load order. */
#hide-menu .project-selector i.fa-angle-down::before {
    content: "\f107";
}

/* Chevron follows the selector text colour (white on themed headers) instead of
   the grey the submodule paints menu-toggle icons. `inherit` keeps it theme-aware. */
#hide-menu .project-selector i.fa-angle-down {
    color: inherit;
}

/* Below 980px the menu-toggle line-height (38px) leaks onto the dropdown links
   via `.btn-header a`, making each row oversized. Restore a normal row height. */
@media (max-width: 979px) {
    #hide-menu .b-dropdown-menu li > a {
        line-height: 22px !important;
    }
}

/* Cap the workspace name on desktop so an over-long name truncates with an
   ellipsis (the element already sets overflow/ellipsis/nowrap) instead of
   stretching the header — some names run ~500px wide. Mobile keeps the
   responsive `max-width:95%` from the per-theme files. */
@media (min-width: 980px) {
    #hide-menu .project-selector-text {
        max-width: 400px;
    }
}

/* ============ Page title — trim oversized vertical margin ============
   The submodule base (themes/{default,modern_old}/css/main.css) sets
   `.page-title { margin: 12px 0 28px }`, whose 28px bottom gap pushes page
   content down too far. Tighten to a balanced 10px (the value overwatch already
   uses). reset.css loads after main.css/db.css in head.phtml, so this plain
   selector wins on source order; overwatch re-asserts the same value. */
.page-title {
    margin: 10px 0;
}

/* ============ Headings — drop the crowding negative tracking ============
   The submodule base (themes/{default,modern_old}/css/main.css) sets
   `letter-spacing:-1px` on h1, `h1 small` and h2. At 22-24px that pulls the
   glyphs together and reads badly, especially for Cyrillic. Reset to normal
   tracking for every theme. Same specificity as the submodule rules, and
   reset.css loads after main.css, so these win on source order. */
h1,
h1 small,
h2 {
    letter-spacing: normal;
}

/* ============ Sidebar — no slide on initial collapse ============
   The pet helper (Gamification/templates/helper.phtml site-wide, dashboard.phtml
   on /dashboard/) restores the collapsed-menu preference from localStorage by
   adding `body.hidden-menu` — but only once the script runs, after the sidebar
   has already painted expanded. The submodule base animates #left-panel/#main
   with a `.1s` transition, so the sidebar visibly slid shut on every load /
   workspace switch. Those templates add `.no-menu-transition` before that
   initial application and drop it on the next frame, so the collapsed state
   appears without animating; user-initiated toggles afterwards still slide. */
.no-menu-transition #left-panel,
.no-menu-transition #content,
.no-menu-transition #main {
    transition: none !important;
}

/* ============ Mobile DGS — left-align the value column ============
   In the mobile grid layout (mobile-body.phtml) each field renders as a
   `label : value` row, and the submodule right-aligns the whole value column via
   `.b-db-table[data-mobile] .b-dgs-table-container .e-table-head { text-align:right }`.
   Right-aligned values read awkwardly — push every value cell back to the left.
   Same specificity as the submodule rule, and reset.css loads after
   main-mobile.css, so it wins on source order. */
.b-db-table[data-mobile] .b-dgs-table-container .e-table-head {
    text-align: left;
}

/* The submodule hides the native list bullet (`ul { list-style-type:none }`)
   and re-renders it as a TRAILING `li:after { content:'•' }`, which sat after
   the text on the right — fine while the column was right-aligned, but now that
   the value column is left-aligned (above) the trailing bullet reads as a marker
   on the wrong side. Restore the native left-hand bullet instead: re-enable
   list-style with a small inline-start padding for the marker box, and drop the
   trailing pseudo-bullet. Both overrides match the submodule rules' specificity
   and win on source order. */
.b-db-table[data-mobile] .b-dgs-table-container .e-table-head ul {
    list-style-type: disc;
    padding-inline-start: 10px;
}

.b-db-table[data-mobile] .b-dgs-table-container .e-table-head li:after {
    content: none;
}

/* ============ Sidebar — wrap long menu labels ============
   Long navigation labels must wrap onto the next line instead of being clipped
   by the fixed-width sidebar. The legacy submodule keeps second/third-level
   anchors `display:block`, and overwatch wraps via `nav ul li a { display:flex }`
   — both rely on the browser default, which a narrow sidebar or an over-long
   single word can still clip. Guarantee wrapping (and break one over-long word)
   for every theme. `#left-panel` raises specificity above the per-theme nav
   rules so this holds regardless of CSS load order. */
#left-panel nav ul li a,
#left-panel nav span.menu-item-parent,
#left-panel nav span.sub-menu-item {
    white-space: normal;
    overflow-wrap: break-word;
}

/* ============ Inputs — themed focus colour ============
   The legacy submodule (themes/default base + bootstrap) paints input focus a
   fixed light blue (`.form-control:focus { border-color:#66afe9 }`) and turns a
   focused text input's trailing addon a hard-coded blue with white text
   (`input[type="text"]:focus + .input-group-addon`). Neither tracks the active
   theme. Re-point them at the focus/primary tokens so the focus ring adopts each
   theme's palette. Same specificity as the submodule rules, and reset.css loads
   after them, so these win on source order. The .has-error / .has-warning /
   .has-success addon variants are more specific and keep their state colours. */
.form-control:focus {
    border-color: var(--input-focus-border);
}

input[type="text"]:focus + .input-group-addon {
    border-color: var(--input-focus-border);
    background-color: var(--color-primary);
    color: var(--color-primary-fg);
}

/* ============ Sidebar — hide the login-info user block ============
   The shared left_panel renders a `.login-info` block (avatar + user name) at
   the top of the sidebar. Product decision: hide it in every theme. The legacy
   submodule and the per-theme files re-assert `display` on `.login-info` and on
   the higher-specificity `.minified .login-info` (collapsed-sidebar) state, so
   force it off to win across all themes and states. */
.login-info {
    display: none !important;
}

/* ============ Links — themed colour ============
   The legacy submodule paints the base link colour a fixed blue
   (`a { color:#3276b1 }`). Point it at the link token so links adopt the active
   theme's primary. Same specificity as the submodule rule, and reset.css loads
   after it, so this wins on source order; per-theme / more specific `a` rules
   (header links, buttons, etc.) still override. */
a {
    color: var(--link-fg);
}

/* ============ Tabs — active-tab accent ============
   The submodule underlines the active tab with a hard-coded blue shadow
   (`.nav-tabs > li.active > a { box-shadow:0 -2px 0 #5384AF }`, plus the
   tabs-left/right/below directional variants). Re-point the accent at the primary
   token; only the shadow is overridden, so the submodule's other active-tab
   properties (border, margin, font-weight) stay. */
.nav-tabs > li.active > a {
    box-shadow: 0 -2px 0 var(--color-primary);
}

.tabs-left .nav-tabs > li.active > a {
    box-shadow: -2px 0 0 var(--color-primary);
}

.tabs-right .nav-tabs > li.active > a {
    box-shadow: 2px 0 0 var(--color-primary);
}

.tabs-below .nav-tabs > li.active > a {
    box-shadow: 0 2px 0 var(--color-primary);
}

/* ============ select2 multi-select chips — themed background ============
   The submodule (themes/{default}/css/main.css) paints multi-select tag chips
   the legacy bootstrap blue (#3276B1 fill, #285E8E darker border, #285E8E
   focus fill). Re-point them at the primary tokens so the chips adopt each
   theme's brand. Same specificity as the submodule rules, and reset.css loads
   after main.css, so these win on source order. */
.select2-container-multi .select2-choices .select2-search-choice {
    background-color: var(--color-primary);
    border-color: var(--color-primary-active);
    color: var(--color-primary-fg);
}

.select2-container-multi .select2-choices .select2-search-choice-focus {
    background: var(--color-primary-active);
}

/* ============ select2 dropdown — no horizontal page shift inside dialogs ============
   The m2m fields (Library, Class Schedule "Add" store dialogs) use select2 v3,
   which appends its dropdown (.select2-drop) and a full-document click-mask
   (.select2-drop-mask, position:absolute; left:0) to <body> and sizes them from
   the document scroll width. Inside a dialog on mobile that width can exceed the
   viewport, so the mask makes the page behind horizontally scrollable and the
   dropdown drifts out of line with its field. html already sets
   overflow-x:hidden, but the absolutely-positioned mask still extends the scroll
   area — clamp both to the viewport so they can't introduce horizontal overflow.
   The inline width select2 sets on the drop is always <= the field width, so the
   clamp only ever caps the runaway mask, never a legitimately sized dropdown. */
.select2-drop-mask,
.select2-drop {
    max-width: 100vw;
}

/* ============ Modal open — lock the page behind the dialog ============
   The base .modal-open lock (main.css: position:fixed; overflow:hidden) is
   overridden by the theme's db.css to
     body.modal-open { position:absolute; overflow:visible; width/height:100% }
   which leaves the page scrollable/pannable behind an open dialog. Since
   select2 (v3) appends its dropdown to <body> and positions it from the field's
   document offset, any background movement shifts the dropdown off its field
   (m2m "Add" dialogs, e.g. Class Schedule / Library).

   Two things are needed:

   1. Freeze the document scroller. The real scroll container is <html>
      (overflow-y auto; body is a tall static box), so overflow:hidden here
      freezes the current offset with no jump and leaves <body> untranslated.
      Do NOT lock by making body position:fixed with a top offset: that shifts
      body's origin and breaks select2's positionDropdown math, throwing the
      dropdown off-screen when it flips above the field in a short (landscape)
      viewport.

   2. Remove the horizontal pan surface. db.css's `position:absolute` makes the
      background document-anchored; on a page whose background overflows
      horizontally (a wide grid, the off-screen sidebar) touch devices still pan
      it — iOS/WKWebView ignores overflow:hidden for the pan gesture — and the
      body-appended dropdown rides along while the position:fixed dialog/field
      stay put. (/lesson-timesheet/ has no horizontal overflow, so it looked
      fine.) Reverting <body> to its normal in-flow box while locked removes
      that pan surface. Its normal box is `position: relative` (the theme sets
      that, plus z-index:0) — NOT `static`: a themed background paints its
      `body::before` layer (z-index:-1) above the base `body { background }`
      only because that relative+z-index makes <body> a stacking context.
      Setting `position: static` here drops the stacking context, so the
      themed `body::before` falls behind the base background and the whole page
      background visibly changes the moment a dialog opens. `relative` (with no
      offset) is also select2's positioning baseline, so the dropdown math stays
      exact. The dialog scrolls on its own (.b-store-dialog overflow-y:scroll),
      so tall forms are unaffected.

   The `modal-scroll-locked` class is toggled on <html> by modal_scroll_lock.js
   while any dialog is open. Both rules out-specify db.css (reset.css loads after
   it), so no !important is needed. */
html.modal-scroll-locked {
    overflow: hidden;
}

html.modal-scroll-locked body {
    position: relative;
    overflow: hidden;
    height: auto;
}

/* ============ react-select option menus — brand hover/selected ============
   react-select (classNamePrefix="select", used by the Tests quiz builder's
   Subject / Grade level / question-type fields, among others) colours the
   focused option its own default light blue (#DEEBFF) and the selected option
   #2684FF — neither tracks the theme, so the menus read off-brand. Re-point the
   focused (hover/keyboard) and selected options at the primary tokens, matching
   every other dropdown on the platform. react-select injects its styles via
   emotion at runtime (after this file) and some menus portal to <body>, so the
   rule is global and !important. */
.select__option--is-focused {
    background-color: var(--color-primary) !important;
    color: var(--color-primary-fg) !important;
}

.select__option--is-selected {
    background-color: var(--color-primary-active) !important;
    color: var(--color-primary-fg) !important;
}

/* ============ smallBox growl notification — themed background ============
   The SmartAdmin growl (themes/default submodule jimbo.js → jQuery.smallBox)
   sets the toast background inline to a fixed #296191 via
   `.css("background-color", settings.color)`. The served theme makes a single,
   non-severity-coloured smallBox call, so re-point the fill at the primary
   token here instead of editing the submodule JS. !important beats the inline
   style; token-driven so it tracks every theme. */
#divSmallBoxes .SmallBox {
    background-color: var(--color-primary) !important;
}

/* ============ Tests (Quizzes) React app — re-point hardcoded palette at tokens ============
   The Tests plugin ships a self-contained React/Vite bundle
   (plugins/Tests/static/tests/index.css) whose SCSS hardcodes the *default*
   theme's palette — periwinkle #6485DF for primary accents, #58C075 green for
   success, #E74C3C / #cf3d3d reds for danger. On any rebranded theme (Victory,
   modern, overwatch) the quiz builder, its validation states and the MUI
   notification popups therefore clash with the active brand.

   We must not touch the app's own CSS, so re-skin it from here: map each
   hardcoded accent onto the matching theme token. The bundle's stylesheet is
   injected in <body> (after this file, which loads in <head>) and the MUI
   Snackbar/Alert is emotion-injected at runtime, so !important is needed to win
   the cascade. Token-driven, so one block serves every theme — including
   default, where the tokens equal the original hexes, leaving it unchanged. */

/* --- Builder: primary-blue accents (add/clone/toggle buttons, active marker, card edge) --- */
.tests-app-root .builder-container__add-btn,
.tests-app-root .question__clone-btn,
.tests-app-root .question__toggle-mode-action-btn {
    background-color: var(--color-primary) !important;
}

.tests-app-root .item-wrap__main {
    border-top-color: var(--color-primary) !important;
}

.tests-app-root .question_active {
    border-left-color: var(--color-primary) !important;
}

/* --- Builder: success (save button, correct-answer checkbox / radio) --- */
.tests-app-root .builder-container__save-btn {
    background-color: var(--color-success) !important;
}

.tests-app-root .question-options__checkbox:checked + label::before,
.tests-app-root .question-options__radio:checked + label::before,
.tests-app-root .test-info__checkbox:checked + label::before {
    background-color: var(--color-success) !important;
    border-color: var(--color-success) !important;
}

/* --- Builder: soft-blue tints (editor toolbar/borders, summary panel, checkbox hover/active) --- */
.tests-app-root .editor-toolbar {
    background-color: var(--color-primary-soft-bg) !important;
}

.tests-app-root .editor-content,
.tests-app-root .editor-input {
    border-color: var(--color-primary-soft-border) !important;
}

.tests-app-root .test-info__summary {
    background-color: var(--color-primary-soft-bg) !important;
}

.tests-app-root .question-options__checkbox:not(:disabled):not(:checked) + label:hover::before,
.tests-app-root .question-options__radio:not(:disabled):not(:checked) + label:hover::before,
.tests-app-root .test-info__checkbox:not(:disabled):not(:checked) + label:hover::before,
.tests-app-root .question-options__checkbox:not(:disabled):active + label::before,
.tests-app-root .question-options__radio:not(:disabled):active + label::before,
.tests-app-root .test-info__checkbox:not(:disabled):active + label::before {
    background-color: var(--color-primary-soft-bg) !important;
    border-color: var(--color-primary-soft-border) !important;
}

/* --- Builder: danger (remove button, validation borders/message, matching "incorrect" mark) --- */
.tests-app-root .question__remove-btn {
    background-color: var(--color-danger) !important;
}

.tests-app-root .error-input,
.tests-app-root .error-question {
    border-color: var(--color-danger) !important;
}

.tests-app-root .error-options {
    border-left-color: var(--color-danger) !important;
}

.tests-app-root .input-error-message {
    color: var(--color-danger) !important;
}

.tests-app-root .match-question-options__checkbox:checked + label::before {
    background-color: var(--color-danger) !important;
    border-color: var(--color-danger) !important;
}

/* --- Modal action buttons (rendered in a MUI portal outside .tests-app-root) --- */
.test-modal-btn_primary {
    background-color: var(--color-primary) !important;
}

.test-modal-btn_default {
    color: var(--color-primary) !important;
}

.test-modal-btn_primary:hover,
.test-modal-btn_default:hover {
    background-color: var(--color-primary-hover) !important;
}

.test-modal-btn_success {
    background-color: var(--color-success) !important;
}

.test-modal-btn_success:hover {
    background-color: var(--color-success-hover) !important;
}

.test-modal-btn_danger {
    background-color: var(--color-danger) !important;
}

.test-modal-btn_danger:hover {
    background-color: var(--color-danger-hover) !important;
}

/* ============ jQuery UI autocomplete — wrap long suggestions ============
   The jQuery UI autocomplete menu (ul.ui-autocomplete, appended to <body>) pins
   its width to the source input, so a suggestion that is a single unbreakable
   token — e.g. an object name like `too_long_game_world_object_name...` in the
   GameWorldManager object fields (templates/field_object.phtml) — overflows the
   dropdown's right edge and spills across neighbouring content. white-space is
   already normal, so only an explicit break is missing: wrap the item and break
   one over-long word. Generic jQuery UI markup, so this serves every theme.

   The .ui-state-focus / .ui-state-active / .ui-widget-content state selectors are
   needed because jquery-ui-1.10.3.custom.css re-asserts `white-space:nowrap` on
   the hovered/active item via `.ui-menu .ui-menu-item a.ui-state-focus{…}` (three
   classes); without matching that specificity the suggestion stops wrapping again
   on hover. reset.css loads after the jQuery UI stylesheet, so equal specificity
   wins on source order. */
.ui-autocomplete .ui-menu-item a,
.ui-autocomplete .ui-menu-item a.ui-state-focus,
.ui-autocomplete .ui-menu-item a.ui-state-active,
.ui-autocomplete .ui-menu-item a.ui-widget-content,
.ui-autocomplete .ui-menu-item-wrapper {
    white-space: normal;
    overflow-wrap: break-word;
}

/* --- MUI Snackbar/Alert notification popups (success / error / warning / info) ---
   Also a body-level portal; MuiAlert variant="filled" carries severity-specific
   background classes that default to MUI's own green/red/orange/blue. */
.MuiAlert-filledSuccess {
    background-color: var(--color-success) !important;
    color: #ffffff !important;
}

.MuiAlert-filledError {
    background-color: var(--color-danger) !important;
    color: var(--color-danger-fg) !important;
}

.MuiAlert-filledWarning {
    background-color: var(--color-warning) !important;
    color: var(--color-warning-fg) !important;
}

.MuiAlert-filledInfo {
    background-color: var(--color-info) !important;
    color: var(--color-info-fg) !important;
}

/* ============ Mobile bottom-nav content clearance ============
   The fixed bottom mobile nav (.b-mobile-nav, from themes/default/menu_bar.php)
   is shown below 980px on every directory=default theme, but no theme reserves
   space for it, so page content — action buttons ("Save"), grid pagination —
   is hidden behind the bar. Pad #content, the innermost wrapper that holds the
   page content: because body is overflow:hidden the actual scroll happens on an
   inner element, so padding must live inside it, not on #main. The `body`
   prefix lifts specificity above the theme overlays' own `#content { padding }`
   so this cross-theme rule wins regardless of load order. The clearance value
   lives in tokens.css (--mobile-nav-clearance). */
@media (max-width: 979px) {
    body #content {
        padding-bottom: var(--mobile-nav-clearance);
    }

    /* The quiz builder (Tests React app, #tests-app-root, mounted by
       Tests/templates/app.phtml on the create/edit-test pages) renders its own
       tall content ending in the Save action row (.builder-container__save-btn).
       The #content clearance above doesn't reliably reach it — the app root is
       the effective scroll surface there — so reserve the same space on the app
       root itself, a normal-flow block whose bottom padding is always honoured. */
    body .tests-app-root {
        padding-bottom: var(--mobile-nav-clearance);
    }
}

/* ============ Primary top action on the certificate sheet ============
   The certificate sheet promotes its «Save» action to the primary button style
   (StudyAchievements/static/js/certificate.js swaps the class, because the DGS
   toolbar template hard-codes `btn btn-default` and takes no per-action style).

   The themes then paint that button with
   `.e-db-button.btn-primary { border-radius: 8px !important }`, which is written
   for a button standing on its own. Inside a `.btn-group` it beats Bootstrap's
   own group geometry, so the promoted button comes out rounded on all four
   corners while the buttons beside it stay squared where they meet.

   These two rules put the group geometry back for the sheet's own toolbar —
   scoped by the store ident, which every action of that store carries — and
   stay right whichever action ends up first or last (Download appears only once
   the certificate has a PDF). `!important` because the theme rule carries it. */
.btn-group > .e-db-button.e-db-action-certificate_values.btn-primary:not(:first-child) {
    border-top-left-radius: 0 !important;
    border-bottom-left-radius: 0 !important;
}

.btn-group > .e-db-button.e-db-action-certificate_values.btn-primary:not(:last-child) {
    border-top-right-radius: 0 !important;
    border-bottom-right-radius: 0 !important;
}

/* ============ DGS row highlight — soft red ============
   A gentler alternative to the theme's own `m-row-red` (LightSalmon), which
   reads as an alarm against the softer `m-row-yellow`. Draft certificates are
   an ordinary in-progress state, not an error, so they get this muted tint
   rather than the alarm colour. Defined here, not in the theme submodule, so a
   colour tweak stays a one-line change in the main repo; no theme rule targets
   this class, so the `!important` — matching the palette it sits beside — wins
   uncontested. */
.b-db-table .m-row-soft-red td {
    background-color: MistyRose !important;
}

/* ============ Form section captions — dialog size ============
   A form's section panels (`sections()` on a ClassSchema) render through the
   theme's widget component, whose caption is an `<h2>`. Nothing styles that
   `<h2>` for a section — `jarvis-widgets.css` sizes `.jarviswidget > header h2`,
   and a section widget is `.b-section-widget` instead — so it falls back to
   Bootstrap's page-heading 30px. Inside a dialog that is larger than the
   dialog's own title and pushes the fields it labels down the sheet.

   14px is what every other panel heading in the app already uses, so a section
   caption stops shouting without becoming a size of its own.

   Scoped to `.b-store-dialog`, the wrapper only an ajax dialog carries
   (store/form.phtml). A full-page form renders through store/form_new.phtml as
   `.b-db-form-new` and never gets this class, so `new`-mode forms keep the
   page-heading size they have today. */
.b-store-dialog .b-section-widget > header h2 {
    font-size: 14px;
}
