/* ============================================================================
   mobile-responsive.css  —  Epic #244 (mobile & tablet responsive review)

   PURPOSE
   -------
   Single home for every mobile/tablet responsive fix in the #244 epic.
   Loaded LAST in _Host.cshtml so these rules win on equal specificity.

   DESKTOP SAFETY BY CONSTRUCTION
   ------------------------------
   Every rule in this file MUST live inside a `@media (max-width: …)` block.
   Nothing here may apply at desktop widths, so desktop rendering cannot
   regress. Bootstrap 5 breakpoints:
       phones   : max-width 575.98px
       tablet   : 576px – 991.98px  (iPad portrait 768 sits here)
   Prefer the narrowest breakpoint that actually needs the fix — many panels
   fit fine at 768px and only break below 576px.

   Sections are grouped by ticket so review maps 1:1 to the board.
   ============================================================================ */


/* ---------------------------------------------------------------------------
   #252 — User Directory search header (UserSearch.razor)
   The header is a non-wrapping flex row: 280px title block + 250px search
   input + toggle + export button (~668px), so below phone width the right
   edge (and the export/search controls) are clipped off-screen. Let it wrap
   and stack the title block above full-width controls.
   --------------------------------------------------------------------------- */
@media (max-width: 575.98px) {
    .user-search-header {
        flex-wrap: wrap !important;
        min-height: 0 !important;
    }

    /* Both the title block and the controls block go full width and stack */
    .user-search-header > div {
        min-width: 0 !important;
        flex: 1 1 100% !important;
        border-right: none !important;
    }

    .user-search-header > div:first-child {
        padding: 0.75rem 1rem !important;
    }

    /* Controls: left-align and allow wrapping so nothing is pushed off-screen */
    .user-search-header > div:last-child {
        justify-content: flex-start !important;
        flex-wrap: wrap !important;
        padding: 0 1rem 0.75rem !important;
        gap: 0.5rem !important;
    }

    /* Search input spans the row instead of a fixed 250px */
    .user-search-header .srn-search-input-wrapper {
        width: 100% !important;
    }
    .user-search-header .srn-search-input-field {
        width: 100% !important;
    }

    /* #263 follow-up: the toggle (~160px) and export button (~160px) were
       each just under half the 311px available content width, so they broke
       onto their own line — two half-empty rows with a floating control and
       a dead gutter, instead of reading as one compact toolbar. Trim each
       just enough (~16px combined) that they share a row like the paired
       controls they are; the search bar keeps its own full-width row below. */
    .user-search-header .form-check.form-switch {
        flex: 0 1 auto !important;
        gap: 0.4rem !important;
    }
    .user-search-header .form-check-label {
        font-size: 0.75rem !important;
    }
    .user-search-header .btn-export-header {
        height: 34px !important;
        padding: 0 0.8rem !important;
        font-size: 0.8rem !important;
        gap: 0.35rem !important;
    }
}


/* ---------------------------------------------------------------------------
   #253 — Dashboard Client Overview header controls (ClientOverview.razor)
   The overview header is a space-between flex row; its controls block (client
   search box + From/To date pickers, ~563px, nowrap) is pushed right and
   clipped off-screen below phone width. Let the header wrap so the controls
   drop under the title, and let the controls themselves wrap. Harmless for the
   narrower company-admin variant (a row that already fits stays one row).
   --------------------------------------------------------------------------- */
@media (max-width: 575.98px) {
    .hud-overview-header {
        flex-wrap: wrap !important;
        row-gap: 0.5rem !important;
    }

    .hud-overview-controls {
        flex-wrap: wrap !important;
        width: 100% !important;
        justify-content: flex-start !important;
        row-gap: 0.5rem !important;
    }
}


/* ---------------------------------------------------------------------------
   #250 — Grid → mobile card view (part 1: Parts search grid)
   The global rule `.glass-grid .e-grid .e-table { min-width: 1300px }` cages
   every grid at 1300px, forcing internal horizontal scroll on phones. The
   Parts grid is a single TEMPLATE column whose row template
   (.part-result-container, PartsSearch.razor.css) ALREADY has its own
   max-width:575.98px rule that stacks it vertically — it was just imprisoned
   by that min-width. Releasing it (scoped to the Parts wrapper only, so true
   multi-column grids are untouched) lets the existing responsive card layout
   breathe: each part becomes a stacked image-over-details card.
   True multi-column grids (Order History etc.) get a proper label:value card
   transformation in a later part of this ticket.
   --------------------------------------------------------------------------- */
