/* =============================================================================
   MwDataGrid CSS — Global Stylesheet
   Prefix: mw-dg-*
   ============================================================================= */

/* NOTE: Composition wrapper — flex column so the container fills remaining
   space after toolbar + filter panel.  height:100% propagates the ancestor's
   height constraint; without it, the container's own height:100% resolves to
   auto and Virtualize renders all items (no scrolling → scrollTop clamps to 0). */
.mw-dg-comp {
    position: relative;
    height: 100%;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* NOTE: Toolbar — tab shape, left-aligned above the grid */
.mw-dg-toolbar {
    display: inline-flex;
    align-items: center;
    gap: 1px;
    padding: 4px 6px;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.02) 0%, transparent 120px),
    var(--mud-palette-surface);
    border: 1px solid rgba(255, 255, 255, 0.07);
    border-bottom: none;
    border-radius: 8px 8px 0 0;
    position: relative;
    /* NOTE: Override MudBlazor's default border-radius for all children inside the toolbar */
    --mud-default-borderradius: 6px;
}

/* NOTE: Concave corner — pseudo-element with radial gradient */
.mw-dg-toolbar::after {
    content: '';
    position: absolute;
    right: -12px;
    bottom: 0;
    width: 12px;
    height: 12px;
    background: radial-gradient(circle at 0 0, transparent 10.5px, var(--mud-palette-surface) 11.5px);
    pointer-events: none;
}

/* NOTE: Second toolbar row (SwapGridSwitchInOwnToolbarRow) — the pane switcher on its own
   full-width strip under the toolbar's tab, the mockup's facetbar position. flex-shrink: 0 so it
   never gets squeezed by the grid body below it; the switcher inside may still shrink. */
.mw-dg-swaprow {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 4px;
    min-width: 0;
    padding: 6px 8px;
    background: var(--mud-palette-surface);
    border: 1px solid rgba(255, 255, 255, 0.07);
    border-bottom: 1px solid var(--mud-palette-table-lines);
    /* NOTE: The tab above already draws this edge — a second one reads as a seam. */
    border-top: none;
    position: relative;
    /* NOTE: Same override as the toolbar, so MudBlazor children match the toolbar's radius. */
    --mud-default-borderradius: 6px;
}

/* NOTE: The switcher owns this row, so it uses all of it by default — a host-supplied switch
   (its wrapper) stretches, and the built-in per-pane buttons split the row in equal parts. A
   host-supplied MwSwitchGroup still needs its own FullWidth for its BUTTONS to divide the
   space; this only hands the group the width to divide. */
.mw-dg-swaprow > * {
    flex: 1 1 auto;
    min-width: 0;
}

.mw-dg-swaprow > .mw-dg-swap-btn {
    flex: 1 1 0;
    justify-content: center;
    margin-left: 0;
}

/* NOTE: With a swap row present the ROW is what meets the grid body, so it — not the toolbar —
   owns the corner cleanup: the body's top-left radius is already dropped by the rule below
   (:has(.mw-dg-toolbar) still matches), and the row spans the full width, so the toolbar's
   concave corner would hang over a filled surface instead of the page background. */
.mw-dg-comp:has(.mw-dg-swaprow) > .mw-dg-toolbar::after {
    display: none;
}

/* NOTE: Two-row toolbar — with the switcher on its own full-width row below, the top row spans the
   full width too (not the content-sized tab), so the search can stretch across it and line up with
   the switch row. The search grows to fill; the filter icon, contextual actions and the select
   control stay at their content width on the right. When the select control expands (select mode),
   it takes more width and the flexing search contracts to make room — flexbox does this for free. */
.mw-dg-comp:has(.mw-dg-swaprow) > .mw-dg-toolbar,
.mw-dg-comp:has(.mw-dg-compact) > .mw-dg-toolbar {
    display: flex;
    width: 100%;
    box-sizing: border-box;
}

.mw-dg-comp:has(.mw-dg-swaprow) > .mw-dg-toolbar .mw-dg-search-field,
.mw-dg-comp:has(.mw-dg-compact) > .mw-dg-toolbar .mw-dg-search-field {
    flex: 1 1 auto;
    max-width: none;
}

/* NOTE: Compact (mobile) toolbar — the desktop "tab" (surface fill, border, rounded corners, concave
   notch) reads as a floating card on a phone. On compact the toolbar becomes a flat, transparent
   strip with only a bottom hairline (the mockup's .toolstrip): it blends into the page, spans the
   width, and its search fills the row. */
.mw-dg-comp:has(.mw-dg-compact) > .mw-dg-toolbar {
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    border-radius: 0;
    padding: 8px 4px;
    gap: 8px;
}

.mw-dg-comp:has(.mw-dg-compact) > .mw-dg-toolbar::after {
    display: none;
}

/* NOTE: Grid loses top-left radius when toolbar is present */
.mw-dg-comp:has(.mw-dg-toolbar) > .mw-dg-container,
.mw-dg-comp:has(.mw-dg-toolbar) > .mw-dg-compact {
    border-top-left-radius: 0;
}

/* NOTE: Grid loses top-right radius and top border when filter panel is expanded */
.mw-dg-comp > .mw-dg-container,
.mw-dg-comp > .mw-dg-compact {
    transition: border-top-right-radius 0.25s ease-out, border-top-color 0.25s ease-out;
}
.mw-dg-comp:has(.mw-dg-filter-wrap--open) > .mw-dg-container,
.mw-dg-comp:has(.mw-dg-filter-wrap--open) > .mw-dg-compact {
    border-top-right-radius: 0;
    border-top-color: transparent;
}


/* NOTE: Advanced filter panel — grid-row accordion (0fr → 1fr) */
.mw-dg-filter-wrap {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.25s ease-out;
}
.mw-dg-filter-wrap--open {
    grid-template-rows: 1fr;
}
.mw-dg-filter-panel {
    overflow: hidden;
    min-height: 0;
    padding: 0 12px;
    background: var(--mud-palette-surface);
    border: 1px solid transparent;
    border-bottom: none;
    transition: padding 0.25s ease-out, border-color 0.25s ease-out;
}
.mw-dg-filter-wrap--open .mw-dg-filter-panel {
    padding: 12px;
    border-color: rgba(255, 255, 255, 0.07);
}

.mw-dg-filter-toggle {
    flex-shrink: 0;
}


/* NOTE: Integrated search field */
.mw-dg-search-field {
    /* NOTE: --mw-dg-search-width is set on .mw-dg-toolbar from the SearchFieldWidth
       parameter; when unset, the field keeps its auto width capped at 200px. */
    width: var(--mw-dg-search-width, auto);
    max-width: var(--mw-dg-search-width, 200px);
    min-width: 120px;
}

.mw-dg-search-field .mud-input-slot {
    font-size: 0.8125rem;
}

