/* ==========================================================
   AVOps style overrides
   --------------------------------------------------------
   Make the actual data in inputs visually heavier than the
   field labels and group legends so values stand out.

   Weight stack (heaviest -> lightest):
     data values .......... 700 (bold)
     fieldset legends ..... 600 (semi-bold)
     field labels ......... 400 (normal)

   Loaded AFTER Radzen and Syncfusion CSS in App.razor.
   !important is used on the data rules because the Syncfusion
   bootstrap5 theme sets font-weight with high specificity that
   plain selectors can't beat on cascade order alone.
   ========================================================== */

/* ---------- Radzen ---------- */

/* Group titles on a <RadzenFieldset> */
.rz-fieldset-legend {
    font-weight: 600 !important;
}

/* Form-field labels (RadzenFormField, generic Radzen labels) */
.rz-form-field-label,
.rz-label {
    font-weight: 400 !important;
}

/* Data inside Radzen inputs */
.rz-textbox,
.rz-textarea,
.rz-dropdown .rz-dropdown-label,
.rz-numeric input,
.rz-spinner-input,
.rz-calendar input,
.rz-datepicker input,
.rz-mask {
    font-weight: 700 !important;
}


/* ---------- Syncfusion ---------- */

/* Floating field labels on SfTextBox / SfNumericTextBox / SfComboBox / etc.
   (the small text that floats above the input)                              */
.e-float-text,
.e-float-text.e-label-top,
.e-float-text.e-label-bottom,
.e-input-group .e-float-text,
.e-float-input .e-float-text,
.e-float-input.e-input-group .e-float-text,
.e-control-wrapper .e-float-text {
    font-weight: 400 !important;
}

/* Checkbox / radio labels — these are labels, not data */
.e-checkbox-wrapper .e-label,
.e-radio-wrapper .e-label {
    font-weight: 400 !important;
}

/* Data inside Syncfusion inputs — broad net to beat the theme's
   high-specificity rules. */
input.e-input,
textarea.e-input,
.e-input-group input.e-input,
.e-input-group textarea.e-input,
.e-float-input input.e-input,
.e-float-input textarea.e-input,
.e-control-wrapper input.e-input,
.e-control-wrapper textarea.e-input,
.e-input-group.e-control-wrapper input.e-input,
.e-input-group.e-control-wrapper textarea.e-input,
.e-float-input.e-control-wrapper input.e-input,
.e-float-input.e-control-wrapper textarea.e-input,
input.e-numerictextbox,
input.e-combobox,
input.e-dropdownlist,
input.e-autocomplete,
input.e-textbox,
input.e-datepicker,
input.e-datetimepicker,
input.e-timepicker,
input.e-maskedtextbox,
.e-ddl input.e-input,
.e-combobox input.e-input,
.e-dropdownlist input.e-input,
.e-numerictextbox input.e-input,
.e-datepicker input.e-input,
.e-datetimepicker input.e-input,
.e-multiselect input.e-input {
    font-weight: 700 !important;
}

/* Syncfusion date / time / datetime pickers have an extra wrapper class
   (.e-date-wrapper / .e-datetime-wrapper / .e-time-wrapper) that the theme
   uses for higher-specificity rules. Match that specificity so the bold
   weight wins. */
.e-date-wrapper input.e-input,
.e-datetime-wrapper input.e-input,
.e-time-wrapper input.e-input,
.e-input-group.e-date-wrapper input.e-input,
.e-input-group.e-datetime-wrapper input.e-input,
.e-input-group.e-time-wrapper input.e-input,
.e-control-wrapper.e-date-wrapper input.e-input,
.e-control-wrapper.e-datetime-wrapper input.e-input,
.e-control-wrapper.e-time-wrapper input.e-input,
.e-input-group.e-control-wrapper.e-date-wrapper input.e-input,
.e-input-group.e-control-wrapper.e-datetime-wrapper input.e-input,
.e-input-group.e-control-wrapper.e-time-wrapper input.e-input {
    font-weight: 700 !important;
}