@media (max-width: 575.98px) {
    .parts-search-grid-wrapper .e-grid .e-table {
        min-width: 0 !important;
        table-layout: auto !important;
    }
}


/* ---------------------------------------------------------------------------
   #252 — Part Details split-pane stacks on mobile (PartDetails.razor)
   .main-stage is a 3-column CSS grid (left specimen pane | 12px splitter |
   right data pane). Its existing max-width:768px rules only tweak padding/QR —
   they never collapse the grid, so below tablet width the two panes squash to
   ~120px each and ALL field text clips ("SPECIFICA…", "MANUFACTU…"). Collapse
   to a single stacked column (the component already ships a compact-mode
   single-column variant, so this matches its own design), hide the drag
   splitter, and let the panes size to content and the view scroll.

   BREAKPOINT (fixed 2026-07-16): this rule originally used max-width:767.98px,
   which EXCLUDES exactly 768px — i.e. iPad portrait, the single most common
   tablet target — so the split-pane stayed two-column and clipped on the very
   device the "iPad portrait 768 sits here" comment claims it covers. Measured
   at 768px: cols = "300px 12px 330px" (still 3-track) with 20 clipping children
   ("DDSRN94…", "CTSS XTR…", tab "OR[DERS]" all cut). Widened to 991.98px, the
   TABLET ceiling this file's own header defines, so the whole tablet band stacks
   to a single readable column. Desktop (>=992px, incl. the 1280px control test)
   keeps the two-column layout untouched — verified by measurement, not just
   construction. Single-column is never a clipping bug, only less dense, so a
   wider ceiling is a safe one-directional relaxation.
   --------------------------------------------------------------------------- */
@media (max-width: 991.98px) {
    .main-stage:not(.compact-mode) {
        grid-template-columns: 1fr !important;
        gap: 16px !important;
        padding: 16px !important;
        height: auto !important;
        overflow: visible !important;
    }

    /* The draggable splitter is meaningless once the panes stack */
    .main-stage .layout-splitter {
        display: none !important;
    }

    /* Let each pane grow to its content instead of the fixed 700px min */
    .main-stage .glass-panel {
        min-height: 0 !important;
    }
}


/* ---------------------------------------------------------------------------
   #250/#252 — Parts grid: no inline row-expander on PHONES, keep on tablets
   Product decision (Craig, 2026-07-14): the inline detail-row expander crams
   the full Part Details panel into the grid-row width, which is unavoidably
   cramped on a phone (even stacked). On a phone the row card itself is the
   right experience; the inline expander only makes sense at tablet width and up
   (iPad portrait = 768px), where there's room. So below 768px remove the detail
   toggle column entirely (header + row cells + indent, so the table stays
   aligned and the card reclaims full width — no leftover gutter) and suppress
   any detail row that manages to open. At >=768px the expander is untouched.
   --------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
    .parts-search-grid-wrapper .e-grid .e-detailrowcollapse,
    .parts-search-grid-wrapper .e-grid .e-detailrowexpand,
    .parts-search-grid-wrapper .e-grid .e-detailheadercell,
    .parts-search-grid-wrapper .e-grid .e-detailindentcell {
        display: none !important;
    }

    /* Belt-and-braces: if a detail row is expanded (e.g. before resize), hide it */
    .parts-search-grid-wrapper .e-grid .e-detailrow {
        display: none !important;
    }
}


/* ---------------------------------------------------------------------------
   #255 — Parts filter bar: category-filter input clips on phones
   .filter-panel-bar is a non-wrapping flex row (FILTERS toggle + a 200px
   "TYPE TO FILTER CATEGORIES" input pushed right via margin-left:auto). Below
   phone width the row can't fit both, so the input's right edge (and its clear
   button) clip off-screen. Let the bar wrap and drop the filter input to a
   full-width second line.
   --------------------------------------------------------------------------- */