.mw-dg-search-field.mud-input-control .mud-input.mud-input-outlined:focus-within {
    box-shadow: 0 0 0 3px rgba(var(--mud-palette-primary-rgb), 0.08);
    border-radius: 6px;
}


/* NOTE: Search highlight */
.mw-dg-search-highlight {
    background: rgba(var(--mud-palette-warning-rgb), 0.30);
    color: inherit;
    border-radius: 2px;
    padding: 0 1px;
}

/* NOTE: Container — overflow-anchor:none disables Chrome's scroll anchoring.
   Virtualize manages scroll position via spacer heights; Chrome's anchoring
   resets scrollTop to 0 when a full row recycle removes all anchor candidates. */
.mw-dg-container {
    overflow: auto;
    overflow-anchor: none;
    position: relative;
    width: 100%;
    border-radius: var(--mw-dg-radius, 8px);
    border: 1px solid rgba(255, 255, 255, 0.07);
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.02) 0%, transparent 120px),
    var(--mud-palette-surface);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3),
    0 8px 24px rgba(0, 0, 0, 0.15),
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    0 0 80px -20px rgba(var(--mud-palette-primary-rgb), 0.08);
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.12) transparent;
}

.mw-dg-container::-webkit-scrollbar {
    width: 5px;
    height: 5px;
}

.mw-dg-container::-webkit-scrollbar-track {
    background: transparent;
}

.mw-dg-container::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.1);
    border-radius: 3px;
}

.mw-dg-container::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.2);
}

.mw-dg-container::-webkit-scrollbar-corner {
    background: transparent;
}

/* NOTE: Table — border-collapse:separate avoids Chrome rendering artifacts
   with position:sticky headers (collapsed borders are shared between cells,
   which confuses the compositor during scroll-layer repaint). */
.mw-dg-table {
    table-layout: auto;
    width: max-content;
    min-width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: 0.875rem;
    line-height: 1.4;
}

/* NOTE: Opt-out of the min-width:100% stretch for embedded/compact grids. With it dropped the table is
   width:max-content (sized to its columns), so a few narrow columns inside a wide parent stay together
   instead of spreading to fill the parent's width. Apply by wrapping the grid in <div class="mw-dg-fit">. */
.mw-dg-fit .mw-dg-table {
    min-width: 0;
}

/* =============================================================================
   Header
   ============================================================================= */

.mw-dg-th {
    position: sticky;
    top: 0;
    z-index: 4;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.035) 0%, rgba(255, 255, 255, 0.01) 100%),
    var(--mud-palette-surface);
    padding: 0 16px;
    height: var(--mw-dg-th-height, 52px);
    text-align: left;
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    white-space: nowrap;
    color: rgba(255, 255, 255, 0.35);
    border-bottom: none;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06),
                inset 0 -1px 0 rgba(255, 255, 255, 0.06);
    transition: color 0.15s ease;
}

.mw-dg-header-row .mw-dg-th:first-child {
    border-top-left-radius: max(0px, calc(var(--mw-dg-radius, 8px) - 1px));
}

.mw-dg-header-row .mw-dg-th:last-child {
    border-top-right-radius: max(0px, calc(var(--mw-dg-radius, 8px) - 1px));
}

/* =============================================================================
   Column group bands — the optional spanning header row above the column headers.
   One cell per contiguous run of same-ColumnGroup columns; blank fillers above
   ungrouped columns. The band row is sticky at the very top; the regular header
   row slides its sticky offset down by the band height (mw-dg-has-bands).
   ============================================================================= */

.mw-dg-band-th {
    position: sticky;
    top: 0;
    z-index: 4;
    height: var(--mw-dg-band-height, 24px);
    padding: 0 16px;
    text-align: left;
    font-weight: 600;
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    white-space: nowrap;
    color: color-mix(in srgb, var(--mw-dg-band-accent, rgba(255, 255, 255, 0.45)) 75%, transparent);
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.02) 100%),
    var(--mud-palette-surface);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06),
                inset 0 -2px 0 color-mix(in srgb, var(--mw-dg-band-accent, rgba(255, 255, 255, 0.2)) 45%, transparent);
}

/* NOTE: Filler cells above ungrouped columns — surface only, no label, no accent underline. */
.mw-dg-band-th--blank {
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
}

/* NOTE: With a band row present the top corner rounding moves up to the band row. */
.mw-dg-band-row .mw-dg-band-th:first-child {
    border-top-left-radius: max(0px, calc(var(--mw-dg-radius, 8px) - 1px));
}

.mw-dg-band-row .mw-dg-band-th:last-child {
    border-top-right-radius: max(0px, calc(var(--mw-dg-radius, 8px) - 1px));
}

.mw-dg-has-bands .mw-dg-header-row .mw-dg-th {
    top: var(--mw-dg-band-height, 24px);
}

.mw-dg-has-bands .mw-dg-header-row .mw-dg-th:first-child {
    border-top-left-radius: 0;
}

.mw-dg-has-bands .mw-dg-header-row .mw-dg-th:last-child {
    border-top-right-radius: 0;
}

/* NOTE: Group boundary — a vertical hairline on the FIRST column of each band, drawn down the
   header (restating the th's inset shadows: box-shadow does not compose across rules), the
   filter row, and every body cell. */
.mw-dg-th.mw-dg-th--band-start {
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06),
                inset 0 -1px 0 rgba(255, 255, 255, 0.06),
                inset 1px 0 0 rgba(255, 255, 255, 0.12);
}

.mw-dg-cell--band-start {
    box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.08);
}

.mw-dg-th--sortable {
    cursor: pointer;
    user-select: none;
}

.mw-dg-th--sortable:hover {
    color: rgba(255, 255, 255, 0.8);
}

.mw-dg-header-text {
    vertical-align: middle;
}

/* NOTE: Sort indicators */
.mw-dg-sort-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: 3px;
    font-size: 0.5rem;
    vertical-align: middle;
    color: var(--mud-palette-primary);
    transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

.mw-dg-sort-desc {
    transform: rotate(180deg);
}

.mw-dg-sort-index {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 14px;
    height: 14px;
    font-size: 0.55rem;
    font-weight: 700;
    border-radius: 7px;
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    margin-left: 3px;
    vertical-align: middle;
    padding: 0 3px;
}

/* =============================================================================
   Rows & Cells
   ============================================================================= */

.mw-dg-row {
    height: 52px;
    position: relative;
}

.mw-dg-row:hover {
    background: rgba(var(--mud-palette-primary-rgb), 0.04);
    transition: background 0.1s ease;
}

/* Whole-row click affordance — set when the grid has an OnRowClick handler. */
.mw-dg-row-clickable .mw-dg-row,
.mw-dg-row-clickable .mw-dg-cell {
    cursor: pointer;
}

.mw-dg-cell {
    padding: 0 16px;
    height: inherit;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    border-bottom: 1px solid rgba(255, 255, 255, 0.035);
    vertical-align: middle;
    color: var(--mud-palette-text-primary);
}

