﻿/* =====================================================================
   NepalBrokers — App-wide styles. Matches the prototype's light/green
   palette (primary #0F7A4A on #F6F7F5 background with white cards).
   ===================================================================== */

:root {
    --font-serif: "Playfair Display", Georgia, serif;
    --font-mono: "JetBrains Mono", ui-monospace, monospace;

    /* Brand palette (matches prototype) */
    --nb-primary: #0F7A4A;
    --nb-primary-dark: #0B5E39;
    --nb-primary-bg: #ECF7EF;
    --nb-primary-ring: rgba(15, 122, 74, .22);

    --nb-gold: #C6922A;
    --nb-red: #D2385A;
    --nb-blue: #0284C7;
    --nb-amber: #D97706;
    --nb-violet: #7C3AED;

    /* Surfaces */
    --nb-bg: #F6F7F5;
    --nb-bg-soft: #FAFBFA;
    --nb-card: #FFFFFF;
    --nb-border: #E5E7EB;
    --nb-border-soft: #EFF1EE;

    /* Foreground */
    --nb-fg: #0F172A;
    --nb-fg-muted: #64748B;
    --nb-fg-soft: #94A3B8;

    /* Shadows */
    --nb-shadow-sm: 0 1px 2px rgba(15, 23, 42, .04);
    --nb-shadow-md: 0 4px 16px rgba(15, 23, 42, .07);
    --nb-shadow-lg: 0 12px 36px rgba(15, 23, 42, .12);

    /* Motion */
    --nb-transition: 150ms cubic-bezier(.4, 0, .2, 1);
    --nb-radius: 12px;
    --nb-radius-sm: 8px;
}

/* =====================================================================
   CONTROL SIZING STANDARD — read this before adding any new control
   -----------------------------------------------------------------------
   Added 2026-07-22 after a live UAT bug: a shared native-select class
   (.nb-fsel) shipped with zero width rules, so mobile browsers sized
   each dropdown to its WIDEST <option> text instead of the current
   value or the viewport. It was invisible to layout/overflow testing
   because the surrounding CONTAINER wrapped correctly — only the
   control's own box was undisciplined. The rules below exist so this
   class of bug doesn't recur, in this file or in a page's own <style>
   block. A companion full-app control-sizing audit (2026-07-22) swept
   every page against this standard; see that audit's fix list for the
   concrete instances it found and corrected.

   1. Native <select>/<input>/<textarea> ALWAYS need an explicit
      max-width (or width) in CSS, never just a min-width. Browsers can
      size an unstyled <select> to its widest <option>, not the current
      selection — don't rely on "today's option list is short enough."

   2. MudBlazor form components (MudTextField, MudSelect,
      MudNumericField, MudAutocomplete, MudDatePicker) default
      FullWidth=true already — don't add redundant width CSS to them.
      Just make sure the immediate container (a MudItem xs=/sm=, a flex
      child) is itself responsive. If a field needs an inline
      Style="min-width:...", always pair it with a max-width in that
      same Style so there's still a ceiling.

   3. Every MudDialog invocation must pass explicit
      DialogOptions { MaxWidth = MaxWidth.Small, FullWidth = true }
      (or a deliberately-chosen alternative) at the ShowAsync call
      site. Never omit DialogOptions — an omitted argument falls
      through to MudBlazor's own engine default, which nobody chose on
      purpose and can silently change on a MudBlazor version bump.

   4. Any custom badge/pill/chip showing a backend-driven COUNT (unread
      messages, pending items, selection totals) must cap the displayed
      value (e.g. "99+") the way the topbar notification bell already
      does (MudBadge Max="99"), and should carry max-width plus
      white-space:nowrap; overflow:hidden; text-overflow:ellipsis so an
      unexpectedly large number never crowds its neighbor. See
      .nav-pill below for the reference pattern.

   5. Any custom badge/pill/chip showing backend-driven TEXT of
      variable length (a role name, a ward/area name, a plan name)
      needs the same ellipsis treatment. See .rail-foot-name in
      NavMenu.razor for the reference pattern.

   6. Segmented/toggle-button groups (.nb-seg and similar) must have
      overflow-x:auto (or flex-wrap, if wrapping mid-group looks
      acceptable for that control) — never assume the option count
      stays fixed forever. (This app already grew one such group from
      3 to 4 options after shipping — see the NB-TYPE-EXCHANGE comment
      in Listings.razor.)

   Breakpoints in use throughout this file: 960px (tablet/desktop
   split), 720px (phone/tablet split for most stacking rules), 600px,
   480px (small-phone tightening). Match one of these rather than
   inventing a new breakpoint.
   ===================================================================== */

html, body {
    font-family: "DM Sans", system-ui, sans-serif;
    background: var(--nb-bg);
    color: var(--nb-fg);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

/* ===== iOS / Android hardening =====
   - text-size-adjust: stop Safari inflating text when rotating to landscape.
   - overflow-x hidden: a single stray wide element can't make the whole page
     scroll sideways on a phone.
   - tap-highlight transparent: remove the grey flash box iOS paints over every
     tapped button/link (we already have proper :focus-visible + :hover states). */
html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}
body {
    overflow-x: hidden;
    -webkit-tap-highlight-color: transparent;
}

