/* Base for every rem in the app. theme.js publishes the user's font-size
   preference into --cwmc-root-font-size (see LayoutService.ApplyBaseFontSize);
   16px is the value when no preference has been applied yet. */
html {
    font-size: var(--cwmc-root-font-size, 16px);
}

/* Phones floor at 16px. The desktop preference defaults to 14, which is a
   density choice for a mouse-and-monitor layout and reads as unusably small at
   arm's length -- and because iOS zooms the page whenever a focused input is
   under 16px, a sub-16px root fights the form fields too. max() keeps any
   larger preference the user has set. */
@media (max-width: 599.98px) {
    html {
        font-size: max(var(--cwmc-root-font-size, 16px), 16px);
    }
}

/* ═══════════════════════════════════════════════════
   CWMC Global Styles
   Warm, friendly, approachable — not enterprise SaaS
   ═══════════════════════════════════════════════════ */

/* Hide the oversized toolbar header on date pickers (keep month/year nav visible) */
.mud-picker-toolbar {
    display: none !important;
}

/* ── Layout ── */
.mud-main-content {
    height: 100%;
    min-height: 100vh;
    display: flex;
    background: #f8f9fb;
}

/* Tighter content padding — less wasted gray space */
.mud-main-content > .mud-container {
    padding-top: 6px !important;
    padding-bottom: 6px !important;
    padding-left: 16px !important;
    padding-right: 16px !important;
}

@media (min-width: 1280px) {
    .mud-main-content > .mud-container {
        padding-left: 24px !important;
        padding-right: 24px !important;
    }
}

/* ── Grid / Table font sizes — match legacy site ── */
.mud-table .mud-table-cell,
.mud-table .mud-table-head .mud-table-cell,
.mud-data-grid .mud-table-cell {
    font-size: 0.9375rem !important;
}

/* ── Warning alerts — darken text for readability ── */
.mud-alert-text-warning {
    color: #7a5700 !important;
}

/* ── MudBlazor Component Overrides ── */
.mud-chip.mud-chip-size-medium {
    font-size: var(--mud-typography-default-size) !important;
}

.mud-chip.mud-chip-size-small {
    font-size: var(--mud-typography-body2-size) !important;
}

.mud-chip {
    font-size: var(--mud-typography-default-size);
}

.mud-tabs {
    background-color: var(--mud-palette-surface);
}

.mud-input-control-margin-dense .mud-input > input.mud-input-root,
.mud-input-control-margin-dense div.mud-input-slot.mud-input-root {
    font-size: 0.90em;
}

.mud-input-control > .mud-input-control-input-container > .mud-input-label-inputcontrol {
    font-size: var(--mud-typography-default-size) !important;
}

.mud-simple-table table * tr > td, .mud-simple-table table * tr th {
    font-size: var(--mud-typography-default-size) !important;
}

.mud-expand-panel .mud-expand-panel-header {
    font-size: var(--mud-typography-default-size) !important;
}

.mud-button-year {
    font-size: var(--mud-typography-default-size) !important;
}

.mud-table-cell {
    font-size: var(--mud-typography-default-size) !important;
}

.mud-table-dense .mud-table-cell {
    font-size: var(--mud-typography-body2-size) !important;
}

.mud-button-outlined-size-small {
    font-size: var(--mud-typography-body2-size);
}

.mud-grid.readonly-grid > .mud-grid-item {
    border-bottom: 1px solid var(--mud-palette-table-lines);
    padding-bottom: 2px;
}

.mud-nav-link {
    white-space: normal !important;
}

.mud-table.mud-data-grid .mud-toolbar,
.mud-table.mud-data-grid .mud-toolbar-gutters,
.mud-table.mud-data-grid .mud-table-toolbar {
    height: auto !important;
    padding: 1rem;
}

.mud-table.mud-data-grid .mud-table-pagination-toolbar {
    height: auto !important;
    padding: 0rem !important;
}

/* ── Section Panels (person detail, etc.) ── */
.cwmc-section-body {
    border: 1px solid var(--mud-palette-lines-default);
    border-top: none;
    border-radius: 0 0 6px 6px;
    padding: 16px;
    margin-bottom: 16px;
    background: var(--mud-palette-surface);
}

