/* === BORDERLESS PAGE CONTAINERS ===
   Modern dashboards (Linear, Notion, Stripe, Vercel) don't wrap page content
   in visible card borders. The content hierarchy — header, stats, tabs, grid —
   is already well-defined through spacing and typography. An outer MudPaper
   border is redundant visual noise. */
.mud-container > .mud-paper {
    border: none !important;
    box-shadow: none !important;
}

/* === MODERN TEXT CASING ===
   Material Design 3, Apple HIG, and most modern UIs (Linear, Notion, Vercel)
   use sentence case instead of ALL CAPS. MudBlazor defaults to uppercase on
   tabs and buttons via text-transform. Override globally for better readability
   and a modern, non-shouty feel. */
.mud-tab {
    text-transform: none !important;
    letter-spacing: normal !important;
}
.mud-button-root {
    text-transform: none !important;
    letter-spacing: normal !important;
}

/* Phase U31C: Shrink topbar from 56px to 48px at Xs (<600px) */
@media (max-width: 599px) {
    .closina-topbar {
        min-height: var(--closina-layout-topbar-height-xs);
        height: var(--closina-layout-topbar-height-xs);
    }
}

/* Phase U67 Sub-Phase E (W1): Sticky positioning for the SettingsHubShell mobile
   toggle button so its glyph stays anchored below the topbar while the page
   scrolls. The `top` offset matches the topbar's actual rendered height per
   breakpoint — defaults to --closina-layout-topbar-height (56px) and drops to
   --closina-layout-topbar-height-xs (48px) at Xs to mirror the topbar shrink
   rule above. Token-driven; no hardcoded pixel values (Cat 22). */
/* F27-FU5 (2026-06-21): at <=959px (Xs + Sm — IsMobileOrSmall) the settings-hub
   toggle LEAVES the flex row. Before, it was an in-flow ~56px column + 16px flex
   gap = 72px that squeezed the content column — the DOMINANT content-column reducer
   measured at 375px (content body 293/375; container gutter already 0 at Xs). See
   artifacts/F27-FU5-evidence/before-measurement.md. It becomes a fixed affordance
   anchored below the topbar at the left edge, so the content body (now the sole
   in-flow flex child) reclaims the full ~72px (+30% usable width at 375px). The
   content body carries a matching, media-scoped top clearance
   (.closina-settings-hub-content-clearance) so the page header never renders under
   the fixed toggle (UX-R02/R03 overlap-safety). z-index via --closina-z-* (Cat 22);
   precedent: .closina-mobile-bottom-nav (out-of-flow fixed mobile chrome). The
   toggle only renders at <=959px (shell @if IsMobileOrSmall), so the unconditional
   fixed rule is inert at Md+. The base left:0.25rem is correct ONLY at Xs (<=599px),
   where the app sidebar is a closed temporary overlay (off-screen) and the viewport
   left edge is free; the Sm band (600-959px) keeps a persistent 64px mini-rail at
   the viewport left edge (z-index 1100), so the toggle is offset past it below.
   F81 (2026-07-20, item ⑤B): raise the z-index ABOVE the mini-rail (z 1100). The base
   --closina-z-sticky (100) parked the fixed toggle UNDER the rail whenever the left-offset
   geometry drifted (e.g. under the Sm-band overflow that scrolled content left over the
   toggle), making the settings sub-nav unreachable at 707px. --closina-z-modal (1300) >
   rail (1100) guarantees the toggle always stacks above the rail, so a geometry mismatch
   can never occlude it; the left offset (rule below) now only positions it, never
   un-occludes it. Paired with the F81 Sm-band containment (Fix 14b) that removes the
   left-edge scroll which was clipping it. */
.closina-settings-hub-mobile-toggle {
    position: fixed;
    top: var(--closina-layout-topbar-height);
    left: 0.25rem;
    z-index: var(--closina-z-modal); /* F81 ⑤B: above the 64px mini-rail (z 1100) */
}

/* F27-FU5-a4b fix (2026-06-21): at the Sm band (600-959px — IsMobileOrSmall but
   NOT Xs) the persistent MainLayout mini-rail occupies the viewport left edge
   (--closina-layout-sidebar-width-rail = 64px). The base left:0.25rem viewport
   anchor put the fixed toggle UNDERNEATH that rail (rail z-index 1100 >> toggle
   100), pointer-occluding the settings sub-nav at 768px (ux-auditor UX-R03). Offset
   the toggle past the rail so it sits at the content-area left edge — where the
   pre-fix in-flow sticky toggle rendered. Token-driven (Cat 22). Inert at Xs (rail
   absent) and Md+ (toggle not rendered). */
@media (min-width: 600px) and (max-width: 959px) {
    .closina-settings-hub-mobile-toggle {
        left: calc(var(--closina-layout-sidebar-width-rail) + 0.25rem);
    }
}

@media (max-width: 959px) {
    .closina-settings-hub-content-clearance {
        padding-top: var(--closina-layout-topbar-height);
    }
}

@media (max-width: 599px) {
    .closina-settings-hub-mobile-toggle {
        top: var(--closina-layout-topbar-height-xs);
    }

    .closina-settings-hub-content-clearance {
        padding-top: var(--closina-layout-topbar-height-xs);
    }
}

/* F27-FU5 (a) additive, foldable-scoped: at <=399px (Samsung Fold folded etc.,
   UX-S24) trim the nested settings paper padding below the global <=599px 1rem so
   the Twilio 2-column numeric grid stays usable (~54px/cell at 280px before (b)).
   SCOPED to the settings-hub content (descendant of the clearance wrapper) — no
   global .mud-paper leak to out-of-sweep pages (R4). */
@media (max-width: 399px) {
    .closina-settings-hub-content-clearance .mud-paper {
        padding: 0.75rem !important;
    }
}

/* Responsive Typography */
@media (max-width: 599px) {
    .mud-typography-h4 {
        font-size: 1.5rem !important;
    }
    
    .mud-typography-h5 {
        font-size: 1.25rem !important;
    }
    
    .mud-typography-h6 {
        font-size: 1.1rem !important;
    }
}

/* Responsive Grid Adjustments */
@media (max-width: 959px) {
    .sf-grid .e-gridheader {
        font-size: 0.875rem;
    }
    
    .sf-grid .e-gridcontent {
        font-size: 0.875rem;
    }
    
    /* Hide less important columns on mobile */
    .sf-grid .e-hide-mobile {
        display: none;
    }
}

/* Mobile-First Card Layouts */
@media (max-width: 599px) {
    .mud-paper {
        margin: 0.5rem !important;
        padding: 1rem !important;
    }
    
    .mud-card-content {
        padding: 1rem !important;
    }
    
    /* Stack buttons vertically on mobile */
    .mud-button-group-root {
        flex-direction: column !important;
        width: 100%;
    }
    
    .mud-button-group-root > * {
        width: 100%;
        border-radius: var(--closina-radius-sm) !important;
        margin: 2px 0 !important;
    }
}

/* Touch-Friendly Controls */
@media (hover: none) and (pointer: coarse) {
    /* Increase tap targets for touch devices */
    .mud-icon-button {
        padding: 12px !important;
    }

    .mud-button {
        min-height: 48px !important;
    }

    .mud-input input {
        min-height: 48px !important;
        font-size: 16px !important; /* Prevent zoom on iOS */
    }
}

/* Phase F82 (2026-07-20): shared "keyboard-shortcut hint" utility.
   A passive keyboard-shortcut affordance (e.g. the topbar Ctrl+K / Cmd+K search
   badge, command-palette per-row shortcut chips) is meaningless on a touch device
   with no physical keyboard, so hide it there. This is a width-INDEPENDENT signal
   (a small desktop window with a mouse keeps its keyboard, and correctly keeps the
   hint). The bare class is a no-op on non-touch; the touch media-query hides it.
   The deliberately-opened Help-panel Keyboard-Shortcuts cheatsheet does NOT carry
   this class — it is a reference the user chose to open, not a passive hint. */
.closina-kbd-hint {
    /* Visible by default; hidden only under the touch media-query below. */
}

@media (hover: none) and (pointer: coarse) {
    .closina-kbd-hint {
        display: none !important;
    }
}

/* Responsive Navigation */
@media (max-width: 599px) {
    .mud-drawer-content {
        width: 280px !important;
    }
    
    /* Auto-close drawer on mobile after navigation */
    .mud-drawer-overlay {
        display: block !important;
    }
}

/* Dashboard Responsive */
@media (max-width: 959px) {
    /* Stack KPI cards in 2x2 grid on tablets */
    .dashboard-kpi-grid > .mud-grid-item {
        flex-basis: 50% !important;
        max-width: 50% !important;
    }
}

@media (max-width: 599px) {
    /* Stack KPI cards vertically on mobile */
    .dashboard-kpi-grid > .mud-grid-item {
        flex-basis: 100% !important;
        max-width: 100% !important;
    }
    
    /* Adjust chart heights for mobile */
    .mud-chart {
        height: 250px !important;
    }
}

/* Loading States */
.loading-wrapper {
    position: relative;
    min-height: 200px;
}

.skeleton-animation {
    animation: skeleton-loading 1.5s infinite ease-in-out;
}

@keyframes skeleton-loading {
    0% {
        opacity: 0.7;
    }
    50% {
        opacity: 1;
    }
    100% {
        opacity: 0.7;
    }
}

/* Improve Syncfusion Grid Mobile Experience */
@media (max-width: 599px) {
    .e-grid .e-toolbar {
        flex-wrap: wrap;
    }
    
    .e-grid .e-toolbar .e-toolbar-items {
        width: 100%;
    }
    
    /* Make grid horizontally scrollable on mobile */
    .e-grid {
        overflow-x: auto;
    }
    
    .e-grid .e-gridcontent {
        min-width: 600px;
    }
}

/* Mobile Logout Button - Phase 11f */
/* Shows only on mobile/tablet viewports (<960px) */
.mobile-logout-button {
    position: fixed;
    top: 8px;
    right: 60px; /* Position to left of hamburger menu */
    z-index: var(--closina-z-maximum);
    display: none; /* Hidden by default */
}

/* Show only on mobile and tablet viewports */
@media (max-width: 959px) {
    .mobile-logout-button {
        display: block;
    }
}

.btn-logout-mobile {
    background: transparent;
    border: none;
    color: var(--closina-primary-text);
    font-size: var(--closina-icon-nav); /* U68 Sub-E: 20px (icon glyph in mobile logout button) */
    padding: 8px 12px;
    cursor: pointer;
    border-radius: var(--closina-radius-sm);
    transition: background-color var(--closina-transition);
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;  /* Touch target minimum per accessibility standards */
    min-height: 44px; /* Touch target minimum per accessibility standards */
}

.btn-logout-mobile:hover {
    background-color: var(--closina-overlay-hover);
}

.btn-logout-mobile:active {
    background-color: var(--closina-overlay-active);
}

.btn-logout-mobile i {
    pointer-events: none;
}

/* Admin Dashboard Tab Navigation - Phase 11f Issue 15 */
/* Mobile-optimized tabs for better UX on small screens */
@media (max-width: 768px) {
    /* Compact tab sizing on mobile */
    .dashboard-tabs .mud-tabs-toolbar {
        min-height: 48px;
    }

    /* Reduce icon size on mobile for better balance */
    .dashboard-tabs .mud-tab .mud-icon-root {
        font-size: var(--closina-icon-nav) !important; /* U68 Sub-E: 20px (was 1.25rem hardcode) */
        margin-right: 4px;
    }

    /* Slightly smaller text for tab labels */
    .dashboard-tabs .mud-tab .mud-button-label {
        font-size: 0.8rem;
        white-space: nowrap;
    }

    /* Reduce padding for more compact tabs */
    .dashboard-tabs .mud-tab {
        padding: 8px 12px !important;
        min-width: auto;
    }

    /* Ensure horizontal scrolling works smoothly */
    .dashboard-tabs .mud-tabs-toolbar-wrapper {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: thin;
    }

    /* Hide scrollbar but keep functionality */
    .dashboard-tabs .mud-tabs-toolbar-wrapper::-webkit-scrollbar {
        height: 3px;
    }

    .dashboard-tabs .mud-tabs-toolbar-wrapper::-webkit-scrollbar-thumb {
        background-color: var(--closina-scrollbar-thumb);
        border-radius: var(--closina-radius-sm, 3px);
    }
}