.mw-dg-cell:has(.mud-switch-m3),
.mw-dg-cell:has(.mud-switch),
.mw-dg-cell:has(.mw-live-switch) {
    overflow: visible;
    text-overflow: unset;
}

/* =============================================================================
   ShowFullContentOnHover — pop-out reveal for width-restricted cells
   ============================================================================= */

/* NOTE: Opt-in per column (ShowFullContentOnHover, only when a fixed Width is set), or grid-wide
   via ShowFullContentOnHoverByDefault. A reveal cell's two layers are BOTH position:absolute, so
   the <td> holds no in-flow content and its width is pinned entirely by the inline width/min-width.
   That is the whole point: an in-flow inline-block/text child would feed its intrinsic (nowrap)
   width into the auto table-layout algorithm and blow the column out — and collapse it again the
   moment the child goes absolute on hover. With nothing in flow, the column can never resize. */
.mw-dg-cell--reveal {
    position: relative;
    overflow: visible;
}

/* NOTE: In-flow view — fills the cell and clips ITSELF (its own overflow), independent of the
   <td>, so it stays truncated even though the cell is overflow:visible for the overlay's sake.
   top:50% + translateY centres the single line vertically without a flex wrapper (which would
   break text-overflow: ellipsis). */
.mw-dg-reveal-inflow {
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    padding: 0 16px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* NOTE: The pop-out — hidden until the cell is armed. The mw-dg-reveal-on class is added by the
   grid's delegated pointer handler ONLY while the pointer is over a cell whose text actually
   overflows (measured scrollWidth > clientWidth). A cell whose content fits never gets it, so it
   never pops — CSS alone can't distinguish truncated from fitting, which is why this is JS-driven. */
.mw-dg-reveal-overlay {
    display: none;
}

.mw-dg-cell--reveal.mw-dg-reveal-on {
    z-index: 3;
}

/* NOTE: Shares the in-flow layer's left origin + horizontal padding, so the first characters land
   at the exact same x — the overlay reads as the cell itself extending. It grows right with
   width:max-content (capped), opaque so it fully covers the in-flow line beneath it, and lifts
   above neighbours (z-index below the sticky header at z-index:4). */
.mw-dg-cell--reveal.mw-dg-reveal-on .mw-dg-reveal-overlay {
    display: block;
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    width: max-content;
    max-width: min(720px, 85vw);
    padding: 5px 16px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    background: var(--mud-palette-surface);
    border-radius: 6px;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08),
                0 6px 20px rgba(0, 0, 0, 0.45);
    z-index: 3;
}

/* NOTE: Both layers track the per-size cell padding (horizontal only, so the overlay keeps its
   vertical card padding) — text never shifts x on hover. Dense is last so it wins when both
   size and dense classes are present, exactly as the per-size cell rules resolve. */
.mw-dg-size-tiny .mw-dg-reveal-inflow,
.mw-dg-size-tiny .mw-dg-cell--reveal.mw-dg-reveal-on .mw-dg-reveal-overlay {
    padding-left: 8px;
    padding-right: 8px;
}

.mw-dg-size-small .mw-dg-reveal-inflow,
.mw-dg-size-small .mw-dg-cell--reveal.mw-dg-reveal-on .mw-dg-reveal-overlay {
    padding-left: 12px;
    padding-right: 12px;
}

.mw-dg-size-large .mw-dg-reveal-inflow,
.mw-dg-size-large .mw-dg-cell--reveal.mw-dg-reveal-on .mw-dg-reveal-overlay {
    padding-left: 20px;
    padding-right: 20px;
}

.mw-dg-size-huge .mw-dg-reveal-inflow,
.mw-dg-size-huge .mw-dg-cell--reveal.mw-dg-reveal-on .mw-dg-reveal-overlay {
    padding-left: 24px;
    padding-right: 24px;
}

.mw-dg-dense .mw-dg-reveal-inflow,
.mw-dg-dense .mw-dg-cell--reveal.mw-dg-reveal-on .mw-dg-reveal-overlay {
    padding-left: 8px;
    padding-right: 8px;
}

/* NOTE: Hover accent — primary color bar on left edge via inset shadow */
.mw-dg-row:hover > td:first-child {
    box-shadow: inset 3px 0 0 var(--mud-palette-primary);
    transition: box-shadow 0.1s ease;
}

/* =============================================================================
   Size Levels
   ============================================================================= */

/* NOTE: Tiny — 30px rows, maximum density */
.mw-dg-size-tiny .mw-dg-th {
    padding: 0 8px;
    font-size: 0.65rem;
}

.mw-dg-size-tiny .mw-dg-row {
    height: 30px;
}

.mw-dg-size-tiny .mw-dg-cell {
    padding: 0 8px;
    font-size: 0.75rem;
}

/* NOTE: Small — 38px rows, dense operational */
.mw-dg-size-small .mw-dg-th {
    padding: 0 12px;
    font-size: 0.7rem;
}

.mw-dg-size-small .mw-dg-row {
    height: 38px;
}

.mw-dg-size-small .mw-dg-cell {
    padding: 0 12px;
    font-size: 0.8125rem;
}

/* NOTE: Medium — 52px rows, default (sizes in base rules) */

/* NOTE: Large — 62px rows, comfortable */
.mw-dg-size-large .mw-dg-th {
    padding: 0 20px;
    font-size: 0.8rem;
}

.mw-dg-size-large .mw-dg-row {
    height: 62px;
}

.mw-dg-size-large .mw-dg-cell {
    padding: 0 20px;
    font-size: 0.9375rem;
}

/* NOTE: Huge — 76px rows, presentation/accessibility */
.mw-dg-size-huge .mw-dg-th {
    padding: 0 24px;
    font-size: 0.85rem;
}

.mw-dg-size-huge .mw-dg-row {
    height: 76px;
}

.mw-dg-size-huge .mw-dg-cell {
    padding: 0 24px;
    font-size: 1rem;
}

/* =============================================================================
   Dense — reduces vertical padding, keeps row height from Density
   ============================================================================= */

/* NOTE: Dense — tightens cell padding so content packs tighter within the row.
   Header height is NOT shrunk — it stays at --mw-dg-th-height (= row height)
   so header and rows always match visually regardless of cell content height. */
.mw-dg-dense .mw-dg-th {
    padding: 0 8px;
}

.mw-dg-dense .mw-dg-cell {
    padding: 1px 8px;
}

/* NOTE: Set CSS variables per size level. Header height equals row height by default;
   override with --mw-dg-th-height via HeaderHeightOverridePx parameter. */
.mw-dg-size-tiny {
    --mw-dg-th-height: 30px;
    --mw-dg-row-height: 30px;
}

.mw-dg-size-small {
    --mw-dg-th-height: 38px;
    --mw-dg-row-height: 38px;
}