/* ── Save Bar (top of tab content) ── */
.cwmc-save-bar {
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    padding: 8px 16px;
    margin-bottom: 12px;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 8px;
}

/* ── Save Bar (top of tab content) ── */
.cwmc-save-bar {
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    padding: 8px 16px;
    margin-bottom: 12px;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 8px;
}

/* ── Page Container (admin pages) ── */
.page-container {
    animation: fadeIn 0.2s ease;
}

@keyframes fadeIn {
    from { opacity: 0; transform: translateY(4px); }
    to { opacity: 1; transform: translateY(0); }
}

/* ── Sidebar chip sizing ── */
.cwmc-sidebar .mud-chip.mud-chip-size-small {
    font-size: 0.625rem;
    height: 1.125rem;
}

/* ── Error boundary ── */
.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

/* ── Responsive show/hide: use MudBlazor's utilities, not these ──
   MudBlazor already ships breakpoint display helpers at the same 600px
   boundary, in every display mode we need:

     show on phones only   →  d-block d-sm-none   (or d-flex d-sm-none)
     show on desktop only  →  d-none d-sm-block
     hide a button         →  d-none d-sm-inline-flex
     hide a table column   →  d-none d-sm-table-cell

   The classes below predate that discovery and are a second, parallel
   definition of "small" — keep them only for the call sites still using
   them (Groups, GroupMembersTab, GroupMessagesTab, and the Super Admin
   pages) and reach for the d-* utilities in anything new. Note d-none
   already carries !important, so it needs none of the stacked-table
   workarounds further down this file. */
.hide-on-mobile { display: none; }
@media (min-width: 600px) { .hide-on-mobile { display: table-cell !important; } }

@media (max-width: 599.98px) {
    .hide-on-phone { display: none !important; }
}

/* ── Mobile tabs ──
   MudBlazor gives every tab a 160px minimum, so three tabs (480px) overflow a
   phone and the tab bar pages one tab at a time behind scroll arrows — admins
   couldn't see the other tabs existed. Let tabs shrink to their natural width
   on phones; pages with many tabs still scroll, but 2–4 tab pages fit fully. */