/* Extra small screens - hide icons entirely for max space (foldable devices) */
@media (max-width: 399px) {
    .dashboard-tabs .mud-tab .mud-icon-root {
        display: none;
    }

    /* More space for text when icons are hidden */
    .dashboard-tabs .mud-tab {
        padding: 8px 16px !important;
    }
}

/* Admin Dashboard Scroll Indicator - Phase 11f Issue 16 */
/* Provides visual feedback that more content is available below the fold */
.dashboard-scroll-container {
    position: relative;
}

/* Subtle gradient fade at bottom to indicate scrollable content */
.dashboard-scroll-container::after {
    content: '';
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: 60px;
    background: linear-gradient(to top, var(--closina-fade-overlay), transparent);
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--closina-transition-slow);
    z-index: var(--closina-z-base);
}

/* Show gradient when page is scrollable and not at bottom */
@media (min-height: 600px) {
    .dashboard-scroll-container::after {
        opacity: 1;
    }
}

/* Hide gradient on very short viewports where it might interfere */
@media (max-height: 599px) {
    .dashboard-scroll-container::after {
        display: none;
    }
}

/* Page Header Title — now uses Typo.h4 HtmlTag="h1" directly.
   Mobile responsive sizing handled by .mud-typography-h4 rule above. */

/* Skip to Main Content Link - WCAG 2.4.1 */
/* Visually hidden until focused for keyboard navigation.
   Uses clip-rect pattern for true 0px computed size (fixes touch target audit). */
.skip-to-main-content {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
    z-index: var(--closina-z-maximum);
    background-color: var(--closina-primary-hover);
    color: var(--closina-primary-text, #ffffff);
    font-size: 1rem;
    font-weight: 600;
    text-decoration: none;
}

/* Show when focused via keyboard */
.skip-to-main-content:focus {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    top: 0;
    width: auto;
    height: auto;
    min-height: 44px;
    overflow: visible;
    outline: 2px solid var(--closina-focus-ring);
    outline-offset: 2px;
}

/* Ensure main content can receive focus when skipped to */
#main-content:focus {
    outline: none;
}

/* Visually-hidden utility class for screen-reader-only content (Phase U28 retest Fix 8).
   Used by rail-mode nav link labels and the MainLayout sidebar aria-live announcer.
   Standard "sr-only" clip-rect pattern — element has 0 visible footprint but is
   announced by assistive technology. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Dark mode: skip-to-content link */
[data-theme="dark"] .skip-to-main-content {
    background-color: var(--closina-primary);
    color: var(--closina-primary-text);
}

/* Phase U15d: UX-S16 MudDrawer width:0 workaround REMOVED.
   The drawer now collapses naturally via DrawerVariant.Temporary in the new
   ClosinaTheme shell (MainLayout.razor). No CSS hack needed. */

/* ============================================
   Phase B10: Mobile Responsiveness Enhancements
   ============================================ */

/* ────────────────────────────────────────────────────────────────────────────
   TOUCH TARGET MINIMUM — house floor (44x44), and the WCAG bar it is NOT
   ────────────────────────────────────────────────────────────────────────────
   ⚠ CITATION ANCHOR (Phase Z39). Every "44px touch target" comment in this file
   refers back here. Read this before adding or editing one.

   • The bar we grade CONFORMANCE against is WCAG 2.5.8 Target Size (Minimum) —
     Level AA — 24x24 CSS px. It applies to POINTER INPUTS GENERALLY, mouse and
     desktop INCLUDED (five exceptions: Spacing, Equivalent, Inline, User agent
     control, Essential; the Spacing exception is a 24 CSS px DIAMETER CIRCLE
     test — there is NO 8px figure anywhere in 2.5.8).
   • WCAG 2.5.5 Target Size (Enhanced) is 44x44 at Level AAA. We do NOT claim
     AAA. Before Z39 this file cited 2.5.5 as though it were the bar; it is not.
   • The 44x44 floor enforced below at max-width 959px is therefore a HOUSE
     floor on PLATFORM-CONVENTION grounds (Apple HIG 44pt / Material 48dp), not
     a WCAG obligation. It is KEPT — relaxing it toward 24px would push touch
     below both platform conventions and regress usability.
   • Consequence for desktop: a desktop target of 24–43px is COMPLIANT and is
     not a finding. Do not "fix" one to 44px citing WCAG.

   Ensures all interactive elements are at least 44x44px on touch viewports.
   Covers both mobile (<600px) and tablet (600-959px) since tablets are touch devices.
   This complements the existing touch-friendly controls (hover: none) rules above. */
@media (max-width: 959px) {
    /* Ensure icon buttons meet touch target minimum */
    .mud-icon-button {
        min-width: 44px !important;
        min-height: 44px !important;
    }

    /* Ensure regular buttons meet touch target minimum */
    .mud-button {
        min-height: 44px !important;
    }

    /* Ensure smaller MudButton variants still meet minimum */
    .mud-button-root.mud-button-size-small {
        min-height: 44px !important;
        padding: 6px 16px !important;
    }

    /* House 44px touch floor (see citation anchor above): MudNumericField
       increment/decrement spin buttons are ~24px wide by default (they aren't
       .mud-icon-button, so the rule above misses them). In this MudBlazor version they
       render as .mud-button-root inside .mud-input-numeric-spin with aria-label
       Increment/Decrement. ~24px would sit right on the WCAG 2.5.8 AA 24x24 boundary,
       so widen the tap target on touch viewports to the house floor. */
    .mud-input-numeric-spin .mud-button-root {
        min-width: 44px !important;
        min-height: 44px !important;
    }

    /* Ensure chip/tag elements are tappable (house 44px touch floor — see anchor above) */
    .mud-chip {
        min-height: 44px;
        padding: 4px 12px;
    }

    /* Ensure table row action buttons are tappable */
    .e-grid .e-rowcell .mud-icon-button {
        min-width: 44px !important;
        min-height: 44px !important;
    }

    /* Select dropdown touch targets */
    .mud-select .mud-input-control {
        min-height: 44px !important;
    }

    /* Pagination buttons */
    .mud-pagination .mud-pagination-item {
        min-width: 44px !important;
        min-height: 44px !important;
    }

    /* Phase U31: Touch target floor for side navigation rows. HOUSE floor, not WCAG
       (see citation anchor above). MudBlazor 9.x ships .mud-nav-link with
       min-height: 36px — that clears the WCAG 2.5.8 AA 24x24 bar, so it is only under
       our house 44px touch floor. Pinned by MobileTouchTargetConvention_Tests. */
    .closina-shell-sidebar .mud-nav-link,
    .closina-shell-sidebar .mud-nav-group .mud-nav-link {
        min-height: 44px !important;
    }

    /* Phase U60 Sub-Phase C: UX-S04 HOUSE touch-target floor for MudMenuItem (platform
       convention, not WCAG — see citation anchor above).
       Dense density renders 32px-tall rows by default: above the WCAG 2.5.8 AA 24x24
       bar, below our 44px house touch floor on mobile.
       Covers ProfileMenu rows, action-column overflow menu items, sidebar group expanders,
       and ~43 other call sites across the Blazor client. Pinned by
       MudMenuItemTouchTargetConvention_Tests. */
    .mud-menu-item {
        min-height: 44px;
        padding-top: 8px;
        padding-bottom: 8px;
    }

    /* Phase U67 Sub-Phase B: UX-S04 HOUSE touch-target floor for settings rail
       navigation links (platform convention, not WCAG — see citation anchor above).
       Default MudNavLink min-height is 36px (~41px effective after padding): above the
       WCAG 2.5.8 AA 24x24 bar, below our 44px house touch floor on mobile.
       Covers the consolidated Settings
       hub surfaces (/m/settings, /u/settings) introduced by Phase U53. Pinned by
       SettingsRailTouchTargetConvention_Tests. */
    .closina-settings-rail .mud-nav-link {
        min-height: 44px;
        padding-top: 8px;
        padding-bottom: 8px;
    }

    /* Phase I19: Touch target floor for links inside MudAlert banners. HOUSE floor
       (see citation anchor above). MudLink renders as inline anchor with ~17-24px
       height — note the low end is genuinely under the WCAG 2.5.8 AA 24x24 bar, though
       an inline link in running text may qualify for 2.5.8's Inline exception. Inside
       an alert it serves as a primary CTA, so we raise it to the 44px house touch
       floor on mobile regardless. */
    .mud-alert .mud-link {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
    }
}

/* Horizontal Scroll Indicator for Syncfusion Grids - Phase B10 Step 1.2
   Provides visual feedback that horizontal scrolling is available on mobile.
   Uses gradient fade on right edge to indicate more content. */