.mw-dg-size-medium {
    --mw-dg-th-height: 52px;
    --mw-dg-row-height: 52px;
}

.mw-dg-size-large {
    --mw-dg-th-height: 62px;
    --mw-dg-row-height: 62px;
}

.mw-dg-size-huge {
    --mw-dg-th-height: 76px;
    --mw-dg-row-height: 76px;
}

/* =============================================================================
   Tree mode — connectors + chevron
   Used when the grid is configured with ParentIdSelector or ChildrenSelector.
   ============================================================================= */

/* The tree cell drops its own padding so connector lines reach across the row.
   The actual cell padding lives on the inner flex container. */
.mw-dg-cell--tree {
    padding: 0 !important;
    height: 1px; /* makes child height: 100% behave inside table cells */
}

.mw-dg-tree-cell {
    display: flex;
    align-items: center;
    height: 100%;
    min-height: var(--mw-dg-row-height, 52px);
    padding-right: 16px;
}

/* Per-depth slot. Width 22px ≈ a single ASCII column. */
.mw-dg-tree-guide {
    align-self: stretch;
    width: 22px;
    flex-shrink: 0;
    position: relative;
}

/* Through-line: vertical line spanning the full row height */
.mw-dg-tree-guide--through::before {
    content: "";
    position: absolute;
    left: 9px;
    top: -1px;
    bottom: -1px;
    width: 1px;
    background: rgba(255, 255, 255, 0.12);
}

/* L-branch: vertical line top→middle, then horizontal middle→right */
.mw-dg-tree-guide--last::before {
    content: "";
    position: absolute;
    left: 9px;
    top: -1px;
    height: calc(50% + 1px);
    width: 1px;
    background: rgba(255, 255, 255, 0.12);
}

.mw-dg-tree-guide--last::after {
    content: "";
    position: absolute;
    left: 9px;
    top: 50%;
    width: 12px;
    height: 1px;
    background: rgba(255, 255, 255, 0.12);
}

/* T-branch: vertical line full height, plus horizontal middle→right */
.mw-dg-tree-guide--tee::before {
    content: "";
    position: absolute;
    left: 9px;
    top: -1px;
    bottom: -1px;
    width: 1px;
    background: rgba(255, 255, 255, 0.12);
}

.mw-dg-tree-guide--tee::after {
    content: "";
    position: absolute;
    left: 9px;
    top: 50%;
    width: 12px;
    height: 1px;
    background: rgba(255, 255, 255, 0.12);
}

/* Leaf rows: horizontal segment extends past the chevron-pad to almost reach the name.
   Chevroned rows keep the short segment so the line doesn't cross the chevron icon. */
.mw-dg-tree-cell--leaf .mw-dg-tree-guide--last::after,
.mw-dg-tree-cell--leaf .mw-dg-tree-guide--tee::after {
    width: 32px;
}

/* Accented connector (TreeConnectorColorSelector): the parent→row segment renders in
   --mw-dg-tree-accent with a soft glow (theme edge-glow language). Only the incoming edge is
   accented — on a tee, the vertical's lower half continues to LATER siblings and stays neutral
   via the half-height gradient. Rules repeat the hover/selected selectors below so the accent
   survives both states. */
.mw-dg-tree-guide--accent.mw-dg-tree-guide--last::before,
.mw-dg-tree-guide--accent::after,
.mw-dg-table tbody tr:hover .mw-dg-tree-guide--accent.mw-dg-tree-guide--last::before,
.mw-dg-table tbody tr:hover .mw-dg-tree-guide--accent::after,
.mw-dg-table tbody tr.mw-dg-row--selected .mw-dg-tree-guide--accent.mw-dg-tree-guide--last::before,
.mw-dg-table tbody tr.mw-dg-row--selected .mw-dg-tree-guide--accent::after {
    background: var(--mw-dg-tree-accent, var(--mud-palette-primary));
    box-shadow: 0 0 6px color-mix(in srgb, var(--mw-dg-tree-accent, var(--mud-palette-primary)) 55%, transparent);
}

.mw-dg-tree-guide--accent.mw-dg-tree-guide--tee::before,
.mw-dg-table tbody tr:hover .mw-dg-tree-guide--accent.mw-dg-tree-guide--tee::before,
.mw-dg-table tbody tr.mw-dg-row--selected .mw-dg-tree-guide--accent.mw-dg-tree-guide--tee::before {
    background: linear-gradient(
        to bottom,
        var(--mw-dg-tree-accent, var(--mud-palette-primary)) 0%,
        var(--mw-dg-tree-accent, var(--mud-palette-primary)) 50%,
        rgba(255, 255, 255, 0.12) 50%,
        rgba(255, 255, 255, 0.12) 100%
    );
    box-shadow: 0 0 6px color-mix(in srgb, var(--mw-dg-tree-accent, var(--mud-palette-primary)) 35%, transparent);
}

/* Pass-through accent: the path's vertical crossing an intermediate row (any slot shape) — full
   height, arm untouched. Declared AFTER the --accent tee gradient at matching specificity, so a
   row that is both a target and a pass-through (two accented siblings) gets the solid vertical. */
.mw-dg-tree-guide--accent-pass.mw-dg-tree-guide::before,
.mw-dg-tree-guide--accent-pass.mw-dg-tree-guide--tee::before,
.mw-dg-table tbody tr:hover .mw-dg-tree-guide--accent-pass.mw-dg-tree-guide::before,
.mw-dg-table tbody tr.mw-dg-row--selected .mw-dg-tree-guide--accent-pass.mw-dg-tree-guide::before {
    background: var(--mw-dg-tree-accent, var(--mud-palette-primary));
    box-shadow: 0 0 6px color-mix(in srgb, var(--mw-dg-tree-accent, var(--mud-palette-primary)) 35%, transparent);
}

/* Accented trunk: the path's start under the parent's expanded chevron. */
.mw-dg-tree-chev-slot--accent.mw-dg-tree-chev-slot--expanded::after,
.mw-dg-table tbody tr:hover .mw-dg-tree-chev-slot--accent.mw-dg-tree-chev-slot--expanded::after,
.mw-dg-table tbody tr.mw-dg-row--selected .mw-dg-tree-chev-slot--accent.mw-dg-tree-chev-slot--expanded::after {
    background: var(--mw-dg-tree-accent, var(--mud-palette-primary));
    box-shadow: 0 0 6px color-mix(in srgb, var(--mw-dg-tree-accent, var(--mud-palette-primary)) 55%, transparent);
}

/* Hover & selection brighten the connector lines (incl. chevron's downward trunk) */
.mw-dg-table tbody tr:hover .mw-dg-tree-guide::before,
.mw-dg-table tbody tr:hover .mw-dg-tree-guide::after,
.mw-dg-table tbody tr:hover .mw-dg-tree-chev-slot--expanded::after {
    background: rgba(255, 255, 255, 0.22);
}