/* Right-align the data inside numeric textboxes. Numeric values
   read better right-aligned (digit columns line up, decimal points
   align). The padding-right keeps the last digit from touching the
   right edge / spin-button divider. Scoped to SfNumericTextBox only -
   other inputs keep their default left alignment. */
input.e-numerictextbox,
.e-numeric input.e-input,
.e-numerictextbox input.e-input,
.e-input-group.e-control-wrapper input.e-numerictextbox {
    text-align: right !important;
    padding-right: 8px !important;
}


/* ==========================================================
   AVWebOps responsive form pattern
   --------------------------------------------------------
   Opt-in by wrapping the form's outer markup in
   <div class="av-form"> ... </div>. Inside it:

     1. Use Bootstrap's container-fluid + responsive col classes
        (col-12 col-md-6 col-xl-4 etc.) so columns stack at
        narrow widths instead of clinging side-by-side.
     2. Pair inputs with a <RadzenStack Orientation="Horizontal"
        Wrap="Wrap" Gap="10px"> - the rules below make each
        Syncfusion control flex to fill the row and shrink/wrap
        on phones without overflowing.
     3. DROP per-input Width="160px" / "180px" / etc. on
        SfTextBox / SfNumericTextBox / SfDatePicker / SfComboBox.
        Their fixed pixel widths prevent shrinking. If a field
        truly needs a hard width, set it locally via inline
        style; otherwise let the flex rule below handle it.
     4. Use .av-form-actions for the Save/Cancel/etc. button row -
        it centers, gaps, and wraps the buttons cleanly.

   Reference implementation: FrmInventoryAddEdit.razor.
   ========================================================== */

.av-form .e-input-group,
.av-form .e-control-wrapper,
.av-form .e-ddl,
.av-form .e-combobox,
.av-form .e-datepicker,
.av-form .e-datetimepicker,
.av-form .e-timepicker,
.av-form .e-numerictextbox,
.av-form .e-textbox,
.av-form .e-maskedtextbox,
.av-form .e-multiselect {
    flex: 1 1 160px;
    min-width: 0;
    max-width: 100%;
}

/* Button row at the bottom of an .av-form. Wraps on narrow
   viewports; pads in from the sides on wider ones.
   Gap matches the visual rhythm of RadzenStack Gap="10px" with
   a bit more breathing room since these are primary actions. */
.av-form-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 16px;
    padding: 20px clamp(8px, 5vw, 80px);
}

/* Two-input pair that should sit side-by-side as long as the
   parent column gives them room, then wrap to stacked on narrow
   widths. Use as a wrapper around exactly two Syncfusion / Radzen
   inputs - for example a Show Start / Show End date pair in a
   narrower column where the default flex-basis: 160px is too
   greedy and forces an unwanted wrap.

   Inputs inside use a smaller basis (140px) and shrink to zero
   so the pair stays side-by-side down to ~290px-wide columns. */