@media (max-width: 599.98px) {
    .mud-tabs .mud-tab {
        /* !important because MudTabs writes min-width:160px as an inline style
           (its MinimumTabWidth default) — a stylesheet rule can't override it. */
        min-width: 0 !important;
        flex: 1 0 auto;
        padding: 6px 10px;
    }

    /* Drop tab icons on phones: the labels are the information, and MudTabs'
       scroll-button logic is sticky (once the arrows render they shrink the
       content area and never dismiss), so tabs must be compact enough to fit
       the reduced width or admins get a one-tab-at-a-time pager. */
    .mud-tabs .mud-tab .mud-icon-root {
        display: none;
    }

    /* ...but min-width:0 above shrinks a tab to exactly its label, and MudBlazor
       hangs the count badge off the label's top-right, outside that box. With
       .mud-tab's overflow:hidden the badge got sliced in half and what survived
       sat on top of the next tab's first letter. Let it escape the box, and
       reserve room for it so it doesn't collide with the neighbour.
       :has() is progressive — where it isn't supported the badge is still
       whole, just tighter. */
    .mud-tabs .mud-tab {
        overflow: visible;
    }

    .mud-tabs .mud-tab:has(.mud-badge) {
        padding-right: 22px;
        margin-right: 4px;
    }

    /* ── List toolbars (search + filter toggles above a card list) ──
       MudStack rows lay these out for desktop, where a 360px search box beside
       a checkbox is right. On a phone the row wraps but the children keep their
       content width, so the search box stopped at 241px of a 319px card and the
       placeholder truncated mid-word. Stack them and let each fill. */
    .cwmc-list-toolbar {
        /* !important: MudStack writes .flex-row / .align-center classes of equal
           specificity, and whichever loses the source-order coin toss wins. */
        flex-direction: column !important;
        align-items: stretch !important;
    }

    .cwmc-list-toolbar > * {
        width: 100%;
    }

    .cwmc-list-toolbar .mud-input-control {
        max-width: none !important;
        min-width: 0 !important;
    }

    /* Bulk actions stay reachable while scrolling a long list — selecting three
       requests near the bottom and then hunting back to the top for the button
       is the whole reason bulk actions go unused on a phone.

       Fixed, not sticky: MudTabs sets overflow:hidden on .mud-tabs (it needs it
       for the panel slide), which makes that element the sticky element's scroll
       container, so a sticky bar scrolled away with the panel instead of pinning.
       Nothing in the ancestor chain sets a transform or filter, so fixed anchors
       to the viewport as intended. Bottom rather than top puts it in thumb reach,
       clear of the app bar, and safe-area-inset keeps it off the iPhone home bar. */
    .cwmc-select-bar {
        position: fixed;
        left: 12px;
        right: 12px;
        bottom: calc(12px + env(safe-area-inset-bottom, 0px));
        /* Above page content, below every MudBlazor overlay layer (app bar 1100,
           drawer, popovers, dialogs) so a dropdown or the nav still covers it. */
        z-index: 1000;
        display: flex;
        align-items: center;
        gap: 8px;
        margin: 0;
        padding: 8px 10px;
        border-radius: 10px;
        background: var(--mud-palette-surface);
        border: 1px solid var(--mud-palette-primary);
        box-shadow: 0 4px 16px rgba(16, 24, 40, .18);
    }

    .cwmc-select-bar > .mud-button-root:first-child {
        flex: 1;
    }

    /* Reserve room so the floating bar never covers the last card. */
    .has-select-bar {
        padding-bottom: 76px;
    }

    /* ── Stacked tables (MudTable phone mode) ──
       MudBlazor turns each cell into a space-between flex row expecting a
       data-label on the left; cells WITHOUT a label render next to an empty
       16px-padded pseudo-element, which shoves all content to the right edge.
       Left-align unlabeled cells and drop the phantom label. Labeled cells
       (DataLabel="...") keep MudBlazor's label/value layout. */
    .mud-xs-table .mud-table-cell:not([data-label]) {
        justify-content: flex-start;
    }
    .mud-xs-table .mud-table-cell:not([data-label])::before {
        display: none;
    }
    /* MudBlazor's flex display outguns .hide-on-mobile inside stacked tables;
       re-assert the hide. */
    .mud-xs-table .mud-table-cell.hide-on-mobile {
        display: none !important;
    }

    /* ── Compact person pickers (recipient / add-member tables) ──
       One tappable line per person: checkbox + name, with contact info
       indented beneath, instead of MudBlazor's one-cell-per-line stack. */
    .mobile-select-table .mud-table-row {
        display: flex !important;
        flex-wrap: wrap;
        align-items: center;
        padding: 2px 0;
        border-bottom: 1px solid var(--mud-palette-table-lines);
    }
    .mobile-select-table .mud-table-row .mud-table-cell {
        border-bottom: none;
        padding: 2px 6px;
    }
    .mobile-select-table .mud-table-row .mud-table-cell:last-child {
        border-bottom: none;
    }
    .mobile-select-table .mud-table-row .mud-table-cell:nth-child(2) {
        flex: 1 1 auto;
    }
    .mobile-select-table .mud-table-cell.mobile-secondary {
        flex-basis: 100%;
        padding: 0 12px 2px 54px;
        overflow-wrap: anywhere;
    }

    /* ── iOS zoom prevention ──
       Mobile Safari zooms the whole page when a focused input's font-size is
       under 16px. MudBlazor inputs inherit the 14px root, so every search box
       and form field triggered a jarring zoom-jump on iPhones. */
    .mud-input > input.mud-input-root,
    .mud-input > textarea.mud-input-root,
    .mud-select .mud-input-root {
        font-size: 16px !important;
    }

    /* Small icon buttons are ~30px — below the 44px touch guideline. Grow the
       tap area on phones without changing the icon size. MudSwitch's thumb
       also carries .mud-icon-button internally — exclude it or the extra
       padding deforms the toggle. */
    .d-sm-none .mud-icon-button:not(.mud-switch-base),
    .mobile-select-table .mud-icon-button:not(.mud-switch-base) {
        padding: 10px;
    }

    /* Tighten card padding on phones. Pages nest pa-4 papers (page container +
       inner cards), which cost 60+px of a ~400px screen in pure padding. */
    .pa-4 {
        padding: 12px !important;
    }
}