.mw-dg-table tbody tr.mw-dg-row--selected .mw-dg-tree-guide::before,
.mw-dg-table tbody tr.mw-dg-row--selected .mw-dg-tree-guide::after,
.mw-dg-table tbody tr.mw-dg-row--selected .mw-dg-tree-chev-slot--expanded::after {
    background: rgba(var(--mud-palette-primary-rgb, 139, 126, 255), 0.45);
}

/* Chevron slot: stretches to the full row height and hosts the downward trunk,
   so the connector always reaches the row's bottom edge. (Row heights vary with
   cell content — the previous fixed calc() against --mw-dg-row-height left a gap
   whenever a row rendered taller than the nominal height.) */
.mw-dg-tree-chev-slot {
    position: relative;
    align-self: stretch;
    display: flex;
    align-items: center;
    flex-shrink: 0;
    margin-right: 4px;
}

/* Expand/collapse chevron — the button itself stays unrotated so we can host
   a stable downward-trunk pseudo-element. Only the SVG icon rotates. */
.mw-dg-tree-chev {
    width: 18px;
    height: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background: none;
    border: none;
    border-radius: 3px;
    color: rgba(255, 255, 255, 0.55);
    cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease;
}

.mw-dg-tree-chev:hover {
    background: rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.95);
}

.mw-dg-tree-chev svg {
    transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1);
}

.mw-dg-tree-chev--expanded {
    color: rgba(255, 255, 255, 0.85);
}

.mw-dg-tree-chev--expanded svg {
    transform: rotate(90deg);
}

/* Downward trunk: connects the expanded chevron icon to the children's branch
   lines below — from just under the icon to 1px past the row edge (bridging the
   row border, matching the guide lines' ±1px bleed). */
.mw-dg-tree-chev-slot--expanded::after {
    content: "";
    position: absolute;
    left: 9px; /* chevron horizontal center (chevron is 18px wide) */
    top: calc(50% + 9px); /* bottom edge of the 18px icon centered on the row */
    bottom: -1px;
    width: 1px;
    background: rgba(255, 255, 255, 0.12);
    pointer-events: none;
}

/* Empty placeholder so leaf rows still align with chevroned siblings */
.mw-dg-tree-chev-pad {
    display: inline-block;
    width: 18px;
    height: 18px;
    margin-right: 4px;
    flex-shrink: 0;
}

/* Wrapper for the actual cell content (label, badge, etc.) */
.mw-dg-tree-content {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
    min-width: 0;
}

/* =============================================================================
   Variants
   ============================================================================= */

.mw-dg-bordered .mw-dg-cell {
    border-right: 1px solid rgba(255, 255, 255, 0.035);
}

.mw-dg-bordered .mw-dg-th {
    border-right: 1px solid rgba(255, 255, 255, 0.06);
}

.mw-dg-striped .mw-dg-row:nth-child(even) {
    background: rgba(255, 255, 255, 0.012);
}

.mw-dg-striped .mw-dg-row:nth-child(even):hover {
    background: rgba(255, 255, 255, 0.04);
}

/* NOTE: Scroll snapping — rows magnet to top edge on scroll stop */
.mw-dg-snap-rows {
    scroll-snap-type: y proximity;
}

.mw-dg-snap-rows .mw-dg-row {
    scroll-snap-align: start;
}

/* =============================================================================
   Filter Row
   ============================================================================= */