/* Smooth scrollbar */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: #CBD5E1; border-radius: 6px; }
::-webkit-scrollbar-thumb:hover { background: #94A3B8; }
::-webkit-scrollbar-track { background: transparent; }

/* Headings use the brand serif */
.mud-typography-h1, .mud-typography-h2, .mud-typography-h3, .mud-typography-h4 {
    font-family: var(--font-serif) !important;
}

.mono { font-family: var(--font-mono); }

/* Visible focus ring for keyboard nav */
*:focus-visible {
    outline: 2px solid var(--nb-primary-ring);
    outline-offset: 2px;
    border-radius: 6px;
}

/* ===== KPI cards ===== */
.kpi-card {
    position: relative;
    overflow: hidden;
    border: 1px solid var(--nb-border);
    border-radius: var(--nb-radius);
    transition: box-shadow var(--nb-transition), transform var(--nb-transition);
}
.kpi-card:hover {
    box-shadow: var(--nb-shadow-md);
    transform: translateY(-1px);
}
.kpi-card .icon-blob {
    position: absolute;
    right: -10px;
    top: -10px;
    width: 60px;
    height: 60px;
    border-radius: 50%;
    opacity: 0.15;
}
/* KPI value uses the demo's mono figure, not the oversized serif h4 */
.kpi-card .mud-typography-h4 {
    font-family: var(--font-mono) !important;
    font-size: 24px !important;
    font-weight: 500 !important;
    letter-spacing: -.01em;
    line-height: 1.15;
    margin: 2px 0;
}
.kpi-card .mud-typography-overline {
    font-size: 11px !important;
    font-weight: 600 !important;
    letter-spacing: .04em !important;
    color: var(--nb-fg-muted) !important;
    text-transform: uppercase !important;
}
/* Demo report-cards are plain (no coloured top accent) — neutralise any inline accent border. */
.kpi-card { border-top: 1px solid var(--nb-border) !important; }

/* Buttons: sentence-case like the demo (MudBlazor/theme uppercases by default) */
.mud-button-root { text-transform: none !important; letter-spacing: 0 !important; }

/* Dialogs/modals: align the surface to the design system — rounded corners,
   soft shadow, and serif titles like the prototype. Styling only; no behaviour. */
.mud-dialog { border-radius: var(--nb-radius) !important; box-shadow: var(--nb-shadow-lg, 0 12px 40px rgba(2,16,8,.16)) !important; }
.mud-dialog .mud-dialog-title { font-family: var(--font-serif); font-weight: 700; letter-spacing: -.01em; color: var(--nb-fg); }
.mud-dialog .mud-dialog-title .mud-typography { font-family: var(--font-serif); font-weight: 700; }

/* ===================================================================
   Shared page primitives (prototype-matched). Used across every page so
   headers, filters, tables and chips are identical app-wide.
   =================================================================== */
.nb-crumbs { font-size: 12px; color: var(--nb-fg-muted); margin-bottom: 8px; }
.nb-crumbs span { color: var(--nb-fg-soft); margin: 0 3px; }
.nb-crumbs a { color: var(--nb-primary); text-decoration: none; }
.nb-crumbs a:hover { text-decoration: underline; }

/* Page header: top-align the actions to the title (not the subtitle baseline) and
   give the block real breathing room so it never reads as a cramped strip. */
.nb-pagehead { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 24px; flex-wrap: wrap; }
.nb-pagehead .nb-h1 { font-family: var(--font-serif); font-weight: 700; font-size: 26px; margin: 0; letter-spacing: -.01em; color: var(--nb-fg); line-height: 1.15; }
.nb-pagehead .nb-sub { color: var(--nb-fg-muted); font-size: 13px; margin-top: 6px; line-height: 1.5; max-width: 760px; }
.nb-pagehead .nb-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.nb-seg { display: inline-flex; border: 1px solid var(--nb-border); border-radius: 8px; overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; background: #fff; }
.nb-seg button { border: none; background: #fff; padding: 7px 14px; font-size: 12px; font-weight: 600; color: var(--nb-fg-muted); cursor: pointer; font-family: inherit; transition: background var(--nb-transition), color var(--nb-transition); }
.nb-seg button + button { border-left: 1px solid var(--nb-border); }
.nb-seg button.active { background: var(--nb-primary); color: #fff; }

.nb-btn { display: inline-flex; align-items: center; gap: 6px; border-radius: 8px; border: 1px solid var(--nb-primary); background: var(--nb-primary); color: #fff; padding: 8px 14px; font-weight: 600; cursor: pointer; font-size: 13px; font-family: inherit; transition: all var(--nb-transition); }
.nb-btn:hover { background: var(--nb-primary-dark); border-color: var(--nb-primary-dark); }
.nb-btn.sec { background: #fff; color: var(--nb-fg); border-color: var(--nb-border); }
.nb-btn.sec:hover { background: var(--nb-bg); }
.nb-btn:disabled { opacity: .5; cursor: not-allowed; }

.nb-filters { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; flex-wrap: wrap; }
.nb-search { position: relative; flex: 1; min-width: 220px; max-width: 420px; }
.nb-search input { width: 100%; padding: 8px 12px 8px 34px; border: 1px solid var(--nb-border); border-radius: 8px; background: #fff; font-size: 13px; font-family: inherit; color: var(--nb-fg); outline: none; transition: border-color var(--nb-transition), box-shadow var(--nb-transition); }
.nb-search input:focus { border-color: var(--nb-primary); box-shadow: 0 0 0 3px var(--nb-primary-ring); }
.nb-search-ic { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--nb-fg-muted); display: inline-flex; pointer-events: none; }
.nb-fsel { border: 1px solid var(--nb-border); border-radius: 8px; padding: 8px 10px; font-size: 13px; font-weight: 600; background: #fff; color: var(--nb-fg); cursor: pointer; font-family: inherit; outline: none; max-width: 160px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nb-fsel:focus { border-color: var(--nb-primary); box-shadow: 0 0 0 3px var(--nb-primary-ring); }

.nb-tbl-wrap { background: #fff; border: 1px solid var(--nb-border); border-radius: var(--nb-radius); overflow: hidden; box-shadow: var(--nb-shadow-sm); }
.nb-tbl-scroll { overflow-x: auto; }
.nb-tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.nb-tbl th { text-align: left; padding: 10px 14px; background: var(--nb-bg); border-bottom: 1px solid var(--nb-border); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--nb-fg-muted); font-weight: 700; white-space: nowrap; }
.nb-tbl td { padding: 11px 14px; border-bottom: 1px solid var(--nb-border-soft); vertical-align: middle; color: var(--nb-fg); }
.nb-tbl tbody tr { transition: background var(--nb-transition); }
.nb-tbl tbody tr:hover td { background: #FAFBFA; }
.nb-tbl tbody tr:last-child td { border-bottom: none; }
.nb-tbl .t-title { font-weight: 600; line-height: 1.25; }
.nb-tbl .t-sub { font-size: 11px; color: var(--nb-fg-muted); margin-top: 1px; }
.nb-tbl .t-dash { color: var(--nb-fg-soft); }
.nb-tbl .t-link { color: var(--nb-primary); font-weight: 500; cursor: pointer; }
.nb-tbl .t-link:hover { text-decoration: underline; }
.nb-tbl .t-empty { text-align: center; color: var(--nb-fg-muted); padding: 28px 12px !important; font-size: 13px; }

.nb-chip { display: inline-flex; align-items: center; padding: 3px 9px; border-radius: 999px; font-size: 11px; font-weight: 600; background: var(--nb-bg); color: var(--nb-fg-muted); border: 1px solid var(--nb-border); }
.nb-chip.gold { background: #FBF4E3; color: var(--nb-gold); border-color: #E8CE7A; }
.nb-chip.red { background: #FBE7EC; color: var(--nb-red); border-color: #F3B5C4; }
.nb-chip.blue { background: #E6F3FA; color: var(--nb-blue); border-color: #B8DEF0; }
.nb-chip.green { background: var(--nb-primary-bg); color: var(--nb-primary); border-color: var(--nb-primary-ring); }
.nb-chip.slate { background: #EEF2F6; color: #334155; border-color: #D6DCE4; }
.nb-chip.violet { background: #EDE5FE; color: var(--nb-violet); border-color: #D4B8F0; }

/* KPI card grid + card (prototype report-card), reusable on Dashboard / Brokers / Reports */
/* KPI grid follows the canonical tiers: 4 cols desktop (≥960), 2 cols tablet
   (601–959), 1 col mobile (≤600). (Was 900/560 — normalized to the standard
   breakpoints; the only affected zones are 901–959 and 561–600, which no common
   device width lands in.) */
.nb-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 16px; }
@media (max-width: 959.98px) { .nb-kpis { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .nb-kpis { grid-template-columns: 1fr; } }
.nb-kpi { position: relative; overflow: hidden; background: #fff; border: 1px solid var(--nb-border); border-radius: var(--nb-radius); padding: 16px 18px; box-shadow: var(--nb-shadow-sm); }
.nb-kpi .lbl { font-size: 11px; color: var(--nb-fg-muted); text-transform: uppercase; letter-spacing: .04em; font-weight: 700; }
.nb-kpi .val { font-family: var(--font-mono); font-size: 26px; font-weight: 600; letter-spacing: -.02em; margin-top: 6px; line-height: 1.05; }
.nb-kpi .delta { font-size: 11px; font-weight: 600; margin-top: 4px; color: var(--nb-fg-muted); }
.nb-kpi .delta.up { color: #059669; }
.nb-kpi .delta.down { color: var(--nb-red); }
.nb-kpi .blob { position: absolute; right: -10px; top: -10px; width: 60px; height: 60px; border-radius: 50%; background: var(--nb-primary-bg); opacity: .5; }

/* ===== Chips (status + tags) ===== */
.chip-green { background: #ECF7EF !important; color: #0F7A4A !important; }
.chip-gold  { background: #FBF4E3 !important; color: #C6922A !important; }
.chip-red   { background: #FBE7EC !important; color: #D2385A !important; }
.chip-blue  { background: #E6F3FA !important; color: #0284C7 !important; }
.chip-amber { background: #FEF4E3 !important; color: #D97706 !important; }
.chip-slate { background: #EEF2F6 !important; color: #334155 !important; }
.chip-violet { background: #EDE5FE !important; color: #7C3AED !important; }

/* ===== Hero gradients ===== */
.hero-gradient,
.wallet-hero {
    background: linear-gradient(135deg, #0F7A4A 0%, #0B5E39 100%);
    border-radius: 14px;
    padding: 24px;
    color: white;
    position: relative;
    overflow: hidden;
    box-shadow: var(--nb-shadow-md);
}
.wallet-hero::after,
.hero-gradient::after {
    content: "";
    position: absolute;
    right: -60px;
    top: -60px;
    width: 220px;
    height: 220px;
    background: radial-gradient(circle, rgba(255, 255, 255, .12), transparent 70%);
    pointer-events: none;
}

/* ===== Topbar search ===== */
.topbar-search {
    flex: 1;
    max-width: 520px;
    position: relative;
    margin-left: 12px;
}
.topbar-search input {
    width: 100%;
    padding: 7px 12px 7px 32px;
    border: 1px solid var(--nb-border);
    border-radius: var(--nb-radius-sm);
    background: var(--nb-bg);
    font-size: 13px;
    color: var(--nb-fg);
    outline: none;
    font-family: inherit;
    transition: border-color var(--nb-transition), box-shadow var(--nb-transition);
}
.topbar-search input::placeholder { color: var(--nb-fg-soft); }
.topbar-search input:focus {
    border-color: var(--nb-primary);
    background: #fff;
    box-shadow: 0 0 0 3px var(--nb-primary-ring);
}
.topbar-search-icon {
    position: absolute;
    left: 8px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--nb-fg-muted) !important;
    pointer-events: none;
}

/* ===== Sidebar (green rail) ===== */
.nb-drawer {
    overflow: hidden !important;
    /* Keep the drawer below the top app-bar's z-index so its contents
       can never float over main content. */
    z-index: 1100 !important;
}
.nb-drawer .mud-drawer-content {
    background: #ffffff !important;
    color: var(--nb-fg) !important;
    border-right: 1px solid var(--nb-border) !important;
    /* Pin rail-footer to the bottom of the drawer so the user avatar/role
       sits flush with the bottom of the sidebar instead of floating mid-page
       and overlapping main content on shorter screens. */
    display: flex !important;
    flex-direction: column !important;
    overflow: hidden !important;
    height: 100% !important;
    max-height: 100% !important;
    box-sizing: border-box;
}
.nb-drawer .mud-drawer-content > .mud-nav-menu {
    flex: 1 1 auto !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    min-height: 0 !important;
}
.nb-drawer .mud-drawer-content > .nav-brand,
.nb-drawer .mud-drawer-content > .scope-pill {
    flex: none !important;
}
.nb-drawer .mud-drawer-content > .rail-footer {
    flex: none !important;
    max-width: 100%;
    box-sizing: border-box;
    overflow: hidden;
}

/* NB-DRAWER-CHROME (moved from NavMenu's <style> during the scoped-CSS migration): these style
   MudBlazor drawer internals (.mud-drawer-content, .mud-navmenu) via the stable .nb-drawer class,
   which sits on MainLayout's <MudDrawer>. They have no plain-HTML ancestor to anchor Blazor
   ::deep on in the all-Mud shell, so they stay in this global layer next to the .nb-drawer rules
   above. Placed AFTER them so the 100dvh height wins on source order, and the real .mud-navmenu
   scroll takes effect (MudBlazor 7 renders .mud-navmenu; the hyphenated .mud-nav-menu the older
   rule above targets does not exist in this version, so this is the live scroll rule). */
.nb-drawer .mud-drawer-content {
    display: flex;
    flex-direction: column;
    /* dvh tracks the *visible* viewport as mobile browser chrome shows/hides, so the rail never
       gets cut off the way a static 100vh does on iOS. */
    height: 100dvh !important;
    min-height: 0;
    /* When the drawer is a full-height overlay on a phone, keep the footer above the iOS home
       indicator. */
    padding-bottom: env(safe-area-inset-bottom, 0px);
    box-sizing: border-box;
}
.nb-drawer .mud-navmenu,
.nb-drawer .nav-skeleton {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    padding-right: 4px; /* breathing room so the scrollbar never sits on text */
    -webkit-overflow-scrolling: touch; /* momentum scroll on iOS */
    overscroll-behavior: contain;      /* don't chain-scroll the page behind */
    /* Firefox */
    scrollbar-width: thin;
    scrollbar-color: rgba(148, 163, 184, .5) transparent;
}
/* WebKit / Chromium / Edge */
.nb-drawer .mud-navmenu::-webkit-scrollbar,
.nb-drawer .nav-skeleton::-webkit-scrollbar {
    width: 6px;
}
.nb-drawer .mud-navmenu::-webkit-scrollbar-track,
.nb-drawer .nav-skeleton::-webkit-scrollbar-track {
    background: transparent;
}
.nb-drawer .mud-navmenu::-webkit-scrollbar-thumb,
.nb-drawer .nav-skeleton::-webkit-scrollbar-thumb {
    background: rgba(148, 163, 184, .4);
    border-radius: 3px;
    transition: background .15s ease;
}
.nb-drawer .mud-navmenu:hover::-webkit-scrollbar-thumb,
.nb-drawer .nav-skeleton:hover::-webkit-scrollbar-thumb {
    background: rgba(148, 163, 184, .65);
}

/* NB-LOGO-HOME: the brand is now an <a> to /dashboard. Strip the anchor's default
   underline + link colour so it renders exactly as the old <div> did. */
.nav-brand {
    display: flex;
    align-items: center;
    gap: 12px;
    /* NB-RAIL-ALIGN (2026-07-28): the rail brand and the topbar sit side by side on desktop, so
       their bottom borders read as ONE horizontal line across the window. They didn't: 18/16px
       padding made this block 71px tall against the topbar's 64px, so the line stepped 7px at the
       rail's edge, and the two borders were different greys (--nb-border-soft #EFF1EE here vs
       --nb-border #E5E7EB there) so the halves didn't even match in colour. Pin the height to the
       same variable the topbar uses and share its border colour. */
    height: var(--nb-topbar-h, 64px);
    box-sizing: border-box;
    padding: 0 16px;
    border-bottom: 1px solid var(--nb-border);
    margin-bottom: 8px;
    text-decoration: none;
    color: inherit;
    cursor: pointer;
}
.nav-brand:hover { text-decoration: none; color: inherit; }
.nav-group-label {
    color: var(--nb-fg-muted) !important;
    letter-spacing: .1em !important;
    font-weight: 700 !important;
    font-size: 10.5px !important;
    text-transform: uppercase !important;
    padding-left: 16px !important;
    margin-top: 8px !important;
}
.nav-row {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    width: 100%;
}
.nav-pill {
    margin-left: auto;
    padding: 1px 7px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 700;
    line-height: 1.6;
    background: #ffffff;
    border: 1px solid var(--nb-border);
    color: var(--nb-fg-muted);
    max-width: 40px;
    flex: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.nav-pill-red   { background: #DC2626; color: #ffffff; border-color: transparent; }
.nav-pill-amber { background: #F59E0B; color: #1f1300; border-color: transparent; }
.nav-pill-green { background: #16A34A; color: #ffffff; border-color: transparent; }

/* MudNavLink — dark text on the white rail; light-green pill on hover/active (matches demo) */
.nb-drawer .mud-nav-link {
    color: var(--nb-fg) !important;
    margin: 1px 8px;
    border-radius: 8px;
    padding: 8px 12px !important;
    min-height: 38px !important;
    font-size: 13px;
    /* NB-NAV-WEIGHT: the rail set no font-weight at all, so labels inherited MudBlazor's 400
       and read washed out against the icons. 550 gives them presence without shouting; the
       active item moves to 700 below so it stays distinguishable by weight as well as colour. */
    font-weight: 550;
    transition: background var(--nb-transition), color var(--nb-transition);
}
.nb-drawer .mud-nav-link .mud-nav-link-icon,
.nb-drawer .mud-nav-link .mud-icon-root {
    color: var(--nb-fg-muted) !important;
    /* Slim, outline-weight icons like the demo's Lucide rail (Material's 24px
       filled glyphs read heavy/"default"); 20px outline is lighter + cleaner. */
    font-size: 20px !important;
    width: 20px !important;
    height: 20px !important;
}
/* Tighten the gap between icon and label so the rail reads as one clean column. */
.nb-drawer .mud-nav-link .mud-nav-link-icon { margin-right: 12px !important; }
.nb-drawer .mud-nav-link:hover {
    background: var(--nb-primary-bg) !important;
    color: var(--nb-primary) !important;
}
.nb-drawer .mud-nav-link:hover .mud-nav-link-icon,
.nb-drawer .mud-nav-link:hover .mud-icon-root {
    color: var(--nb-primary) !important;
}
.nb-drawer .mud-nav-link.mud-nav-link-active,
.nb-drawer .mud-nav-link.active {
    background: var(--nb-primary-bg) !important;
    color: var(--nb-primary) !important;
    /* NB-NAV-WEIGHT: was 600 against an inherited 400. Now that resting weight is 550,
       the active row needs 700 to keep the same contrast step. */
    font-weight: 700;
}
.nb-drawer .mud-nav-link.mud-nav-link-active .mud-nav-link-icon,
.nb-drawer .mud-nav-link.mud-nav-link-active .mud-icon-root {
    color: var(--nb-primary) !important;
}
.nb-drawer .mud-nav-menu { padding: 0 !important; }

/* ===== Listing cards ===== */
.listing-card {
    background: #fff;
    border: 1px solid var(--nb-border);
    border-radius: var(--nb-radius);
    overflow: hidden;
    cursor: pointer;
    transition: box-shadow var(--nb-transition), transform var(--nb-transition);
}
.listing-card:hover {
    box-shadow: var(--nb-shadow-md);
    transform: translateY(-2px);
}
.listing-card .photo {
    aspect-ratio: 16 / 10;
    background: linear-gradient(135deg, #DFE8DF, #B2CEB9);
    display: grid;
    place-items: center;
    font-size: 48px;
    position: relative;
}
.listing-card .body { padding: 12px 14px; }
.listing-card .price { font-family: var(--font-mono); font-weight: 600; font-size: 16px; }
.listing-card .title { font-weight: 600; font-size: 13px; margin-top: 2px; }
.listing-card .meta {
    color: var(--nb-fg-muted);
    font-size: 12px;
    margin-top: 4px;
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
}

/* ===== Dashboard panels ===== */
.panel {
    background: #fff;
    border: 1px solid var(--nb-border);
    border-radius: var(--nb-radius);
    padding: 16px;
    box-shadow: var(--nb-shadow-sm);
}
.panel-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
}
.panel-head h6 { margin: 0; font-size: 14px; font-weight: 700; }
.panel-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 4px;
    border-bottom: 1px solid var(--nb-border-soft);
    transition: background var(--nb-transition);
}
.panel-row:last-child { border-bottom: none; }

/* ===== Links ===== */
a {
    color: var(--nb-primary);
    text-decoration: none;
    transition: color var(--nb-transition);
}
a:hover {
    color: var(--nb-primary-dark);
    text-decoration: underline;
}

/* ===== Mud component polish ===== */
.mud-paper {
    transition: box-shadow var(--nb-transition);
}
.mud-button-filled-primary {
    box-shadow: 0 2px 6px rgba(15, 122, 74, .25) !important;
    transition: transform var(--nb-transition), box-shadow var(--nb-transition) !important;
}
.mud-button-filled-primary:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(15, 122, 74, .35) !important;
}
.mud-table-row { transition: background var(--nb-transition); }
.mud-tabs .mud-tab.mud-tab-active {
    color: var(--nb-primary) !important;
}

/* Inputs */
.mud-input-outlined > .mud-input-control-input-container > .mud-input.mud-input-outlined:focus-within {
    border-color: var(--nb-primary) !important;
}

/* =====================================================================
   PROTOTYPE PARITY — reusable plain primitives + scoped MudBlazor lift.
   These let pages shed Material chrome and match the approved demo
   exactly. The `nb-` prefix avoids collisions with MudBlazor internals;
   the MudBlazor overrides are scoped to `.nb-main-content` so the app
   bar, drawer, dialogs and pop-over menus are never affected.
   ===================================================================== */

/* ---- Plain card (demo .card): border + soft shadow, no Material elevation ---- */
.nb-card { background: var(--nb-card); border: 1px solid var(--nb-border); border-radius: var(--nb-radius); box-shadow: var(--nb-shadow-sm); overflow: hidden; }
.nb-card-head { padding: 12px 16px; border-bottom: 1px solid var(--nb-border-soft); display: flex; align-items: center; gap: 8px; }
.nb-card-head .nb-card-title { margin: 0; font-size: 14px; font-weight: 700; color: var(--nb-fg); display: inline-flex; align-items: center; gap: 8px; }
.nb-card-body { padding: 16px; }
.nb-card-body.p0 { padding: 0; }

/* ---- Grid helpers (demo .grid-2/3/4) ---- */
.nb-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.nb-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.nb-grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.nb-grid-2.mb, .nb-grid-3.mb, .nb-grid-4.mb { margin-bottom: 16px; }
.nb-row-7-5 { display: grid; grid-template-columns: 7fr 5fr; gap: 16px; }
@media (max-width: 960px) { .nb-grid-2, .nb-grid-3, .nb-grid-4, .nb-row-7-5 { grid-template-columns: 1fr; } }

/* ---- Highlight row (demo .highlight-row): Recent/VIP/Featured + list widgets ---- */
.nb-hl { display: flex; gap: 10px; align-items: center; padding: 10px 14px; border-bottom: 1px solid var(--nb-border-soft); cursor: pointer; transition: background var(--nb-transition); }
.nb-hl:last-child { border-bottom: none; }
.nb-hl:hover { background: #FAFBFA; }
.nb-hl .pic { width: 42px; height: 42px; border-radius: 10px; background: linear-gradient(135deg, #DFE8DF, #B2CEB9); display: grid; place-items: center; font-size: 18px; flex: none; color: #0B5E39; }
.nb-hl .pic.gold { background: linear-gradient(135deg, #FBF4E3, #E8CE7A); color: #8A6D1E; }
.nb-hl .grow { flex: 1; min-width: 0; }
.nb-hl .nm { font-weight: 600; font-size: 13px; color: var(--nb-fg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nb-hl .meta { font-size: 11px; color: var(--nb-fg-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---- Small avatar (demo .avatar) for plain rows ---- */
.nb-av { width: 36px; height: 36px; border-radius: 50%; background: var(--nb-primary); color: #fff; display: grid; place-items: center; font-weight: 600; font-size: 12px; flex: none; }
.nb-av.gold { background: #FBF4E3; color: var(--nb-gold); }
.nb-av.muted { background: var(--nb-primary-bg); color: var(--nb-primary); }

/* ---- Ghost / small / block buttons to pair with .nb-btn ---- */
.nb-btn.ghost { background: transparent; color: var(--nb-fg-muted); border-color: transparent; box-shadow: none; }
.nb-btn.ghost:hover { background: var(--nb-bg); color: var(--nb-fg); }
.nb-btn.sm { padding: 5px 10px; font-size: 12px; }
.nb-btn.block { width: 100%; justify-content: center; }

/* ---- Inline "See all" link button in card heads ---- */
.nb-seeall { margin-left: auto; background: transparent; border: none; color: var(--nb-fg-muted); font-size: 12px; font-weight: 600; cursor: pointer; font-family: inherit; padding: 4px 8px; border-radius: 6px; transition: background var(--nb-transition), color var(--nb-transition); white-space: nowrap; }
.nb-seeall:hover { background: var(--nb-bg); color: var(--nb-primary); }

/* ---- Soft info band (demo digest / quick-task strips): a clean bordered card
   with a thin 3px accent rule instead of the heavy 4px Material left-border. ---- */
.nb-band { background: #fff; border: 1px solid var(--nb-border); border-radius: var(--nb-radius); box-shadow: var(--nb-shadow-sm); padding: 14px 16px; }
.nb-band.accent { border-left: 3px solid var(--nb-primary); }
.nb-band.accent-red { border-left: 3px solid var(--nb-red); }
.nb-band-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; flex-wrap: wrap; }
.nb-band-head .t { font-size: 14px; font-weight: 700; color: var(--nb-fg); }
.nb-band-head .nb-spacer { margin-left: auto; }

/* ---- Task row (demo todo): round check + colored left rule, no Material card ---- */
.nb-task { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 8px; border: 1px solid var(--nb-border-soft); margin-bottom: 8px; transition: background var(--nb-transition); }
.nb-task:last-child { margin-bottom: 0; }
.nb-task.overdue { background: #FEF2F2; border-color: #FBD9D9; }
.nb-task .grow { flex: 1; min-width: 0; cursor: pointer; }
.nb-task .ti { font-size: 13px; font-weight: 600; color: var(--nb-fg); }
.nb-task .ti.done { text-decoration: line-through; opacity: .5; font-weight: 400; }
.nb-task .mt { font-size: 11px; font-weight: 600; }
.nb-task .mt.red { color: var(--nb-red); }
.nb-task .mt.green { color: var(--nb-primary); }

/* ---- Mono number convention ---- */
.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* ---- MudBlazor lift: soften Material chrome inside the page body only.
   Scoped to .nb-main-content so the appbar, drawer, dialogs and menus
   (which portal outside, or are styled separately) are never touched. ---- */
.nb-main-content .mud-paper {
    border: 1px solid var(--nb-border);
    border-radius: var(--nb-radius);
    box-shadow: var(--nb-shadow-sm) !important;
}

/* MudChip → demo pill (rounded, lowercase, compact) */
.nb-main-content .mud-chip {
    border-radius: 999px !important;
    font-weight: 600 !important;
    font-size: 11px !important;
    min-height: 22px !important;
    height: auto !important;
    text-transform: none !important;
}

/* MudTable → demo .tbl (uppercase muted header, soft rows, subtle hover) */
.nb-main-content .mud-table th {
    text-transform: uppercase; font-size: 11px; letter-spacing: .06em;
    color: var(--nb-fg-muted) !important; font-weight: 700 !important;
    background: var(--nb-bg) !important; border-bottom: 1px solid var(--nb-border) !important;
}
.nb-main-content .mud-table td { border-bottom: 1px solid var(--nb-border-soft) !important; font-size: 13px; }
.nb-main-content .mud-table tbody tr:hover td { background: #FAFBFA !important; }

/* MudTabs slider + active label to brand green */
.mud-tabs .mud-tab-slider { background: var(--nb-primary) !important; }
.mud-tabs .mud-tab.mud-tab-active,
.mud-tabs .mud-tab.mud-tab-active .mud-typography { color: var(--nb-primary) !important; }

/* MudTabs bar → clean underline tabs: flat toolbar with a hairline, sentence-case
   labels, muted→green active. Removes the heavy Material tab-strip look across the
   tabbed pages (Wallet, Chat, CRM, Approvals, Roles & access, Payout). */
.nb-main-content .mud-tabs-toolbar { background: transparent !important; border-bottom: 1px solid var(--nb-border); }
.nb-main-content .mud-tab {
    text-transform: none !important; letter-spacing: 0 !important;
    /* NB-MOBILE-MODERATE (2026-09-07): tab height is token-driven now (--tab-h in controls.css,
       40 — was a flat 44) so the tabbed pages read less chunky across every device tier. */
    font-weight: 600; font-size: 13px; color: var(--nb-fg-muted); min-height: var(--tab-h);
}
.nb-main-content .mud-tab:hover { color: var(--nb-fg); background: transparent; }

/* MudDataGrid → demo table chrome (uppercase muted header, 13px rows, soft hover).
   Kept as a grid (it provides sort/filter) but skinned to match the .nb-tbl pages. */
.nb-main-content .mud-data-grid .mud-table-cell { font-size: 13px; }
.nb-main-content .mud-data-grid .mud-table-head .mud-table-cell {
    text-transform: uppercase; font-size: 11px; letter-spacing: .06em;
    color: var(--nb-fg-muted) !important; font-weight: 700 !important;
    background: var(--nb-bg) !important;
}
.nb-main-content .mud-data-grid tbody tr:hover { background: #FAFBFA !important; }

/* ---- Centred page container ----
   Caps page content and centres it, so the app reads as a tidy, framed column
   with even left/right margins on wide monitors. Below the cap it fills the
   available width; the gutter comes from .nb-main-content's horizontal padding
   (24px desktop / 16px mobile), so the layout stays fully responsive (single
   column + small gutters on phones/tablets).
   2026-07-03: raised from the demo's 1280px to 1440px — Shubham found the
   side gutters too wide on large monitors (visible on Chat especially). */
.nb-page-wrap {
    max-width: 1440px;
    margin-left: auto;
    margin-right: auto;
    width: 100%;
    box-sizing: border-box;
    /* Breathing room below the fixed topbar so the breadcrumb/title never jams
       against it (part of the "header feels congested" fix). */
    padding-top: 16px;
}
@media (min-width: 960px) {
    /* 24px desktop gutter (8px-grid best practice) — overrides the 16px base. */
    .nb-main-content {
        padding-left: calc(24px + env(safe-area-inset-left, 0px)) !important;
        padding-right: calc(24px + env(safe-area-inset-right, 0px)) !important;
    }
}

/* ===== Form helpers ===== */
.form-required-marker {
    color: var(--nb-red);
    margin-left: 2px;
    font-weight: 600;
}

/* ===== Tables horizontal scroll on mobile ===== */
.mud-table,
.mud-table-container,
.mud-simple-table {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch; /* momentum scroll for wide tables on iOS */
}

/* ===== Animations ===== */
/* NB-FIXED-CB (2026-07-28) — DO NOT reintroduce `transform` into these keyframes.
   This animation is applied to `.mud-main-content > *`, which is `.nb-page-wrap` — the element
   every page renders inside. `animation-fill-mode: both` makes the final keyframe stick, so
   `transform: translateY(0)` left the wrap with a permanent identity transform (matrix(1,0,0,1,0,0)),
   and ANY transform other than `none` makes an element the containing block for its
   `position: fixed` descendants.
   Net effect: every fixed overlay rendered inside a page was positioned relative to the wrap
   instead of the viewport. The wrap is centred at max-width 1440px, so on a 1920px screen its
   left edge is 365px in — and the Listings ⋮ menu, positioned at the click's viewport X, rendered
   ~220px past the right edge of the screen. Invisible, which is why it read as "the button does
   nothing". Measured on production before and after.
   A 4px slide is not worth a whole class of broken overlays, so the fade is opacity-only. */
@keyframes nb-fade-in {
    from { opacity: 0; }
    to { opacity: 1; }
}
.mud-main-content > * {
    animation: nb-fade-in .25s ease-out both;
}

/* ===== Responsive breakpoints ===== */
@media (max-width: 960px) {
    .topbar-search { max-width: 240px; }
    .hero-gradient,
    .wallet-hero { padding: 18px; }
}

/* ML-2: 721-960px topbar squeeze zone. Below 721px .topbar-search is
   display:none and the app-bar buttons get the shrink treatment in the
   max-width:720px block below; the instant the viewport crosses 721px,
   search reappears (capped at 240px by the block above) at the exact
   moment the button-shrink relief disappears, while nothing in the row
   could shrink (.nb-brand / .topbar-search had no min-width:0, and
   .nb-brand-text is white-space:nowrap) — so 721-820px overflows. Added
   as its own additive block, scoped to exactly this range, instead of
   widening the max-width:720px block below to 960px, because that block
   also carries unrelated KPI/kanban/wizard rules that must not change
   breakpoint. */
@media (min-width: 721px) and (max-width: 960px) {
    .mud-app-bar .mud-button { padding: 4px 8px !important; min-width: 0 !important; }
    .mud-app-bar .mud-button .mud-button-label { font-size: 12px; }
    .nb-brand,
    .topbar-search { min-width: 0; }
}

@media (max-width: 720px) {
    .topbar-search { display: none; }
    .mud-app-bar .mud-button { padding: 4px 8px !important; min-width: 0 !important; }
    .mud-app-bar .mud-button .mud-button-label { font-size: 12px; }

    /* Stack generic 2/3/4 grids on small screens. (The stat/KPI grids —
       .kpi-grid/.ref-stats/.b-stats/.inq-stats/.report-grid — moved to their own
       tiered rule below so they show 2 columns on tablet instead of collapsing to 1.) */
    .grid-2,
    .grid-3,
    .grid-4 {
        grid-template-columns: 1fr !important;
    }

    /* Pipeline + kanban scroll horizontally */
    .pipeline-summary,
    .kanban-board {
        grid-template-columns: repeat(7, minmax(180px, 1fr)) !important;
    }

    /* Tables: horizontal scroll */
    .mud-table-container,
    .mud-simple-table {
        overflow-x: auto;
    }

    /* Wizard steps wrap nicely */
    .wiz-steps { gap: 4px; }
    .wiz-step .label { font-size: 11px; }
    .wiz-step .line { width: 16px !important; margin: 0 4px !important; }
}

/* Stat / KPI grids — ONE rule for the whole family (Wallet .kpi-grid, Referral .ref-stats,
   Brokers .b-stats, Inquiries .inq-stats, Reports .report-grid) so every page steps the same
   way across the canonical tiers: 4 cols desktop (≥960) / 2 cols tablet (601–959) / 1 col
   mobile (≤600). The `.nb-main-content` prefix gives (0,2,0), which beats each page's own
   (0,1,0) base grid without !important — so page <style> base column counts still define
   desktop, and this only takes over below 960. Replaces the scattered per-page 900px rules
   and the old ≤720 forced-1col (which squeezed Brokers to 4 cols at 721–959 and stacked the
   rest a tier too early). */
@media (max-width: 959.98px) {
    .nb-main-content :is(.kpi-grid, .ref-stats, .b-stats, .inq-stats, .report-grid) {
        grid-template-columns: repeat(2, 1fr);
    }
}
@media (max-width: 600px) {
    .nb-main-content :is(.kpi-grid, .ref-stats, .b-stats, .inq-stats, .report-grid) {
        grid-template-columns: 1fr;
    }
}

/* iOS auto-zooms the page whenever a focused TEXT field's font-size is below 16px.
   Pin native + MudBlazor input text to 16px on phones so tapping any field
   (search, filters, login, forms) never triggers that jarring zoom-and-pan.

   NB-SELECT-SIZE (2026-09-06): a native <select> was deliberately DROPPED from this
   list. iOS does not zoom on <select> focus — it opens a wheel picker, not the
   keyboard — so a select never needed the 16px floor. Worse, this !important rule
   silently overrode `.nb-fsel { font-size: 12px }` in the max-width:480px block below
   (a textbook "my fix doesn't apply" case), forcing every filter dropdown to render a
   size larger than intended and reading as "chunky" on phones. MudBlazor's MudSelect
   stays in the list (.mud-select .mud-input-slot) because it focuses a real text input
   under the hood, which CAN zoom. */
@media (max-width: 600px) {
    input,
    textarea,
    .mud-input-root input,
    .mud-input-root textarea,
    .mud-input-slot,
    .mud-select .mud-input-slot {
        font-size: 16px !important;
    }
}

@media (max-width: 480px) {
    .mud-drawer { width: 88% !important; }
    .listing-grid { grid-template-columns: 1fr !important; }
    .hero-balances,
    .hero-secondary {
        flex-direction: column !important;
        gap: 12px !important;
    }
    .nb-fsel { max-width: 130px; font-size: 12px; padding: 7px 8px; }
}

/* NB-TYPOGRAPHY-SCALE / NB-PAGEHEAD mobile rules moved to controls.css (the
   responsive control system). Headings now consume the --fs-* tokens there,
   which redefine per tier in one place. Do not re-add heading sizing here. */

/* =====================================================================
   RESPONSIVE TABLES & TABS (2026-07-23) — mobile readability pass.
   Fixes reported on three UAT screenshots (Brokers compact table, CRM
   customers, Chat tabs): phone numbers / budgets wrapping onto 3–4 lines
   inside cramped cells, wide tables cram-wrapping instead of scrolling,
   and MudTabs labels truncating to "WhatsA…" on phones.
   ===================================================================== */

/* 1) Atomic values never wrap. A phone number or money range must stay on
      ONE line — when a table is squeezed it then overflows its (already
      overflow-x:auto) wrapper and scrolls, instead of breaking "+977 98
      4444 1010" across four lines. Opt a genuinely long free-text column
      back into wrapping with <td class="wrap">. */
@media (max-width: 1024px) {
    .nb-tbl td { white-space: nowrap; }
    .nb-tbl td.wrap, .nb-tbl th.wrap { white-space: normal; }
}
.mono, .num { white-space: nowrap; }

/* 2) Utility: keep one atomic value (a phone number, a short code) on a
      single line. Applied to the phone cells of the MudBlazor data tables
      (Customers) — deliberately NOT blanket-applied to every Mud cell, so
      key/value tables with long prose values (Profile info, Listing specs,
      notes) keep wrapping their text instead of forcing a wide scroll. */
.nb-nowrap { white-space: nowrap; }

/* 3) MudTabs: never truncate a tab label to "WhatsA…". Let each tab take
      its natural width and rely on MudBlazor's built-in scroll buttons to
      reach tabs that don't fit (Chat / CRM / Wallet / Approvals / Payout). */
.nb-main-content .mud-tabs .mud-tab {
    white-space: nowrap;
    min-width: unset;
    overflow: visible;
    text-overflow: clip;
}
@media (max-width: 600px) {
    .nb-main-content .mud-tabs .mud-tab { padding-left: 10px !important; padding-right: 10px !important; font-size: 12.5px; }
}

/* 4) .inq-row grid lists (CRM Inquiries tab, Inquiries page): hold the row
      at a min width and let the list scroll horizontally as one unit, so the
      columns stay aligned rather than collapsing into each other on a phone. */
@media (max-width: 720px) {
    .inq-list { overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .inq-list .inq-row { min-width: 820px; }
}

/* 5) REUSABLE CARD TRANSFORM for .nb-tbl on phones.
      Usage: <table class="nb-tbl nb-cards"> and tag the cells —
        • primary cell → class="cell-title"   → renders as the card heading
        • value cells  → data-label="Phone"   → renders "PHONE        value"
        • actions cell → class="cell-actions"  → kept, right-aligned, no label
      Any other <td> (spacer / favourite star / empty header) is hidden on
      phones. Above 600px the table renders exactly as before. */
@media (max-width: 600px) {
    /* The <table> itself must become a block too — leaving it display:table
       lets it size to the widest cell's content and overflow the card. */
    .nb-tbl.nb-cards { display: block; width: 100%; border-collapse: separate; }
    .nb-tbl.nb-cards thead { display: none; }
    .nb-tbl.nb-cards tbody,
    .nb-tbl.nb-cards tr { display: block; width: 100%; box-sizing: border-box; }
    .nb-tbl.nb-cards tr {
        border: 1px solid var(--nb-border);
        border-radius: var(--nb-radius-sm);
        box-shadow: var(--nb-shadow-sm);
        background: #fff;
        margin-bottom: 10px;
        padding: 6px 12px 10px;
    }
    .nb-tbl.nb-cards tbody tr:hover td { background: transparent; }
    /* hidden by default — only opted-in cells render */
    .nb-tbl.nb-cards td { display: none; }
    .nb-tbl.nb-cards td[data-label],
    .nb-tbl.nb-cards td.cell-title,
    .nb-tbl.nb-cards td.cell-actions {
        display: flex;
        align-items: center;
        gap: 14px;
        border: none;
        padding: 5px 0;
        white-space: normal;
    }
    .nb-tbl.nb-cards td[data-label] {
        justify-content: space-between;
        text-align: right;
        flex-wrap: wrap;
    }
    .nb-tbl.nb-cards td[data-label]::before {
        content: attr(data-label);
        flex: none;
        text-align: left;
        font-size: 10.5px;
        font-weight: 700;
        letter-spacing: .05em;
        text-transform: uppercase;
        color: var(--nb-fg-muted);
    }
    .nb-tbl.nb-cards td.cell-title {
        flex-direction: column;
        align-items: flex-start;
        gap: 2px;
        font-size: 15px;
        font-weight: 700;
        color: var(--nb-fg);
        padding: 2px 0 8px;
        border-bottom: 1px solid var(--nb-border-soft);
        margin-bottom: 4px;
    }
    .nb-tbl.nb-cards td.cell-title .t-title { font-size: 15px; font-weight: 700; }
    .nb-tbl.nb-cards td.cell-actions { justify-content: flex-end; }
    /* Empty-state row ("No X match these filters") must still show as a card. */
    .nb-tbl.nb-cards td.t-empty { display: block; text-align: center; }
    /* NB-REG-MOBILE: an expandable row's detail panel (a full form, e.g. the approvals
       placement picker) spans every column — render it as a plain block, full card width,
       rather than hiding it like an untagged cell. */
    .nb-tbl.nb-cards td.cell-block { display: block; padding: 6px 0; border: none; text-align: left; }
}

/* ===== Reduce motion ===== */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}

/* ===== Print-friendly tweaks ===== */
@media print {
    .mud-app-bar,
    .mud-drawer { display: none !important; }
    .mud-main-content { padding: 0 !important; }
}

/* ===== Blazor circuit reconnect overlay =====
   #components-reconnect-modal is toggled by the framework: it gets the class
   `components-reconnect-show`, `components-reconnect-hide`, `components-reconnect-failed`,
   or `components-reconnect-rejected` based on circuit state. Default style is
   hidden; the `-show`/`-failed`/`-rejected` classes flip it to flex. */
.nb-reconnect {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 100000;
    background: rgba(15, 23, 42, 0.55);
    align-items: center;
    justify-content: center;
    font-family: "DM Sans", system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
}
#components-reconnect-modal.components-reconnect-show,
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-rejected {
    display: flex;
}
.nb-reconnect-card {
    background: #ffffff;
    border-radius: 12px;
    padding: 28px 32px;
    min-width: 280px;
    box-shadow: 0 20px 60px rgba(15, 23, 42, 0.35);
    text-align: center;
}
.nb-reconnect-card > div { display: none; }
#components-reconnect-modal.components-reconnect-show .components-reconnect-show { display: block; }
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed { display: block; }
#components-reconnect-modal.components-reconnect-rejected .components-reconnect-rejected { display: block; }
.nb-reconnect-text {
    color: #0F172A;
    font-size: 15px;
    font-weight: 600;
    margin: 8px 0 12px;
}
.nb-reconnect-card button {
    background: #0F7A4A;
    color: #ffffff;
    border: none;
    border-radius: 8px;
    padding: 8px 18px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    margin: 0 4px;
}
.nb-reconnect-card button:hover { background: #0B5E39; }
.nb-reconnect-spinner {
    width: 32px;
    height: 32px;
    border: 3px solid #E5E7EB;
    border-top-color: #0F7A4A;
    border-radius: 50%;
    margin: 0 auto;
    animation: nb-reconnect-spin 0.9s linear infinite;
}
@keyframes nb-reconnect-spin {
    to { transform: rotate(360deg); }
}

/* =====================================================================
   Auth split-screen (login + register) — matches the client prototype:
   green gradient brand hero on the left, form panel on the right.
   Shared by Login.razor and Register.razor.
   ===================================================================== */
.nb-login { min-height: 100vh; display: grid; grid-template-columns: 1.05fr 1fr; background: #fff; }

.nb-login-hero {
    position: relative;
    background: linear-gradient(135deg, #0F7A4A 0%, #0B5E39 50%, #083F25 100%);
    color: #fff; padding: 48px 56px;
    display: flex; flex-direction: column; justify-content: space-between; overflow: hidden;
}
.nb-login-hero::before {
    content: ""; position: absolute; width: 520px; height: 520px; border-radius: 50%;
    background: radial-gradient(circle, rgba(255,255,255,.10), transparent 70%); right: -160px; top: -160px;
}
.nb-login-hero::after {
    content: ""; position: absolute; width: 380px; height: 380px; border-radius: 50%;
    background: radial-gradient(circle, rgba(198,146,42,.18), transparent 70%); left: -120px; bottom: -120px;
}
.nb-login-hero .brand-mini { display: flex; align-items: center; gap: 12px; position: relative; z-index: 2; }
.nb-login-hero .brand-mini .mark {
    width: 42px; height: 42px; border-radius: 12px; background: rgba(255,255,255,.15);
    display: grid; place-items: center; backdrop-filter: blur(8px); border: 1px solid rgba(255,255,255,.25);
}
.nb-login-hero .brand-mini .name { font-family: var(--font-serif); font-size: 22px; font-weight: 700; letter-spacing: -.01em; }
.nb-login-hero .brand-mini .name .a { color: #FFE598; }
.nb-login-hero .pitch { position: relative; z-index: 2; max-width: 460px; }
.nb-login-hero .pitch h2 { font-family: var(--font-serif); font-size: 38px; line-height: 1.15; font-weight: 700; margin: 0 0 16px; letter-spacing: -.02em; }
.nb-login-hero .pitch h2 em { font-style: normal; background: linear-gradient(135deg, #FFE598 0%, #C6922A 100%); -webkit-background-clip: text; background-clip: text; color: transparent; }
.nb-login-hero .pitch p { font-size: 15px; line-height: 1.55; opacity: .88; margin: 0 0 28px; }
.nb-login-hero .features { display: grid; gap: 14px; margin-top: 6px; }
.nb-login-hero .feature { display: flex; gap: 12px; align-items: flex-start; font-size: 13.5px; opacity: .95; }
.nb-login-hero .feature .ic {
    width: 28px; height: 28px; border-radius: 8px; background: rgba(255,255,255,.14);
    display: grid; place-items: center; flex: none; font-size: 14px; border: 1px solid rgba(255,255,255,.18);
}
.nb-login-hero .feature strong { display: block; margin-bottom: 2px; font-weight: 600; }
.nb-login-hero .feature .sub { opacity: .72; font-size: 12.5px; line-height: 1.45; }
.nb-login-hero .hero-footer { position: relative; z-index: 2; font-size: 12px; opacity: .7; display: flex; justify-content: space-between; gap: 12px; }

.nb-login-form-wrap { display: flex; align-items: center; justify-content: center; padding: 40px 24px; background: #fff; overflow-y: auto; }
.nb-login-card { width: 100%; max-width: 420px; }
.nb-login-card .login-brand { display: flex; align-items: center; gap: 10px; margin-bottom: 24px; }
.nb-login-card .login-brand .brand-mark { background: var(--nb-primary); width: 32px; height: 32px; border-radius: 10px; display: grid; place-items: center; }
.nb-login-card .login-brand .brand-name { font-family: var(--font-serif); font-size: 18px; font-weight: 700; }
.nb-login-card .login-brand .brand-name span { color: var(--nb-primary); }
.nb-login-card h1 { font-family: var(--font-serif); font-size: 30px; margin: 0 0 6px; letter-spacing: -.02em; font-weight: 700; }
.nb-login-card .sub { color: var(--nb-fg-muted); font-size: 14px; margin: 0 0 28px; line-height: 1.55; }

/* NB-AUTH-GOOGLE (2026-08-23): "Continue with Google" sits above the phone/email toggle. The button
   itself is drawn by Google's own library into .nb-google-slot — their branding rules require their
   button, so nothing here styles the control, only the space it lands in. The whole block is hidden
   (not removed) during the two-step code prompt: removing it would destroy the DOM node Google
   rendered into and the button would not come back when the user pressed "Start over". */
.nb-login-card .nb-google { margin-bottom: 18px; }
.nb-login-card .nb-google.is-hidden,
.nb-login-card .nb-google-or.is-hidden { display: none; }
.nb-login-card .nb-google-slot { display: flex; justify-content: center; min-height: 44px; }
.nb-login-card .nb-google-note { font-size: 12.5px; color: var(--nb-fg-muted); text-align: center; margin-top: 8px; }
.nb-login-card .nb-google-or { display: flex; align-items: center; gap: 12px; margin: 18px 0; color: var(--nb-fg-soft); font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.nb-login-card .nb-google-or::before,
.nb-login-card .nb-google-or::after { content: ""; flex: 1; height: 1px; background: var(--nb-border); }

.nb-login-card .login-tabs { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; background: var(--nb-bg); padding: 4px; border-radius: 10px; margin-bottom: 18px; }
.nb-login-card .login-tabs button { border: none; background: transparent; padding: 9px 10px; border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 13px; color: var(--nb-fg-muted); transition: all .15s; }
.nb-login-card .login-tabs button.active { background: #fff; color: var(--nb-fg); box-shadow: 0 1px 3px rgba(0,0,0,.08); }

.nb-login-card .field-label { display: block; font-size: 11px; font-weight: 700; color: var(--nb-fg-muted); text-transform: uppercase; letter-spacing: .06em; margin: 0 0 6px; }
.nb-login-card .input-wrap { position: relative; margin-bottom: 14px; }
.nb-login-card .nb-input { width: 100%; padding: 12px 14px; border: 1.5px solid var(--nb-border); border-radius: 10px; font-size: 14px; background: #fff; transition: border-color .15s, box-shadow .15s; }
.nb-login-card .nb-input:focus { outline: none; border-color: var(--nb-primary); box-shadow: 0 0 0 4px var(--nb-primary-bg); }
.nb-login-card .pw-with-toggle { padding-right: 64px; }
.nb-login-card .pw-toggle { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); background: transparent; border: none; color: var(--nb-fg-muted); cursor: pointer; font-size: 11px; font-weight: 700; padding: 6px 10px; letter-spacing: .04em; }
.nb-login-card .pw-toggle:hover { color: var(--nb-primary); }

.nb-login-card .util-row { display: flex; align-items: center; justify-content: flex-end; font-size: 12.5px; margin: 4px 0 18px; gap: 10px; flex-wrap: wrap; }
.nb-login-card .util-row label { display: flex; gap: 8px; align-items: center; color: var(--nb-fg-muted); cursor: pointer; user-select: none; }
.nb-login-card .util-row label input { accent-color: var(--nb-primary); }
.nb-login-card .util-row .muted { color: var(--nb-fg-soft); }

.nb-login-card .auth-submit { width: 100%; display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 13px 16px; font-size: 14px; font-weight: 700; border-radius: 10px; border: 1px solid var(--nb-primary); background: var(--nb-primary); color: #fff; cursor: pointer; transition: background .15s, border-color .15s; }
.nb-login-card .auth-submit:hover { background: var(--nb-primary-dark); border-color: var(--nb-primary-dark); }
.nb-login-card .auth-submit:disabled { opacity: .55; cursor: not-allowed; }

.nb-login-card .login-foot { text-align: center; font-size: 13px; color: var(--nb-fg-muted); margin-top: 22px; }
.nb-login-card .login-foot a { color: var(--nb-primary); font-weight: 600; }

/* NB-MFA-LOGIN: the two-step (OTP) step of the sign-in form. */
.nb-login-card .nb-otp-note { background: var(--nb-primary-bg); border: 1px solid var(--nb-primary); border-radius: 10px; padding: 12px 14px; font-size: 13px; line-height: 1.5; color: var(--nb-fg); margin: 0 0 18px; }
.nb-login-card .nb-otp-input { font-family: var(--font-mono, monospace); font-size: 22px; font-weight: 700; letter-spacing: .35em; text-align: center; }

/* Auth split-screen collapses to a single centered form on tablet & phone. Normalized to the
   canonical desktop tier (was 900) so the two-column hero shows only at true desktop widths. */
@media (max-width: 959.98px) {
    .nb-login { grid-template-columns: 1fr; background: radial-gradient(1200px 600px at 50% -100px, #DFF1E4 0%, var(--nb-bg) 60%); }
    .nb-login-hero { display: none; }
    .nb-login-form-wrap { padding: 24px; background: transparent; }
    .nb-login-card { background: #fff; border-radius: 16px; padding: 28px 24px; border: 1px solid var(--nb-border); box-shadow: var(--nb-shadow-md); }
}

/* NB-PLACE-SHOW: the signed-in member's province · municipality · ward (PlacementLine.razor).
   Lives here rather than in a style block on the component so that "no placement" renders
   literally nothing — a style tag is still markup, and the rule the client set is silence.

   Wrapping is the mobile requirement, not a nicety: brokers work from phones, and
   "Sudurpashchim · Godawari Municipality · Kailali · Ward 12" is far wider than a 320px screen.
   flex-wrap plus overflow-wrap keeps it stacking downward instead of pushing the page sideways.
   The separator is a ::before on each part after the first, so it can never orphan onto a line of
   its own, and being generated content it stays decorative rather than being read out as a word. */
.nb-place {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    min-width: 0;
    font-size: 12.5px;
    line-height: 1.55;
    color: var(--nb-fg-muted);
    margin-top: 2px;
}
.nb-place-part { overflow-wrap: anywhere; }
.nb-place-part + .nb-place-part::before {
    content: "\00B7";
    color: var(--nb-fg-soft);
    margin: 0 7px 0 5px;
}

/* NB-VIP-SET: the inline favourite / VIP toggles (CustomerTagToggles.razor), used on the CRM
   tables, both kanban boards and the customers grid.

   Two things this has to get right, both of them mobile ones. First the tap target: MudBlazor's
   Size.Small icon button is about 30px, and these sit inside table rows and cards whose own tap
   navigates — a near miss opens the customer instead of tagging them, which is the exact failure
   the map had. 44px is the floor, applied here rather than by switching to a larger button so the
   icon stays visually small inside a dense row.

   Second, the "by budget" chip. It is visible text, not a tooltip, because a phone cannot hover
   and this label is the whole explanation of why unticking VIP on a big-budget customer leaves
   them VIP. It must never be the thing that makes a row scroll sideways, hence the wrap. */
.nb-tag-toggles {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    flex-wrap: wrap;
}
.nb-tag-toggles .nb-tag-toggle {
    /* NB-MOBILE-MODERATE (2026-09-07): 44→40. This page-specific rule's specificity (0,2,0) beat
       the global coarse floor, so it was the one control still measuring 44 after the app-wide
       relax — the documented holdout from the proof run. */
    min-width: 40px;
    min-height: 40px;
}
.nb-vip-auto {
    display: inline-block;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .02em;
    line-height: 1.4;
    padding: 2px 7px;
    border-radius: 999px;
    white-space: nowrap;
    color: #1D4ED8;
    background: #EFF6FF;
    border: 1px solid #BFDBFE;
}

/* NB-VIP-SET: the same explanation on a create form. Sits under the VIP checkbox and only when
   the budget already crosses the line, so it reads as an answer to what the broker just typed. */
.nb-vip-hint {
    display: block;
    font-size: 11.5px;
    line-height: 1.5;
    color: #1D4ED8;
    background: #EFF6FF;
    border: 1px solid #BFDBFE;
    border-radius: 8px;
    padding: 7px 10px;
    margin-top: 6px;
}

/* NB-TOUCH-44 (2026-08-23): third-party controls that ship below the 44px touch floor.

   Found by measuring the real page at a 320px viewport rather than by reading markup — which is
   why it was missed: none of this is our markup. MudBlazor renders numeric spinners at 24x28 and
   Leaflet its zoom controls at 30x30, and on Add Listing the spinners land on PRICE and AREA, the
   two fields the quick-add screen exists to capture. Two 24px arrows stacked against each other,
   on the field that decides what a property is advertised at, is a mis-tap that costs real money.

   Coarse pointers only. On a mouse these sizes are fine and enlarging them would make every form
   look clumsy for no gain — the floor exists because a fingertip is ~9mm, not because small
   buttons are wrong. `pointer: coarse` is the honest test: it asks what the user is pointing WITH,
   rather than inferring it from viewport width and getting touchscreen laptops wrong. */
@media (pointer: coarse) {
    /* The numeric spinners are HIDDEN on touch rather than enlarged, and that is the whole
       decision. They are stacked vertically inside the field — two 28px buttons making up its
       56px height — so raising each to the 44px floor would produce an 88px control and break
       the field it lives in. Enlarging was the obvious move and it is the wrong one.

       Hiding costs nothing real: nobody sets a price of Rs 1,45,00,000 by tapping an arrow that
       moves in steps of one. The numeric keyboard IS the input on a phone, and MudBlazor keeps
       the field fully usable without the buttons. Desktop, where the arrows are both reachable
       and occasionally handy, is untouched. */
    .mud-input-control.mud-input-number-control .mud-input-numeric-spin {
        display: none;
    }

    /* MudBlazor's icon buttons and Size.Small buttons are the two controls that turn up
       under-sized again and again: they are what dense list rows use for their actions, which
       measured 22 sub-44px targets on /listings and 19 on /customers at a 320px viewport.

       Only the TARGET grows — icon and label sizing are untouched, so rows stay as tight as they
       look on a desktop. Coarse pointers only, for the same reason as everything else in this
       block: a fingertip is ~9mm whatever the screen. */
    .mud-icon-button,
    .mud-button-root.mud-button-filled-size-small,
    .mud-button-root.mud-button-outlined-size-small,
    .mud-button-root.mud-button-text-size-small {
        /* NB-MOBILE-MODERATE (2026-09-07): relaxed 44→40 on the 'controls too big on mobile'
           report. 40 clears WCAG 2.5.8 AA (24) with margin and reads far less chunky. Leaflet
           zoom stays 44 below (its own accessibility contract + TouchTargetFloorTests). */
        min-height: 40px;
        min-width: 40px;
    }
    /* NB-ICONBTN-COMPACT (2026-09-07): min-height alone can't shrink a MudIconButton — MudBlazor
       sizes it by PADDING (~48px), so on a phone every action icon (kebab menus, chat actions,
       the bell) stayed 48. Trim the padding so icon buttons actually land at ~40 on touch. */
    .mud-icon-button { padding: 8px; }

    /* Leaflet writes width/height inline on these, so the floor needs the same specificity path
       it uses. Kept to the anchors themselves so the control bar keeps its own layout.
       NB-MOBILE-MODERATE (2026-09-07): the owner flagged the zoom control as too big on a phone.
       Relaxed 44→34 — compact, but still well above WCAG 2.5.8 AA (24px) and above Leaflet's own
       30px default. Coarse-scoped, so a mouse (~26px Leaflet default) is untouched. */
    .leaflet-touch .leaflet-bar a,
    .leaflet-control-zoom a {
        min-width: 30px;
        min-height: 30px;
        line-height: 30px;
    }

    /* NB-TOUCH-44-OWN (2026-08-27): the block above was written against MUDBLAZOR's class names,
       so it silently skipped every control this project styles itself. Measured on production at
       375px with `pointer: coarse` confirmed active: 12 kebabs at 28x28 on /listings, filter chips
       at 22px on /crm and /todo, .nb-btn at 37px, .nb-seg toggles at 31px.
       The floor was never a MudBlazor policy — it is a fingertip policy. */
    .nb-btn,
    .nb-seg button,
    .nb-brand.nb-topbar-brand {
        /* NB-MOBILE-MODERATE (2026-09-07): relaxed 44→40 with the MudBlazor floor above. */
        min-height: 40px;
    }

    /* The chips and toggles are laid out in horizontal rows, so widening them costs nothing and
       stops two filters sitting inside one thumb. */
    .nb-seg button {
        min-width: 44px;
    }

    /* The filter-chip touch floor moved to controls.css (--chip-touch-h). It is a control-sizing
       decision, so it lives with the other control tokens. Was 44x44; rebalanced to 32px min-height
       + 24px min-width there after the "too big/chunky" report (still clears WCAG 2.5.8 AA 24px).
       Touch only — desktop/mouse keeps the compact 22px base. Do not re-add chip sizing here. */

    /* Icon-only toolbar actions collapse to their icon at phone widths. Height is already fine on
       these; only width falls short. NOTE: this rule alone did NOT fix "New Listing" — that button
       carries its own explicit min-width floor (in the NB-MAINLAYOUT-CHROME block at the foot of
       this file, held at the 44px touch minimum), because an unflagged rule from here loses to that
       !important whatever the specificity. Kept for the other toolbar actions, which have no such
       override. */
    .mud-toolbar .mud-button-root {
        min-width: 44px;
    }

    /* The row kebab is the one target where the obvious fix is wrong. It sits in a dense table, so
       a 44px HEIGHT would either inflate every row or, worse, spill the hit area into the rows
       above and below — turning a small-target problem into a wrong-row problem, on a menu whose
       entries include destructive actions. Width is free: the control sits at the row's right edge
       with empty space beside it, and widening moves it no closer to its vertical neighbours.
       Raising the height needs the ROW to grow first, which is a list-density decision, not a CSS
       one. Left for the owner; recorded in the QA notes. */
    .nb-iconbtn {
        min-width: 44px;
    }
}

/* ============================================================================
   NB-MAINLAYOUT-CHROME (moved from MainLayout's <style> during the scoped-CSS
   migration). These target MudBlazor shell internals (.nb-topbar on MudAppBar,
   .nb-main-content on MudMainContent, .nb-drawer on MudDrawer, the
   .nb-newlisting-btn MudButton) or the PORTALED notification popover (.nb-notif-*
   — a MudPopover renders at the document root, outside MainLayout), none of which
   has a plain-HTML ancestor for Blazor ::deep in the all-Mud shell, so they live
   in this global layer. Appended at the end so they keep the same cascade
   position they had as a trailing <style> (after app.css's own rules).
   MainLayout's own plain elements (brand, search box + dropdown, sync pill,
   bottom tab bar) are scoped in MainLayout.razor.css.
   ============================================================================ */

/* Single source of truth for the fixed top bar height (the content offset below
   references the SAME variable, so header and content can never drift apart). */
:root { --nb-topbar-h: 64px; }

.nb-topbar {
    background: #FFFFFF !important;
    color: #0F172A !important;
    border-bottom: 1px solid #E5E7EB;
    /* iOS notch: pad past the status-bar cut-out and inset edges in landscape. */
    padding-left: env(safe-area-inset-left, 0px) !important;
    padding-right: env(safe-area-inset-right, 0px) !important;
    padding-top: env(safe-area-inset-top, 0px) !important;
    height: calc(var(--nb-topbar-h) + env(safe-area-inset-top, 0px)) !important;
    min-height: calc(var(--nb-topbar-h) + env(safe-area-inset-top, 0px)) !important;
    box-sizing: border-box;
}
.nb-topbar .mud-toolbar {
    min-height: var(--nb-topbar-h) !important;
    height: var(--nb-topbar-h) !important;
}
@media (min-width: 960px) {
    .nb-topbar {
        left: 260px !important;
        width: calc(100% - 260px) !important;
    }
    .nb-drawer,
    .nb-drawer .mud-drawer-content {
        top: 0 !important;
        height: 100vh !important;
        max-height: 100vh !important;
    }
}
.nb-main-content {
    padding-top: calc(var(--nb-topbar-h) + env(safe-area-inset-top, 0px)) !important;
    padding-right: calc(16px + env(safe-area-inset-right, 0px)) !important;
    padding-bottom: 16px !important;
    padding-left: calc(16px + env(safe-area-inset-left, 0px)) !important;
}
@media (min-width: 960px) {
    /* Desktop gutter widened to 24px, and the topbar brand + hamburger hide (the
       persistent rail already shows the brand and never collapses). */
    .nb-main-content {
        padding-left: calc(24px + env(safe-area-inset-left, 0px)) !important;
        padding-right: calc(24px + env(safe-area-inset-right, 0px)) !important;
    }
    .nb-topbar-brand,
    .nb-hamburger { display: none !important; }
}
@media (max-width: 959.98px) {
    /* Reserve space for the bottom tab bar; the drawer is a temporary overlay
       here, so main content must never carry a left margin/padding for it. */
    .nb-main-content {
        padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px)) !important;
        padding-left: calc(16px + env(safe-area-inset-left, 0px)) !important;
        margin-left: 0 !important;
    }
    /* Even if MudBlazor leaves the closed temporary drawer in the DOM, push it
       fully off-screen so the green gradient can't bleed past the left edge. */
    .nb-drawer:not(.mud-drawer--open) {
        transform: translateX(-105%) !important;
        visibility: hidden !important;
        pointer-events: none !important;
    }
    /* Raise the OPEN temporary drawer above its own MudBlazor backdrop (z-index
       1301) so nav-link taps reach the links instead of being eaten by the
       backdrop. Docked desktop mode has no backdrop and is untouched. */
    .nb-drawer.mud-drawer--open {
        z-index: 1302 !important;
    }
}
@media (max-width: 599.98px) {
    :root { --nb-topbar-h: 56px; }       /* standard mobile app-bar height */
    /* NB-TOUCH-44-OWN: the New-Listing button is a PRIMARY action; hold it at the
       44px touch floor (icon-only, label hidden by MainLayout.razor.css). */
    .nb-newlisting-btn { min-width: 44px !important; padding: 6px !important; }
    .nb-newlisting-btn .mud-button-start-icon { margin: 0 !important; }
    /* NB-BELL-COMPACT (2026-09-07): the notification bell shipped at MudBlazor's default 48px and
       read big on a phone — trim its padding to ~40px on phones (desktop keeps 48). */
    .nb-topbar .mud-badge-root .mud-icon-button { padding: 8px !important; }
    /* NB-INPUT-COMPACT (2026-09-07): MudBlazor outlined inputs are 56px on a phone (18.5px slot
       padding), so a form reads as a wall of tall boxes. Trim to ~45px on phones — the label
       notches onto the outline so nothing overlaps. Desktop/tablet keep 56. */
    .nb-main-content .mud-input-outlined .mud-input-slot {
        padding-top: 13px !important;
        padding-bottom: 13px !important;
    }
}

/* NB-PAYOUT-MOBILE (2026-09-08): the Super-Admin payout ladder is a 4-column table wider than
   a phone, so its (already overflow-x:auto) container scrolls. Give the table a real min-width
   so the columns keep their natural size instead of collapsing — the collapse squeezed the
   percent cell until MudBlazor's dense outlined input (flex:0 1 auto + 14px left padding) shrank
   to ~5px of content and clipped the value ("10 %" showed as "1 %"). Then let that input fill its
   cell and give it vertical room so the digits are no longer cut top and bottom. Phones only;
   desktop/tablet keep the original layout. */
@media (max-width: 600px) {
    .nb-payout-table table { min-width: 460px !important; }
    .nb-payout-pct.mud-input-control { width: 100% !important; max-width: 118px !important; }
    .nb-payout-pct .mud-input-control-input-container { width: 100% !important; }
    .nb-payout-pct .mud-input { width: 100% !important; max-width: none !important; }
    .nb-payout-pct input.mud-input-slot {
        flex: 1 1 auto !important;
        padding-left: 8px !important;
        font-size: 15px !important;
        line-height: 1.7 !important;
        text-align: left !important;
    }
}

/* ===== NB-NOTIF-CENTRE: bell dropdown (a PORTALED MudPopover — rendered at the
   document root, so these must stay global, not scoped to MainLayout). ===== */
.nb-notif-popover { max-width: min(360px, calc(100vw - 24px)); }
.nb-notif-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 14px 8px;
}
.nb-notif-head-title { font-weight: 700; font-size: 14px; color: #0F172A; }
.nb-notif-allread {
    background: transparent;
    border: none;
    color: #0F7A4A;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    padding: 2px 4px;
}
.nb-notif-allread:hover { text-decoration: underline; }
.nb-notif-empty {
    padding: 24px 16px;
    text-align: center;
    font-size: 13px;
    color: #64748B;
}
.nb-notif-list { max-height: 420px; overflow-y: auto; min-width: 300px; }
.nb-notif-row {
    display: flex;
    flex-direction: column;
    gap: 2px;
    width: 100%;
    text-align: left;
    background: transparent;
    border: none;
    border-bottom: 1px solid #F1F5F9;
    padding: 10px 14px;
    cursor: pointer;
}
.nb-notif-row:hover { background: #ECF7EF; }
.nb-notif-row.is-unread { background: #F5FBF7; }
.nb-notif-row.is-unread .nb-notif-row-title::before {
    content: "";
    display: inline-block;
    width: 7px;
    height: 7px;
    margin-right: 7px;
    border-radius: 50%;
    background: #0F7A4A;
    vertical-align: middle;
}
.nb-notif-row-title { font-size: 13px; font-weight: 600; color: #0F172A; overflow-wrap: break-word; }
.nb-notif-row-body {
    font-size: 12px;
    color: #475569;
    white-space: normal;
    line-height: 1.35;
    overflow-wrap: break-word;
}
.nb-notif-row-time { font-size: 11px; color: #94A3B8; }