.responsive-grid-container {
    position: relative;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.responsive-grid-container::after {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 40px;
    background: linear-gradient(to right, transparent, var(--closina-fade-overlay));
    pointer-events: none;
    opacity: 1;
    transition: opacity var(--closina-transition-slow);
}

/* Hide indicator when scrolled to right edge (controlled via JS class) */
.responsive-grid-container.scrolled-end::after {
    opacity: 0;
}

/* Syncfusion grid specific horizontal scroll indicator */
@media (max-width: 599px) {
    .e-grid-wrapper {
        position: relative;
    }

    /* Right edge gradient to indicate scroll availability */
    .e-grid-wrapper::after {
        content: '';
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        width: 30px;
        background: linear-gradient(to right, transparent, var(--closina-fade-overlay));
        pointer-events: none;
        z-index: var(--closina-z-base);
    }

    /* Improve grid scroll experience */
    .e-grid .e-content {
        overflow-x: auto !important;
        -webkit-overflow-scrolling: touch;
    }
}

/* Dialog Padding Reduction for Mobile - Phase B10 Step 1.3
   Reduces padding on dialogs for mobile viewports to maximize content space.
   Standard pa-6 (24px) is too large on 375px screens. */
@media (max-width: 599px) {
    /* Reduce dialog content padding on mobile */
    .mud-dialog-content {
        padding: 12px !important;
    }

    /* Reduce dialog title padding */
    .mud-dialog-title {
        padding: 12px 12px 8px 12px !important;
    }

    /* Reduce dialog actions padding */
    .mud-dialog-actions {
        padding: 8px 12px 12px 12px !important;
    }

    /* Ensure dialogs don't exceed viewport */
    .mud-dialog {
        margin: 8px !important;
        max-height: calc(100dvh - 16px) !important;
        max-width: calc(100vw - 16px) !important;
    }

    /* Make dialog paper responsive */
    .mud-dialog .mud-dialog-paper {
        width: 100% !important;
        margin: 0 !important;
    }
}

/* Stat Card Flex Behavior - Phase B10 Step 1.4
   Allows CompactStatCard to shrink gracefully on small viewports
   while maintaining minimum readable size. */
.compact-stat-card {
    flex-shrink: 1;
    min-width: 140px;
}

@media (max-width: 599px) {
    .compact-stat-card {
        min-width: 0;
    }

    /* Hide icons on mobile — free up space for labels */
    .compact-stat-card .mud-icon-root {
        display: none;
    }

    /* Tighter internal spacing on mobile */
    .compact-stat-card {
        padding: 6px 8px !important;
    }

    /* Slightly smaller value text on mobile */
    .compact-stat-card .stat-card-value {
        font-size: 1.1rem !important;
        margin-right: 6px !important;
    }

    /* Note: MudGrid gutter overflow fix moved to system-wide Fix 21 (U09).
       The per-breakpoint stat card overrides below remain for mobile-specific spacing. */

    /* Remove stat card internal margin on mobile for symmetric alignment */
    .compact-stat-card.mud-paper {
        margin: 0 !important;
    }
}

/* 6-card stat layouts - proper grid at intermediate widths */
@media (min-width: 600px) and (max-width: 959px) {
    /* 6-card layouts should show 3 per row on tablets */
    .stat-grid-6 > .mud-grid-item {
        flex-basis: 33.333% !important;
        max-width: 33.333% !important;
    }
}

@media (max-width: 599px) {
    /* 6-card layouts should show 2 per row on phones */
    .stat-grid-6 > .mud-grid-item {
        flex-basis: 50% !important;
        max-width: 50% !important;
    }
}

/* 4-card stat layouts - fix md breakpoint showing 3 cards */
@media (min-width: 960px) and (max-width: 1279px) {
    /* 4-card layouts should show all 4 on medium screens */
    .stat-grid-4 > .mud-grid-item {
        flex-basis: 25% !important;
        max-width: 25% !important;
    }
}

@media (min-width: 600px) and (max-width: 959px) {
    /* 4-card layouts should show 2 per row on tablets */
    .stat-grid-4 > .mud-grid-item {
        flex-basis: 50% !important;
        max-width: 50% !important;
    }
}

/* U69 F9.C (2026-05-01): tightened gap on dashboard-analytics pages -- saves ~8px chrome
   per page across the 4 actual <FilterRow> consumers (Member/Admin SMS+Call analytics).
   FilterRow.razor sets `mb-2` (8px) on the wrapping MudGrid; this rule documents the
   intent in CSS for grep-discoverability and enforces the value defensively in case
   MudBlazor spacing-class semantics change in a future upgrade. Per Cat 22, the value
   tracks the page-spacing scale; we use a literal 8px here because Mud's `mb-2` is
   itself the canonical 8px source -- introducing `--closina-space-filter-row-gap`
   would create two sources of truth. */
.filter-row {
    margin-bottom: 8px; /* mirrors mb-2 set in FilterRow.razor; U69 F9.C */
}

/* Filter Row Responsive Fixes - Phase B10
   Prevents filter controls from bunching at tablet widths (768-960px) */
@media (min-width: 600px) and (max-width: 959px) {
    /* Filter rows should show 2 filters per row on tablets */
    .filter-row > .mud-grid-item {
        flex-basis: 50% !important;
        max-width: 50% !important;
    }
}

/* Improved lg breakpoint support - Phase B10
   Many components jump directly from md to xl, missing lg */
@media (min-width: 1280px) and (max-width: 1919px) {
    /* FilterRow: show 3 filters + button on lg screens */
    .filter-row.filter-row-3 > .mud-grid-item {
        flex-basis: 25% !important;
        max-width: 25% !important;
    }

    /* FilterRow: show 2 filters + button on lg screens (for 2-filter layouts) */
    .filter-row.filter-row-2 > .mud-grid-item {
        flex-basis: 33.333% !important;
        max-width: 33.333% !important;
    }
}

/* ============================================
   Phase X03: Page-content horizontal-overflow guard (REUSABLE — app-wide)
   ============================================
   Two template-level mechanisms produced a horizontal scrollbar + edge-bleed
   inside the page content region (most visible with the sidebar PINNED open,
   which narrows content into the 600-960px tablet band). Live-measured on
   /a/m/sms/analytics @ ~770px content width: 8px content overflow + the End
   Date picker bleeding past the right edge. Both are systemic, not page-local:

   1. Un-shrinkable flex/grid children: a MudGrid item whose content has an
      intrinsic min-width (e.g. a date picker with clear+calendar adornments)
      refuses to shrink below content-size, forcing the item — and the whole
      grid — wider than its container. `min-width: 0` lets grid items shrink to
      their column (the standard flexbox min-content fix), so a 50% column is
      truly 50% instead of min-content.

   2. MudGrid gutter overshoot in a MaxWidth=False container: a spaced MudGrid
      (`mud-grid-spacing-xs-*`) uses negative horizontal margins for its gutters
      which overshoot a full-width (`MaxWidth.False`) MudContainer by the gutter,
      producing the residual horizontal scrollbar. `overflow-x: clip` on that
      container removes ONLY the margin overshoot — legitimately-wide content
      (Syncfusion grids, the dashboard exceptions table) carries its own
      `overflow-x: auto` scroller, so its content scrolls within itself and is
      unaffected by the ancestor clip.

   Live-verified: SMS analytics content overflow 8px -> 0; /a/identity/users
   (grid page) unchanged 0 -> 0 (no regression). */
.closina-main-content .mud-grid > .mud-grid-item {
    min-width: 0;
}
.closina-main-content .mud-container-maxwidth-false {
    overflow-x: clip;
}

/* F81 Sub-Phase C (2026-07-20, item ②): at the Sm band (<=959px — narrow tablets
   ~838px + Samsung Fold unfolded ~707px) the `overflow-x: clip` above HARD-CUTS live
   content of a MaxWidth.False detail page (e.g. /m/outreach/{id}) — clipping the header
   title with no scroll recovery. Soften to `overflow-x: auto` across the tablet band so
   overflow scrolls-within instead of being silently cut. KEEP `clip` at desktop (>=960px),
   where it exists ONLY to absorb the MudGrid negative-margin gutter overshoot (which is
   pure margin, never content — so clipping it there is correct). */
@media (max-width: 959px) {
    .closina-main-content .mud-container-maxwidth-false {
        overflow-x: auto;
    }
}

/* X03: wrap the page-header actions block across the FULL tablet band (<=959px),
   not just Xs. A header with many actions — e.g. /a/feature-management's GA-count
   chip + "Save Changes (N)" button + connection-status indicator + refresh — is
   ~860px intrinsic and overflows the content scroller at tablet content-widths
   (165px @768 with the sidebar pinned). The Xs-only wrap (Fix 8, added with the
   view-toggle-overlap fix) didn't reach the 600-959 band where wide headers
   actually overflow. flex-wrap only wraps when the row doesn't fit, so pages whose
   actions already fit at tablet are unaffected (no-op). Scoped to
   `.closina-page-header-actions` only — does NOT extend the broader Fix-8
   `.mud-paper` row-wrap into the tablet band. The toggle keeps its natural width
   here too (display:grid must not shrink). Verified: feature-management 165px->0 @768. */
@media (max-width: 959px) {
    .closina-page-header-actions {
        flex-wrap: wrap !important;
        gap: 8px !important;
    }
    .closina-page-header-actions .mud-toggle-group {
        flex-shrink: 0 !important;
    }
}

/* ============================================
   Phase C08: Public Booking Time Slots
   ============================================ */

/* Time slot container with responsive max-height
   Uses clamp() for fluid height based on viewport */
.time-slots-container {
    max-height: clamp(200px, 40vh, 400px);
    overflow-y: auto;
}

/* Booking type card hover effect for public profile page */
.booking-type-card {
    transition: transform var(--closina-transition-fast), box-shadow var(--closina-transition-fast);
}

.booking-type-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--closina-shadow-md);
}

/* Cursor pointer utility */
.cursor-pointer {
    cursor: pointer;
}

/* ============================================
   UX Audit Fixes - 2026-02-04
   Touch Target Size — house 44px floor (see citation anchor near the top of this
   file; the WCAG bar is 2.5.8 AA 24x24, NOT 2.5.5, which is AAA and not claimed)
   ============================================ */

/* Fix 1: Syncfusion Grid Pagination Touch Targets
   Original size: 10-19px — under the WCAG 2.5.8 AA 24x24 floor, so a genuine AA
   failure as well as unusable on touch devices.
   Raised to: >= 44x44px (house touch floor, comfortably above the 24x24 AA bar)
   Covers mobile + tablet (touch devices) */
@media (max-width: 959px) {
    .e-grid .e-pager .e-mfirst,
    .e-grid .e-pager .e-mprev,
    .e-grid .e-pager .e-mnext,
    .e-grid .e-pager .e-mlast {
        min-width: 44px !important;
        min-height: 44px !important;
        display: flex !important;
        align-items: center !important;
        justify-content: center !important;
        padding: 8px !important;
    }

    /* Increase icon size within pagination buttons */
    .e-grid .e-pager .e-mfirst .e-icons,
    .e-grid .e-pager .e-mprev .e-icons,
    .e-grid .e-pager .e-mnext .e-icons,
    .e-grid .e-pager .e-mlast .e-icons {
        font-size: 18px !important;
    }

    /* Pager info and page numbers also need touch-friendly sizing */
    .e-grid .e-pager .e-numericitem {
        min-width: 44px !important;
        min-height: 44px !important;
        display: flex !important;
        align-items: center !important;
        justify-content: center !important;
    }
}

/* Fix 2: Syncfusion Grid Filter Icon Touch Targets
   Original size: 18x14px — under the WCAG 2.5.8 AA 24x24 floor, so a genuine AA
   failure as well as unusable on touch devices. (NB the 18px font-size set below is
   the icon GLYPH, not the target; the target is the .e-filtermenudiv box.)
   Raised to: >= 44x44px (house touch floor, comfortably above the 24x24 AA bar)
   Covers mobile + tablet (touch devices) */
@media (max-width: 959px) {
    .e-grid .e-filtermenudiv {
        min-width: 44px !important;
        min-height: 44px !important;
        display: flex !important;
        align-items: center !important;
        justify-content: center !important;
    }

    /* Increase the filter icon size */
    .e-grid .e-filtermenudiv .e-icons {
        font-size: 18px !important;
    }

    /* Column header filter buttons */
    .e-grid .e-headercell .e-filtermenudiv {
        min-width: 44px !important;
        min-height: 44px !important;
    }

    /* Sort icons in headers also need touch targets */
    .e-grid .e-headercell .e-sortfilterdiv {
        min-width: 44px !important;
        min-height: 44px !important;
        display: flex !important;
        align-items: center !important;
        justify-content: center !important;
    }
}

/* Fix 3: FAB Stacking on Mobile & Tablet (Phase P02: extended from 599px to 959px)
   Issue: Copilot FAB (bottom:24px) and Feedback FAB (bottom:100px) need larger gap on touch.
   Solution: Stack vertically — copilot at 80px (bottom), feedback at 148px (80 + 56btn + 12gap).
   Extended to 959px to cover tablets, which are touch devices and so fall under the
   house 44px touch floor (see citation anchor above — not a WCAG 2.5.5 obligation). */
@media (max-width: 959px) {
    /* Copilot FAB: above the bottom nav area (bottom of the stack) */
    .copilot-fab-container,
    .mud-fab-fixed-bottom-right {
        bottom: 80px !important;
    }

    /* Feedback FAB: stacked above copilot FAB */
    .feedback-fab-container {
        bottom: 148px !important;
    }
}