.mw-dg-filter-row .mw-dg-filter-cell {
    padding: 5px 12px;
    position: sticky;
    top: var(--mw-dg-th-height, 52px);
    z-index: 3;
    background: var(--mud-palette-surface);
    border-top: none;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.mw-dg-size-tiny .mw-dg-filter-row .mw-dg-filter-cell {
    padding: 2px 6px;
}

.mw-dg-size-small .mw-dg-filter-row .mw-dg-filter-cell {
    padding: 3px 8px;
}

.mw-dg-size-large .mw-dg-filter-row .mw-dg-filter-cell {
    padding: 6px 16px;
}

.mw-dg-size-huge .mw-dg-filter-row .mw-dg-filter-cell {
    padding: 8px 20px;
}

/* NOTE: Dense filter row — header is no longer shrunk by Dense,
   so sticky top uses the same --mw-dg-th-height as the base rule. */

.mw-dg-filter-input {
    width: 100%;
    height: 26px;
    padding: 0 8px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.025);
    color: var(--mud-palette-text-primary);
    font-size: 0.75rem;
    font-family: inherit;
    outline: none;
    box-sizing: border-box;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.mw-dg-filter-input::placeholder {
    color: rgba(255, 255, 255, 0.2);
}

.mw-dg-filter-input:focus {
    border-color: var(--mud-palette-primary);
    box-shadow: 0 0 0 3px rgba(var(--mud-palette-primary-rgb), 0.08);
}

/* =============================================================================
   Column Resize Handle
   ============================================================================= */

.mw-dg-resize-handle {
    position: absolute;
    right: -1px;
    top: 8px;
    bottom: 8px;
    width: 3px;
    cursor: col-resize;
    z-index: 5;
    border-radius: 2px;
    opacity: 0;
    background: var(--mud-palette-primary);
    transition: opacity 0.12s ease;
}

.mw-dg-th:hover .mw-dg-resize-handle {
    opacity: 0.3;
}

.mw-dg-resize-handle:hover {
    opacity: 0.7 !important;
}

.mw-dg-resize-handle:active {
    opacity: 1 !important;
}

/* =============================================================================
   Column Drag-Drop Reorder
   ============================================================================= */

.mw-dg-th--dragging {
    opacity: 0.35;
}

/* =============================================================================
   Selection
   ============================================================================= */

.mw-dg-select-th,
.mw-dg-select-cell {
    width: 42px !important;
    min-width: 42px !important;
    max-width: 42px !important;
    text-align: center;
    padding: 0 !important;
}

.mw-dg-row--selected {
    background: rgba(var(--mw-mc-primary), 0.06) !important;
}

.mw-dg-row--selected:hover {
    background: rgba(var(--mw-mc-primary), 0.1) !important;
}

.mw-dg-row--selected > td:first-child {
    box-shadow: inset 3px 0 0 var(--mud-palette-primary) !important;
}

/* =============================================================================
   Edit State
   ============================================================================= */

.mw-dg-cell--editing {
    padding: 0 !important;
    position: relative;
    background: rgba(var(--mud-palette-primary-rgb), 0.12) !important;
    box-shadow: inset 0 0 0 1.5px var(--mud-palette-primary);
    border-radius: 6px;
}

/* NOTE: Inline-edit cells suppress td-level glow — the input handles its own focus styling */
.mw-dg-cell--editing:has(.mw-dg-inline-edit) {
    background: transparent !important;
    box-shadow: none;
    border-radius: 0;
}

/* =============================================================================
   Inline Edit — always-on input that looks like text when idle
   ============================================================================= */

.mw-dg-cell:has(.mw-dg-inline-edit) {
    padding: 0 !important;
}

.mw-dg-inline-edit {
    width: 100%;
    height: 100%;
    padding: 0 16px;
    border: none;
    background: transparent;
    color: inherit;
    font-size: inherit;
    font-family: inherit;
    outline: none;
    box-sizing: border-box;
    cursor: text;
    -moz-appearance: textfield;
}

.mw-dg-inline-edit::-webkit-inner-spin-button,
.mw-dg-inline-edit::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* NOTE: Show number spinners on hover */
.mw-dg-inline-edit:hover::-webkit-inner-spin-button,
.mw-dg-inline-edit:hover::-webkit-outer-spin-button {
    -webkit-appearance: auto;
}

.mw-dg-inline-edit:hover[type="number"] {
    -moz-appearance: auto;
}

.mw-dg-inline-edit:focus {
    background: rgba(var(--mud-palette-primary-rgb), 0.10);
    box-shadow: inset 0 0 0 1.5px var(--mud-palette-primary);
    border-radius: 4px;
    caret-color: var(--mud-palette-primary);
}

.mw-dg-size-tiny .mw-dg-inline-edit { padding: 0 8px; }
.mw-dg-size-small .mw-dg-inline-edit { padding: 0 12px; }
.mw-dg-size-large .mw-dg-inline-edit { padding: 0 20px; }
.mw-dg-size-huge .mw-dg-inline-edit { padding: 0 24px; }

.mw-dg-cell--error {
    box-shadow: inset 0 -2px 0 var(--mud-palette-error);
}

.mw-dg-edit-input {
    width: 100%;
    height: 100%;
    padding: 0 16px;
    border: none;
    border-radius: 6px;
    background: rgba(var(--mw-mc-primary), 0.04);
    color: var(--mud-palette-text-primary);
    font-size: inherit;
    font-family: inherit;
    outline: none;
    box-sizing: border-box;
    caret-color: var(--mud-palette-primary);
}

.mw-dg-size-tiny .mw-dg-edit-input {
    padding: 0 8px;
}

.mw-dg-size-small .mw-dg-edit-input {
    padding: 0 12px;
}

.mw-dg-size-large .mw-dg-edit-input {
    padding: 0 20px;
}

.mw-dg-size-huge .mw-dg-edit-input {
    padding: 0 24px;
}

.mw-dg-cell--error .mw-dg-edit-input {
    border-bottom-color: var(--mud-palette-error);
    caret-color: var(--mud-palette-error);
}

.mw-dg-edit-errors {
    position: absolute;
    bottom: -26px;
    left: 4px;
    z-index: 10;
    background: var(--mud-palette-background);
    padding: 4px 10px;
    border-radius: 4px;
    border: 1px solid rgba(var(--mw-mc-error), 0.25);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
}

.mw-dg-edit-error {
    color: var(--mud-palette-error);
    font-size: 0.7rem;
    font-weight: 500;
}

/* =============================================================================
   Compact Collapsible View
   ============================================================================= */

.mw-dg-compact {
    overflow: auto;
}

.mw-dg-compact-row {
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
    cursor: pointer;
    transition: background 0.1s ease;
}

.mw-dg-compact-row:active {
    background: rgba(255, 255, 255, 0.04);
}

.mw-dg-compact-summary {
    display: flex;
    align-items: center;
    padding: 10px 12px;
    min-height: 44px;
    gap: 8px;
}

/* NOTE: Compact view density overrides for summary row height */
.mw-dg-compact.mw-dg-size-tiny .mw-dg-compact-summary {
    min-height: 30px;
    padding: 2px 8px;
    font-size: 0.75rem;
}

.mw-dg-compact.mw-dg-size-small .mw-dg-compact-summary {
    min-height: 38px;
    padding: 4px 10px;
    font-size: 0.8125rem;
}

.mw-dg-compact.mw-dg-size-medium .mw-dg-compact-summary {
    min-height: 52px;
    padding: 10px 14px;
    font-size: 0.875rem;
}

.mw-dg-compact.mw-dg-size-large .mw-dg-compact-summary {
    min-height: 62px;
    padding: 14px 18px;
    font-size: 0.9375rem;
}

.mw-dg-compact.mw-dg-size-huge .mw-dg-compact-summary {
    min-height: 76px;
    padding: 18px 22px;
    font-size: 1rem;
}

.mw-dg-compact-left {
    flex: 1;
    min-width: 0;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: flex;
    gap: 6px;
}

.mw-dg-compact-right {
    flex-shrink: 0;
    color: rgba(255, 255, 255, 0.5);
    font-size: 0.8rem;
    display: flex;
    align-items: center;
    gap: 8px;
}

.mw-dg-compact-chevron {
    flex-shrink: 0;
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary);
    transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
    width: 20px;
    text-align: center;
}

/* NOTE: Compact column-header row (opt-in via ShowCompactColumnHeaders) — mirrors the summary row's
   flex layout so its labels sit above the matching Left/Right summary cells. Sticky within the scroll
   container so the labels stay while cards scroll. */
.mw-dg-compact-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 14px;
    min-height: 26px;
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--mud-palette-background-grey);
    border-bottom: 1px solid var(--mud-palette-lines-default);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
}

/* NOTE: Invisible chevron placeholder — reserves the same width as each row's chevron so the header's
   right block lines up with the rows'. */
.mw-dg-compact-chevron--spacer {
    visibility: hidden;
}

.mw-dg-compact-row--expanded .mw-dg-compact-chevron {
    transform: rotate(90deg);
}

.mw-dg-compact-row--expanded .mw-dg-compact-summary {
    border-left: 2px solid var(--mud-palette-primary);
    padding-left: 10px;
}

.mw-dg-compact-detail {
    padding: 4px 12px 14px 24px;
    display: flex;
    flex-direction: column;
    gap: 0;
}

.mw-dg-compact-field {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    min-height: 28px;
    padding: 6px 0;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.mw-dg-compact-field:last-child {
    border-bottom: none;
}

.mw-dg-compact-label {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--mud-palette-text-secondary);
    flex-shrink: 0;
    min-width: 80px;
}

.mw-dg-compact-value {
    font-size: 0.8125rem;
    text-align: right;
    white-space: normal;
    word-break: break-word;
    color: var(--mud-palette-text-primary);
}

/* NOTE: Inline edit inside a compact detail field — unlike the desktop cell's invisible overlay input,
   touch needs a visible affordance: a dashed underline that solidifies to primary while focused. */
.mw-dg-compact-value--editable {
    flex: 1;
    min-width: 0;
}