@media (max-width: 575.98px) {
    .parts-filter-panel .filter-panel-bar {
        flex-wrap: wrap !important;
        padding-left: 1rem !important;
        padding-right: 1rem !important;
    }

    .parts-filter-panel .pill-filter-wrap {
        margin-left: 0 !important;
        width: 100% !important;
    }

    .parts-filter-panel .pill-filter-input {
        width: 100% !important;
        flex: 1 1 auto !important;
    }
}


/* ---------------------------------------------------------------------------
   #251 — Dialogs must not exceed the viewport on phones/tablets
   Two mechanisms:
   (a) Syncfusion SfDialogs render as .e-dialog with a fixed inline width
       (VanStock/PartInclusion import 1200px, EditHelp 800px, WhatsNew 600px,
       global saving 800px). A mobile max-width ceiling shrinks only the ones
       wider than the viewport — it never enlarges or breaks a smaller dialog.
   (b) DialogGeneric (Bootstrap modal) has inner content with inline
       min-width:460px / 650px (.ndo-dialog) that forces horizontal overflow
       inside the modal on a phone. Relax those min-widths.
   Both are one-directional relaxations, so desktop and normal-size dialogs are
   unaffected.
   --------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
    .e-dialog {
        max-width: calc(100vw - 24px) !important;
    }

    /* DialogGeneric (Bootstrap modal) inner min-widths that overflow phones */
    .ndo-dialog {
        min-width: 0 !important;
    }
    .modal-content [style*="min-width"],
    .modal-body [style*="min-width"] {
        min-width: 0 !important;
    }
}


/* ---------------------------------------------------------------------------
   #250 (part 2) — TRUE multi-column grids become stacked "label: value" cards
   A multi-column Syncfusion grid is unreadable on a phone: the table is forced
   wide, scrolls horizontally inside its card, and columns clip (e.g. the Users
   grid = 740px of columns in a 375px viewport, with Name/Client cut off).
   Below 576px each ROW becomes a card and each CELL a label:value line.

   `js/mobile-grid-cards.js` supplies the `data-label` (the column heading) and
   tags only genuinely multi-column grids with `.srn-grid-cards` — so the Parts
   search grid (a single template column that already renders its own card) is
   left alone automatically.

   `:not(.e-hide)` is essential: Syncfusion marks hidden columns with `e-hide`,
   and without it a blanket `display:flex` resurrects columns the grid
   deliberately hides (e.g. the internal User Id).
   --------------------------------------------------------------------------- */