/* ============================================================================
   Fix 3b (Phase U103): keep bottom-right pager controls out of the FAB column
   ============================================================================
   The FABs are position:fixed to the VIEWPORT's right edge (x in [vw-80, vw-24]).
   Pager controls are right-aligned inside the CONTENT column, which on a
   MaxWidth.False list page reaches to one page gutter from that same edge - so the
   controls end at roughly vw-24, i.e. exactly the FAB's right edge, and sit UNDER it
   (z-index auto vs 9998/9999) at EVERY width >= 600px. Measured live at 768px: the
   FAB covered 47% of the card-list page-size select and won document.elementFromPoint,
   so a tap aimed at page-size opened the AI Assistant instead.

   Reserving the FAB column as padding-right separates the two objects on the
   HORIZONTAL axis, where the geometry is invariant. That is what makes this correct
   regardless of scroll position, grid height mode (AutoHeight / ContainerOffset /
   natural flow), or which FAB happens to be present in the band - unlike a vertical
   reserve, which depends on all three.

   NOT applied below 600px: the copilot FAB is display:none there (responsive.css
   "Phase U31 Sub-Phase E" block) and the feedback FAB is not rendered at all at
   SmAndDown, so Xs has zero FABs and needs no reserve.

   !important is required, not stylistic:
     - .standard-card-list-pager also carries MudBlazor's .pa-2 utility, which declares an
       !important 8px padding (StandardCardList.razor:103), and this declaration must beat it;
     - the Syncfusion bootstrap5 sheet resets pager padding via the `padding` SHORTHAND
       inside its own max-width media query, which would otherwise wipe padding-right.
   ============================================================================= */
@media (min-width: 600px) {
    .standard-card-list-pager,
    .e-grid .e-pager {
        padding-right: var(--closina-layout-fab-column) !important;
    }
}

/* Fix 4: Toolbar Button Spacing (Phase P02: extended from 599px to 959px)
   Issue: Buttons have only 4px gap (house convention UX-S05 wants >= 8px).
   NB Phase Z39: the >= 8px adjacency gap is a HOUSE convention, NOT WCAG 2.5.8.
   2.5.8 is the 24x24 SIZE minimum; its Spacing exception is a 24 CSS px diameter
   circle test. There is no 8px figure anywhere in 2.5.8.
   Solution: Increase spacing between adjacent toolbar buttons on touch devices */
@media (max-width: 959px) {
    /* Add spacing between MudIconButtons in toolbars */
    .e-grid .e-toolbar .mud-icon-button,
    .mud-toolbar .mud-icon-button {
        margin-right: 4px !important;
    }

    /* Ensure button groups have proper spacing */
    .mud-button-group .mud-icon-button + .mud-icon-button {
        margin-left: 4px !important;
    }
}

/* Fix 6: Timezone Update Link Touch Target
   Issue: Link is 46x16px (height too small)
   Solution: Increase clickable area
   Covers mobile + tablet (touch devices) */
@media (max-width: 959px) {
    .mud-link[href*="timezone"],
    a.mud-link:contains("Update") {
        min-height: 44px !important;
        display: inline-flex !important;
        align-items: center !important;
        padding: 8px 4px !important;
    }
}

/* Fix 9: FAB Clearance for Empty State Pages (UX Audit 2026-02-18)
   Issue: Copilot and Feedback FABs (positioned at bottom:80px and bottom:148px)
   overlap empty state action buttons ("Import Contacts", etc.) on mobile.
   Affects ~30-50 pages that show empty states with CTA buttons at the bottom.
   Solution: Add bottom padding to empty state containers to clear both FABs. */
@media (max-width: 959px) {
    .mud-alert.empty-state,
    .empty-state-actions,
    .smart-loading-empty-state {
        padding-bottom: 224px !important; /* 152px copilot + 56px FAB + 16px gap */
    }
}

/* Fix 10 (J2): Toolbar Widget Crowding on Touch Devices (UX Audit 2026-02-18)
   Issue: Help, Theme, Announcement, Onboarding toolbar widgets crowd
   on narrow viewports (<480px), causing overlap and undersized touch targets.
   Solution (what this block ACTUALLY does): hide the low-priority Help and
   Onboarding toolbar widgets below 480px. That is the whole mechanism — fewer
   widgets means the survivors stop crowding.
   ⚠️ Corrected Phase Z39 exit /a4a: this comment previously claimed it also
   "enforce[d] minimum gap between toolbar icon buttons" and had been "increased
   to 4px" for the adjacency gap. BOTH were false about the block below, which
   contains no gap/margin/padding declaration at all — and 4px would not satisfy
   the house UX-S05 convention anyway, which is >=8px. The earlier Z39 pass
   rewrote this line and re-attributed the phantom 4px to a NAMED house rule,
   which made a false comment look more authoritative rather than less. The
   adjacency gap (UX-S05, >=8px) is a HOUSE convention, not WCAG 2.5.8 — 2.5.8
   specifies a 24x24 size minimum and contains no 8px figure. */
@media (max-width: 480px) {
    /* Hide HelpPanel and Onboarding widgets on very small screens */
    .help-panel-toolbar-widget,
    .onboarding-toolbar-widget {
        display: none !important;
    }
}

/* Fix 18 (P03-C): KanbanViewToggle Labels — Hide on Mobile (UX Audit 2026-02-20)
   Issue: "List" and "Kanban" text labels in MudToggleGroup cause 81% overlap at 375px.
   Solution: Hide text labels on mobile, show icon-only toggle.

   Phase Z25 Sub-A (2026-05-26): same pattern applied to AppointmentViewToggle's
   .appointment-toggle-label spans — legacy <MudButtonGroup> view switcher in
   /m/appointments header wrapped/truncated at 375px ("Calenda·" / "Toda·"),
   driving UX-R20 chrome density to ~39% (mobile-tier ERROR). Both toggles
   stay icon-only at Xs; aria-label preserves screen-reader access (Cat 56). */
@media (max-width: 599px) {
    .kanban-toggle-label,
    .appointment-toggle-label {
        display: none !important;
    }
}

/* Fix 19 (P03-C): Main Content FAB Clearance (UX Audit 2026-02-20)
   Issue: Page content (filter buttons, action buttons) near viewport bottom
   overlaps with fixed-position FABs (Copilot at bottom:148px, Feedback at bottom:80px).
   Fix 9 handles empty states; this handles non-empty page content.
   Solution: Add bottom padding to main content area on mobile. */
@media (max-width: 959px) {
    .mud-main-content {
        padding-bottom: 100px !important;
    }
}

/* Fix 19b: Foldable device FAB clearance — reduce bottom padding for narrow screens.
   100px is 28% of a 360px viewport; 60px keeps FAB clearance without wasting space. */
@media (max-width: 399px) {
    .mud-main-content {
        padding-bottom: 60px !important;
    }
}

/* ========================================
   Foldable Device Support (Samsung Fold folded: ~280-360px) — Phase U14g.1
   UX-S24: CSS rules for narrow viewports below 400px.
   Tightens spacing, reduces typography, and adjusts layout for foldable devices
   in folded state. Supplements standardgrid.css foldable rules.
   ======================================== */
@media (max-width: 399px) {
    /* Tighter dialog margins — 4px instead of 8px to maximize content area */
    .mud-dialog {
        margin: 4px !important;
        max-height: calc(100dvh - 8px) !important;
        max-width: calc(100vw - 8px) !important;
    }

    .mud-dialog-content {
        padding: 8px !important;
    }

    .mud-dialog-title {
        padding: 8px 8px 4px 8px !important;
        font-size: 1rem !important;
    }

    .mud-dialog-actions {
        padding: 4px 8px 8px 8px !important;
    }

    /* Compact stat cards — narrower padding and smaller text */
    .compact-stat-card {
        padding: 4px 6px !important;
    }

    .compact-stat-card .stat-card-value {
        font-size: 0.95rem !important;
    }

    /* Compact page title for foldable */
    h1.mud-typography-h4,
    h1.mud-typography {
        font-size: 1.1rem !important;
    }

    /* Reduce tab font size further on foldable */
    .mud-tab {
        font-size: 0.7rem !important;
        padding: 4px 6px !important;
    }

    /* MudPaper inside container — tighter padding */
    .mud-container > .mud-paper {
        padding: 4px 8px 8px !important;
    }

    /* Chip sizing — more compact for narrow viewport */
    .mud-chip {
        padding-left: 6px !important;
        padding-right: 6px !important;
        font-size: 0.75rem !important;
    }

    /* Typography scale-down for foldable */
    .mud-typography-h4 {
        font-size: 1.25rem !important;
    }

    .mud-typography-h5 {
        font-size: 1.1rem !important;
    }

    .mud-typography-h6 {
        font-size: 1rem !important;
    }

    .mud-typography-body1 {
        font-size: 0.875rem !important;
    }

    .mud-typography-body2 {
        font-size: 0.8rem !important;
    }
}

/* Fix 21 (U09): MudGrid Negative-Margin Right-Edge Overflow (System-Wide)
   Issue: MudGrid spacing-xs-6 (default) expands 24px beyond MudPaper via
   margin-left:-24px + width:calc(100%+24px). The Syncfusion grid uses plain
   width:100% and stays correctly contained, creating a visible mismatch where
   stat cards, filters, and buttons breach the right edge of the page.
   Solution: Reset negative-margin overflow for page-level MudGrids inside MudPaper.
   Safe because dialog grids are portalled to <body> (not inside .mud-paper). */
.mud-paper > .mud-grid {
    width: 100% !important;
    margin-left: 0 !important;
    margin-top: 0 !important;
}
.mud-paper > .mud-grid > .mud-grid-item {
    padding-left: 12px !important;
    padding-top: 12px !important;
}

/* Fix 21b (U100 SP-C): stat-strip MudGrids NOT caught by Fix 21's `.mud-paper >`
   child combinator. A spaced stat-card `<MudGrid>` that sits directly in a
   MaxWidth.False `<MudContainer>` or inside a `*StatsCards` wrapper component
   keeps MudBlazor's `width: calc(100% + 24px)` + negative gutter margins, so the
   last card overshoots the container right edge (~8px @1920, ~4px @375 — until now
   absorbed as a border-trim by the deliberate `.mud-container-maxwidth-false`
   `overflow-x: clip`). This is the horizontal-axis analog of Fix 21: constrain the
   grid to `width: 100%` + zero the outer gutter, restoring the inter-card gutter via
   item padding. Both card types covered: CompactStatCard (`.compact-stat-card` root)
   and PercentageStatCard (no distinctive root class → keyed on its
   `.stat-card-value-large` value marker). Scoped via `:has(> .mud-grid-item …)` so
   only genuine stat-strip grids are affected (dialog/content grids untouched). */
.mud-grid:has(> .mud-grid-item > .compact-stat-card),
.mud-grid:has(> .mud-grid-item .stat-card-value-large) {
    width: 100% !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
}
.mud-grid:has(> .mud-grid-item > .compact-stat-card) > .mud-grid-item,
.mud-grid:has(> .mud-grid-item .stat-card-value-large) > .mud-grid-item {
    padding-left: 12px !important;
}

/* Fix 11 (K1): Syncfusion Grid Filterbar Cell Touch Targets (UX Audit 2026-02-18)
   Issue: Grid filterbar input cells render at ~30px height on touch devices — above
   the WCAG 2.5.8 AA 24x24 floor, but below our house 44px touch floor.
   Solution: Enforce 44px minimum on filterbar cells at touch breakpoint. */
@media (max-width: 959px) {
    .e-grid .e-filterbar .e-filterbarcell,
    .e-grid .e-filterbar .e-filterbarcell input,
    .e-grid .e-filterbar .e-filterbarcell .e-input-group {
        min-height: 44px !important;
    }
}

/* Fix 12 (K2): Toolbar Buttons Touch Target Enforcement (UX Audit 2026-02-18)
   Issue: Some toolbar action buttons (Export, Column Chooser) render below
   44px on touch devices.
   Solution: Enforce minimum touch target size on all toolbar buttons. */
@media (max-width: 959px) {
    .e-grid .e-toolbar .e-toolbar-item .e-btn,
    .e-grid .e-toolbar .e-toolbar-item button {
        min-height: 44px !important;
        min-width: 44px !important;
    }
}