/* ── List toolbar search width ──
   The search field is a flex child of a space-between row, so with flex:1 it
   grows to whatever is left over: on a wide monitor that was a 1400px+ input
   for a search box. MudTextField's own Style="max-width" lands on an inner
   element, not the flex item that actually grows, so the cap has to go here.
   The phone block below removes it again so the field can fill a narrow card. */
.cwmc-list-toolbar .mud-input-control {
    max-width: 360px;
}

/* ── Bulk-selection bar (above a list, appears once rows are selected) ──
   Plain inline row on desktop; the phone block below floats it. */
.cwmc-select-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
}

/* ══════════════════════════════════════════════════════════════════
   PHONE READABILITY
   Admins run this portal from a phone, and the desktop type scale
   (14px base, 12px body2/caption) is too small to read at arm's
   length. Phones get a larger scale by re-declaring MudBlazor's
   typography variables.

   They're declared on :root by the theme provider's injected <style>,
   which the browser sees AFTER this file — a :root rule here would
   lose on source order. Declaring them on <body> sidesteps that:
   body's own value beats the one it would inherit from :root, no
   matter which stylesheet came first.

   Everything downstream already reads these variables (MudText, the
   .mud-table-cell rules above, chips, expansion panels), so raising
   them here lifts the whole portal rather than one page at a time.
   ══════════════════════════════════════════════════════════════════ */