@media (max-width: 575.98px) {
    .srn-grid-cards .e-gridheader {
        display: none !important;   /* the label comes from data-label instead */
    }

    /* SPECIFICITY IS LOAD-BEARING HERE. site.css ships
       `.glass-grid .e-grid .e-table { min-width: 1300px !important; table-layout: fixed !important }`
       — (0,3,0) and !important. A plain `.srn-grid-cards .e-table` is only (0,2,0), so
       !important-vs-!important is decided on specificity and the 1300px cage WINS.
       Measured on /Orders/index at a 375px viewport: table/row = 1300px inside a 341px
       scroller (959px of dead horizontal scroll), so every card's right edge, border and
       rounded corners sat off-screen and each row read as a strip, not a card. The
       stacking assertions still passed — flex-direction:column is true at any width —
       which is exactly why the test never caught it.
       The Users grid escaped only because its wrapper is `.user-search-grid-wrapper`,
       not `.glass-grid`; that's luck, not design.
       `.srn-grid-cards.e-grid .e-gridcontent .e-table` is (0,4,0), so it beats the cage
       outright rather than relying on stylesheet order. */
    .srn-grid-cards.e-grid .e-gridcontent .e-table {
        min-width: 0 !important;
        width: 100% !important;
        table-layout: auto !important;
        display: block !important;
    }

    .srn-grid-cards .e-gridcontent tbody {
        display: block !important;
        width: 100% !important;
    }

    /* one row = one card. A vertical FLEX stack (not block) so cells can be
       re-ordered: the person's Name/avatar is floated to the top as a header
       (see the focal-point rule below) instead of being the 2nd equal line.
       A soft shadow gives the card separation on the light (corporate) theme
       where the faint cyan border alone all but disappears; it's invisible on
       the dark themes, so it's a safe universal lift. */
    .srn-grid-cards .e-gridcontent .e-row {
        display: flex !important;
        flex-direction: column !important;
        width: 100% !important;
        margin: 0 0 12px 0;
        /* The card's closing gutter lives HERE, not on `:last-child`, because
           `:last-child` is positional and cannot see whether the last cell is
           actually visible. Once empty cells are hidden (and Syncfusion already
           hides `e-hide` columns), the DOM-last cell is often display:none — so a
           `:last-child` padding lands on nothing and the card closes on the cell's
           own 7px instead of 12px. Measured on /Orders/index: 11px top vs 7px
           bottom, and it varied ROW TO ROW with whether Notes had a value. 5px here
           + the cell's 7px = the intended 12px on every card, whatever is hidden. */
        padding-bottom: 5px;
        border: 1px solid rgba(0, 242, 255, 0.18);
        border-radius: 8px;
        overflow: hidden;
        background: rgba(0, 0, 0, 0.25);
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
    }

    /* THEME-CHROME TRAP — the ticket's own warning, hit for real (measured on
       /Orders/index at corporate/light). The corporate overlay ships
       `html[data-app-theme="corporate"] .glass-grid .e-grid .e-rowcell {
            background: var(--corp-chrome); border-bottom: 1px var(--corp-chrome-border); }`
       at specificity (0,4,1) !important — HIGHER than the base card rules (0,4,0) — so
       on the light theme every card reverted to a WHITE table with full-width internal
       horizontal rules, and the card's own translucent tint was painted over. The Users
       grid escaped only by luck: its wrapper is `.user-search-grid-wrapper`, which the
       overlay's `.glass-grid` selector doesn't match.
       Neutralise both in card mode so the card's own background shows and the internal
       cell borders vanish — on EVERY theme. On the dark themes the cells are already
       transparent with a 0px border, so this is a safe no-op there.
       (0,5,0) here clears the (0,4,1) theme rule; hover isn't a concern on a phone. */
    .srn-grid-cards.e-grid .e-gridcontent .e-row .e-rowcell {
        background: transparent !important;
        border-bottom: 0 !important;
    }

    /* one cell = a quiet CAPTION stacked above its VALUE (was a ragged
       label | right-pinned-value row with a dead gutter between them).
       Stacking + left-align gives every value one clean reading axis and lets
       long emails use the full width instead of being squeezed into 66%. */
    .srn-grid-cards .e-gridcontent .e-rowcell:not(.e-hide) {
        display: flex !important;
        flex-direction: column !important;
        align-items: stretch !important;
        gap: 2px;
        width: 100% !important;
        height: auto !important;
        border: none !important;
        padding: 7px 14px !important;
        text-align: left !important;
        white-space: normal !important;
        overflow: visible !important;
        text-overflow: clip !important;
        overflow-wrap: anywhere;
        line-height: 1.4;
    }

    /* A caption with no value under it is noise: it labels nothing, and the blank
       line where the value should be breaks the card's rhythm. `mobile-grid-cards.js`
       marks these (they are not `:empty` — Blazor renders `<!--!-->&nbsp;`, so CSS
       alone cannot see them). Drop the whole line so a card states only what's true.
       On /Orders/index this removes JOB REF + NOTES from every card in DEV's data. */
    .srn-grid-cards .e-gridcontent .e-rowcell.srn-cell-empty {
        display: none !important;
    }

    /* The leading command column has NO heading (so no caption) and holds a single
       small control. `align-items: stretch` on the card cell was pulling that control
       to the full 313px card width — a big empty bar as the FIRST and most prominent
       thing on the card, with its count badge stranded against the far-right corner.
       Let it size to its content and sit at the card's left edge like the button it is. */
    .srn-grid-cards .e-gridcontent .e-rowcell:not([data-label]):not(.e-hide) {
        align-items: flex-start !important;
    }

    /* the caption is deliberately small & faint so it labels without shouting —
       the repeated uppercase labels were the loudest thing on every card. */
    .srn-grid-cards .e-gridcontent .e-rowcell:not(.e-hide)::before {
        content: attr(data-label);
        font-size: 0.625rem;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        font-weight: 600;
        opacity: 0.4;
        line-height: 1.4;
    }

    /* a little extra air at the card's top edge (the bottom gutter is on the card
       itself — see the padding-bottom note on .e-row above) */
    .srn-grid-cards .e-gridcontent .e-rowcell:not(.e-hide):first-child {
        padding-top: 11px !important;
    }

    /* long values (emails) must wrap, not ellipse away */
    .srn-grid-cards .e-gridcontent .e-rowcell:not(.e-hide) > * {
        white-space: normal !important;
        overflow: visible !important;
        text-overflow: clip !important;
        min-width: 0;
        max-width: 100%;
        overflow-wrap: anywhere;
    }

    /* ---- FOCAL POINT ----------------------------------------------------
       Promote the person to the top of the card as its header. Keyed on the
       "Name" column, so it's a harmless no-op on any grid without one (they
       keep the clean stacked-caption layout above). The Name template already
       ships avatar + name + role; we just float it up with `order`, drop its
       now-redundant caption, and add a hairline divider so the card reads as
       "a person, then their details" — a clear anchor the eye lands on first.
       The divider uses a mid-grey alpha so it shows on both light and dark
       themes (a themed cyan line vanishes on corporate's white card). */
    .srn-grid-cards .e-gridcontent .e-rowcell[data-label="Name" i]:not(.e-hide) {
        order: -1;
        padding: 12px 14px !important;
        margin-bottom: 2px;
        border-bottom: 1px solid rgba(130, 134, 142, 0.28) !important;
    }
    .srn-grid-cards .e-gridcontent .e-rowcell[data-label="Name" i]:not(.e-hide)::before {
        display: none;
    }
    /* a larger avatar gives the header a stronger anchor on the left edge */
    .srn-grid-cards .e-gridcontent .e-rowcell[data-label="Name" i] .user-avatar {
        width: 40px !important;
        height: 40px !important;
        font-size: 0.95rem !important;
        display: flex !important;
        align-items: center !important;
        justify-content: center !important;
    }
}