/* Fix 13 (P02-R4): Syncfusion Checkbox and Filter Icon Touch Targets
   Issue: Checkbox frames (span.e-frame.e-icons) render at 14x14px,
   filter icons (div.e-filtermenudiv.e-icons) render at 18x14px — both under the
   WCAG 2.5.8 AA 24x24 floor (a genuine AA failure), and far below our house 44px
   touch floor. See Fix 24 for the desktop half of the same problem.
   Solution: Enforce 44px minimum on both element types. */
@media (max-width: 959px) {
    .e-grid .e-frame.e-icons {
        min-width: 44px !important;
        min-height: 44px !important;
        display: flex !important;
        align-items: center !important;
        justify-content: center !important;
    }

    .e-grid .e-filtermenudiv.e-icons {
        min-width: 44px !important;
        min-height: 44px !important;
        display: flex !important;
        align-items: center !important;
        justify-content: center !important;
    }
}

/* Fix 14 (P02-R4): MudTab Minimum Touch Target Height
   Issue: MudTab elements can render below 44px on mobile.
   Solution: Enforce the house 44px minimum height (platform convention — see the
   citation anchor above; NOT WCAG 2.5.5, which is AAA and not claimed). */
@media (max-width: 959px) {
    .mud-tab {
        min-height: 44px !important;
    }
}

/* Fix 14b: MudTab Adjacent Spacing on Touch (UX Audit 2026-03-08)
   Issue: Adjacent .mud-tab elements render with 0px gap, violating the house UX-S05
   adjacency convention (≥8px between adjacent interactive targets) on touch devices.
   NB Phase Z39: this is a HOUSE convention, not WCAG 2.5.8 — 2.5.8 is the 24x24 SIZE
   minimum and its Spacing exception is a 24 CSS px diameter circle test, with no 8px
   figure anywhere in it. Each tab already clears 24x24 via Fix 14 above.
   Solution: Add margin-left to adjacent tabs for touch spacing. */
@media (max-width: 959px) {
    .mud-tab + .mud-tab {
        margin-left: 4px !important;
    }
}

/* Fix 14c: MudButtonGroup Adjacent Spacing on Touch (UX Audit 2026-03-08)
   Issue: Adjacent buttons in MudButtonGroup (e.g., List/Kanban toggle) render
   with 0px gap. On touch devices this causes mis-taps.
   Solution: Add minimal separation between grouped buttons at touch breakpoint. */
@media (max-width: 959px) {
    .mud-button-group-root:not(.mud-button-group-override-styles) > .mud-button-root + .mud-button-root {
        margin-left: 2px !important;
    }
}

/* Fix 15 (P02-R4): Grid Action Button Group Spacing
   Issue: Action buttons within grid row [role="group"] containers
   have insufficient spacing (<8px) on touch devices.
   Solution: Enforce the house UX-S05 8px adjacency gap. NB Phase Z39: this is a HOUSE
   convention, not WCAG 2.5.8 — 2.5.8 is the 24x24 SIZE minimum and its Spacing
   exception is a 24 CSS px diameter circle test, with no 8px figure anywhere in it. */
@media (max-width: 959px) {
    .e-grid [role="group"] {
        gap: 8px !important;
    }
}

/* Fix 17 (P02-R4): MudInput Field Minimum Touch Target Height
   Issue: Input fields (.mud-input-slot) can render below 44px on mobile.
   Solution: Enforce 44px minimum height for comfortable touch input. */
@media (max-width: 959px) {
    .mud-input-slot {
        min-height: 44px !important;
    }
}

/* ============================================
   Viewport Overflow Fixes - 2026-02-04
   UX Audit: Prevent horizontal scroll on mobile
   ============================================ */

/* Fix 7: Admin Dashboard MudTabs Viewport Overflow
   Issue: Tabs extend 517px beyond viewport on mobile (375px) and
   369px beyond viewport on tablet (768px) — same root cause,
   different breakpoint.
   Solution: Force horizontal scrolling within the tab bar, not page.
   Upper bound 959px covers both Xs+Sm; Md+ has enough horizontal
   space that `overflow-x: auto` stays dormant.
   Updated: 2026-02-04 (mobile fix), 2026-05-18 (tablet extension
   per Phase A07 ux-auditor follow-up — bumped 599 → 959).

   Phase U84 Sub-E audit (2026-05-19): Reviewed against the 46
   `<MudTabs>` consumers in the codebase (settings pages, detail
   pages, dashboards, billing, dialogs, embedded components).
   Decision: KEEP AS-IS at `@media (max-width: 959px)` scope.
   Rationale:
   - `.mud-tabs { max-width: 100vw }` prevents whole-page overflow
     (UX-R04 Viewport Fit). Universally safe at Xs+Sm.
   - `.mud-tabs-tabbar-wrapper, .mud-tabs-toolbar-wrapper`
     `overflow-x: auto` is additive — kicks in only when content
     exceeds container; dormant when tabs fit. Non-destructive.
   - `.mud-tabs-toolbar { flex-wrap: nowrap }` matches MudBlazor's
     default (the framework uses arrow-button scrolling, not wrap),
     so this is consistent with framework behavior, not a regression.
   - `.mud-tab { padding: 8px 12px; font-size: 13px }` satisfies
     UX-S04 touch target sizing at Xs+Sm.
   - Dialog consumers (ContactDialog, *CallDetailsDialog, etc.):
     rules apply within dialog container width via `max-width: 100%`
     (parent-relative), not absolute. Safe at all dialog sizes.
   - SmartViewTabs.razor (StandardGrid SmartView strip) does NOT
     use MudTabs (custom `<div class="smart-view-tabs">`), so this
     cluster does NOT regress the SmartView UX.
   Scope-to-class refinement was considered and rejected: the
   widening is appropriate for every tabbed page evaluated; the
   complexity of per-page class scoping (`.tabs-on-*-page`) would
   not add value. */
@media (max-width: 959px) {
    /* Constrain MudTabs container strictly */
    .mud-tabs {
        max-width: 100vw !important;
        width: 100% !important;
        overflow: hidden !important;
        box-sizing: border-box !important;
    }

    /* Make tab bar horizontally scrollable */
    .mud-tabs-tabbar-wrapper,
    .mud-tabs-toolbar-wrapper {
        max-width: 100% !important;
        overflow-x: auto !important;
        overflow-y: hidden !important;
        -webkit-overflow-scrolling: touch !important;
        scrollbar-width: thin;
    }

    /* Tab bar: nowrap so tabs stay in one row */
    .mud-tabs-toolbar {
        flex-wrap: nowrap !important;
    }

    /* Tabs: shrinkable, nowrap text, compact sizing */
    .mud-tab {
        white-space: nowrap !important;
        padding: 8px 12px !important;
        font-size: 13px !important;
    }

    /* Constrain tab panels container */
    .mud-tabs-panels {
        max-width: 100% !important;
        overflow-x: auto !important;
        padding: 8px !important;
        box-sizing: border-box !important;
    }

    /* Override PanelClass="pa-6" on mobile */
    .mud-tabpanel.pa-6,
    .mud-tabpanel {
        padding: 8px !important;
        max-width: 100% !important;
        overflow-x: auto !important;
        box-sizing: border-box !important;
    }

    /* Constrain content inside tab panels (MudPaper, MudGrid, etc.) */
    .mud-tabpanel > * {
        max-width: 100% !important;
        box-sizing: border-box !important;
    }

    /* Tables inside tabs must scroll within their container */
    .mud-tabpanel .mud-table,
    .mud-tabpanel .mud-simple-table {
        display: block !important;
        overflow-x: auto !important;
        max-width: 100% !important;
    }

    .mud-tabpanel .mud-table table,
    .mud-tabpanel .mud-simple-table table {
        min-width: 400px !important;
        width: max-content !important;
    }
}

/* Fix 8: Admin/Member Page Header Action Buttons Overflow
   Issue: Header actions row (MemberFilterSelect + view-toggle + Refresh, etc.) is a nowrap
   flex row that overflows at Xs and collapses the MudToggleGroup view-toggle into an
   overlapping pill (a4b X03 follow-up). The original selector `.admin-page-header` is NEVER
   rendered (the component emits `closina-page-header-compact`), so this wrap rule was DEAD.
   Solution: target the real ChildContent wrapper `closina-page-header-actions` so the toolbar
   wraps at Xs — the toggle then gets a full-width line and lays out side-by-side. */
@media (max-width: 599px) {
    /* AdminPageHeader/MemberPageHeader action buttons container */
    .closina-page-header-actions,
    .page-header-actions {
        flex-wrap: wrap !important;
        gap: 8px !important;
    }

    /* Allow buttons to wrap to next line */
    .closina-page-header-actions .mud-button,
    .page-header-actions .mud-button {
        flex-shrink: 1 !important;
    }

    /* The MudToggleGroup view-toggle is display:grid — it must NOT shrink (shrinking
       collapses its tracks → segment overlap, the a4b finding). Keep its natural width
       so flex-wrap drops it to its own line intact instead of squashing it. */
    .closina-page-header-actions .mud-toggle-group {
        flex-shrink: 0 !important;
    }

    /* Specific fix for "Show Archived" button + other controls row */
    .mud-paper > .d-flex.align-center.justify-space-between {
        flex-wrap: wrap !important;
        gap: 8px !important;
    }

    /* Make buttons stack when they don't fit */
    .mud-paper > .d-flex.align-center.justify-space-between > * {
        flex-shrink: 1 !important;
        min-width: 0 !important;
    }

    /* Force button text to truncate if needed */
    .mud-button .mud-button-label {
        overflow: hidden !important;
        text-overflow: ellipsis !important;
        white-space: nowrap !important;
    }
}

/* Fix 9: MudAlert with d-flex Content Overflow
   Issue: Dashboard stuck members alert causes overflow
   Solution: Make alert content responsive */
@media (max-width: 599px) {
    /* Stack alert content vertically on mobile */
    .mud-alert-message .d-flex.align-center.justify-space-between {
        flex-direction: column !important;
        align-items: flex-start !important;
        gap: 12px !important;
    }

    /* Full-width button in alert on mobile */
    .mud-alert-message .d-flex .mud-button {
        width: 100% !important;
        margin-left: 0 !important;
    }
}

/* Fix 10: Syncfusion Grid Viewport Overflow
   CONSOLIDATED: Rules moved to standardgrid.css for single source of truth
   See standardgrid.css "Critical Mobile Viewport Containment" section */

/* Fix 11: MudTable Overflow on Mobile
   Issue: Tables in dashboard tabs extend beyond viewport
   Solution: Make tables horizontally scrollable
   Updated: 2026-02-04 - Use max-content for flexible sizing
   Updated: 2026-05-23 (U80 follow-up) - Extended to MudSimpleTable used
   OUTSIDE tabs (Fix 7 already covers MudSimpleTable INSIDE tabs at line
   1180). Motivating cohort site: AdminMemberOnboardingDashboardPage
   Conversion Funnel + Stuck Members tables — flagged by U80 ui-reviewer
   as INFO out-of-scope (Sub-Phase D was charts-only). 3-column
   Stage/Count/Rate table clipped the rightmost column at 375×667. */
@media (max-width: 599px) {
    /* Wrap MudTable in scrollable container */
    .mud-table,
    .mud-simple-table {
        overflow-x: auto !important;
        display: block !important;
        -webkit-overflow-scrolling: touch !important;
    }

    .mud-table-container {
        overflow-x: auto !important;
        -webkit-overflow-scrolling: touch !important;
    }

    /* Table sizes based on content, scrolls within container */
    .mud-simple-table table,
    .mud-table table {
        min-width: max-content !important;
    }
}

/* Fix 12: MudGrid Item Overflow Prevention
   Issue: Grid items can extend beyond parent
   Solution: Constrain grid items to parent width */
