/*
 * app.css — layout + components for BaseSource.WebAppBill.
 * Consumes ONLY the variables in tokens.css. Vanilla CSS, no framework.
 */

/* ===================== Reset / base ===================== */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
    margin: 0;
    font-family: 'Be Vietnam Pro', 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    font-size: var(--fs-body);
    line-height: 1.55;
    color: var(--text);
    background: var(--page-bg);
}
a { color: var(--primary); text-decoration: none; }
a:hover { text-decoration: underline; }
h1, h2, h3, h4 { margin: 0 0 8px; font-weight: 700; color: var(--text); }
img, svg { vertical-align: middle; }
button { font-family: inherit; }

/* Visible keyboard focus everywhere. */
:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 4px; }

/* Global [hidden] reset — components that set an explicit display (.bm-btn, .bm-modal-footer, grids)
   otherwise beat the UA [hidden] rule and leak hidden elements on pages without a local guard. This
   makes the attribute authoritative everywhere (the tx-detail drawer, KPI sections, 2FA modal, etc.).
   .bm-modal:not([hidden]){display:flex} still wins when the attribute is removed to open a modal. */
[hidden] { display: none !important; }

.bm-icon { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.bm-icon-sm { width: 16px; height: 16px; }

/* ===================== App shell ===================== */
.bm-app { min-height: 100vh; }

.bm-sidebar {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    width: var(--sidebar-width);
    background: var(--sidebar-bg);
    color: var(--sidebar-text);
    border-right: 1px solid var(--sidebar-border);
    display: flex;
    flex-direction: column;
    z-index: 40;
    transition: transform 0.2s ease;
}
.bm-sidebar-brand {
    height: var(--topbar-height);
    display: flex;
    align-items: center;
    padding: 0 16px;
    border-bottom: 1px solid var(--sidebar-border);
}
.bm-brand-link { display: flex; align-items: center; gap: 10px; color: var(--sidebar-text); font-weight: 700; }
.bm-brand-link:hover { text-decoration: none; }
.bm-brand-logo { width: 28px; height: 28px; }
.bm-brand-text { font-size: var(--fs-body); }

.bm-sidebar-nav { flex: 1; overflow-y: auto; padding: 12px 8px; }
.bm-nav-list, .bm-nav-sublist { list-style: none; margin: 0; padding: 0; }

.bm-nav-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    min-height: var(--touch);
    padding: 8px 12px;
    margin: 2px 0;
    border: none;
    background: transparent;
    color: var(--sidebar-text);
    font-size: var(--fs-sub);
    text-align: left;
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.bm-nav-item:hover { background: var(--sidebar-active); text-decoration: none; color: var(--sidebar-text); }
.bm-nav-item .bm-nav-icon { width: 20px; height: 20px; flex: 0 0 20px; color: var(--sidebar-icon); fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.bm-nav-label { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bm-nav-item.is-active { background: var(--sidebar-active); color: var(--sidebar-active-text); font-weight: 600; }
.bm-nav-item.is-active .bm-nav-icon { color: var(--sidebar-icon); }

.bm-nav-item.is-disabled { opacity: 0.5; cursor: not-allowed; }
.bm-nav-soon {
    font-size: var(--fs-label);
    font-weight: 600;
    color: var(--sidebar-text-muted);
    background: rgba(148, 163, 184, 0.16);
    padding: 1px 6px;
    border-radius: 999px;
}

.bm-nav-caret { width: 16px; height: 16px; margin-left: auto; color: var(--sidebar-text-muted); transition: transform 0.15s ease; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.bm-nav-sublist { max-height: 0; overflow: hidden; transition: max-height 0.2s ease; padding-left: 14px; }
.bm-nav-group.is-open > .bm-nav-group-toggle .bm-nav-caret { transform: rotate(180deg); }
.bm-nav-group.is-open > .bm-nav-sublist { max-height: 600px; }
.bm-nav-subitem { font-size: var(--fs-sub); }

.bm-sidebar-backdrop {
    position: fixed;
    inset: 0;
    background: var(--overlay);
    z-index: 39;
    border: none;
}

.bm-shell {
    margin-left: var(--sidebar-width);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

/* ===================== Topbar ===================== */
.bm-topbar {
    position: sticky;
    top: 0;
    height: var(--topbar-height);
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 16px;
    background: var(--topbar-bg);
    border-bottom: 1px solid var(--border);
    z-index: 30;
}
.bm-topbar-spacer { flex: 1; }
.bm-topbar-actions { display: flex; align-items: center; gap: 8px; }

.bm-icon-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--touch);
    height: var(--touch);
    border: none;
    background: transparent;
    color: var(--text);
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.bm-icon-btn:hover { background: var(--grid-line-soft); }
.bm-hamburger { display: none; }

.bm-badge-count {
    position: absolute;
    top: 6px; right: 6px;
    min-width: 16px; height: 16px;
    padding: 0 4px;
    font-size: var(--fs-label);
    font-weight: 700;
    line-height: 16px;
    color: #FFFFFF;
    background: var(--danger);
    border-radius: 999px;
    text-align: center;
}

/* ===================== Dropdowns ===================== */
.bm-dropdown { position: relative; }
.bm-dropdown-menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 220px;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 6px;
    display: none;
    z-index: 50;
}
.bm-dropdown.is-open > .bm-dropdown-menu { display: block; }
.bm-dropdown-menu-wide { min-width: 320px; }
.bm-dropdown-menu-right { right: 0; }

.bm-dropdown-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    min-height: var(--touch);
    padding: 8px 10px;
    border: none;
    background: transparent;
    color: var(--text);
    font-size: var(--fs-sub);
    text-align: left;
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.bm-dropdown-item:hover { background: var(--grid-line-soft); text-decoration: none; color: var(--text); }
.bm-dropdown-item-danger { color: var(--danger); }
.bm-dropdown-item-danger:hover { background: #FEF2F2; }
.bm-dropdown-divider { height: 1px; background: var(--border); margin: 6px 4px; }
.bm-logout-form { margin: 0; }

.bm-account-btn {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: var(--touch);
    padding: 0 8px;
    border: none;
    background: transparent;
    color: var(--text);
    cursor: pointer;
    border-radius: var(--radius-sm);
}
.bm-account-btn:hover { background: var(--grid-line-soft); }
.bm-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px; height: 32px;
    background: var(--primary);
    color: #FFFFFF;
    font-weight: 700;
    border-radius: 999px;
}
.bm-account-name { font-size: var(--fs-sub); font-weight: 600; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.bm-dropdown-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 10px;
    font-weight: 700;
    font-size: var(--fs-sub);
    border-bottom: 1px solid var(--border);
}
.bm-dropdown-scroll { max-height: 360px; overflow-y: auto; padding: 4px; }
.bm-dropdown-empty { padding: 16px 10px; text-align: center; color: var(--text-muted); font-size: var(--fs-sub); }

.bm-notif-item {
    display: block;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    color: var(--text);
}
.bm-notif-item:hover { background: var(--grid-line-soft); text-decoration: none; }
.bm-notif-item-unread { background: #EFF6FF; }
.bm-notif-title { font-weight: 600; font-size: var(--fs-sub); }
.bm-notif-body { font-size: var(--fs-sub); color: var(--text-muted); }

/* ===================== Content / page ===================== */
.bm-content { flex: 1; padding: 24px; }
.bm-page { max-width: 1280px; margin: 0 auto; }
.bm-page-header { margin-bottom: 16px; }
.bm-page-title { font-size: calc(var(--fs-title) + 2px); }
.bm-page-subtitle { color: var(--text-muted); margin: 0; }

.bm-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    padding: 20px;
}
.bm-help { font-size: var(--fs-sub); color: var(--text-muted); margin: 6px 0 0; }

/* ===================== Buttons ===================== */
.bm-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: var(--touch);
    padding: 10px 16px;
    font-size: var(--fs-body);
    font-weight: 600;
    border-radius: var(--radius-sm);
    border: 1px solid transparent;
    cursor: pointer;
    background: transparent;
    color: var(--text);
}
.bm-btn:hover { text-decoration: none; }
.bm-btn:disabled { opacity: 0.6; cursor: not-allowed; }
.bm-btn-block { width: 100%; }
.bm-btn-sm { padding: 6px 10px; font-size: var(--fs-sub); min-height: var(--touch); }
/* Extra-small action button (drawer row actions, dense toolbars). Global source of truth — pages must NOT
   redefine this locally; every page loads app.css.

   The full --touch target, not the 30px (later 36px) this used to be. The buttons wearing this class are
   the ones pressed most often in a working day — "Thu", "In lại", "Hoàn lại", "Xem" — by collectors who
   are frequently older, on a phone, outdoors, in a hurry. */
.bm-btn-xs { padding: 5px 10px; font-size: var(--fs-sub); min-height: var(--touch); }

.bm-btn-primary { background: var(--primary); color: var(--primary-contrast); border-color: var(--primary); }
.bm-btn-primary:hover { background: var(--primary-hover); border-color: var(--primary-hover); color: #FFFFFF; }

.bm-btn-ghost { background: transparent; color: var(--text); border-color: var(--border); }
.bm-btn-ghost:hover { background: var(--grid-line-soft); color: var(--text); }

.bm-btn-outline { background: transparent; color: var(--primary); border-color: var(--primary); }
.bm-btn-outline:hover { background: #EFF6FF; }

.bm-btn-danger { background: var(--danger); color: #FFFFFF; border-color: var(--danger); }
.bm-btn-danger:hover { background: #B91C1C; color: #FFFFFF; }

.bm-btn-google { background: #FFFFFF; color: var(--text); border-color: var(--border); }
.bm-btn-google:hover { background: var(--grid-line-soft); color: var(--text); }
.bm-google-icon { flex: 0 0 18px; }

/* Tint buttons: soft semantic fill + strong text/icon (icon inherits currentColor), so copy/export/action
   buttons read at a glance without a heavy solid fill. Palette matches .badge-* / .bm-alert-* (both themes
   are light, so the fixed hexes stay legible on navy and sheet). Consumed by P2 (copy) + P3 (toolbar). */
.bm-btn-tint-info    { background: #DBEAFE; color: #1E40AF; border-color: #BFDBFE; }
.bm-btn-tint-info:hover    { background: #BFDBFE; color: #1E40AF; }
.bm-btn-tint-warn    { background: #FEF3C7; color: #92400E; border-color: #FDE68A; }
.bm-btn-tint-warn:hover    { background: #FDE68A; color: #92400E; }
.bm-btn-tint-success { background: #DCFCE7; color: #166534; border-color: #BBF7D0; }
.bm-btn-tint-success:hover { background: #BBF7D0; color: #166534; }
.bm-btn-tint-danger  { background: #FEE2E2; color: #991B1B; border-color: #FECACA; }
.bm-btn-tint-danger:hover  { background: #FECACA; color: #991B1B; }

/* Loading spinner utility. */
.bm-spinner {
    width: 16px; height: 16px;
    border: 2px solid rgba(255, 255, 255, 0.4);
    border-top-color: #FFFFFF;
    border-radius: 50%;
    animation: bm-spin 0.7s linear infinite;
}
@keyframes bm-spin { to { transform: rotate(360deg); } }

/* ===================== Forms ===================== */
.bm-field { margin-bottom: 16px; }
.bm-label { display: block; margin-bottom: 6px; font-size: var(--fs-sub); font-weight: 600; }
.bm-input, .bm-select, .bm-textarea {
    display: block;
    width: 100%;
    min-height: var(--touch);
    padding: 10px 12px;
    /* 16px minimum prevents iOS auto-zoom on focus. */
    font-size: var(--fs-body);
    color: var(--text);
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}
.bm-input:focus, .bm-select:focus, .bm-textarea:focus { border-color: var(--primary); outline: none; box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15); }
.bm-input.is-invalid { border-color: var(--danger); }
.bm-field-error, .field-validation-error { display: block; margin-top: 6px; font-size: var(--fs-sub); color: var(--danger); }
/* Quick-pick chips under a field (a row of .bm-btn-outline preset buttons). Was duplicated in
   pages/transactions.css with two different margin-top values (6px / 8px); 8px is the one that was
   actually winning the cascade (later rule, equal specificity) — kept here to stay visually identical. */
.bm-quick-chips { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }

.bm-alert { padding: 10px 14px; border-radius: var(--radius-sm); font-size: var(--fs-sub); margin-bottom: 16px; }
.bm-alert:empty { display: none; }
.bm-alert-danger { background: #FEE2E2; color: #991B1B; border: 1px solid #FECACA; }
.bm-alert-success { background: #DCFCE7; color: #166534; border: 1px solid #BBF7D0; }
.bm-alert-warning { background: #FEF3C7; color: #92400E; border: 1px solid #FDE68A; }
/* asp-validation-summary renders a <ul>; hide bullets, keep spacing. */
.bm-alert ul { margin: 0; padding-left: 18px; }
/* Hide the summary box entirely when the form is valid (it still renders an empty <ul>). */
.validation-summary-valid { display: none; }
.field-validation-valid { display: none; }

/* ===================== Auth pages ===================== */
.bm-auth { background: var(--page-bg); }
.bm-auth-wrap {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px 16px;
}
.bm-auth-card {
    width: 100%;
    max-width: 420px;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow);
    padding: 28px 24px;
}
.bm-auth-brand { text-align: center; margin-bottom: 20px; }
.bm-auth-logo { width: 48px; height: 48px; margin-bottom: 8px; }
.bm-auth-title { font-size: calc(var(--fs-title) + 2px); margin-bottom: 4px; }
.bm-auth-subtitle { color: var(--text-muted); margin: 0; font-size: var(--fs-sub); }
.bm-auth-form { margin: 0; }
.bm-auth-divider { display: flex; align-items: center; text-align: center; color: var(--text-muted); margin: 16px 0; font-size: var(--fs-sub); }
.bm-auth-divider::before, .bm-auth-divider::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.bm-auth-divider span { padding: 0 12px; }
.bm-auth-footer { margin-top: 20px; text-align: center; font-size: var(--fs-sub); color: var(--text-muted); }
.bm-auth-footer p { margin: 6px 0; }

.bm-noaccess-text { color: var(--text); line-height: 1.7; }
.bm-noaccess-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 20px; }

/* ===================== Modal (settings + shared dialogs) ===================== */
.bm-modal {
    position: fixed;
    inset: 0;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 16px;
    z-index: 1050;
}
.bm-modal:not([hidden]) { display: flex; }
.bm-modal-backdrop { position: absolute; inset: 0; background: var(--overlay); border: none; }
.bm-modal-dialog {
    position: relative;
    width: 100%;
    max-width: 560px;
    max-height: calc(100vh - 32px);
    display: flex;
    flex-direction: column;
    background: var(--card-bg);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
}
.bm-modal-sm { max-width: 440px; }
/* Form-wrapped modals: a <form> wraps the body+footer, so it must be the flex column the dialog expects.
   Without this the form sizes to its content and the footer clips below the viewport (e.g. the invoice
   modal once several mốc rows are added). One rule fixes every form-wrapped modal; markup unchanged. */
.bm-modal-dialog > form { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; overflow: hidden; }
.bm-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 20px;
    border-bottom: 1px solid var(--border);
}
.bm-modal-title { font-size: calc(var(--fs-body) + 1px); margin: 0; }
.bm-modal-body { padding: 20px; overflow-y: auto; flex: 1 1 auto; min-height: 0; }
.bm-modal-footer {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
    padding: 14px 20px;
    border-top: 1px solid var(--border);
}
.bm-settings-section { margin-bottom: 20px; }
.bm-settings-section:last-child { margin-bottom: 0; }
.bm-settings-heading { font-size: var(--fs-sub); margin-bottom: 10px; padding-bottom: 6px; border-bottom: 1px solid var(--grid-line-soft); }
.bm-settings-placeholder { color: var(--text-muted); font-size: var(--fs-sub); margin: 0; }

/* ===================== Drawer + shared layer backdrop (bmDrawer) ===================== */
.bm-layer-backdrop { position: fixed; inset: 0; background: var(--overlay); z-index: 1040; }
.bm-scroll-lock { overflow: hidden; }
.bm-drawer {
    position: fixed;
    top: 0; right: 0; bottom: 0;
    width: min(480px, 100%);
    background: var(--card-bg);
    box-shadow: var(--shadow-lg);
    z-index: 1050;
    display: flex;
    flex-direction: column;
    transform: translateX(0);
}

/* ===================== Toast ===================== */
.bm-toast-wrap {
    position: fixed;
    top: 16px; right: 16px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    z-index: 1100;
    max-width: min(360px, calc(100vw - 32px));
}
.bm-toast {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-left: 4px solid var(--text-muted);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow);
    padding: 12px 14px;
    animation: bm-toast-in 0.2s ease;
}
@keyframes bm-toast-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
.bm-toast-title { font-weight: 700; font-size: var(--fs-sub); margin-bottom: 2px; }
.bm-toast-msg { font-size: var(--fs-sub); color: var(--text); }
.bm-toast-success { border-left-color: var(--success); }
.bm-toast-error { border-left-color: var(--danger); }
.bm-toast-warning { border-left-color: var(--warn); }
.bm-toast-info { border-left-color: var(--primary); }

/* ===================== Table (sheet) ===================== */
.bm-table-wrap { overflow-x: auto; border: 1px solid var(--grid-line); border-radius: var(--radius); background: var(--card-bg); }
.bm-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sub); }
.bm-table th, .bm-table td { padding: 8px 12px; border: 1px solid var(--grid-line); text-align: left; height: 40px; }
.bm-table thead th { position: sticky; top: 0; background: var(--page-bg); font-weight: 700; z-index: 1; }
.bm-table tbody tr:hover { background: var(--row-hover); }
.bm-table tbody tr.is-selected { background: var(--row-selected); }
.bm-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.bm-table.is-compact th, .bm-table.is-compact td { height: 34px; padding: 6px 10px; }
.money-pos { color: var(--money-pos); }
.money-neg { color: var(--money-neg); }

/* ===================== Skeleton + empty-state ===================== */
/* ===================== Pager ===================== */
.bm-pager { display: inline-flex; align-items: center; gap: 6px; }
.bm-pager-btn {
    min-width: var(--touch);
    height: var(--touch);
    padding: 0 12px;
    border: 1px solid var(--border);
    background: var(--card-bg);
    color: var(--text);
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.bm-pager-btn:hover:not(:disabled) { background: var(--grid-line-soft); }
.bm-pager-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.bm-pager-info { font-size: var(--fs-sub); color: var(--text-muted); padding: 0 6px; }

.bm-skeleton {
    display: block;
    height: 14px;
    border-radius: 6px;
    background: linear-gradient(90deg, #EEF2F7 25%, #E2E8F0 37%, #EEF2F7 63%);
    background-size: 400% 100%;
    animation: bm-shimmer 1.2s ease-in-out infinite;
}
@keyframes bm-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
.bm-empty { padding: 40px 16px; text-align: center; color: var(--text-muted); }

/* ===================== Bottom nav (mobile only, <992px) =====================
   Hidden by default (desktop, ≥992px is pixel-identical to before this bar existed); the mobile media
   query below flips display to grid. z-index 35 sits between the topbar (30) and the sidebar backdrop
   (39) so the off-canvas sidebar/backdrop and any modal/drawer (1050) still layer above it. */
.bm-bottom-nav {
    display: none;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 35;
    /* One equal column per cell, however many the role draws (4 for a collector or a partner, 5 with
       "Menu" for someone who is both) — a fixed repeat(5) would leave a 4-cell bar with an empty slot. */
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    /* box-sizing: border-box is global (top of file), so a plain "60px" would let the safe-area padding
       below eat INTO the 60px instead of extending it. Today env(safe-area-inset-bottom) always resolves
       to 0 — the viewport meta in _Layout.cshtml has no viewport-fit=cover, so no browser ever exposes a
       real inset here — so this calc() is currently a no-op and .bm-bottom-nav is exactly 60px either
       way. It stays as calc() so the bar is already correct, with no further change needed here, if
       viewport-fit=cover is ever added: a plain "60px" would then squeeze the cells into a 26px content
       box on a notched device (inset ~34px), under the --touch minimum. The bar's own height is a token so
       "Chữ lớn" can make room for its taller cells and the content padding below follows it. */
    height: calc(var(--bottom-nav-height) + env(safe-area-inset-bottom));
    background: var(--topbar-bg);
    border-top: 1px solid var(--border);
    padding-bottom: env(safe-area-inset-bottom);
}
.bm-bottom-nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-height: var(--touch);
    border: none;
    background: transparent;
    color: var(--text-muted);
    font-family: inherit;
    cursor: pointer;
}
.bm-bottom-nav-item:hover { color: var(--text); text-decoration: none; }
.bm-bottom-nav-icon { width: 24px; height: 24px; flex: 0 0 24px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
/* Label size comes from --fs-label. "Hoa hồng & dịch vụ" and "Cộng tác viên" are the longest; a 5-cell bar at
   320px leaves ~64px per cell, so the label may wrap to two lines (still inside the bar) rather than
   overflow into the neighbouring cell. */
.bm-bottom-nav-label { font-size: var(--fs-label); line-height: 1.15; text-align: center; max-width: 100%; overflow-wrap: anywhere; }
.bm-bottom-nav-item.is-active { color: var(--primary); font-weight: 600; }

/* ===================== Responsive: off-canvas sidebar under 992px ===================== */
@media (max-width: 991.98px) {
    .bm-sidebar { transform: translateX(-100%); box-shadow: var(--shadow-lg); }
    body.bm-sidebar-open .bm-sidebar { transform: translateX(0); }
    .bm-shell { margin-left: 0; }
    .bm-hamburger { display: inline-flex; }
    .bm-bottom-nav { display: grid; }
    /* Bottom nav's real on-screen height is 60px + the safe-area inset (see .bm-bottom-nav) — this has to
       match that exactly, or content is left peeking out from under the bar (too little) or pushed up
       further than the bar reaches (too much, double-counting the inset). */
    .bm-content { padding: 16px; padding-bottom: calc(16px + var(--bottom-nav-height) + env(safe-area-inset-bottom)); }
    .bm-account-name { display: none; }
    .bm-dropdown-menu-wide { min-width: min(320px, calc(100vw - 24px)); }
}

@media (min-width: 992px) {
    /* Backdrop only meaningful for the mobile off-canvas. */
    .bm-sidebar-backdrop { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    * { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
}

/* ===================== Phase 8 layout add-ons ===================== */
/* Account dropdown: Số dư + Ví summary (parity item 27). */
.bm-account-summary { padding: 10px 14px 4px; }
.bm-account-summary-row { display: flex; justify-content: space-between; gap: 12px; font-size: var(--fs-sub); padding: 3px 0; }
.bm-account-summary-row span:first-child { color: var(--text-muted); }
.bm-account-summary-row span:last-child { font-weight: 600; }
.bm-account-topup { display: inline-block; margin-top: 6px; font-size: var(--fs-sub); font-weight: 600; }
.tabular-nums { font-variant-numeric: tabular-nums; }

/* Passive Trial-Balance banner — mounted site-wide (partner-only). */
.bm-trial-banner {
    background: #FEF2F2; border: 1px solid #FECACA; color: #991B1B;
    padding: 10px 14px; border-radius: var(--radius-sm); font-size: var(--fs-sub); margin-bottom: 16px;
}
.bm-trial-banner a { color: #991B1B; font-weight: 700; text-decoration: underline; }

/* Xác thực hai lớp modal — self-hosted QR host. */
.bm-2fa-qr { display: flex; justify-content: center; margin: 4px 0 16px; }
.bm-2fa-qr img { border: 6px solid #fff; border-radius: 8px; box-shadow: var(--shadow-sm); }

/* Mobile: ≥16px inputs so iOS Safari does not zoom on focus. */
@media (max-width: 640px) {
    .bm-input, .bm-select, .bm-textarea { font-size: var(--fs-body); }

    /* Row actions reach the full --touch target on a phone, which is where this app is actually used.
       Row buttons are allowed to WRAP rather than shrink (.bc-col-actions drops its nowrap below), because
       a row that runs off the side of the screen is worse than a row two lines tall. */
    .bm-btn-xs { min-height: var(--touch); padding: 8px 12px; }
    .bc-col-actions { white-space: normal; }
    .bc-col-actions .bm-btn { margin-top: 4px; }

    /* Tick boxes are pressed with a thumb, often a wet or dirty one. The browser default (~13px) is the
       smallest target on any of these screens and sits right next to the money it decides. */
    .bm-table input[type="checkbox"] { width: 22px; height: 22px; }

    /* Card mode text. 13.5px reads as fine print on a phone held at arm's length in daylight; the table
       becomes one card per row at these widths anyway, so there is room for the extra pixels. */
    .bm-table { font-size: var(--fs-body); }
}

/* ── BillCollect page chrome (site-wide) ──────────────────────────────────────
   Promoted here from the page stylesheets: four screens now render the same head,
   help text, toolbar and action column, and the guideline's rule for a class used
   across the whole site is that it lives in app.css, not in a fifth copy. This is
   the only declaration: the local copies the two older pages carried were removed,
   because page CSS loads after this file and would silently win. */
.bc-page-head { display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap; margin-bottom: 16px; }
.bc-page-head > div:first-child { margin-right: auto; }
.bc-head-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.bc-help { font-size: var(--fs-sub); color: var(--text-muted); }
.bc-toolbar { display: flex; align-items: flex-end; gap: 20px; flex-wrap: wrap; margin-bottom: 12px; }
.bc-col-actions { white-space: nowrap; }
.bc-col-actions .bm-btn + .bm-btn { margin-left: 6px; }

/* Secondary line under a primary cell value (bill code under a customer name). */
.bc-sub { display: block; margin-top: 2px; font-size: var(--fs-sub); color: var(--text-muted); }

.bc-section-title { margin: 24px 0 10px; font-size: calc(var(--fs-body) + 1px); font-weight: 700; color: var(--text); }

/* ── Thẻ số liệu (site-wide) ──
   Promoted here when "Tổng quan" became the third screen wanting the same card. Đối tác and Khoản nộp
   each carried their own copy, which is the drift this rule exists to stop: page CSS loads after this
   file, so a fourth local copy would silently win and the four would diverge one edit at a time.
   The two modifiers travel with it — they are the shared meanings, not per-page decoration:
   .is-owed is money still to be handed over, .is-profit is money kept. */
.bc-stat-grid { display: flex; gap: 10px; flex-wrap: wrap; margin: 0 0 16px; }
.bc-stat {
    flex: 1 1 180px; display: flex; flex-direction: column; gap: 2px;
    padding: 12px 14px; border: 1px solid var(--grid-line); border-radius: var(--radius-sm);
    background: var(--card-bg);
}
.bc-stat-num { font-size: calc(var(--fs-title) + 2px); font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.bc-stat-label { font-size: var(--fs-sub); color: var(--text-muted); }
.bc-stat.is-owed .bc-stat-num { color: var(--warn); }
.bc-stat.is-profit .bc-stat-num { color: var(--money-pos); }

/* ── In-page tabs (site-wide) ──
   Promoted out of partner.css once a second screen ("Danh sách thu": Chờ thu | Kiểm tra lại) needed the
   same bar. Page CSS loads after this file, so a local copy on either host would silently win and let the
   two drift. Panels are toggled with the [hidden] attribute alone — the global reset above handles it. */
.bc-tabbar {
    display: flex; gap: 4px; flex-wrap: wrap;
    border-bottom: 1px solid var(--border); margin-bottom: 16px;
}
.bc-tab {
    appearance: none; background: transparent; border: none; cursor: pointer;
    padding: 10px 16px; min-height: var(--touch);
    font-size: var(--fs-sub); font-weight: 600; color: var(--text-muted);
    border-bottom: 2px solid transparent; border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}
.bc-tab:hover { color: var(--text); background: var(--row-hover); }
.bc-tab.is-active { color: var(--primary); border-bottom-color: var(--primary); }
.bc-tab:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }

/* ── "Chữ lớn": tables become cards at every width ──
   The same reflow each page declares inside its own breakpoint, applied unconditionally while
   data-text="large" is on <html>. Wrapped in :where() so the selectors keep the specificity of the page
   rules they mirror — a page's own card adjustments keep winning here exactly as they do on a phone. */
:where(:root[data-text="large"]) .bm-reflow-table thead { display: none; }
:where(:root[data-text="large"]) .bm-reflow-table,
:where(:root[data-text="large"]) .bm-reflow-table tbody,
:where(:root[data-text="large"]) .bm-reflow-table tfoot,
:where(:root[data-text="large"]) .bm-reflow-table tr,
:where(:root[data-text="large"]) .bm-reflow-table td,
:where(:root[data-text="large"]) .bm-reflow-table tfoot th { display: block; width: 100%; }
:where(:root[data-text="large"]) .bm-reflow-table tr { border: 1px solid var(--grid-line); border-radius: 8px; margin-bottom: 10px; padding: 6px 4px; }
:where(:root[data-text="large"]) .bm-reflow-table td { display: flex; justify-content: space-between; gap: 12px; text-align: right; border: none; border-bottom: 1px solid var(--grid-line-soft); height: auto; padding: 6px 10px; }
:where(:root[data-text="large"]) .bm-reflow-table td:last-child { border-bottom: none; }
:where(:root[data-text="large"]) .bm-reflow-table td::before { content: attr(data-label); font-weight: 600; color: var(--text-muted); text-align: left; }
:where(:root[data-text="large"]) .bm-reflow-table { font-size: var(--fs-body); }
:where(:root[data-text="large"]) .bc-col-actions { white-space: normal; }
/* What is typed grows; the example inside an empty box stays at the secondary size, so a long hint
   ("Tên, mã, ghi chú hoặc chữ đầu…") still fits the box instead of being cut mid-word. */
:where(:root[data-text="large"]) .bm-input::placeholder,
:where(:root[data-text="large"]) .bm-textarea::placeholder { font-size: var(--fs-sub); }
/* On a wide screen one card per row would stretch a label a whole page away from its value: the cards
   sit side by side instead, each about a phone wide. */
@media (min-width: 861px) {
    :where(:root[data-text="large"]) .bm-reflow-table tbody { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 10px; }
    :where(:root[data-text="large"]) .bm-reflow-table tbody tr { margin-bottom: 0; }
}