@media (max-width: 599.98px) {
    body {
        --mud-typography-default-size: 1rem;        /* 14 → 16 */
        --mud-typography-body1-size: 1rem;          /* 14 → 16 */
        --mud-typography-body2-size: .875rem;       /* 12 → 14 */
        --mud-typography-caption-size: .8125rem;    /* 12 → 13 */
        --mud-typography-subtitle1-size: 1rem;
        --mud-typography-subtitle2-size: 1rem;
        --mud-typography-button-size: .9375rem;
        --mud-typography-overline-size: .75rem;
        --mud-typography-h6-size: 1.125rem;         /* 16 → 18 */
        --mud-typography-h5-size: 1.25rem;          /* 18 → 20 */
    }

    /* The dense-input shrink is a desktop density trick; on a phone it
       undoes the scale above for every filter and search box. */
    .mud-input-control-margin-dense .mud-input > input.mud-input-root,
    .mud-input-control-margin-dense div.mud-input-slot.mud-input-root {
        font-size: 1rem;
    }

    /* Select values render in a div slot, not an <input>, so the iOS
       zoom rule above doesn't reach them. */
    .mud-select .mud-input-slot.mud-input-root {
        font-size: 16px;
    }

    /* The page title and its action buttons share one row; with two
       buttons ("Export" + "Add New") the title was being crushed, so
       let the row wrap instead. */
    .cwmc-page-header {
        flex-wrap: wrap;
        row-gap: 8px;
    }
    .cwmc-page-header > .mud-stack {
        min-width: 0;
    }

    /* MudTable's toolbar is a single non-wrapping row (count · spacer ·
       search), which squeezed the search box to a few characters. */
    .mud-table-toolbar {
        height: auto !important;
        flex-wrap: wrap;
        gap: 8px;
        padding: 10px 12px !important;
    }
    .mud-table-toolbar .mud-input-control {
        max-width: none !important;
    }

    /* ── Stacked-table cards ──
       Opt in with Class="mobile-card-table". MudBlazor's stacked (phone)
       table renders every cell as one more label/value line, so ten rows
       read as a single unbroken ribbon with nothing marking where one
       record ends and the next begins. This makes each row a discrete
       card. */
    .mobile-card-table .mud-table-container {
        overflow: visible;
    }

    .mobile-card-table .mud-table-body {
        border-top: none;
    }

    /* Flex, not block: a SelectColumn checkbox is its own stacked cell, so a
       block card put the checkbox on a line of its own above the name — it read
       as a stray box floating over the record rather than part of it, and cost
       ~22px of height per row. Side by side, vertically centred. */
    .mobile-card-table .mud-table-body .mud-table-row {
        display: flex;
        align-items: center;
        gap: 2px;
        padding: 4px 6px;
        background: var(--mud-palette-surface);
        border: 1px solid var(--mud-palette-lines-default);
        border-radius: 10px;
        margin-bottom: 10px;
        overflow: hidden;
        box-shadow: 0 1px 2px rgba(16, 24, 40, .05);
    }

    .mobile-card-table .mud-table-body .mud-table-row > .mud-table-cell:first-child {
        flex: 0 0 auto;
        padding: 0;
    }

    /* Striping is row-level contrast; against a card border it just
       makes every other card look disabled. Out-specifies MudBlazor's
       .mud-table-striped tbody .mud-table-row:nth-of-type(odd). */
    .mobile-card-table.mud-table-striped .mud-table-body .mud-table-row:nth-of-type(odd) {
        background: var(--mud-palette-surface);
    }

    /* The per-cell rules that drew the stacked table's row separators
       now sit inside the card and read as clutter. */
    .mobile-card-table .mud-table-body .mud-table-row .mud-table-cell,
    .mobile-card-table .mud-table-body .mud-table-row .mud-table-cell:last-child {
        border-bottom: none;
    }

    /* A card whose content is one rich block shouldn't also carry
       MudBlazor's space-between label layout, or its "Name" pseudo-label. */
    .mobile-card-table .mud-table-cell.mobile-card-body {
        display: block;
        flex: 1 1 auto;
        min-width: 0;
        padding: 6px 2px;
    }
    .mobile-card-table .mud-table-cell.mobile-card-body::before {
        display: none;
    }

    /* Whole-card tap target for the People list. Display comes from d-flex
       d-sm-none on the element itself. */
    .cwmc-person-card {
        align-items: center;
        gap: 8px;
        color: inherit;
        text-decoration: none;
    }

    .cwmc-person-card__main {
        flex: 1;
        min-width: 0;
    }

    .cwmc-person-card__go {
        flex-shrink: 0;
        color: var(--mud-palette-text-secondary);
    }

    /* ── Hand-built phone card lists (inside a d-block d-sm-none block) ── */
    .cwmc-mcard {
        background: var(--mud-palette-surface);
        border: 1px solid var(--mud-palette-lines-default);
        border-radius: 10px;
        box-shadow: 0 1px 2px rgba(16, 24, 40, .05);
        padding: 12px 14px;
        margin-bottom: 10px;
    }

    .cwmc-mcard--selected {
        border-color: var(--mud-palette-primary);
        box-shadow: 0 0 0 1px var(--mud-palette-primary);
    }

    /* Centred, not flex-start: MudBlazor's checkbox carries internal padding, so
       its visual box sits lower than its layout box and a top-aligned name read
       ~10px high of the tick beside it. */
    .cwmc-mcard__top {
        display: flex;
        align-items: center;
        gap: 8px;
    }

    /* Filter panels — collapsed by default on phones (see .cwmc-filter-toggle).
       Five stacked full-width dropdowns cost a whole screen before the first
       record; the search box stays out here because it's the one people use. */
    .cwmc-filters:not(.is-open) .cwmc-filter-field {
        display: none;
    }

    .cwmc-mcard__title {
        flex: 1;
        min-width: 0;
        font-size: 1.0625rem;
        font-weight: 700;
        line-height: 1.3;
        overflow-wrap: anywhere;
    }

    .cwmc-mcard__when {
        flex-shrink: 0;
        text-align: right;
        font-size: .75rem;
        line-height: 1.35;
        color: var(--mud-palette-text-secondary);
    }

    /* Contact lines: full-width tap targets, not inline links crammed
       side by side. 44px keeps them thumb-sized. */
    .cwmc-mcard__contact {
        display: flex;
        align-items: center;
        gap: 8px;
        min-height: 44px;
        font-size: .9375rem;
        overflow-wrap: anywhere;
        text-decoration: none;
    }

    .cwmc-mcard__contact .mud-icon-root {
        font-size: 1.125rem;
        color: var(--mud-palette-text-secondary);
        flex-shrink: 0;
    }

    .cwmc-mcard__meta {
        font-size: .8125rem;
        color: var(--mud-palette-text-secondary);
    }

    .cwmc-mcard__divider {
        border: none;
        border-top: 1px solid var(--mud-palette-lines-default);
        margin: 10px 0;
    }
}