/* ---------------------------------------------------------------------------
   #252 — Detail-panel SfTab strip density on phones
   VERIFIED FIRST (see the ticket): the "detail-panel forms don't stack" half of
   this ticket does NOT reproduce — the rendered detail panels use responsive
   `col-md-*` classes which already stack to full width on phones (zero plain
   `col-N`, nothing cramped). No change needed there.
   What IS real: the SfTab strip. Syncfusion does handle the overflow (it adds a
   horizontal scroller + arrows, so nothing is unreachable), but each tab is
   ~150px, so barely 2 of 8 tabs fit on a phone and users end up arrow-clicking.
   Tighten the tab padding/label below 576px so noticeably more tabs fit, while
   keeping Syncfusion's scroller intact for the rest.
   --------------------------------------------------------------------------- */
@media (max-width: 575.98px) {
    .e-tab .e-tab-header .e-toolbar-item .e-tab-wrap {
        padding: 0 8px !important;
    }

    .e-tab .e-tab-header .e-toolbar-item .e-tab-text {
        font-size: 0.78rem !important;
        letter-spacing: 0 !important;
    }

    .e-tab .e-tab-header .e-toolbar-item {
        min-width: 0 !important;
    }

    .e-tab .e-tab-header .e-toolbar-item .e-tab-icon {
        margin-right: 4px !important;
    }
}


/* ---------------------------------------------------------------------------
   #255 — DB Health "holo-row" loses data on phones
   `.holo-row` (dbhealth.css) is a CSS grid: `220px 1fr 96px 66px` + 12px gaps
   = ~418px of fixed track in a ~282px row on a phone. The result isn't just
   cramped, it's LOSSY: the 1fr bar collapses to 0px and the execution-count
   badge lands entirely off-screen (left 398 at a 375px viewport), so the number
   is simply unreadable — silently missing data, not merely ugly.
   Below 576px, give the label its own line and lay the bar / value / badge
   beneath it, so everything fits and the bar is visible again.
   (SysAdmin-only page, but real data loss, so worth fixing.)
   --------------------------------------------------------------------------- */