@media (max-width: 599px) {
    .mud-grid-item {
        max-width: 100% !important;
        overflow: hidden !important;
    }

    /* Prevent MudPaper from overflowing */
    .mud-grid-item > .mud-paper {
        max-width: 100% !important;
        overflow: hidden !important;
    }
}

/* Fix 13: MudChip Group Overflow
   Issue: Sort chips in feedback page can overflow
   Solution: Allow chip groups to wrap */
@media (max-width: 599px) {
    .mud-chip-set,
    .mud-button-group-root:not(.mud-button-group-vertical) {
        flex-wrap: wrap !important;
        gap: 4px !important;
    }

    /* Reduce chip padding on mobile */
    .mud-chip {
        padding-left: 8px !important;
        padding-right: 8px !important;
    }
}

/* Fix 14b: Sm-band horizontal-overflow containment (Phase F81, 2026-07-20, item ④)
   Issue: the aggressive body/.mud-main-content `overflow-x: hidden; max-width: 100vw`
   containment below is scoped to @media (max-width: 599px) ONLY. The Sm band
   (600-959px — Samsung Fold unfolded ~707px, narrow tablets ~838px) therefore had NO
   body-level containment, while the sidebar stays a fixed 64px mini-rail for all >=600px.
   Any content wider than (viewport - 64px rail) produced a REAL body horizontal scroll
   -> content shifted LEFT under the fixed rail, hiding the page's left edge ("many pages"
   on Fold). The <=599px block never covered this band (Fold folded is <=399px; unfolded
   sits ABOVE every existing threshold).
   Solution: contain on `.closina-main-content` — which sits INSIDE the rail margin — with
   plain `overflow-x: hidden` + `max-width: 100%`, NOT `max-width: 100vw` on children
   (100vw ignores the 64px fixed rail and is itself an overflow source). Legitimately-wide
   inner content (Syncfusion grids, the F81 MaxWidth.False detail containers) keeps its own
   `overflow-x: auto` scroller, so it scrolls WITHIN itself rather than shifting the body. */
@media (max-width: 959px) {
    body {
        overflow-x: hidden;
    }
    .closina-main-content {
        max-width: 100%;
        overflow-x: hidden;
    }
}

/* Fix 14: Global Viewport Overflow Prevention
   Issue: Various elements can cause horizontal scroll
   Solution: Add overflow protection at body/container level
   Updated: 2026-02-04 - More aggressive containment */
