/* =============================================================================
   DotNetShared.MudMobile — shared mobile-density layer for MudBlazor apps.

   WHY THIS EXISTS
   MudTheme exposes Palette / Typography / Shadows / LayoutProperties but has no
   density or spacing axis, so no theme can fix mobile padding. MudBlazor's
   defaults are desktop-first: a page nests pa-4 main content (16px) inside a
   pa-2 card (8px) inside a bordered+radiused MudPaper with mb-2, which on a
   430px iPhone spends ~48px of width on chrome before any content renders, and
   leaves a single-row flex layout of fixed-width decorations (timestamps,
   chips, icon buttons) to squeeze the actual payload text down to an ellipsis.

   DESIGN RULES THIS FILE ENCODES (all standard practice, not invention)
     1. A homogeneous list is ONE bordered container with 1px-divided rows —
        not N individually bordered cards. See GitHub .Box/.Box-row, Sentry's
        issue stream, Stripe/Vercel/Linear tables, iOS UITableView grouped
        style. Material 3 agrees: cards are for "a single contained concept";
        repeating rows are the List component, which uses dividers.
     2. Below the sm breakpoint that container goes edge-to-edge, leaving one
        gutter (Material 16dp / iOS HIG 16pt) instead of three nested ones.
     3. Rows become two-line: payload on top, metadata beneath. Never truncate
        the payload to make room for metadata.
     4. Tap targets >= 40px (HIG says 44pt; 40 is the practical floor for
        secondary row actions).

   HOW IT STAYS EASY TO REMOVE
   Every DESKTOP layout rule lives in the consuming markup (MudBlazor `d-flex`
   utilities + inline styles), never here. This file only (a) adds the opt-in
   .app-list container chrome and (b) overrides layout below the sm breakpoint.
   Delete the <link> and the markup renders exactly as it did before, with the
   app-* class names inert. See README.md.

   SCOPING RULE — IMPORTANT FOR ANYONE EDITING THIS FILE
   Never write a bare `.mud-paper` / `.mud-card` rule. MudBlazor renders
   dialogs, menus, popovers, tooltips, select and autocomplete dropdowns as
   .mud-paper too; an unscoped rule flattens all of them. Every rule below is
   scoped either to an opt-in app-* class or to a specific MudBlazor region.

   Load AFTER MudBlazor.min.css and after the app's own app.css so these win.
   ============================================================================= */


/* =============================================================================
   PART 1 — .app-list : bordered container, divided rows.   (all viewports)
   Opt in by wrapping a run of row elements:  <div class="app-list"> ... </div>
   ============================================================================= */

.app-list {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius);
    /* Clips the square corners of the first/last row against the rounded container,
       which is what makes the "one card, many rows" read work. */
    overflow: hidden;
}

/* Strip each row's own card chrome — the container now owns the border and radius.
   Child combinator (not descendant) so a MudPaper nested INSIDE a row, e.g. an
   expanded detail panel, keeps its own styling. */
.app-list > .mud-paper {
    border: 0 !important;
    border-radius: 0 !important;
    margin: 0 !important;
    box-shadow: none !important;
}

/* Dividers between rows, never above the first or below the last. */
.app-list > .mud-paper + .mud-paper {
    border-top: 1px solid var(--mud-palette-lines-default) !important;
}

.app-list > .mud-paper:hover {
    background-color: var(--mud-palette-action-default-hover);
}


/* =============================================================================
   PART 2 — .app-row : severity accent + two-line-capable row.
   Markup contract (desktop layout supplied by the markup itself, see header):

     <MudPaper class="pa-2 app-row app-row-error">
       <div class="d-flex align-center app-row-head" style="gap:8px">
         <icon/>
         <div class="d-flex align-center app-row-main" style="gap:8px; flex:1 1 auto; min-width:0">
           <div class="d-flex align-center app-row-meta" style="gap:8px"> ...timestamp, chips... </div>
           <div class="app-row-summary"> ...the payload text... </div>
         </div>
         <div class="app-row-actions"> ...icon buttons... </div>
       </div>
     </MudPaper>
   ============================================================================= */