.mw-dg-compact-inline-edit {
    width: 100%;
    padding: 2px 0;
    border: none;
    border-bottom: 1px dashed rgba(255, 255, 255, 0.2);
    background: transparent;
    color: var(--mud-palette-text-primary);
    font-size: 0.8125rem;
    font-family: inherit;
    text-align: right;
    outline: none;
    box-sizing: border-box;
    cursor: text;
    -moz-appearance: textfield;
}

.mw-dg-compact-inline-edit:focus {
    border-bottom: 1px solid var(--mud-palette-primary);
}

.mw-dg-compact-inline-edit::-webkit-inner-spin-button,
.mw-dg-compact-inline-edit::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* =========================================================================
   NOTE: Detail rows — expandable content below each data row (mw-dg-detail-*)
   ========================================================================= */

.mw-dg-detail-row {
    background: transparent;
}

.mw-dg-detail-row:hover {
    background: transparent;
}

.mw-dg-detail-cell {
    padding: 0;
    border-top: none;
}

.mw-dg-detail-cell .mw-dg-detail-inner {
    padding: 12px 20px 16px 20px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

/* NOTE: Detail toggle column */

.mw-dg-detail-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
}

.mw-dg-detail-chev {
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    border: none;
    background: none;
    padding: 4px;
    border-radius: 50%;
    color: var(--mud-palette-text-secondary);
    transition: transform 200ms cubic-bezier(0.25, 0.8, 0.5, 1),
                color 200ms ease;
}

.mw-dg-detail-chev:hover {
    background-color: rgba(255, 255, 255, 0.06);
}

.mw-dg-detail-chev--expanded {
    transform: rotate(90deg);
    color: var(--mud-palette-primary);
}

/* =========================================================================
   NOTE: Row DnD — drag handle + drop feedback (tree reparenting via mw-dnd)
   The handle renders when the grid's RowDraggable predicate matches; the
   drop classes are toggled from C# via MwDragController.AddClassToMatchingAsync
   (direct DOM, no Blazor re-render).
   ========================================================================= */

.mw-dg-drag-handle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    margin-left: 2px;
    border-radius: 3px;
    color: rgba(255, 255, 255, 0.45);
    cursor: grab;
    opacity: 0;
    touch-action: none;
    transition: opacity 0.12s ease, color 0.12s ease;
}

.mw-dg-table tbody tr:hover .mw-dg-drag-handle {
    opacity: 1;
}

.mw-dg-drag-handle:hover {
    color: rgba(255, 255, 255, 0.95);
    background: rgba(255, 255, 255, 0.08);
}

.mw-dg-drag-handle:active {
    cursor: grabbing;
}

/* Placeholder keeps non-draggable rows (e.g. the tree root) aligned with their
   draggable siblings — same box, nothing to grab. */
.mw-dg-drag-handle--placeholder {
    visibility: hidden;
    pointer-events: none;
}

/* Valid drop target: row tint painted on the cells (td background wins over
   the tr-level hover background). */
.mw-dg-table tbody tr.mw-dg-row--drop-target > .mw-dg-cell {
    background: rgba(var(--mud-palette-success-rgb, 76, 175, 80), 0.16);
    box-shadow: inset 0 1px 0 rgba(var(--mud-palette-success-rgb, 76, 175, 80), 0.55),
                inset 0 -1px 0 rgba(var(--mud-palette-success-rgb, 76, 175, 80), 0.55);
}

/* Forbidden drop target (self or descendant of the dragged row — would create a cycle). */
.mw-dg-table tbody tr.mw-dg-row--drop-forbidden > .mw-dg-cell {
    background: rgba(var(--mud-palette-error-rgb, 244, 67, 54), 0.12);
    box-shadow: inset 0 1px 0 rgba(var(--mud-palette-error-rgb, 244, 67, 54), 0.45),
                inset 0 -1px 0 rgba(var(--mud-palette-error-rgb, 244, 67, 54), 0.45);
}


/* ============================================================================
   Grid swap (mw-dg-swap-*) — independent panes (each typically a complete grid)
   slide in horizontally in place of the grid body while the toolbar stays put.
   The wrappers are layout-neutral (display: contents) unless panes are declared,
   so grids without the feature render exactly as before.
   ============================================================================ */

.mw-dg-swap-viewport,
.mw-dg-swap-track,
.mw-dg-swap-pane {
    display: contents;
}

.mw-dg-swap-viewport--on {
    display: block;
    flex: 1;
    min-height: 0;
    position: relative;
    overflow: hidden;
}

/* NOTE: Carousel track — one cell for the primary grid plus one per pane, in declaration
   order. The hosting grid sets --mw-dg-swap-cells (cell count) and --mw-dg-swap-index (the
   cell slid to) inline, so EVERY switch — pane-to-pane included — is the same horizontal
   slide by whole cells. */
/* NOTE: Two position owners, never at once (see MwDataGrid.SwapTrackStyle):
   • swipe OFF (desktop mode switch) — Blazor drives via --mw-dg-swap-index, this transform runs.
   • swipe ON (mobile facets) — mw-swipe.ts sets an inline transform that OVERRIDES this one and
     follows the finger 1:1; --mw-dg-swap-index is not emitted, so Blazor never rewrites the style.
   touch-action: pan-y keeps vertical scroll native while the gesture claims only the horizontal.
   The timing matches the mockup (.34s) — snappier than the old .46s, which is a real part of why
   the mockup swipe felt better. */
.mw-dg-swap-viewport--on > .mw-dg-swap-track {
    display: flex;
    width: calc(var(--mw-dg-swap-cells, 2) * 100%);
    height: 100%;
    touch-action: pan-y;
    transform: translateX(calc(var(--mw-dg-swap-index, 0) * (-100% / var(--mw-dg-swap-cells, 2))));
    transition: transform 0.34s cubic-bezier(0.32, 0.72, 0.28, 1);
}

/* NOTE: While the finger is down mw-swipe.ts adds this so the follow is instant (no lag behind the
   finger); it is removed on release so the snap animates. */
.mw-dg-swap-viewport--on > .mw-dg-swap-track.mw-dg-swap-track--dragging {
    transition: none;
}

/* NOTE: Strict child chain — an embedded grid renders its own (display: contents)
   swap wrappers, and a descendant selector here would style those too, collapsing
   the embedded grid into a fraction-width, zero-height box. */
.mw-dg-swap-viewport--on > .mw-dg-swap-track > .mw-dg-swap-pane {
    display: flex;
    flex-direction: column;
    width: calc(100% / var(--mw-dg-swap-cells, 2));
    min-width: 0;
    min-height: 0;
    flex-shrink: 0;
}

/* NOTE: The in-pane loading bar while a pane's OnActivatedAsync runs (non-blocking mode) */
.mw-dg-swap-pane-loading {
    flex-shrink: 0;
}

/* NOTE: The pane that just slid in staggers its first rows upward-fading in.
   Detail rows interleave with data rows, so the nth-child delays only need to
   be monotonic, not exact. */