.av-field-pair {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.av-field-pair > .e-input-group,
.av-field-pair > .e-control-wrapper,
.av-field-pair > .e-ddl,
.av-field-pair > .e-combobox,
.av-field-pair > .e-datepicker,
.av-field-pair > .e-datetimepicker,
.av-field-pair > .e-timepicker,
.av-field-pair > .e-numerictextbox,
.av-field-pair > .e-textbox,
.av-field-pair > .e-maskedtextbox {
    flex: 1 1 140px;
    min-width: 0;
    max-width: 100%;
}

/* Search-style SfTextBox kept at its natural Width on desktop but
   allowed to shrink (rather than overflow) when its container is
   narrower than the explicit pixel width - e.g. on a phone where
   a Width="380px" textbox would otherwise force horizontal scroll. */
.av-search-input,
.av-search-input.e-input-group,
.av-search-input.e-control-wrapper {
    max-width: 100% !important;
}

/* AVGrid global search box - shown on both desktop and mobile. On desktop it
   sits inline in the toolbar at the SfTextBox's fixed width; the mobile block
   (max-width:640px) stretches it to a full row, since there the per-column
   filter bar, grid header, and filter toolbar button are all hidden and this
   is the only way to search. */
.av-grid-action-search {
    align-items: center;
}

/* Append "lbs" to weight values in the Cases grid. Syncfusion's
   column Format property only accepts standard number/date format
   specifiers and renders custom strings (like "{0:N0} lbs")
   literally, so we use the av-fld-{field} class that AVGrid
   already stamps on every cell to inject the suffix via ::after.
   - Scoped to .e-rowcell so the header isn't suffixed too
   - :not(:empty) keeps blank cells blank (no orphan " lbs")
   - The cell's text-align is preserved by the inline pseudo */
.e-rowcell.av-fld-fldCaseWeight:not(:empty)::after {
    content: " lbs";
}


/* ==========================================================
   FrmCalendar: keep the SfSchedule usable on a real phone
   --------------------------------------------------------
   The page's inline <style> block in FrmCalendar.razor sets
   the schedule to flex/percentage heights that work fine on
   desktop and in Chrome DevTools phone-mode, but the same
   rules emitted inside a Razor `<style>` block (with the
   `@@media` escape) did NOT match on real mobile devices —
   the schedule collapsed to ~200px tall. Keeping the rule
   in a plain .css file sidesteps that, and the heights below
   force SfSchedule + every inner table/content wrapper to
   500px so the month grid remains usable.

   Why this isn't just a min-height: SfSchedule's Height="100%"
   only resolves against a parent with an EXPLICIT height.
   And Syncfusion's JS stamps inline pixel heights on its
   inner elements, so the inner content-wrap rules need
   !important to win over the inline style.
   ========================================================== */
@media (max-width: 640px) {
    .av-cal-root {
        height: auto !important;
        min-height: calc(100vh - 120px) !important;
    }
    .av-cal-body {
        flex: 0 0 auto !important;
        height: 500px !important;
        min-height: 500px !important;
    }
    .av-cal-schedule {
        height: 500px !important;
        min-height: 500px !important;
    }

    /* Force SfSchedule and every inner wrapper to 500px so the
       browser has a concrete height to give the percentage
       calculation, and so Syncfusion's inline pixel heights
       are beaten by !important. */
    .av-cal-schedule .e-schedule,
    .av-cal-schedule .e-schedule .e-table-wrap,
    .av-cal-schedule .e-schedule .e-outer-table,
    .av-cal-schedule .e-schedule .e-month-view,
    .av-cal-schedule .e-schedule .e-week-view,
    .av-cal-schedule .e-schedule .e-day-view,
    .av-cal-schedule .e-schedule .e-agenda-view {
        height: 500px !important;
        min-height: 500px !important;
    }

    /* The scrollable grid area underneath SfSchedule's own
       toolbar (~50px). Let it fill what's left of 500px. */
    .av-cal-schedule .e-schedule .e-content-wrap,
    .av-cal-schedule .e-schedule .e-table-container {
        height: calc(500px - 50px) !important;
        min-height: calc(500px - 50px) !important;
        max-height: calc(500px - 50px) !important;
        overflow-y: auto !important;
    }
}


/* ==========================================================
   Mobile header: collapse to just the responsive hamburger
   --------------------------------------------------------
   On narrow viewports the RadzenHeader was stacking the
   sidebar toggle and menu onto 3-4 lines. The AVMainMenu's
   Responsive="true" hamburger already exposes every menu
   path, so hide everything else and keep the header on a
   single row.
   ========================================================== */
@media (max-width: 640px) {
    /* Hide the sidebar toggle - redundant with the menu's
       own hamburger. */
    .rz-header .rz-sidebar-toggle,
    .rz-header button.rz-sidebar-toggle {
        display: none !important;
    }

    /* The toggle's column wrapper would otherwise still
       reserve 1/12 of the row. Collapse it. */
    .rz-header .rz-row > .rz-col-xs-1:first-child,
    .rz-header .rz-row > .rz-col-sm-1:first-child,
    .rz-header .rz-row > .rz-col-md-1:first-child {
        display: none !important;
    }

    /* Keep the header row on a single line and remove the
       column gutters that were forcing wrap. */
    .rz-header .rz-row {
        flex-wrap: nowrap !important;
        margin: 0 !important;
    }

    .rz-header .rz-row > [class*="rz-col"] {
        padding-left: 0 !important;
        padding-right: 0 !important;
    }

    /* Tighten the AVMainMenu wrapper so the hamburger sits
       flush at the top-left. */
    .rz-header .menu-control {
        margin: 0 !important;
        padding: 0 !important;
    }

    /* Force the header itself to a single-row height. */
    .rz-header {
        min-height: 3rem !important;
        height: auto !important;
        padding: 0 8px !important;
    }
}


/* ==========================================================
   Venues / Vendors / Hotels / Trucks grid - narrow-mode card
   --------------------------------------------------------
   In stacked mode each cell normally takes its own line.
   For address-style records the city / state / zip make more
   sense on a single line ("Minneapolis, MN 55401") under-
   neath the name and address. The wrapper classes
   .av-grid-stack-venues  (FrmVenueSelect.razor)
   .av-grid-stack-vendors (FrmVendorSelect.razor)
   .av-grid-stack-hotels  (FrmHotelSelect.razor)
   .av-grid-stack-trucks  (FrmTruckSelect.razor)
   each set alongside .av-grid-stack, opt those grids into
   this behavior; every other grid keeps the default stacking.

   Each table uses a different field-name prefix:
       Venues  -> fldVenuCity / fldVenuState / fldVenuZip
       Vendors -> fldVenCity  / fldVenState  / fldVenZip
       Hotels  -> fldHotCity  / fldHotState  / fldHotZip
       Trucks  -> fldTrukCity / fldTrukState / fldTrukZip
   ========================================================== */
@media (max-width: 640px) {

    /* NOTE: selectors below chain BOTH wrapper classes
       (e.g. .av-grid-stack.av-grid-stack-venues) - this gives
       them one extra class of specificity over the generic
       .av-grid-stack .e-grid .e-row { display: flex } rule
       defined later in this file, so the address layout wins
       the cascade regardless of source order. */

    /* Switch the row from flex-column to plain block so cells
       can flow inline where we tell them to. Cells that stay
       display:block (name, address) still get their own line. */
    .av-grid-stack.av-grid-stack-venues .e-grid .e-row,
    .av-grid-stack.av-grid-stack-vendors .e-grid .e-row,
    .av-grid-stack.av-grid-stack-hotels .e-grid .e-row,
    .av-grid-stack.av-grid-stack-trucks .e-grid .e-row {
        display: block !important;
    }

    /* City / state / zip render inline next to each other.
       width:auto cancels the 100% width that the generic
       .e-rowcell rule applies; line-height matches the rest. */
    .av-grid-stack.av-grid-stack-venues .e-grid .e-rowcell.av-fld-fldVenuCity,
    .av-grid-stack.av-grid-stack-venues .e-grid .e-rowcell.av-fld-fldVenuState,
    .av-grid-stack.av-grid-stack-venues .e-grid .e-rowcell.av-fld-fldVenuZip,
    .av-grid-stack.av-grid-stack-vendors .e-grid .e-rowcell.av-fld-fldVenCity,
    .av-grid-stack.av-grid-stack-vendors .e-grid .e-rowcell.av-fld-fldVenState,
    .av-grid-stack.av-grid-stack-vendors .e-grid .e-rowcell.av-fld-fldVenZip,
    .av-grid-stack.av-grid-stack-hotels .e-grid .e-rowcell.av-fld-fldHotCity,
    .av-grid-stack.av-grid-stack-hotels .e-grid .e-rowcell.av-fld-fldHotState,
    .av-grid-stack.av-grid-stack-hotels .e-grid .e-rowcell.av-fld-fldHotZip,
    .av-grid-stack.av-grid-stack-trucks .e-grid .e-rowcell.av-fld-fldTrukCity,
    .av-grid-stack.av-grid-stack-trucks .e-grid .e-rowcell.av-fld-fldTrukState,
    .av-grid-stack.av-grid-stack-trucks .e-grid .e-rowcell.av-fld-fldTrukZip {
        display: inline-block !important;
        width: auto !important;
        max-width: none !important;
        vertical-align: baseline !important;
    }

    /* Separators between the three pieces - ", " after city,
       a non-breaking space after state. :not(:empty) keeps
       blank cells from emitting an orphan comma or space. */
    .av-grid-stack.av-grid-stack-venues .e-grid .e-rowcell.av-fld-fldVenuCity:not(:empty)::after,
    .av-grid-stack.av-grid-stack-vendors .e-grid .e-rowcell.av-fld-fldVenCity:not(:empty)::after,
    .av-grid-stack.av-grid-stack-hotels .e-grid .e-rowcell.av-fld-fldHotCity:not(:empty)::after,
    .av-grid-stack.av-grid-stack-trucks .e-grid .e-rowcell.av-fld-fldTrukCity:not(:empty)::after {
        content: ", ";
        white-space: pre;
    }

    .av-grid-stack.av-grid-stack-venues .e-grid .e-rowcell.av-fld-fldVenuState:not(:empty)::after,
    .av-grid-stack.av-grid-stack-vendors .e-grid .e-rowcell.av-fld-fldVenState:not(:empty)::after,
    .av-grid-stack.av-grid-stack-hotels .e-grid .e-rowcell.av-fld-fldHotState:not(:empty)::after,
    .av-grid-stack.av-grid-stack-trucks .e-grid .e-rowcell.av-fld-fldTrukState:not(:empty)::after {
        content: "\00a0";
    }
}


/* ==========================================================
   Customers grid - narrow-mode card layout (CSS Grid)
   --------------------------------------------------------
   Customers need two side-by-side pairs in the stacked card:
       Line 1: Company (spans full width, bold "title")
       Line 2: First   Last
       Line 3: City,   State
   The inline-block trick used for venues/vendors/hotels/trucks
   can't force a line break between Last and City without an
   extra DOM element, so we lay this row out with CSS Grid:
   two columns, full-width "title" cells span both. Wrapper
   class .av-grid-stack-customers (set alongside .av-grid-stack
   in FrmCustomerSelect.razor) opts in.

   Specificity note: same 4-class chain trick used elsewhere -
   .av-grid-stack.av-grid-stack-customers beats the generic
   .av-grid-stack .e-grid .e-row { display: flex } rule below.
   ========================================================== */
@media (max-width: 640px) {

    /* Switch the row to a 2-column grid. Visible cells flow into
       the grid in DOM order; av-mobile-hide and e-hide cells are
       display:none so they don't take slots. */
    .av-grid-stack.av-grid-stack-customers .e-grid .e-row {
        display: grid !important;
        grid-template-columns: auto 1fr !important;
        column-gap: 0 !important;
        row-gap: 0 !important;
    }

    /* Default: any cell that doesn't get an explicit column
       below spans the full row (matches the existing block
       behavior for Company / title cells). */
    .av-grid-stack.av-grid-stack-customers .e-grid .e-rowcell {
        grid-column: 1 / -1 !important;
        width: auto !important;
        max-width: 100% !important;
    }

    /* First name in col 1, Last name in col 2 (auto-flow puts
       them on the same row since col 1 then col 2 fills row 2). */
    .av-grid-stack.av-grid-stack-customers .e-grid .e-rowcell.av-fld-fldCustFirstName {
        grid-column: 1 !important;
    }
    .av-grid-stack.av-grid-stack-customers .e-grid .e-rowcell.av-fld-fldCustLastName {
        grid-column: 2 !important;
    }

    /* City in col 1 of the next row, State in col 2. */
    .av-grid-stack.av-grid-stack-customers .e-grid .e-rowcell.av-fld-fldCustCity {
        grid-column: 1 !important;
    }
    .av-grid-stack.av-grid-stack-customers .e-grid .e-rowcell.av-fld-fldCustState {
        grid-column: 2 !important;
    }

    /* Visual separators inside the cells:
         "First " (space after First so "Last" doesn't butt up)
         "City, " (comma+space after City)
       :not(:empty) keeps blank cells from emitting an orphan space. */
    .av-grid-stack.av-grid-stack-customers .e-grid .e-rowcell.av-fld-fldCustFirstName:not(:empty)::after {
        content: "\00a0";
    }
    .av-grid-stack.av-grid-stack-customers .e-grid .e-rowcell.av-fld-fldCustCity:not(:empty)::after {
        content: ", ";
        white-space: pre;
    }
}


/* ==========================================================
   AVWebOps responsive grid (stacked rows on narrow screens)
   --------------------------------------------------------
   Opt-in by wrapping an <AVGrid> (or any SfGrid) in
   <div class="av-grid-stack"> ... </div>. Below the breakpoint
   each row collapses from a single horizontal table row into a
   vertical stack of cells, so the grid no longer needs to
   scroll horizontally on a phone.

   Layout below the breakpoint:
     - header row hidden
     - each .e-row becomes a card-like block (border + padding)
     - cells stack vertically, text wraps
     - first visible cell is emphasised as the row's "title"
     - alternating row backgrounds so rows are easy to separate
       even without gridlines

   Pager / toolbar are left alone - they already wrap.
   Filter bar (when toggled on) collapses to one cell per line
   below the breakpoint so its inputs aren't squashed.
   ========================================================== */

@media (max-width: 640px) {

    /* The wrapper itself must clip - otherwise an over-wide table
       still pushes the pager off the right edge of the viewport
       even though its own cells are stacked block elements. */
    .av-grid-stack {
        max-width: 100% !important;
        overflow-x: hidden !important;
    }

    /* Make sure the grid itself can shrink to its container
       and doesn't try to be wider than the viewport. */
    .av-grid-stack .e-grid,
    .av-grid-stack .e-gridcontent,
    .av-grid-stack .e-gridcontent .e-content,
    .av-grid-stack .e-grid .e-table {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
    }

    /* AutoFit gives the data area a fixed pixel width during the
       OnGridDataBound pass - cancel it so the table flows to its
       parent width. */
    .av-grid-stack .e-grid .e-content {
        overflow-x: hidden !important;
    }

    /* Abandon table layout entirely in narrow mode. If we leave
       the <table>/<tbody>/<tr> as table-layout, even with cells
       set to display:block the tr is sized by the table's column
       widths - and because 12 of our 15 columns are hidden, the
       visible cell ends up squeezed to 1/Nth of the available
       width. Switching every level to block makes each row fill
       its container so cells can use the full width. */
    .av-grid-stack .e-grid .e-table,
    .av-grid-stack .e-grid .e-table > tbody {
        display: block !important;
        width: 100% !important;
        max-width: 100% !important;
    }

    /* The <colgroup>/<col> elements are now irrelevant (table
       layout is gone) but kill any inline pixel widths anyway so
       a future revert to table layout doesn't inherit stale
       AutoFit values. */
    .av-grid-stack .e-grid colgroup col {
        width: auto !important;
    }

    /* Hide the header row, the column-resize handles, and the
       horizontal scrollbar shim that Syncfusion injects. */
    .av-grid-stack .e-grid .e-gridheader,
    .av-grid-stack .e-grid .e-headercontent,
    .av-grid-stack .e-grid .e-movablescrollbar,
    .av-grid-stack .e-grid .e-scrollbar {
        display: none !important;
    }

    /* Each row becomes a vertically stacked block. The flex
       column gives us natural wrapping; height: auto overrides
       the RowHeight="25" set on the <SfGrid> for desktop;
       width: 100% works now that the <table>/<tbody> are
       display:block above and no longer constrain the tr. */
    .av-grid-stack .e-grid .e-row {
        display: flex !important;
        flex-direction: column !important;
        width: 100% !important;
        max-width: 100% !important;
        box-sizing: border-box !important;
        height: auto !important;
        padding: 8px 12px !important;
        border-bottom: 1px solid #d0d0d0 !important;
    }

    /* Alternating row colors. Target both Syncfusion's own
       .e-altrow class and a nth-of-type fallback for cases
       where AllowGrouping splits the row sequence. */
    .av-grid-stack .e-grid .e-row:nth-of-type(odd) {
        background-color: #ffffff !important;
    }

    .av-grid-stack .e-grid .e-row:nth-of-type(even),
    .av-grid-stack .e-grid .e-altrow {
        background-color: #f4f6fa !important;
    }

    /* Selected row keeps its highlight but layered on top of
       the alternating background. */
    .av-grid-stack .e-grid .e-row.e-selectionbackground,
    .av-grid-stack .e-grid .e-row.e-active {
        background-color: #d9e6ff !important;
    }

    /* Cells: full-width block, no table borders, allow wrapping. */
    .av-grid-stack .e-grid .e-rowcell {
        display: block !important;
        width: 100% !important;
        max-width: 100% !important;
        border: none !important;
        padding: 2px 0 !important;
        height: auto !important;
        min-height: 0 !important;
        line-height: 1.35 !important;
        white-space: normal !important;
        overflow: visible !important;
        text-overflow: clip !important;
        text-align: left !important;
    }

    /* Re-hide cells Syncfusion marked as hidden via Visible=false
       (column chooser, hidden boolean flags, etc). The display:block
       rule above would otherwise pull them back into view. */
    .av-grid-stack .e-grid .e-rowcell.e-hide,
    .av-grid-stack .e-grid td.e-hide {
        display: none !important;
    }

    /* Hide cells the page opted out of via AVGrid's
       MobileVisibleFields parameter - those columns stay in the DOM
       (so sort/filter still know about them), they just don't paint
       on phones. */
    .av-grid-stack .e-grid .e-rowcell.av-mobile-hide {
        display: none !important;
    }

    /* Cells that ARE listed in MobileVisibleFields get this class.
       The override here re-shows them even when Syncfusion marked
       the column .e-hide (i.e. Visible=false on desktop). Wins over
       the .e-hide rule above due to equal specificity + later source
       order. Lets a page expose desktop-hidden fields on phones
       (e.g. Address1 / Zip on the Hotels grid). */
    .av-grid-stack .e-grid .e-rowcell.av-mobile-show {
        display: block !important;
    }

    /* Title row: the cell tagged av-mobile-title (either the first
       entry of MobileVisibleFields or the first visible column when
       MobileVisibleFields is unset) is shown larger / bolder so each
       row card has an obvious heading. */
    .av-grid-stack .e-grid .e-rowcell.av-mobile-title {
        font-weight: 700 !important;
        font-size: 1.05em !important;
        padding-bottom: 4px !important;
    }

    /* Filter bar (when user toggles the filter button on) -
       one cell per line so each filter input gets full width. */
    .av-grid-stack .e-grid .e-filterbar {
        display: block !important;
    }

    .av-grid-stack .e-grid .e-filterbarcell {
        display: block !important;
        width: 100% !important;
        padding: 4px 8px !important;
    }

    /* Pager - the default Syncfusion pager assumes ~500px of width
       between the numeric buttons, the page-size dropdown, and the
       "1 of N" message bar. On a phone all that wraps onto three
       lines. The rules below collapse everything into a single
       row: [<<] [<] [>] [>>]  1 of N
       - the page-size dropdown is hidden (it's already in the
         AVGrid toolbar above the grid)
       - the numeric page buttons are hidden (redundant with the
         "1 of N" message and they're the main culprit for wrap)
       - the message bar sits inline with the arrows. */
    .av-grid-stack .e-grid .e-gridpager {
        display: flex !important;
        flex-wrap: nowrap !important;
        justify-content: center !important;
        align-items: center !important;
        gap: 0 8px !important;
        padding: 6px 4px !important;
        width: 100% !important;
        max-width: 100% !important;
        box-sizing: border-box !important;
    }

    /* Arrow cluster: keep its children on one line and remove the
       default right-float that pushes the message bar around. */
    .av-grid-stack .e-grid .e-pagercontainer {
        display: flex !important;
        flex-wrap: nowrap !important;
        align-items: center !important;
        margin: 0 !important;
        padding: 0 !important;
        float: none !important;
        max-width: 100% !important;
    }

    /* Drop the numeric (1,2,3,...) buttons - they wrap aggressively
       and the message bar already shows the current page. */
    .av-grid-stack .e-grid .e-numericcontainer {
        display: none !important;
    }

    /* "X of Y items" message bar - inline next to the arrows
       instead of floated/blocked onto its own row. */
    .av-grid-stack .e-grid .e-parentmsgbar {
        float: none !important;
        width: auto !important;
        margin: 0 !important;
        padding: 0 !important;
        white-space: nowrap !important;
    }

    /* The page-size dropdown ("15 items per page") is redundant on
       this page - the AVGrid toolbar already exposes a page-size
       dropdown above the grid. Hide the pager copy so the bottom
       bar is just arrows + the page indicator. */
    .av-grid-stack .e-grid .e-pagesizes {
        display: none !important;
    }

    /* AVGrid toolbar buttons that don't apply in stacked mode:
         - Filter / search:  no column headers to host a filter row
         - Choose Columns:   user can't see column boundaries anyway
       Hide their RadzenStack wrappers so the rest of the toolbar
       (Add / Refresh / Print / Export / page-size) stays usable. */
    .av-grid-stack .av-grid-action-filter,
    .av-grid-stack .av-grid-action-cols {
        display: none !important;
    }

    /* Reveal the global search box (hidden on desktop) so phones have a way to
       search now that the per-column filter bar/header is hidden. Give it a full
       row so the input isn't squashed next to the other toolbar buttons. */
    .av-grid-stack .av-grid-action-search {
        display: flex !important;
        flex: 1 1 100% !important;
        padding: 4px 0 !important;
    }

    .av-grid-stack .av-grid-action-search .e-control-wrapper,
    .av-grid-stack .av-grid-action-search .e-input-group {
        width: 100% !important;
    }
}

/* Full-height dialog content for FrmFileViewer / FrmSpreadsheetEdit
   lives in those components' own <style> blocks (search for
   ".rz-dialog-content" there) - Radzen's .rz-dialog-content is
   `flex: 0 1 auto` and never grows, so each component opts its
   dialog into a grow-to-fill layout via :has(). */

/* ============================================================
   FrmShowArchive (Archive Old Shows) — responsive stacking.
   The two analysis panels (Space by Table / Shows to be Archived)
   sit side by side on desktop and stack on narrow screens.
   Lives here, not in the page's inline <style>, because @media
   rules in inline component styles fail on real mobile browsers
   (see "@media rules belong in avops-overrides.css" in CLAUDE.md).
   ============================================================ */
@media (max-width: 900px) {
    .FrmShowArchiveGrids {
        grid-template-columns: 1fr !important;
    }
}

/* FrmDatabaseStatistics — stack the summary grid and pie chart
   on narrow screens (same reasoning as FrmShowArchive above). */
@media (max-width: 900px) {
    .FrmDbStatsTop {
        grid-template-columns: 1fr !important;
    }
}

/* ============================================================
   Multiline character counter (AVCountedTextBox component).
   Wraps a multiline SfTextBox and shows "1,234/4,000" at the
   TOP RIGHT of the control, mirroring the label at the top left.
   The counter is a normal flow element ABOVE the input (flex
   column), so it never collides with the textarea's scrollbar
   or text and needs no theme-specific absolute offsets.
   ============================================================ */
.av-counted-box {
    display: flex;
    flex-direction: column;
    width: 100%;
    min-width: 0;
    max-width: 100%;
}

.av-counted-box > .e-input-group,
.av-counted-box > .e-control-wrapper {
    width: 100%;
}

.av-counted-box .av-char-count {
    align-self: flex-end;       /* top RIGHT of the control */
    font-size: 11px;
    line-height: 1.2;
    color: #6c757d;
    padding-right: 4px;
    pointer-events: none;
    user-select: none;
    white-space: nowrap;
}

/* FloatLabelType.Always: the floating label occupies a strip above
   the input's border (Bootstrap5 theme). Pull the counter down into
   that strip so it sits on the SAME line as the label, right-aligned.
   Tweak the -18px if a theme change moves the label strip height. */
.av-counted-flabel .av-char-count {
    margin-bottom: -18px;
    position: relative;
    z-index: 1;
}

/* .av-form responsive sizing: the wrapper now stands in the flex row
   where the bare .e-input-group used to be, so it takes over the
   flex item role (mirrors the .av-form .e-input-group rule above). */
.av-form .av-counted-box {
    flex: 1 1 160px;
}