/* Severity as a 3px inset bar. inset box-shadow rather than border-left so it
   costs no layout width and cannot shift the row's content box.
   The `.mud-paper` qualifier is load-bearing: Part 1's `.app-list > .mud-paper`
   reset also sets `box-shadow: none !important`, so a bare `.app-row-error`
   (0,1,0) would lose to it (0,2,0) and the bar would silently never render.
   Matching its specificity at (0,2,0) and declaring it later wins the cascade,
   and unlike `.app-list > …` it still applies to a row used outside a list. */
.mud-paper.app-row-fatal { box-shadow: inset 3px 0 0 var(--mud-palette-error) !important; }
.mud-paper.app-row-error { box-shadow: inset 3px 0 0 var(--mud-palette-warning) !important; }
.mud-paper.app-row-warn  { box-shadow: inset 3px 0 0 var(--mud-palette-info) !important; }

/* Keep text clear of the accent bar (pa-2 gives 8px; the bar eats 3px of it). */
.app-list > .app-row { padding-left: 12px !important; }


/* =============================================================================
   PART 3 — below the sm breakpoint (MudBlazor sm = 600px).
   ============================================================================= */

@media (max-width: 599.98px) {

    /* --- One page gutter, not three nested ones -----------------------------
       Left/right only. The padding-top on .mud-main-content is the app bar
       offset and MUST NOT be touched here — using the `padding` shorthand
       would clobber it and slide content under the fixed app bar.

       HOST-SHAPE INDEPENDENT — this is deliberate, do not re-narrow it.
       Three different shapes have turned up across four apps so far:
         (A) flat:      <MudMainContent Class="pa-4">@Body</MudMainContent>
                        (RMTools)               → .mud-main-content.pa-4
         (B) nested:    <MudMainContent><MudContainer>@Body</MudContainer></…>
                        (warehouse)             → a .mud-container--gutters
         (C) no shell:  MainLayout is bare @Body; each area's *Chrome.razor
                        renders <MudAppBar Fixed="false"> + a top-level
                        <MudContainer> with NO MudLayout/MudMainContent at all
                        (Weedable)              → a .mud-container--gutters,
                                                  but not inside any main content
       The first version of this rule matched only (A) and silently no-opped on
       warehouse; the second added `.mud-main-content > .mud-container--gutters`
       and would have silently no-opped on Weedable in exactly the same way.
       Chasing one selector per app is the bug, not the fix — so the container
       arm is now unanchored: ANY `.mud-container--gutters`, wherever it lives.
       MudContainer's default Gutters=true renders that class (MudBlazor's own
       16px/24px gutter, no !important) regardless of any pa-4/pt-4 utility
       class also on it, and MudContainer is a page-layout component by
       definition, so a nested one picking up 12px instead of 16px is a
       non-event. The `.mud-main-content.pa-4` arm stays for shape (A), which
       has no MudContainer to hook.

       `px-4` sits alongside `pa-4` (added 2026-08-01 for Yaya, whose shell is
       `<MudMainContent Class="px-4 pb-4">`). This is NOT the per-app selector
       creep the paragraph above warns against: `px-4` is MudBlazor's own
       horizontal-padding utility and means exactly the same 16px side gutter
       `pa-4` does — an app that writes `px-4 pb-4` instead of `pa-4` has made a
       vertical-spacing choice, not a different layout shape.

       Why this is anchored to a padding utility at all, rather than just
       matching `.mud-main-content`: the rule must only ever SHRINK a gutter
       that already exists, never add one. vrp is the counter-example that
       proves it — its `<MudMainContent Class="vrp-main">` computes
       `padding: 0` and the app supplies its own 14px inset further in, so a
       bare `.mud-main-content` match would have ADDED 12px of padding vrp
       never asked for. Add another utility here only if it genuinely sets
       horizontal padding (`px-3`, `pa-3`, …); never `.mud-main-content` bare. */
    .mud-main-content.pa-4,
    .mud-main-content.px-4,
    .mud-container--gutters {
        padding-left: 12px !important;
        padding-right: 12px !important;
    }

    /* --- List goes edge-to-edge ---------------------------------------------
       Negative margins cancel the page gutter exactly; side borders and radius
       come off because there is no longer any page background beside them. */
    .app-list {
        margin-left: -12px;
        margin-right: -12px;
        border-left: 0;
        border-right: 0;
        border-radius: 0;
    }

    /* --- ...and so does a plain top-level content card -----------------------
       WHY THIS EXISTS (added 2026-08-01, warehouse):
       The page-gutter rule above only collapses the OUTERMOST of the nested
       gutters this library was written to kill — 16px -> 12px, a 4px change per
       side that is invisible to the naked eye. The header's "~48px of chrome"
       problem is mostly the SECOND gutter: a page's own `pa-3`/`pa-4` MudPaper
       sitting directly inside the container adds another 12-16px per side, so
       real content still started 24px in on a 344px viewport (measured) and the
       page looked untouched. Fixing that needed either an `.app-list` opt-in on
       every page (a per-app markup rewrite — explicitly what the README says not
       to do) or this: apply design rule #2 automatically to the one shape where
       "the card IS the page section" is unambiguous.

       Deliberately a DIRECT-CHILD chain, mirroring `.app-list > .mud-paper`:
       only a card that is itself a top-level page section goes full-bleed. A
       MudPaper nested any deeper (inside a MudGrid column, a tab panel, an
       expansion panel) keeps its normal inset, because there its border IS the
       thing separating it from a sibling.

       Satisfies the file's scoping rule without naming `.mud-paper` bare:
       MudBlazor renders dialogs, menus, popovers, tooltips and select/
       autocomplete dropdowns as `.mud-paper` too, but MudPopoverProvider /
       MudDialogProvider TELEPORT every one of them out to their own provider
       at the end of the layout — none is ever a direct child of a page
       container, which is what the `>` here requires. Verified live in both
       warehouse (pattern B) and Weedable (pattern C) by opening a menu with
       this rule active and confirming it kept its radius, width and zero
       margin. Re-check that in any new app rather than assuming it.

       `.mud-table` is listed alongside `.mud-paper` because MudTable does NOT
       render a `.mud-paper` root — it renders `.mud-table .mud-elevation-N`, so
       a `.mud-paper`-only rule silently skips it (confirmed in the live DOM).
       That matters: "filter card + MudTable" is the shape of essentially every
       list page in warehouse, and without this the filter card went full-bleed
       while the table under it stayed inset — worse than not fixing either.
       A top-level table is also the exact case design rule #1 is about, and
       Part 4 below already owns its stacked-mode rendering.

       Host-shape independent for the same reason as the gutter rule above —
       the container arm is unanchored so shapes (A), (B), (C) and whatever
       turns up next all work with no new selector. Verified by eye on
       warehouse (B) and Weedable (C); RMTools (A) follows the same design rule
       but eyeball it next time you're in that app.

       `.app-page-content` is the ESCAPE HATCH, and the only markup opt-in this
       rule has. Direct-child matching is what keeps the rule from grabbing
       cards nested inside a grid column or a dialog, but it also means an app
       whose page content sits in a wrapper INSIDE the container gets nothing —
       Weedable is exactly that: `MudContainer > .weed-sidenav-layout >
       .weed-sidenav-content > @Body`, so every merchant/operator page card is
       two levels down and the rule silently no-ops. Rather than hard-code
       `.weed-sidenav-content` here (per-app selector creep — the exact thing
       the unanchored container arm above was written to end), an app in that
       shape adds `app-page-content` to whichever element actually wraps its
       page body. One class, one place, and it self-documents as "this is the
       page-section container." Requirement: that wrapper must have no side
       padding of its own, or the -12px will overshoot rather than cancel the
       page gutter (Weedable's is `min-width:0` only — check before adding). */
    .mud-container--gutters > .mud-paper,
    .mud-container--gutters > .mud-table,
    .app-page-content > .mud-paper,
    .app-page-content > .mud-table,
    .mud-main-content.pa-4 > .mud-paper,
    .mud-main-content.pa-4 > .mud-table,
    .mud-main-content.px-4 > .mud-paper,
    .mud-main-content.px-4 > .mud-table {
        /* Longhand, never the `margin` shorthand: page cards carry `mb-3`-style
           vertical rhythm utilities that the shorthand would silently wipe. */
        margin-left: -12px !important;
        margin-right: -12px !important;
        border-left: 0 !important;
        border-right: 0 !important;
        border-radius: 0 !important;
    }
    /* Restore the gutter inside the row so text isn't flush to the screen edge. */
    .app-list > .app-row {
        padding-left: 15px !important;
        padding-right: 12px !important;
    }

    /* --- Row becomes two lines: payload on top, metadata below --------------
       column-reverse rather than reordering the DOM: source order stays
       metadata-then-payload (which is the desktop reading order and what
       screen readers announce), while the visual order flips so the payload
       leads. !important is required because the markup carries the desktop
       flex settings inline, and inline styles otherwise win. */
    .app-row-head { align-items: flex-start !important; }

    .app-row-main {
        flex-direction: column-reverse !important;
        align-items: stretch !important;
        gap: 1px !important;
    }

    .app-row-meta {
        flex-wrap: wrap !important;
        gap: 6px !important;
        font-size: 0.72rem;
    }
    .app-row-meta .mud-typography { font-size: 0.72rem; }

    /* Chips. Measured on a 430px viewport: the metadata line has 285px, and three
       Size.Small pills need 240px of it (a long project name alone is 144px), so
       leaving them all as pills forces a second metadata line on every row.
       Project and env therefore flatten to plain text — they're identifiers, not
       states, and text is what dense mobile feeds use. The level keeps its pill
       because its colour is the actual scanning signal. Opt in per chip via the
       marker classes so this never silently reshapes chips elsewhere in a page. */
    .app-row-meta .mud-chip {
        height: 20px !important;
        font-size: 0.7rem !important;
        margin: 0 !important;
    }
    .app-row-meta .app-row-level .mud-chip-content { padding: 0 6px !important; }

    .app-row-meta .app-row-project,
    .app-row-meta .app-row-env {
        background: transparent !important;
        height: auto !important;
        min-height: 0 !important;
        box-shadow: none !important;
    }
    .app-row-meta .app-row-project .mud-chip-content,
    .app-row-meta .app-row-env .mud-chip-content {
        padding: 0 !important;
        height: auto !important;
    }
    .app-row-meta .app-row-project,
    .app-row-meta .app-row-project .mud-chip-content {
        color: var(--mud-palette-primary) !important;
        font-weight: 500;
    }
    .app-row-meta .app-row-env,
    .app-row-meta .app-row-env .mud-chip-content {
        color: var(--mud-palette-text-secondary) !important;
    }

    /* Abbreviated timestamp (drops the seconds), the pattern every dense mobile
       feed uses. Both forms are in the DOM; the short one is hidden by an inline
       style so removing this stylesheet leaves the full one showing on its own.
       !important is required to beat that inline style. */
    .app-row-ts-full { display: none !important; }
    .app-row-ts-short { display: block !important; }

    /* The payload: two-line clamp instead of a single truncated line.
       Overrides the single-line nowrap/ellipsis the desktop stylesheet sets. */
    .app-row-summary {
        white-space: normal !important;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
        line-height: 1.35;
    }

    /* --- Tap targets --------------------------------------------------------
       Size.Small icon buttons render ~30px, below the HIG minimum. */
    .app-row-actions .mud-button-root.mud-icon-button {
        min-width: 40px;
        min-height: 40px;
    }

    /* --- App bar ------------------------------------------------------------
       A wrapping title makes the bar taller than --mud-appbar-height, and any
       app whose main content is offset by that variable then renders its first
       heading clipped underneath. Force one line. */
    .mud-appbar .mud-toolbar {
        padding-left: 4px !important;
        padding-right: 4px !important;
    }
    .mud-appbar .mud-typography-h6,
    .mud-appbar .mud-typography-h5 {
        font-size: 1.05rem !important;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        min-width: 0;
    }

    /* --- Dialogs ------------------------------------------------------------
       MudBlazor's MaxWidth.Small/Medium/Large are fixed pixel widths that leave
       a wasteful inset on a phone. Scoped to .mud-dialog-container's child so
       menus and popovers (also .mud-paper) are unaffected. */
    .mud-dialog-container > .mud-dialog {
        margin: 8px !important;
        width: calc(100% - 16px) !important;
        max-width: calc(100% - 16px) !important;
    }

    /* ...and cap the dialog BODY to the shell we just sized.
       WHY THIS EXISTS (added 2026-08-01, task):
       The rule above only fixes the dialog's own box. The content inside it is
       free to be wider, and hard-coding a pixel width on the dialog body is a
       very common MudBlazor idiom — it's how you stop a short form from
       collapsing to its text width on desktop. task does it in 20 of its 23
       dialogs (`<div style="width:420px">` and friends, up to 472px).
       Measured live at a 430px viewport: the shell was a correct 414px, but a
       472px body rendered right edge at 504px — 74px off-screen. And because
       .mud-dialog-content clips rather than scrolls, the dialog's own
       scrollWidth still read 414: nothing scrolled, no scrollbar appeared,
       the right-hand strip of every such dialog was simply unreachable. That
       is the worst failure shape there is — it looks fine until you go
       looking for the field that isn't there.

       Direct children only, mirroring every other rule in this file: it caps
       the one element that owns the dialog's width, and leaves anything
       deliberately scrollable further in (a wide table with its own
       overflow-x) to scroll inside that cap instead of past it.

       No !important, deliberately: those app widths are INLINE `width`, and
       `max-width` from a stylesheet beats an inline `width` on its own — they
       are different properties, so there is no specificity contest to win.
       Verified both ways in the live DOM (472px -> 366px either way). Only
       reach for !important here if some app starts setting an inline
       `max-width`, which none does today. */
    .mud-dialog-container > .mud-dialog .mud-dialog-content > * {
        max-width: 100%;
    }
}