@media (max-width: 599px) {
    /* Prevent horizontal overflow at page level.
       Use overflow-y: overlay so the vertical scrollbar floats over content
       instead of eating 10px from the layout width. On real mobile devices
       scrollbars are always overlay; this fixes Chromium desktop emulation.
       overflow: overlay is deprecated but still works in Chromium — fallback
       is scrollbar-width: none with a thin custom scrollbar via webkit. */
    html {
        overflow-x: hidden !important;
        overflow-y: overlay !important;  /* Chromium: scrollbar over content, not beside it */
        scrollbar-gutter: auto !important;
    }

    /* Fallback for non-Chromium: hide native scrollbar, content still scrollable */
    html, body {
        scrollbar-width: none !important;
    }
    /* Chromium: thin overlay scrollbar that doesn't affect layout */
    html::-webkit-scrollbar {
        width: 4px !important;
        background: transparent !important;
    }
    html::-webkit-scrollbar-track {
        background: transparent !important;
    }
    html::-webkit-scrollbar-thumb {
        background: var(--closina-scrollbar-thumb) !important;
        border-radius: var(--closina-radius-sm, 2px) !important;
    }

    body {
        overflow-x: hidden !important;
        max-width: 100vw !important;
        width: 100% !important;
        background-color: var(--closina-surface, #fff) !important;
    }

    /* === EDGE-TO-EDGE LAYOUT ===
       Remove card-in-page pattern. Seamless white, zero structural padding. */
    .mud-layout,
    .mud-layout-content,
    .mud-main-content {
        overflow-x: hidden !important;
        max-width: 100vw !important;
        width: 100% !important;
    }

    .mud-container {
        max-width: 100% !important;
        width: 100% !important;
        padding: 0 !important;
        box-sizing: border-box !important;
    }

    .mud-container-maxwidth-false {
        max-width: 100vw !important;
        width: 100% !important;
    }

    .mud-container > .mud-paper {
        max-width: 100% !important;
        box-sizing: border-box !important;
        border: none !important;
        border-radius: 0 !important;
        box-shadow: none !important;
        margin: 0 !important;
        padding: 8px 12px 12px !important;
    }

    body > * {
        max-width: 100vw !important;
        box-sizing: border-box !important;
    }

    /* === CONTENT DENSITY ===
       Goal: First data row visible without scrolling (above the fold).
       Eliminate dead vertical space between navbar -> title -> stats -> tabs -> grid. */

    /* Fix 2: Hide page subtitle on mobile — user already navigated here.
       "Manage System Members And View Statistics" is noise on 375px. */
    .mud-typography-body2.mud-secondary-text {
        display: none !important;
    }

    /* U80 Sub-Phase A: the KPI strip is summary DATA, not subtitle prose —
       keep it visible on mobile and let it flex-wrap. Specificity 0-3-0
       beats the 0-2-0 subtitle-hide rule above. */
    .mud-typography-body2.mud-secondary-text.closina-kpi-strip {
        display: flex !important;
    }

    /* S54-FU1: the OAuth consent-disclosure surfaces are the DISCLOSURE ITSELF, not subtitle
       prose. TWO surfaces carry this marker: the "What Closina stores" body copy on the two
       /legal/*-api-disclosure pages, and the connect-time notice that is the ONLY in-app link to
       them (OAuthConsentDisclosureNotice) — hiding the latter removed the sole path to the
       disclosure on a phone, at the moment consent is granted. The 0-2-0 hide rule above is scoped by class, not by context, so it
       also caught the "What Closina stores" paragraph in every scope group — measured 3/3
       hidden on both /legal/google-api-disclosure and /legal/microsoft-api-disclosure at
       375px, leaving an orphaned heading over blank space. That is the one page a Google or
       Microsoft reviewer is sent to, and what-we-store is precisely what they are there to
       read. Pre-existing (it reproduces on the hydrated path too), found by the S54-FU1
       runtime UX audit. Same 0-3-0 specificity as the U80 carve-out above. */
    .mud-typography-body2.mud-secondary-text.closina-disclosure-body {
        display: block !important;
    }

    /* U80 Sub-Phase C (δ): viewport-clamp the ScopeFilterControl filter popover.
       A button-anchored ~350px popover cannot fit beside a left-positioned Filter
       button in a 375px viewport — whichever side it anchors to, one edge clips.
       So at mobile width the popover is pinned to the viewport as a near-full-width
       card with 8px side margins. MudBlazor 9's popover JS (mudpopoverHelper.
       placePopover) sets inline `left`/`top` on the popovercontent-{id} element —
       which is the .mud-popover node that carries our `scope-filter-popover` marker
       class — so `!important` is required to beat that JS-set inline `left`/`width`.
       Net at 375px: popover width ≈ 359px, fully on-screen, 8px both sides. */
    .mud-popover.scope-filter-popover {
        left: 8px !important;
        right: 8px !important;
        width: auto !important;
        max-width: none !important;
        min-width: 0 !important;
    }

    /* The popover BODY's own min/max-width (set in ScopeFilterControl.razor.css)
       would otherwise re-introduce a fixed width inside the clamped shell — let it
       fill the clamped popover instead. */
    .mud-popover.scope-filter-popover .closina-scope-filter-popover-body {
        min-width: 0 !important;
        max-width: none !important;
        width: 100% !important;
        box-sizing: border-box !important;
    }

    /* Phase U103 Sub-Phase D-FU: bound the popover VERTICALLY too.
       U80 Sub-Phase C above clamped it horizontally (left/right/width) and stopped
       there, so its HEIGHT stayed unbounded: measured live at 375x812 the popover ran
       y=375.8 -> 925.8, putting Apply at y=865-909 -- entirely below the 812px fold.
       And it could not be scrolled to: the popover is position:fixed, every ancestor
       had scrollHeight == clientHeight, and the document itself did not scroll. So a
       user on an iPhone-X-class device could OPEN the filter but never APPLY it.
       Found at the a4b gate while verifying the Sub-Phase D filter fix -- which that
       defect would have made unreachable on the very viewport it targets.

       `top` is pinned for the same reason U80 pinned `left`/`right`: MudBlazor 9's
       mudpopoverHelper.placePopover sets it inline from the anchor button, so a
       max-height alone does not help -- an anchor 375px down plus a 796px cap still
       overflows. Pinning top turns it into a proper viewport sheet, which is what the
       horizontal clamp had already half-made it. !important beats the JS-set inline.

       The BODY scrolls, not the shell, so the whole form including the Apply/Clear row
       is reachable by scrolling INSIDE the popover.

       ⚠️ SCOPE LIMIT, stated rather than implied: this sits in the max-width:599px block,
       matching where the defect was actually MEASURED (375x812) and where U80 already
       turns the popover into a full-width sheet. A SHORT viewport wider than 599px --
       a landscape phone, say 812x375 -- has the same too-tall-to-fit shape and is NOT
       covered here. That case was not reproduced, and guessing at it would repeat the
       mistake this phase keeps finding: `top: 8px` is only correct where the popover is
       already viewport-pinned, so applying it at Sm+ would yank an anchored desktop
       popover to the top of the screen. Fix that case when it is measured, with a
       height-keyed rule (max-height alone is safe at any width; `top` is not). */
    .mud-popover.scope-filter-popover {
        top: 8px !important;
        max-height: calc(100dvh - 16px) !important;
    }

    .mud-popover.scope-filter-popover .closina-scope-filter-popover-body {
        max-height: calc(100dvh - 16px) !important;
        overflow-y: auto !important;
        overscroll-behavior: contain;
    }

    /* Fix 3: Compact page title + kill its wrapper's mb-4 (36px) margin */
    h1.mud-typography-h4,
    h1.mud-typography {
        font-size: 1.25rem !important;
        line-height: 1.3 !important;
        margin-bottom: 0 !important;
    }
    .d-flex.justify-space-between.align-center.mb-4 {
        margin-bottom: 8px !important;
    }

    /* Fix 4: Tighten stat card grid bottom margin */
    .mud-grid.mb-4:has(.compact-stat-card) {
        margin-bottom: 4px !important;
    }

    /* Fix 5: Kill gap between tabs and grid content.
       Tabpanel and grid wrapper have excessive padding/margin. */
    .mud-tabs,
    .mud-tabs-toolbar {
        min-height: 44px !important;
    }
    .mud-tab {
        min-height: 44px !important;      /* House touch floor: must match Fix 14 (44px) */
        min-width: 0 !important;         /* Override MudBlazor 160px default */
        flex: 1 1 0 !important;          /* Equal-width tabs that shrink to fit */
        padding: 4px 16px 4px 8px !important; /* Extra right padding for badge overflow */
        font-size: 0.75rem !important;
    }
    /* Hide tab icons on mobile — text + badge is enough context */
    .mud-tab .mud-icon-root {
        display: none !important;
    }
    .mud-tabpanel {
        padding: 0 !important;
    }

    /* Fix 5c: Remove MudTabs scroll arrows on mobile.
       With compact 0.75rem tabs, 3 short labels ("All Members", "Active", "Inactive")
       fit easily at 375px. The scroll arrows waste ~88px (44px each) and make the
       tab bar look cramped. Hide them and let tabs fill naturally. */
    .mud-tabs .mud-tabs-scroll-button,
    .mud-tabs button.mud-tabs-scroll-button {
        display: none !important;
    }

    /* Fix 5d: Kill bottom margin on MudTabs (mb-4 = 16px dead space).
       The gap between the tab bar and grid search is wasted space on mobile. */
    .mud-tabs.mb-4 {
        margin-bottom: 0 !important;
    }
    /* Also kill all panel padding — grid has its own border/spacing */
    .mud-tabs-panels.pt-4,
    .mud-tabs-panels {
        padding: 0 !important;
    }

    /* Fix 5b: Sentence case for tabs instead of ALL CAPS.
       MudBlazor applies text-transform: uppercase by default on .mud-tab.
       Modern UX (Material Design 3, Apple HIG, Linear, Notion) uses
       sentence case — more readable, less "shouty", better scanability.
       Research: ALL CAPS reduces reading speed ~13-20% (Pelli et al., 2006)
       because ascender/descender word-shape cues are lost. */
    .mud-tab {
        text-transform: none !important;
        letter-spacing: normal !important;
    }

    /* Fix 6: Hide "Drag a column header to group" — desktop-only interaction */
    .e-groupdroparea {
        display: none !important;
    }

    /* Fix 7: Compact Syncfusion grid toolbar */
    .e-toolbar-items {
        padding: 2px 0 !important;
    }
    .e-toolbar .e-toolbar-item .e-tbar-btn {
        padding: 4px !important;
    }
}

/* Fix 19 (UX Audit 2026-03-08, updated 2026-03-09): MudTabs Scroll Arrow Covering Last Tab on Tablet
   Issue: At tablet width (768px), the MudTabs scroll arrow button overlaps the
   last visible tab ("User Management"), making it untappable (UX-R03).
   Root cause: MudBlazor positions scroll buttons with position:absolute over tabs.
   Solution: Give scroll buttons opaque backgrounds so they don't visually overlap
   tab text, and ensure the toolbar has padding for the scroll button area. */
@media (min-width: 600px) and (max-width: 959px) {
    .mud-tabs-toolbar {
        padding-right: 48px !important;
        position: relative !important;
    }

    /* Give scroll arrows opaque background and proper stacking */
    .mud-tabs .mud-tabs-scroll-button {
        flex-shrink: 0 !important;
        background-color: var(--closina-surface) !important;
        z-index: 2 !important;
        min-width: 44px !important;
        min-height: 44px !important;
    }

    /* Dashboard tabs: compact sizing to avoid needing scroll at all */
    .dashboard-tabs .mud-tab {
        padding: 8px 12px !important;
        min-width: auto !important;
        font-size: 0.85rem !important;
    }

    .dashboard-tabs .mud-tab .mud-icon-root {
        font-size: var(--closina-icon-nav) !important; /* U68 Sub-E: 20px (was 1.25rem hardcode) */
        margin-right: 4px !important;
    }
}

/* Fix 21 (UX Audit 2026-03-08): AI FAB Overlap with Page Content on Mobile
   Issue: The AI Assistant floating action button overlaps with page content at
   mobile — covering Import button on /m/contacts and form inputs on /m/settings
   (84% overlap measured).
   Solution: Keep the FAB clear of bottom-area content on touch viewports.
   Note: Copilot is the bottom-of-stack FAB (80px) post-swap; the +56px stacking
   gap above it for the Feedback FAB is owned by the Fix 3 block. */
@media (max-width: 959px) {
    .copilot-fab-container {
        bottom: 80px !important;
    }
}

/* Fix 22 (UX Audit 2026-03-08): Onboarding Banner Icon/Text Alignment on Mobile
   Issue: MudAlert onboarding banner shows 11px icon-to-text vertical center
   misalignment at 375px. The icon remains centered to single-line height while
   text wraps to multiple lines at narrow widths.
   Solution: Align icon to flex-start with small top margin on touch viewports. */
@media (max-width: 959px) {
    .onboarding-banner .mud-alert-icon {
        align-self: flex-start !important;
        margin-top: 4px !important;
    }

    .onboarding-banner .mud-alert-message {
        align-self: center !important;
    }
}

/* Fix 23 (UX Audit 2026-03-08): Page Header Icon/Text Vertical Alignment
   Issue: Icon (40px) and title+subtitle block have different heights, causing
   7-15px top-edge jitter despite align-items:center (centering makes top edges
   differ by half the height difference).
   Solution: Use align-items:stretch so all children get the same height, then
   each child centers its own content internally. Icon is wrapped in a
   .page-header-icon div that stretches and flex-centers the icon within. */
.page-header-group > .mud-icon-button {
    align-self: center !important;
    flex-shrink: 0;
}

/* Fix 24 (UX Audit 2026-03-08): Syncfusion Grid Desktop Touch Targets
   Issue: Checkbox frames (e-frame e-icons) at 14x14px and filter icons
   (e-filtermenudiv) at 18x18px are below the 24px desktop minimum — which Phase Z39
   identifies as the WCAG 2.5.8 Target Size (Minimum) AA floor (24x24, applying to
   pointer inputs including mouse). Fix 13 handles mobile (44px); this is desktop.

   ⚠ Corrected Phase Z39: this comment used to claim "Solution: Set 24px minimum at
   all viewports for these elements", which the rules below contradict —
   .e-filtermenudiv.e-icons is 24px, but .e-frame.e-icons is only 20px. 20px is UNDER
   the 24x24 AA floor, so the checkbox frame is a candidate AA failure at desktop.
   Deliberately NOT changed here: Z39 Sub-Phase D measures the interactive BOX via
   getBoundingClientRect() on the clickable ancestor (the 20px may be an inner glyph
   frame inside a larger hit area), and Sub-Phase E raises whatever it confirms.
   Do not "fix" the 20px on the strength of this comment alone — measure first. */
.e-grid .e-frame.e-icons {
    min-width: 20px;
    min-height: 20px;
}

.e-grid .e-filtermenudiv.e-icons {
    min-width: 24px;
    min-height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Syncfusion grid column header text needs minimum height */
.e-grid .e-headercell .e-headertext {
    min-height: 24px;
    display: inline-flex;
    align-items: center;
}

/* ========================================
   Page Header & Config Banner Alignment Fixes (UX Audit 2026-03-08)
   Fix R09: 7-13px vertical jitter between page header title group and
   action buttons. Config banner icon/text jitter worsens to 20px on mobile.
   ======================================== */

/* Page header: stretch children to equal height, eliminating top-edge jitter */
.page-header-group {
    align-items: stretch !important;

    /* F112: this cluster is a flex ITEM of the header's justify-space-between row, and a flex
       item defaults to min-width:auto — it refuses to shrink below its content's intrinsic
       width. The .closina-page-header-title ellipsis machinery (overflow/text-overflow/
       white-space) is already fully present two levels down, but it never gets the chance to
       run, so at nowrap viewports the cluster pushes the action group off-screen instead of
       ellipsizing. Measured 2026-08-03 at 768x1024: Member 68px overflow with the refresh
       button provably unclickable via elementFromPoint; Admin actions 585px past the viewport
       with NO scrollbar to reach them.

       Deliberately NOT !important. Corrected 2026-08-03 at the a4b gate, because the first
       version of this comment justified that with "nothing else declares min-width on this
       selector", which is FALSE and measurably so: the rule
       ".mud-paper > .d-flex.align-center.justify-space-between > *" inside
       "@media (max-width: 599px)" ALSO declares min-width: 0 !important on this element. The
       real reason no !important is needed is that the other declaration AGREES — both resolve
       to 0 — so there is nothing to override. Measured computed min-width: 0px on both an
       Admin page and a Public page.

       Related measured fact, so nobody reasons from the wrong premise later: the
       "align-items: stretch !important" above is OUTRANKED on Member/Admin pages by
       ".mud-paper > .d-flex.justify-space-between.align-center > .d-flex.align-center"
       (also in this file, center !important, higher specificity) — computed value there is
       "center", NOT stretch. On Public, which is not inside that .mud-paper structure, it
       does win and computes "stretch". That split is PRE-EXISTING and unrelated to F112; the
       visual outcome is correct either way (zero top-edge jitter measured on both).

       Pinned by PageHeaderFlexShrinkConvention_Tests. */
    min-width: 0;
}

/* Fix: MudTooltip wrappers (e.g., ConnectionStatusIndicator) inside page header
   action areas add extra DOM structure that breaks flex alignment, causing 11px
   vertical jitter. Force tooltip roots to inline-flex + center. */
.page-header-group .mud-tooltip-root,
.d-flex.align-center.gap-2 > .mud-tooltip-root {
    display: inline-flex !important;
    align-items: center !important;
}

/* UX Audit 2026-03-30: Section header title/action button alignment.
   3-6px vertical jitter between MudText headings and action buttons in
   d-flex justify-space-between rows inside MudPaper sections. Force children
   to center alignment and normalize line-height. */
.mud-paper > .d-flex.justify-space-between.align-center {
    align-items: center !important;
}
.mud-paper > .d-flex.justify-space-between.align-center > .d-flex.align-center {
    align-items: center !important;
}
.mud-paper > .d-flex.justify-space-between.align-center .mud-typography {
    line-height: 1.4 !important;
}

/* Config health banner: align icon, text, and action button on same baseline.
   UX Audit 2026-03-30: 13px vertical jitter between icon/text and expand button
   caused by align-self: flex-start on icon. Force all children to center. */
.config-health-banner .d-flex.align-center {
    align-items: center !important;
    flex-wrap: nowrap;
}
.config-health-banner .d-flex.align-center > .mud-icon-root {
    flex-shrink: 0;
}

.config-health-banner .mud-alert-message {
    width: 100%;
}

/* Config health banner: increase close icon to the house 44px touch floor (platform
   convention — see citation anchor above; NOT WCAG 2.5.5, which is AAA and not claimed).
   MudAlert's built-in close icon renders at ~26px — that clears the WCAG 2.5.8 AA 24x24
   floor, so this is a comfort improvement, not a conformance fix. Override to 44px. */
.config-health-banner .mud-alert-close .mud-icon-button {
    min-width: 44px;
    min-height: 44px;
}

/* Filled MudAlert icon contrast: MudBlazor Variant.Filled sets a colored background (red, amber,
   blue, green) but SVG icons inside use explicit palette colors from the theme, creating poor
   contrast (e.g., green icons on red). Force all icons, buttons, and SVGs inside filled alerts
   to inherit the alert's text color (white). Applies to ALL filled alerts app-wide. */
.mud-alert-filled-error .mud-icon-root.mud-svg-icon,
.mud-alert-filled-warning .mud-icon-root.mud-svg-icon,
.mud-alert-filled-success .mud-icon-root.mud-svg-icon,
.mud-alert-filled-info .mud-icon-root.mud-svg-icon {
    color: inherit !important;
    fill: currentColor !important;
}
.mud-alert-filled-error .mud-icon-button,
.mud-alert-filled-warning .mud-icon-button,
.mud-alert-filled-success .mud-icon-button,
.mud-alert-filled-info .mud-icon-button {
    color: inherit !important;
}
.mud-alert-filled-error .mud-button-root,
.mud-alert-filled-warning .mud-button-root,
.mud-alert-filled-success .mud-button-root,
.mud-alert-filled-info .mud-button-root {
    color: inherit !important;
}

/* Config health banner: expanded section layout.
   Row layout: text shrinks, Configure button stays right-aligned at consistent position. */
.config-health-banner .config-health-row {
    color: inherit;
    flex-wrap: nowrap !important;
}
.config-health-banner .config-health-row > .d-flex {
    flex: 1;
    min-width: 0;
}
.config-health-banner .config-health-row > a {
    flex-shrink: 0;
    margin-left: 8px;
}
/* Filled MudAlert: Variant.Text buttons and MudLinks are indistinguishable from surrounding
   text on colored backgrounds. Add semi-transparent pill background so they look tappable.
   Applies to ALL filled alerts (ConfigurationHealthBanner, CompactSecurityBar, AnnouncementBanner, etc.).
   Variant.Outlined and Variant.Filled buttons already have visible borders/backgrounds. */
.mud-alert-filled-error .mud-button-text,
.mud-alert-filled-warning .mud-button-text,
.mud-alert-filled-success .mud-button-text,
.mud-alert-filled-info .mud-button-text,
.mud-alert-filled-error .mud-link,
.mud-alert-filled-warning .mud-link,
.mud-alert-filled-success .mud-link,
.mud-alert-filled-info .mud-link {
    background-color: var(--closina-alert-button-pill) !important;
    border-radius: var(--closina-radius-full) !important;
    padding: 4px 12px !important;
    font-weight: 600 !important;
    text-decoration: none !important;
    transition: background-color var(--closina-transition-fast) !important;
}
.mud-alert-filled-error .mud-button-text:hover,
.mud-alert-filled-warning .mud-button-text:hover,
.mud-alert-filled-success .mud-button-text:hover,
.mud-alert-filled-info .mud-button-text:hover,
.mud-alert-filled-error .mud-link:hover,
.mud-alert-filled-warning .mud-link:hover,
.mud-alert-filled-success .mud-link:hover,
.mud-alert-filled-info .mud-link:hover {
    background-color: rgba(255, 255, 255, 0.30) !important;
}

/* Config health banner mobile: summary text can wrap but Configure buttons stay inline */
@media (max-width: 599px) {
    .config-health-banner .config-health-row > .d-flex .mud-typography {
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }
}

/* ========================================
   Fix 25 (UX Audit 2026-03-08 v3): Settings Page Status Row Alignment
   Issue: MudStack Row containers with MudSwitch + text labels have 6-17px
   vertical jitter on settings pages (/a/stripe-settings, /a/openai-settings,
   /a/twilio-settings, /a/calendar-settings). MudSwitch has taller intrinsic
   height than sibling text elements.
   Solution: Force center alignment on settings MudStack rows containing switches.
   ======================================== */
.mud-paper .mud-stack-row:has(.mud-switch) {
    align-items: center !important;
}

/* Settings section headers with inline MudIcon (e.g., "🔑 Stripe Credentials")
   have icon-to-text baseline jitter. Align icon vertically within text block. */
.mud-paper .mud-typography-h5 > .mud-icon-root {
    vertical-align: middle;
}

/* ========================================
   Fix 26 (UX Audit 2026-03-08 v3): Syncfusion Pager Touch Targets
   Issue: Pagination buttons (page numbers, prev/next arrows) render below
   44px on mobile/tablet breakpoints.
   Solution: Enforce 44px minimum on pager navigation elements.
   ======================================== */
@media (max-width: 959px) {
    .e-pager .e-numericitem,
    .e-pager .e-first,
    .e-pager .e-prev,
    .e-pager .e-next,
    .e-pager .e-last,
    .e-pager .e-link {
        min-width: 44px !important;
        min-height: 44px !important;
        display: inline-flex !important;
        align-items: center !important;
        justify-content: center !important;
    }
}

/* ============================================================================
   Phase U31 Sub-Phase D: Hide Copilot FAB on mobile
   ============================================================================
   The Copilot FAB overlaps with the MobileBottomNavBar at Xs (<600px).
   Mobile users reach Copilot via the command palette (Phase U17e CopilotSource).
   Desktop (>=Sm) position is unchanged.
*/
@media (max-width: 599px) {
    .closina-copilot-fab {
        display: none;
    }
}

/* ============================================================================
   Phase U31 Sub-Phase D: Mobile bottom navigation bar
   ============================================================================
   Fixed-position bar visible only at Xs (<600px). Renders 5 items: 4 navigation
   destinations (dashboard, contacts/members, inbox/monitoring, calendar/billing)
   plus a "More" button that opens the sidebar drawer via IShellChromeState.
*/
.closina-mobile-bottom-nav {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: var(--closina-layout-bottom-nav-height, 56px);
    padding-bottom: env(safe-area-inset-bottom, 0);
    display: none;
    z-index: var(--closina-z-sticky);
    background: var(--closina-surface-hover);
    border-top: 1px solid var(--closina-border-strong);
    align-items: center;
    justify-content: space-around;
}

@media (max-width: 599px) {
    .closina-mobile-bottom-nav {
        display: flex;
    }
}

.closina-mobile-bottom-nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex: 1;
    gap: 2px;
    padding: 6px 0;
    min-height: 44px;
    min-width: 44px;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--closina-text-secondary);
    text-decoration: none;
    font: inherit;
    transition: var(--closina-transition-fast);
}