.mw-dg-swap-pane--enter .mw-dg-row {
    animation: mw-dg-swap-row-in 0.3s cubic-bezier(0.22, 1, 0.36, 1) backwards;
}

.mw-dg-swap-pane--enter .mw-dg-row:nth-child(2)  { animation-delay: 0.02s; }
.mw-dg-swap-pane--enter .mw-dg-row:nth-child(3)  { animation-delay: 0.04s; }
.mw-dg-swap-pane--enter .mw-dg-row:nth-child(4)  { animation-delay: 0.06s; }
.mw-dg-swap-pane--enter .mw-dg-row:nth-child(5)  { animation-delay: 0.08s; }
.mw-dg-swap-pane--enter .mw-dg-row:nth-child(6)  { animation-delay: 0.10s; }
.mw-dg-swap-pane--enter .mw-dg-row:nth-child(7)  { animation-delay: 0.12s; }
.mw-dg-swap-pane--enter .mw-dg-row:nth-child(8)  { animation-delay: 0.14s; }
.mw-dg-swap-pane--enter .mw-dg-row:nth-child(9)  { animation-delay: 0.16s; }
.mw-dg-swap-pane--enter .mw-dg-row:nth-child(10) { animation-delay: 0.18s; }
.mw-dg-swap-pane--enter .mw-dg-row:nth-child(n+11) { animation-delay: 0.20s; }

@keyframes mw-dg-swap-row-in {
    from {
        opacity: 0;
        transform: translateY(5px);
    }
}

/* Toolbar: contextual cluster — layout-neutral without the swap feature; with it,
   a real inline-flex box so the exchange can animate. @key re-creates the element
   on toggle, replaying the entrance. */
.mw-dg-toolbar-ctx {
    display: contents;
}

.mw-dg-toolbar-ctx--anim {
    display: inline-flex;
    align-items: center;
    gap: 1px;
    animation: mw-dg-ctx-in 0.18s ease;
}

@keyframes mw-dg-ctx-in {
    from {
        opacity: 0;
        transform: translateY(5px);
    }
}

/* Toolbar: the swap button — primary-tinted so it reads as the view switcher */
.mw-dg-swap-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--mud-palette-primary);
    background: rgba(var(--mud-palette-primary-rgb), 0.12);
    border: 1px solid rgba(var(--mud-palette-primary-rgb), 0.4);
    border-radius: 6px;
    padding: 5px 11px;
    margin-left: 4px;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.15s;
}

.mw-dg-swap-btn:hover {
    background: rgba(var(--mud-palette-primary-rgb), 0.22);
}

.mw-dg-swap-badge {
    font-size: 0.65rem;
    font-weight: 700;
    background: var(--mud-palette-error);
    color: #fff;
    min-width: 17px;
    height: 17px;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 5px;
}

/* ═══════════════════════════════════════════════════
   Opt-in mobile presentation — MobilePosition.Cell lines + row bottom sheet
   (MwDataGrid.MobileRowSheet). Rows show real rendered cells as flowing chip
   lines; a row tap slides a 1/3 or 2/3 sheet up from the bottom.
   ═══════════════════════════════════════════════════ */

/* NOTE: With cell lines present the left (identity) block stops eating the row — it takes a
   FIXED share and the cell lines take the rest. Fixed, not max-width: a shrink-to-fit basis
   makes every row's identity block a different width, so the cell lines start at a different
   x per row — a list of rows instead of a grid. A fixed basis is what aligns the cell column
   down the whole list. Consumers retune the share via --mw-dg-compact-left-width. */
.mw-dg-compact-row--cells .mw-dg-compact-left {
    flex: 0 0 var(--mw-dg-compact-left-width, 42%);
    width: var(--mw-dg-compact-left-width, 42%);
    min-width: 0;
    white-space: normal;
    flex-direction: column;
    align-items: flex-start;
    gap: 3px;
}

.mw-dg-compact-cells {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 2px 0;
}

.mw-dg-compact-cellline {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
    min-width: 0;
}

.mw-dg-compact-cellline:empty {
    display: none;
}

/* NOTE: Cell-line rows breathe — chip lines need more height than text summaries. */
.mw-dg-compact-row--cells .mw-dg-compact-summary {
    align-items: center;
    min-height: 56px;
}

/* ── Row bottom sheet + scrim (fixed overlays; below MudDialog z-index 1400,
      so the assignment dialogs launched FROM the sheet stack above it) ── */

.mw-dg-sheet-scrim {
    position: fixed;
    inset: 0;
    z-index: 1340;
    background: rgba(0, 0, 0, 0.55);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s;
}

.mw-dg-sheet-scrim--open {
    opacity: 1;
    pointer-events: auto;
}

.mw-dg-sheet {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1350;
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-table-lines);
    border-bottom: none;
    border-radius: 22px 22px 0 0;
    box-shadow: 0 -18px 50px -12px rgba(0, 0, 0, 0.5);
    display: flex;
    flex-direction: column;
    transform: translateY(104%);
    transition: transform 0.34s cubic-bezier(0.32, 0.72, 0.28, 1);
}

.mw-dg-sheet--third {
    height: 34dvh;
}

.mw-dg-sheet--twothirds {
    height: 68dvh;
}

.mw-dg-sheet--open {
    transform: translateY(0);
}

.mw-dg-sheet-grab {
    flex: 0 0 auto;
    width: 40px;
    height: 4px;
    border-radius: 99px;
    background: var(--mud-palette-table-lines);
    margin: 10px auto 6px;
}

.mw-dg-sheet-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 6px 16px calc(16px + env(safe-area-inset-bottom));
}

/* =============================================================================
   Built-in selection control (MwSelectControl in the toolbar) + compact select mode
   ============================================================================= */

/* Wrapper pinning the control to the end of the toolbar tab (after search / filter /
   context). A small left margin separates it from the preceding controls. */
.mw-dg-selectcontrol {
    display: inline-flex;
    align-items: center;
    margin-left: 6px;
    flex: 0 0 auto;
}

/* The compact-view check circle — the phone equivalent of the header/row checkbox, shown
   only while select mode is active. Amber = "you are selecting", matching the control's box. */
.mw-dg-compact-check {
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    border-radius: 999px;
    border: 1.5px solid var(--mud-palette-lines-inputs);
    background: var(--mud-palette-background);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: transparent;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}

.mw-dg-compact-check .mud-icon-root {
    font-size: 15px;
}

.mw-dg-compact-check--on {
    background: var(--mud-palette-warning);
    border-color: var(--mud-palette-warning);
    color: var(--mud-palette-warning-text);
}

/* Selected compact row — subtle amber wash + left accent, the mobile echo of
   mw-dg-row--selected, in the select-mode colour language. */
.mw-dg-compact-row--selected {
    background: color-mix(in srgb, var(--mud-palette-warning) 8%, transparent);
    box-shadow: inset 3px 0 0 var(--mud-palette-warning);
}