/* =============================================================================
   PART 4 — polish for MudTable's OWN built-in responsive mode.
   No opt-in class needed here: MudBlazor already ships a stacked label:value
   layout for EVERY MudTable by default — `MudTableBase.Breakpoint` defaults to
   `Breakpoint.Xs` (confirmed in MudBlazor.xml), not `None`, so any table that
   never sets `Breakpoint` at all is already stacking below 600px today, in
   this app and every other MudBlazor app. Elevation/Outlined on the table
   already gives it a card-like container, and MudBlazor's own CSS already
   divides each stacked row with a border (only the last cell gets a
   border-bottom) — so most tables already look like `.app-list`/`.app-row`
   with zero extra CSS or markup, unlike Parts 1-3.

   The one real gap: a trailing action-icon column (or the auto-added
   MultiSelection checkbox column) has no DataLabel by design, so MudBlazor
   still gives it a full-height label:value row for a single icon button —
   wastes a whole row and leaves the button under the 40px HIG tap-target
   floor. Fixed generically below for every Breakpoint value in use:
   `.mud-xs-table` is the class MudBlazor renders for the Xs *default* (so
   this fix applies automatically, with no markup change, to any table in any
   consuming app); `.mud-sm-table` covers tables that explicitly widen the
   threshold to `Breakpoint.Sm` (960px) — used so far by warehouse's
   transactional list pages, see its PROGRESS.md. Add an equivalent block for
   `.mud-md-table`/`.mud-lg-table`/`.mud-xl-table` (their own media queries —
   see MudBlazor.min.css) only if some table adopts one of those instead.

   `:has(.mud-icon-button)` is load-bearing, not decorative: several warehouse
   Detail/editor tables (e.g. PurchaseOrderDetail's line-item grid) have NO
   DataLabel on ANY cell yet (still on the Xs default, unconverted) — without
   this guard, `:not([data-label])` would also match their item-autocomplete /
   numeric-field / date-picker cells and squash them to a right-aligned strip.
   Requiring an icon button inside keeps this scoped to genuine action/
   checkbox columns, which is the only shape it was designed for. */
@media (max-width: 599.98px) {
    /* MudTd with no DataLabel = an unlabeled cell (action icons, or the
       auto-generated MultiSelection checkbox column). Collapse its row to a
       compact strip instead of a full label:value line, and give any icon
       button in it a real tap target. */
    .mud-xs-table .mud-table-cell:not([data-label]):has(.mud-icon-button) {
        justify-content: flex-end;
        padding-top: 4px !important;
        padding-bottom: 4px !important;
    }
    .mud-xs-table .mud-table-cell:not([data-label]) .mud-button-root.mud-icon-button {
        min-width: 40px;
        min-height: 40px;
    }
}

@media (max-width: 960px) {
    /* Same fix, for tables that explicitly widen to Breakpoint.Sm. */
    .mud-sm-table .mud-table-cell:not([data-label]):has(.mud-icon-button) {
        justify-content: flex-end;
        padding-top: 4px !important;
        padding-bottom: 4px !important;
    }
    .mud-sm-table .mud-table-cell:not([data-label]) .mud-button-root.mud-icon-button {
        min-width: 40px;
        min-height: 40px;
    }
}