.closina-mobile-bottom-nav-item.active {
    color: var(--closina-primary);
}

/* Phase U60 Sub-Phase A: removed component-scoped :focus-visible override —
   universal *:focus-visible rule in closina-theme.css provides the focus indicator
   with WCAG 1.4.11-compliant contrast against the tab bar surface. */

.closina-mobile-bottom-nav-label {
    font-size: 0.625rem;
    font-weight: var(--closina-font-weight-medium, 500);
    line-height: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 64px;
}

/* Phase U69 a4b follow-up (2026-05-02): compact AdminContextManageMode on Xs.
   The full description ("You have ManageAll permission. You can create, edit,
   and delete contacts with member selection.") wraps to 3 lines at 375px,
   pushing /a/m/contacts chrome from ~22% to 30.59% — over the Foldable/Mobile
   tier ERROR cap (>30%). At Xs, truncate the description to a single line
   with ellipsis; the "Admin Override Mode" affordance stays fully visible. */
@media (max-width: 599px) {
    .admin-context-manage-mode .admin-context-description {
        display: inline-block;
        max-width: 100%;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        vertical-align: bottom;
    }
}

/* Phase T69 A1 (2026-05-05): viewport overflow fix on .admin-context-section.
   At 375×812 the .admin-context-section's inline content (MudIcon + <strong> +
   long description) caused documentElement.scrollWidth = 1043 vs clientWidth =
   375 — a 668px horizontal overflow. The U69 ellipsis truncation was insufficient
   because the parent flex layout established by the surrounding MudAlert was
   not allowing children to shrink below their min-content size. Adding
   `min-width: 0` to the section permits flex/MudAlert children to shrink under
   pressure, `flex-wrap: wrap` lets the inline icon + label cluster wrap if the
   label itself ever exceeds the viewport (defense-in-depth complement to the
   U69 ellipsis), and `word-break: break-word` on the description prevents a
   pathological long token (e.g. localized description in a future locale)
   from forcing overflow before ellipsis can engage.

   T69 follow-up (2026-05-05, code-reviewer W1): scoped to mobile-only via
   `@media (max-width: 599.98px)` — the overflow only manifests below 600px,
   and forcing `display: flex` globally was changing baseline alignment of
   icon + <strong> + description on desktop where the content already fits.
   The descendant `word-break` rule stays unscoped as defense-in-depth for
   future localized long tokens at any viewport. */
@media (max-width: 599.98px) {
    .admin-context-section {
        min-width: 0;
        display: flex;
        flex-wrap: wrap;
        align-items: center;
    }
}

/* Phase F121 (/a4b): the acting-as banner overflowed its alert at EVERY viewport >= 600px,
   clipping the member context and pushing the "Expand details" toggle (which discloses the
   member's email + phone) entirely outside the dialog. Measured in the ExtraSmall admin release
   dialog: banner 444px inside a 396px alert at 1920 (~101px over), 470px at 768 (~127px over —
   worse than desktop, because the toggle grows to the 44px touch floor below 960px). 375px was
   already clean, which is exactly why the T69 block above did not catch it: it is scoped
   max-width: 599.98px.

   Root cause is NOT the banner root or the flex row. `.admin-context-acting-as-text` sets
   `white-space: nowrap` (AdminContextActingAs.razor.css), so its min-content equals its
   max-content; its flex parent `.mud-alert-message` has no `min-width`, so that parent's
   automatic minimum size resolves to that max-content and the text is never compressed — its
   own `text-overflow: ellipsis` can therefore never engage.

   `min-width: 0` restores the ellipsis. It is conditionally inert: where the line already fits
   (the Medium/Large dialogs most consumers use) nothing changes, because the ellipsis never
   engages. Anchored on the banner testid so it cannot reach unrelated MudAlerts — the same
   shape as the `.config-health-banner .mud-alert-message` rule below.

   ⚠️ BOTH selectors are required. This is a CHAIN, and it was got wrong TWICE — once with only
   `.mud-alert-message`, once with only `.mud-alert-position`. Each single-element attempt measured
   as a complete no-op, so the mechanism is recorded rather than left to be rediscovered a third
   time. Measured ancestor chain with the dialog open at 1920:

       .mud-alert             display:flex   parent:block   min-width:0     w=396
         └ .mud-alert-position  display:flex   parent:FLEX  min-width:auto  w=480  <- flex item
             └ .mud-alert-message display:block  parent:FLEX  min-width:auto  w=444  <- ALSO a flex item
                 └ .admin-context-acting-as                                   w=444

   ⚠️ Do NOT reason from `display`. `display:block` describes an element's OWN INNER formatting
   context; whether it is a FLEX ITEM is decided by its PARENT. `.mud-alert-message`'s parent is
   `.mud-alert-position`, which is `display:flex` — so it IS a flex item, computes `min-width:auto`,
   and floors at its max-content (444px). An earlier revision of this comment claimed the opposite
   ("display:block, so it has no automatic-minimum-size to relax"); that is FALSE and is corrected
   here, because as written it sent the next reader straight back down the failing path.

   Relaxing one link leaves the other binding, which is why both single-element fixes measured
   identical to no fix at all. A/B'd live at all four viewports with both declarations present:
   dialog-content overflow 77/77/103/0 -> 0/0/0/0; banner-vs-alert +101.5/+101.5/+127.5 -> -17 at
   every width; the "Expand details" chevron moves INSIDE the dialog and hit-tests to itself rather
   than to `.mud-overlay-scrim`; and the text finally ellipsises (358 -> 240) instead of clipping
   mid-glyph. Inert at 375px, where the T69 wrap block above already handles it.

   ⚠️ Do NOT instead unscope the T69 block to all viewports. Its actual reducer is
   `flex-wrap: wrap` (plus the razor.css `white-space: normal`), which would turn the slim
   single-line desktop bar into a wrapping block on every consumer — a far larger visual change
   than this. The fix must be global rather than CSS-isolated because both elements are emitted by
   MudAlert itself and never receive AdminContextBanner's scope attribute. */
[data-testid="admin-context-banner"] .mud-alert-position,
[data-testid="admin-context-banner"] .mud-alert-message {
    min-width: 0;
}

.admin-context-section .admin-context-description {
    word-break: break-word;
}

/* =============================================================================
   Phase T83 Sub-C (2026-05-14): Hide helper FABs when any MudBlazor dialog open
   =============================================================================
   The Copilot FAB (z-index: 9998, bottom-right fixed) intercepts pointer
   events on dialog btn-save buttons that overlap its z-index column. The
   existing in-component conditionals only hide the FAB when the FAB's OWN
   panel/feedback dialog is open — not when ANY MudBlazor dialog is rendered.
   This `:has()` selector closes the gap: when the page contains a
   `.mud-overlay-dialog` anywhere, hide the FABs so their pointer events
   don't compete with the active dialog's interactive elements. Matches the
   Linear / Teams / Salesforce SaaS convention (helper FABs hide under modal).

   baseline-check: :has — Safari 15.4+ / Chrome 105+ / Firefox 121+, all at or
   below the Q1 Option β floor in docs/architecture/web-app-browser-baseline.md.
   ============================================================================= */
body:has(.mud-overlay-dialog) .copilot-fab-container,
body:has(.mud-overlay-dialog) .feedback-fab-container,
body:has(.mud-overlay-dialog) .closina-copilot-fab,
body:has(.mud-overlay-dialog) .closina-feedback-fab {
    display: none !important;
}