/* ── Croppie crop dialogs (group image, profile photo, push notification) ──
   The cropper is positioned by dragging the image. Without touch-action:none
   the browser claims that drag for page scrolling, so on a phone the image
   can't be moved at all. Keep the slider out of it: a range input needs its
   own touch handling. */
.croppie-container .cr-boundary,
.croppie-container .cr-viewport {
    touch-action: none;
}

/* The cropper is sized in JS from the container width, but keep it from
   forcing horizontal page scroll if a dialog is narrower than expected. */
.croppie-container {
    max-width: 100%;
}

.croppie-container .cr-slider-wrap {
    max-width: 100%;
}

/* ── Group image picker ──
   The drop zone is a fixed 2:1 box so the empty state teaches the shape the crop
   dialog will enforce, instead of relying on the admin to read "landscape" and
   picture it. Same box holds the preview once an image is chosen. */
.group-image-dropzone {
    width: 100%;
    max-width: 360px;
    aspect-ratio: 2 / 1;
    border: 2px dashed var(--mud-palette-lines-default);
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    transition: border-color .15s ease, background-color .15s ease;
}

.group-image-dropzone.has-image {
    border-style: solid;
}

.group-image-dropzone.is-dragging {
    border-color: var(--mud-palette-primary);
    background-color: var(--mud-palette-action-default-hover);
}

.group-image-preview {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* The empty state is a <label for> so clicking anywhere on the box opens the
   picker within the user's own gesture. See group-image-crop.js. */
.group-image-empty {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 8px 12px;
    cursor: pointer;
}

/* Crop dialog: keep the actions comfortably tappable on a phone.
   Exclude .mud-switch-base: MudSwitch builds its thumb out of a .mud-button-root, so
   a blanket min-height stretches the thumb's hit box past the track and the ball no
   longer sits inside it. The switch already has its own comfortable target. */
.group-image-crop-dialog .mud-dialog-actions .mud-button-root:not(.mud-switch-base),
.group-image-crop-dialog .mud-dialog-content .mud-button-root:not(.mud-switch-base) {
    min-height: 44px;
}

/* ── Group image crop stage ──
   Croppie shades the area between its boundary and the crop frame to show what will
   be cut off. This cropper deliberately sets boundary == frame (anything larger lets
   the image slide sideways and leaves a bare strip), so that shading never renders.
   The stage puts a neutral field behind the frame instead, and rings the frame, so
   its edges are visible and the white padding of "show the whole image" reads as
   part of the saved picture rather than as dialog background. */
.group-image-crop-stage {
    background: var(--mud-palette-background-grey, #f1f3f5);
    border-radius: 8px;
    padding: 16px 12px;
}

.group-image-crop-stage .cr-boundary {
    box-shadow: 0 0 0 2px var(--mud-palette-text-secondary, rgba(0, 0, 0, .45)),
                0 2px 10px rgba(0, 0, 0, .12);
}

/* The frame's own white hairline is redundant next to the ring above, and it
   disappears against white padding anyway. */
.group-image-crop-stage .cr-viewport {
    border-color: transparent;
}

/* Invite send button. Full width on a phone, where it is the only thing to press, but capped on
   desktop: a send button as wide as the field it belongs to reads as a second input rather than
   an action. MudBlazor's FullWidth is a plain bool with no breakpoint, so the cap lives here. */
@media (min-width: 600px) {
    .cwmc-invite-send {
        max-width: 190px;
    }
}

/* Reserve the scrollbar's width whether or not the page needs one. Without this, navigating
   from a short admin screen to a long one shifts everything left by the scrollbar's width as it
   appears, which reads as the layout twitching on every click. Pair to the single container
   width in PageContainer: between them the page frame holds still. */
html {
    scrollbar-gutter: stable;
}