@media (max-width: 575.98px) {
    .holo-row {
        grid-template-columns: minmax(0, 1fr) auto auto !important;
        grid-template-areas:
            "lbl lbl lbl"
            "trk val bdg" !important;
        gap: 4px 8px !important;
    }

    .holo-row.no-badge {
        grid-template-columns: minmax(0, 1fr) auto !important;
        grid-template-areas:
            "lbl lbl"
            "trk val" !important;
    }

    /* the proc name gets a full line and may wrap instead of being ellipsed away */
    .holo-label {
        grid-area: lbl;
        white-space: normal !important;
        overflow: visible !important;
        text-overflow: clip !important;
    }

    .holo-track {
        grid-area: trk;
        min-width: 0 !important;   /* was collapsing to 0 */
    }

    .holo-value {
        grid-area: val;
    }

    .holo-badge {
        grid-area: bdg;
    }
}

/* ─────────────────────────────────────────────────────────────────────────────
   #285 · Utilities console (SysAdmin) — /Settings/SystemSettings/Utilities

   THE DEFECT (measured, not inferred): the 11-item utility menu sits in a
   fixed 240px column whose width/flex/max-width are INLINE styles on
   .utility-sidebar-col (Blazor-bound to _isSidebarExpanded), with
   flex-shrink:0. The content column beside it is `flex:1` — basis 0,
   shrink 1 — so when space runs out the content cannot push the sidebar
   and will not wrap: it just collapses.

       viewport 375 -> content  103px   (unusable — a sliver)
       viewport 500 -> content  228px
       viewport 576 -> content  304px   (tight but usable)
       viewport 768 -> content  496px   (fine; row is nowrap here)

   So this is PHONES ONLY. Tablet measured healthy — do NOT widen this to
   991.98px "for consistency"; that would change a layout that isn't broken.
   (The 767.98-is-a-trap lesson from #252 applies when the tablet IS broken.
   Here it isn't. The breakpoint follows the measurement.)

   THE FIX: on phones the menu becomes a full-width horizontal strip above
   the content, and the content gets the whole viewport width. A stacked
   vertical list would also be "correct", but 11 items x ~51px = ~563px of
   menu to scroll past before reaching the panel you actually came for.

   !important is REQUIRED here: these properties are inline on the element,
   so an ordinary rule loses on specificity and silently does nothing.

   NB: never set `animation: none` on .hud-card — it is opacity:0 until
   hudCardInit runs, so killing the animation BLANKS the card entirely.
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width: 575.98px) {

    /* 1. the sidebar column stops being a column */
    .utility-sidebar-col {
        width: 100% !important;
        flex: 0 0 100% !important;
        max-width: 100% !important;
        margin-bottom: 1rem !important;
    }

    /* its card was h-100 against an 850px min-height row.
       height:auto alone is NOT enough — .hud-card also carries
       `min-height: 250px` (minority-report.css:249), which held a ~250px
       void open under the 55px menu strip. The measurements said "menu is
       55px" and read as fixed; the screenshot showed the void. Scoped to
       THIS card only — every other .hud-card (dashboard KPI tiles) still
       wants its 250px floor.
       Do NOT touch `animation` here: .hud-card is opacity:0 until
       hudCardInit runs (same rule block, minority-report.css:245), so
       disabling the animation blanks the card entirely. */
    .utility-sidebar-col > .hud-card {
        height: auto !important;
        min-height: 0 !important;
    }

    /* 2. the menu itself runs horizontally and scrolls */
    .utility-sidebar-col .cyber-menu {
        flex-direction: row !important;
        flex-wrap: nowrap !important;
        overflow-x: auto !important;
        overflow-y: hidden !important;
        gap: 0.5rem;
        padding: 0 0.75rem 0.25rem !important;
        scrollbar-width: thin;
        -webkit-overflow-scrolling: touch;
    }

    .utility-sidebar-col .cyber-menu-item {
        flex: 0 0 auto !important;
        width: auto !important;
        white-space: nowrap !important;
    }

    /* 3. the collapse toggle is meaningless once width is forced to 100% —
          pressing it would only strip the labels off a full-width strip. */
    .utility-sidebar-col .sidebar-toggle-btn {
        display: none !important;
    }
}
