@charset "UTF-8";
/*
 * ABK CRM — mobile / native-app polish + PWA install & update banners.
 * Loaded on every admin and auth page. Desktop is untouched; all layout
 * refinements live behind small-screen or standalone-display media queries.
 */

/* ------------------------------------------------------------------ */
/*  Native-app feel when launched from the home screen (installed PWA) */
/* ------------------------------------------------------------------ */
@media (display-mode: standalone), (display-mode: fullscreen) {
    /* Respect the notch / status bar and home indicator. */
    .nk-header {
        padding-top: env(safe-area-inset-top);
    }
    .nk-sidebar {
        padding-top: env(safe-area-inset-top);
    }
    body {
        padding-bottom: env(safe-area-inset-bottom);
    }
    /* The web footer is dead weight inside an installed app. */
    .nk-footer {
        display: none;
    }
    /* Kill the iOS tap highlight for a more app-like touch response. */
    a, button, .nk-menu-link {
        -webkit-tap-highlight-color: transparent;
    }
}

/* ------------------------------------------------------------------ */
/*  Phone-sized polish (applies in browser and installed alike)        */
/* ------------------------------------------------------------------ */
@media (max-width: 767.98px) {
    /* Momentum scrolling for wide tables wrapped in .table-responsive. */
    .table-responsive {
        -webkit-overflow-scrolling: touch;
    }
    /* Comfortable 44px touch targets in the collapsed sidebar menu. */
    .nk-sidebar .nk-menu-link {
        padding-top: .75rem;
        padding-bottom: .75rem;
    }
    /* Avoid iOS zoom-on-focus by keeping inputs at >=16px. */
    .form-control, .form-select {
        font-size: 16px;
    }
}

/* ------------------------------------------------------------------ */
/*  App-launcher menu — the mobile sidebar reads as a native app grid   */
/*  of icon tiles instead of a vertical list. Top-level items become    */
/*  tiles; tapping a group tile (has-sub) expands it full-width into a   */
/*  sub-grid. Submenu visibility is driven by the .active class the      */
/*  theme/menu-active.js already toggle on the <li>, so this never       */
/*  fights the theme's inline display animation.                        */
/* ------------------------------------------------------------------ */
@media (max-width: 767.98px) {
    .nk-sidebar-menu .nk-menu {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
        gap: 16px 6px;
        padding: 16px 12px calc(16px + env(safe-area-inset-bottom));
        align-items: start;
    }

    /* Every top-level item is an app tile: a colourful icon badge + label,
       no card behind it (like a native home screen). */
    .nk-sidebar-menu .nk-menu > .nk-menu-item {
        margin: 0;
    }

    .nk-sidebar-menu .nk-menu > .nk-menu-item > .nk-menu-link {
        display: flex !important;
        flex-direction: column;
        align-items: center;
        justify-content: flex-start;
        text-align: center;
        gap: 8px;
        padding: 4px 2px !important;
        background: transparent !important;
        transition: transform .1s ease;
    }

    .nk-sidebar-menu .nk-menu > .nk-menu-item > .nk-menu-link:active {
        transform: scale(.92);
    }

    /* The icon badge — vibrant rounded square with a white glyph. */
    .nk-sidebar-menu .nk-menu-icon {
        margin: 0 !important;
        width: 56px !important;
        height: 56px;
        border-radius: 17px;
        display: flex !important;
        align-items: center;
        justify-content: center;
        line-height: 1 !important;
        color: #fff !important;
        box-shadow: 0 6px 14px rgba(0, 0, 0, .3);
        background: linear-gradient(145deg, #3b82f6, #2563eb);
    }

    .nk-sidebar-menu .nk-menu-icon .icon {
        font-size: 1.5rem;
        color: #fff !important;
    }

    /* Colour palette, cycled by position across every tile (top level and
       submenus alike, since each item is a .nk-menu-item within its <ul>). */
    .nk-sidebar-menu .nk-menu-item:nth-child(10n + 1) > .nk-menu-link .nk-menu-icon { background: linear-gradient(145deg, #3b82f6, #2563eb); }
    .nk-sidebar-menu .nk-menu-item:nth-child(10n + 2) > .nk-menu-link .nk-menu-icon { background: linear-gradient(145deg, #22c55e, #16a34a); }
    .nk-sidebar-menu .nk-menu-item:nth-child(10n + 3) > .nk-menu-link .nk-menu-icon { background: linear-gradient(145deg, #fb923c, #f97316); }
    .nk-sidebar-menu .nk-menu-item:nth-child(10n + 4) > .nk-menu-link .nk-menu-icon { background: linear-gradient(145deg, #f43f5e, #e11d48); }
    .nk-sidebar-menu .nk-menu-item:nth-child(10n + 5) > .nk-menu-link .nk-menu-icon { background: linear-gradient(145deg, #a78bfa, #7c3aed); }
    .nk-sidebar-menu .nk-menu-item:nth-child(10n + 6) > .nk-menu-link .nk-menu-icon { background: linear-gradient(145deg, #22d3ee, #0891b2); }
    .nk-sidebar-menu .nk-menu-item:nth-child(10n + 7) > .nk-menu-link .nk-menu-icon { background: linear-gradient(145deg, #f472b6, #db2777); }
    .nk-sidebar-menu .nk-menu-item:nth-child(10n + 8) > .nk-menu-link .nk-menu-icon { background: linear-gradient(145deg, #2dd4bf, #0d9488); }
    .nk-sidebar-menu .nk-menu-item:nth-child(10n + 9) > .nk-menu-link .nk-menu-icon { background: linear-gradient(145deg, #818cf8, #4f46e5); }
    .nk-sidebar-menu .nk-menu-item:nth-child(10n)     > .nk-menu-link .nk-menu-icon { background: linear-gradient(145deg, #a3e635, #65a30d); }

    /* Label: wraps under the badge, app-tile sized. */
    .nk-sidebar-menu .nk-menu-text {
        white-space: normal !important;
        text-align: center;
        font-size: 12px;
        line-height: 1.15;
        max-width: 100%;
        color: #cbd3e1;
    }

    /* Strip the list-mode chrome: caret + the active left-bar. */
    .nk-sidebar-menu .nk-menu > .nk-menu-item > .nk-menu-link.nk-menu-toggle:after {
        display: none !important;
    }
    .nk-sidebar-menu .nk-menu > .nk-menu-item.active > .nk-menu-link:before {
        display: none !important;
    }

    /* Current page (a leaf tile): ring the badge and brighten the label. */
    .nk-sidebar-menu .nk-menu > .nk-menu-item.active:not(.has-sub) > .nk-menu-link .nk-menu-icon {
        box-shadow: 0 0 0 2px rgba(255, 255, 255, .9), 0 6px 14px rgba(0, 0, 0, .3);
    }
    .nk-sidebar-menu .nk-menu > .nk-menu-item.active:not(.has-sub) > .nk-menu-link .nk-menu-text {
        color: #fff;
        font-weight: 600;
    }

    /* ---- Section-by-section homepage: leaves first (as tiles), then every
       group as a full-width, ALWAYS-OPEN titled section. `order` groups the
       leaf tiles together at the top so sections stack cleanly below. ---- */
    .nk-sidebar-menu .nk-menu > .nk-menu-item:not(.has-sub) {
        order: 1;
    }
    .nk-sidebar-menu .nk-menu > .nk-menu-item.has-sub {
        order: 2;
        grid-column: 1 / -1;
        background: rgba(255, 255, 255, .04);
        border-radius: 18px;
        padding: 8px 10px 12px;
        margin-top: 4px;
    }

    /* No icon on a section title.

       The group's own icon stays in the MARKUP because the desktop sidebar needs it — _Node.cshtml
       records that eleven of seventeen groups used to show a bare label there and the sidebar read
       as two menus stacked on each other. On this grid it is different information: the section
       already has a title and a row of real tiles under it, so a second small badge floating at the
       top-left reads as a fourth item in the group rather than as its heading. Hidden here, kept
       there.

       !important because the tile rules above set display on .nk-menu-icon the same way — measured:
       plain `display:none` computed as flex, `display:none !important` collapsed the box to 0x0. */
    .nk-sidebar-menu .nk-menu > .nk-menu-item.has-sub > .nk-menu-link > .nk-menu-icon {
        display: none !important;
    }

    /* The group tile becomes a (non-tappable) section title row. */
    .nk-sidebar-menu .nk-menu > .nk-menu-item.has-sub > .nk-menu-link {
        flex-direction: row;
        justify-content: flex-start;
        gap: 10px;
        padding: 4px 2px 10px !important;
        pointer-events: none; /* sections never collapse */
    }
    .nk-sidebar-menu .nk-menu > .nk-menu-item.has-sub > .nk-menu-link .nk-menu-icon {
        width: 34px !important;
        height: 34px;
        border-radius: 10px;
    }
    .nk-sidebar-menu .nk-menu > .nk-menu-item.has-sub > .nk-menu-link .nk-menu-icon .icon {
        font-size: 1.05rem;
    }
    .nk-sidebar-menu .nk-menu > .nk-menu-item.has-sub > .nk-menu-link .nk-menu-text {
        font-size: .95rem;
        font-weight: 700;
        color: #fff;
    }

    /* Sub-items are ALWAYS shown as their own tile grid. */
    .nk-sidebar-menu .nk-menu-item.has-sub > .nk-menu-sub {
        display: grid !important;
        grid-template-columns: repeat(auto-fill, minmax(76px, 1fr));
        gap: 14px 6px;
        padding: 2px;
        height: auto !important;
        overflow: visible !important;
    }
    .nk-sidebar-menu .nk-menu-sub .nk-menu-item {
        margin: 0;
    }
    .nk-sidebar-menu .nk-menu-sub .nk-menu-link {
        display: flex !important;
        flex-direction: column;
        align-items: center;
        justify-content: flex-start;
        text-align: center;
        gap: 6px;
        padding: 4px 2px !important;
        background: transparent !important;
    }
    .nk-sidebar-menu .nk-menu-sub .nk-menu-link:active {
        transform: scale(.92);
    }
    /* Slightly smaller badges inside a group. */
    .nk-sidebar-menu .nk-menu-sub .nk-menu-icon {
        width: 46px !important;
        height: 46px;
        border-radius: 14px;
    }
    .nk-sidebar-menu .nk-menu-sub .nk-menu-icon .icon {
        font-size: 1.25rem;
    }
    /* Submenu items without an icon still read as tiles (coloured dot badge). */
    .nk-sidebar-menu .nk-menu-sub .nk-menu-link:not(:has(.nk-menu-icon))::before {
        content: "";
        width: 46px;
        height: 46px;
        border-radius: 14px;
        background: linear-gradient(145deg, #94a3b8, #64748b);
        box-shadow: 0 6px 14px rgba(0, 0, 0, .3);
    }

    /* A group inside a group («Thiết Kế» › Cài đặt, 2026-10-30): a row of its own across the section, a smaller title over
       its own tiles. Left as a tile it took one grid cell and stacked its eight children down that single column. Not
       tappable, like a section title: the tiles under it are what open pages. */
    .nk-sidebar-menu .nk-menu-sub > .nk-menu-item.has-sub {
        grid-column: 1 / -1;
    }
    .nk-sidebar-menu .nk-menu-sub > .nk-menu-item.has-sub > .nk-menu-link {
        flex-direction: row;
        justify-content: flex-start;
        padding: 8px 2px 4px !important;
        pointer-events: none;
    }
    .nk-sidebar-menu .nk-menu-sub > .nk-menu-item.has-sub > .nk-menu-link > .nk-menu-icon,
    .nk-sidebar-menu .nk-menu-sub > .nk-menu-item.has-sub > .nk-menu-link.nk-menu-toggle:after {
        display: none !important;
    }
    .nk-sidebar-menu .nk-menu-sub > .nk-menu-item.has-sub > .nk-menu-link .nk-menu-text {
        text-align: left;
        font-size: 13px;
        font-weight: 700;
        color: #fff;
    }
}

/* ------------------------------------------------------------------ */
/*  Native app shell (phones):                                          */
/*   • top header → slim bar with just the ABK logo, which opens the     */
/*     full-screen home grid (the logo is wired as an .nk-nav-toggle);   */
/*   • left sidebar menu → full-screen "home" app grid;                  */
/*   • a fixed bottom navigation (_MobileFooterNav) with 5 shortcuts.    */
/* ------------------------------------------------------------------ */

/* Bottom nav + back button are phone-only; hidden by default. */
.crm-tabbar,
.crm-back {
    display: none;
}

@media (max-width: 767.98px) {
    /* ---- Top header → slim logo bar (tap logo = Home / open grid) ---- */
    .nk-header,
    .nk-header.is-light {
        position: sticky;
        top: 0;
        z-index: 1030;
        min-height: 52px;
        overflow: visible;
    }
    .nk-header .nk-header-wrap {
        position: relative;
        display: flex !important;
        align-items: center;
        justify-content: center;
        min-height: 52px;
    }
    /* Keep only the brand/logo in the top bar. */
    .nk-header .nk-menu-trigger,
    .nk-header .nk-header-tools,
    .nk-header .nk-header-news {
        display: none !important;
    }
    .nk-header .nk-header-brand {
        display: block !important;
        margin: 0;
    }
    .nk-header .nk-header-brand .logo-img {
        max-height: 30px;
    }

    /* ---- Home is a REAL page (.crm-home): the module app-grid on a dark,
       full-bleed background. Tiles/sections reuse the .nk-sidebar-menu rules
       above (Home/Index.cshtml wraps AdminMenu in .nk-sidebar-menu). The left
       sidebar is no longer used as home on phones — it stays off-canvas. ---- */
    .crm-home {
        width: 100vw;
        margin-left: 50%;
        transform: translateX(-50%);
        margin-top: -18px; /* eat .nk-content top padding for a flush top */
        min-height: calc(100vh - 118px);
        padding: 6px 0 16px;
        /* Fallback only — the real colour comes from the admin Appearance
           "Sidebar" setting via the theme-override in _Layout (default #101924,
           i.e. the same dark surface as the full-site sidebar). */
        background: linear-gradient(185deg, #101924 0%, #0b1119 100%);
    }
    /* Darken the wrapper too (removes any light seam around the panel). */
    .nk-content:has(.crm-home) {
        padding-top: 0;
        background: #0b1119;
    }

    /* Remove DashLite's submenu connector line inside the app grid/sections. */
    .nk-sidebar-menu .nk-menu-sub,
    .crm-home .nk-menu-sub {
        border-left: 0 !important;
        margin-left: 0 !important;
    }
    .nk-sidebar-menu .nk-menu-sub .nk-menu-link::before,
    .crm-home .nk-menu-sub .nk-menu-link::before {
        display: none !important;
    }

    /* ---- Bottom navigation: 5 evenly-spaced shortcut tabs ---- */
    .crm-tabbar {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1050;
        display: flex;
        align-items: stretch;
        background: #fff;
        border-top: 1px solid #e5e9f2;
        box-shadow: 0 -4px 16px rgba(43, 55, 72, .12);
        padding-bottom: env(safe-area-inset-bottom);
    }
    .crm-tab {
        flex: 1 1 0;
        min-width: 0;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 3px;
        padding: 7px 2px;
        min-height: 58px;
        color: #8091a7;
        text-decoration: none;
        font-size: 12px;
        line-height: 1.12;
        text-align: center;
    }
    .crm-tab .icon {
        font-size: 1.3rem;
    }
    .crm-tab span {
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
        max-width: 100%;
        white-space: normal;
        word-break: break-word;
    }
    .crm-tab:active {
        background: #f5f6fa;
    }
    .crm-tab.active {
        color: var(--brand-1, #1c5c3a);
        font-weight: 600;
    }

    /* ---- Top-left back button (inner pages only) ---- */
    .crm-back {
        position: absolute;
        left: 6px;
        top: 50%;
        transform: translateY(-50%);
        z-index: 2;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 40px;
        height: 40px;
        color: #364a63;
        font-size: 1.4rem;
    }
    .crm-back:active {
        color: var(--brand-1, #1c5c3a);
    }

    /* ---- The desktop footer is always dropped on phones ---- */
    .nk-footer {
        display: none !important;
    }

    /* ---- Only the HOME screen reserves space for the bottom nav ---- */
    .crm-home-screen .nk-wrap {
        padding-bottom: calc(68px + env(safe-area-inset-bottom));
    }
}

/* ------------------------------------------------------------------ */
/*  Care-note grid (Customer/StatisticByEmployee Detail) → cards.       */
/*  These "tables" are Bootstrap-grid emulations (a coloured header row */
/*  of col-* cells followed by matching data rows), so table.cards-sm   */
/*  can't apply. On phones: hide the header row and stack each data row  */
/*  into a labelled card using its per-cell data-label.                 */
/* ------------------------------------------------------------------ */
@media (max-width: 767.98px) {
    /* Hide the coloured header cells + the top divider. */
    .crm-carenote > [class*="col-"],
    .crm-carenote > hr {
        display: none !important;
    }

    /* Each data row becomes a card. */
    .crm-carenote > .row {
        display: block;
        margin: 0 0 .75rem;
        padding: .35rem .75rem;
        border: 1px solid #dbdfea;
        border-radius: .5rem;
        background: #fff;
        box-shadow: 0 1px 3px rgba(43, 55, 72, .08);
    }

    .crm-carenote > .row > [class*="col-"] {
        flex: 0 0 100%;
        width: 100% !important;
        max-width: 100%;
        display: flex;
        justify-content: space-between;
        align-items: flex-start;
        gap: 1rem;
        padding: .45rem 0;
        border-bottom: 1px solid #f0f2f7;
        text-align: right;
        white-space: normal;
    }

    .crm-carenote > .row > [class*="col-"]::before {
        content: attr(data-label);
        font-weight: 600;
        color: #526484;
        text-align: left;
        flex: 0 0 35%;
        white-space: nowrap;
    }

    /* The value element fills the rest of the row (instead of shrinking to
       its longest word and wrapping oddly). */
    .crm-carenote > .row > [class*="col-"]:not(.cell-actions) > * {
        flex: 1 1 auto;
        min-width: 0;
    }

    /* Action cell: full width, left-aligned, no label. */
    .crm-carenote > .row > .cell-actions {
        justify-content: flex-start;
        text-align: left;
        border-bottom: none;
        padding-top: .6rem;
    }
    .crm-carenote > .row > .cell-actions::before {
        content: none;
    }

    /* The per-row divider inside the emulated table is redundant now. */
    .crm-carenote > .row > hr {
        display: none;
    }
}

/* ------------------------------------------------------------------ */
/*  Project upsert/detail form — mobile polish. Scoped to .crm-inner-   */
/*  screen so these win over crm-style.css (which loads afterwards).    */
/*  Goals: readable sections, big touch targets, a sticky save bar.     */
/* ------------------------------------------------------------------ */
@media (max-width: 767.98px) {
    /* Reclaim width: tighter card padding. */
    .crm-inner-screen .project-card > .card-header,
    .crm-inner-screen .project-card > .card-body {
        padding-left: 12px !important;
        padding-right: 12px !important;
    }
    .crm-inner-screen .project-card > .card-body {
        padding-bottom: 12px !important;
    }

    /* Header: title, status chips and the 2 action buttons stack cleanly. */
    .crm-inner-screen .project-card .card-header > .d-flex {
        flex-direction: column;
        align-items: stretch !important;
    }
    .crm-inner-screen .project-card .card-header h3 {
        font-size: 1.15rem;
        line-height: 1.3;
    }
    .crm-inner-screen .project-card .card-header .btn-sm {
        flex: 1 1 0;
        justify-content: center;
    }
    .crm-inner-screen .project-card .card-header .hdr-chips {
        margin: 2px 0;
    }

    /* Sections read as clear cards with a prominent title. */
    .crm-inner-screen .project-form .form-section {
        padding: 14px 14px 16px;
        margin-bottom: 14px;
        border-radius: 14px;
        border-left-width: 5px;
    }
    .crm-inner-screen .project-form .form-section-title {
        font-size: 1rem;
        font-weight: 700;
        display: flex;
        align-items: center;
        gap: 8px;
    }

    /* Bigger, more legible inputs (16px avoids iOS zoom). */
    .crm-inner-screen .project-form .form-control,
    .crm-inner-screen .project-form .form-select {
        min-height: 46px;
        font-size: 16px !important;
        padding: .6rem .8rem;
        border-radius: 10px;
    }
    .crm-inner-screen .project-form .form-label {
        font-size: .9rem;
        font-weight: 600;
        margin-bottom: .3rem;
    }
    /* Comfortable gap between stacked fields. */
    .crm-inner-screen .project-form .row.g-3 {
        --bs-gutter-y: 1rem;
    }

    /* ---- Sticky bottom save bar (Back lives in the header now) ---- */
    .crm-inner-screen .project-form .form-actions {
        position: sticky;
        bottom: 0;
        z-index: 20;
        display: flex !important;
        flex-direction: row !important;
        align-items: center;
        gap: 10px;
        margin: 16px -12px -12px;
        padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
        background: #fff;
        border-top: 1px solid #e5e9f2;
        box-shadow: 0 -6px 18px rgba(43, 55, 72, .12);
    }
    .crm-inner-screen .project-form .form-actions > a.btn-light {
        display: none; /* redundant with the top-left back button */
    }
    .crm-inner-screen .project-form .form-actions .ms-auto {
        width: 100%;
        margin: 0 !important;
        display: flex;
        gap: 10px;
    }
    .crm-inner-screen .project-form .form-actions .btn {
        width: auto !important;
        height: 48px;
        flex: 1;
    }
    .crm-inner-screen .project-form .form-actions .btnSave {
        flex: 3; /* Save is the dominant action */
    }

    /* ---- Timeline card: stacks full-width, comfortable spacing ---- */
    .crm-inner-screen #timeline .card-body {
        padding: 14px 12px;
    }
    .crm-inner-screen #timeline .tl-card {
        padding: 12px 14px;
    }
}

/* ------------------------------------------------------------------ */
/*  Projects listing — compact card per project (mobile).               */
/*  Three fixed lines: [Khách Hàng | Trạng thái] / [Giá Trị | Tiến độ]  */
/*  / [Bắt Đầu | Kết Thúc]. STT, Công Ty, Loại dự án and Số Điện Thoại  */
/*  stay off the card. Every other column — Mã dự án, Quy Mô, Vai trò   */
/*  phụ trách, any field surfaced at Quản lý Menu & Trang — follows as  */
/*  a full-width captioned line, so a column added later shows up on    */
/*  the card instead of silently landing in someone else's slot.        */
/*                                                                      */
/*  Cells are picked by the pj-* classes projects.js puts on each       */
/*  column, never by nth-child. Positions differ by role (Sales get no  */
/*  Mã dự án), and the nth-child version of this block went one column  */
/*  out when that column was added: it hid the customer, showed the     */
/*  empty Công Ty in its place and captioned the status "Bắt đầu:".     */
/*                                                                      */
/*  The shown cells' display has no !important on purpose, so a column  */
/*  hidden with Cột (display:none !important by nth-child) stays hidden */
/*  on the card too. Scoped by [data-page-key="projects"] so it          */
/*  overrides the generic cards-sm.                                     */
/* ------------------------------------------------------------------ */
@media (max-width: 767.98px) {
    /* The right column is capped at half the card. As plain `auto` it grew to the widest chip —
       a stage like "Công tác thi công sàn lầu 1" took 202px of a 335px card and left the customer
       name 95px, wrapping to four lines. The chips wrap instead (below). */
    table.cards-sm[data-page-key="projects"] tbody tr {
        display: grid;
        grid-template-columns: minmax(0, 1fr) fit-content(50%);
        align-items: center;
        gap: 5px 10px;
        padding: 12px 14px;
    }
    /* Reset the generic label:value cell styling. */
    table.cards-sm[data-page-key="projects"] tbody td {
        display: block;
        border: none !important;
        padding: 0 !important;
        text-align: left !important;
        white-space: normal !important;
        min-width: 0;
    }
    table.cards-sm[data-page-key="projects"] tbody td::before {
        content: none !important;
    }
    table.cards-sm[data-page-key="projects"] tbody td.pj-stt,
    table.cards-sm[data-page-key="projects"] tbody td.pj-company,
    table.cards-sm[data-page-key="projects"] tbody td.pj-type,
    table.cards-sm[data-page-key="projects"] tbody td.pj-phone {
        display: none !important;
    }
    /* Line 1 — Khách Hàng (left) · Trạng thái (right). */
    table.cards-sm[data-page-key="projects"] tbody td.pj-customer { grid-column: 1; grid-row: 1; }
    table.cards-sm[data-page-key="projects"] tbody td.pj-status { grid-column: 2; grid-row: 1; text-align: right !important; }
    /* Line 2 — Giá Trị (left) · Tiến độ (right). */
    table.cards-sm[data-page-key="projects"] tbody td.pj-value { grid-column: 1; grid-row: 2; }
    table.cards-sm[data-page-key="projects"] tbody td.pj-stage { grid-column: 2; grid-row: 2; text-align: right !important; }
    /* Line 3 — dates. */
    table.cards-sm[data-page-key="projects"] tbody td.pj-start { grid-column: 1; grid-row: 3; }
    table.cards-sm[data-page-key="projects"] tbody td.pj-end { grid-column: 2; grid-row: 3; text-align: right !important; }

    /* Everything else: a full-width line under the three, captioned from its own header. */
    table.cards-sm[data-page-key="projects"] tbody tr:not(.crm-group-row) > td:not(.dataTables_empty):not(.pj-customer):not(.pj-status):not(.pj-value):not(.pj-stage):not(.pj-start):not(.pj-end) {
        grid-column: 1 / -1;
        font-size: 12px;
        color: #526484;
    }
    table.cards-sm[data-page-key="projects"] tbody tr:not(.crm-group-row) > td:not(.dataTables_empty):not(.pj-customer):not(.pj-status):not(.pj-value):not(.pj-stage):not(.pj-start):not(.pj-end)::before {
        content: attr(data-label) ": " !important;
        color: #b0b7c3;
    }
    /* A surfaced field with no value would otherwise print a caption with nothing after it. */
    table.cards-sm[data-page-key="projects"] tbody td:empty {
        display: none !important;
    }

    /* Typography / hierarchy. */
    table.cards-sm[data-page-key="projects"] tbody td.pj-customer .project-upsert-link {
        font-weight: 700; font-size: 15px; color: #364a63 !important;
    }
    table.cards-sm[data-page-key="projects"] tbody td.pj-value .project-upsert-link {
        font-weight: 700; font-size: 15px; color: #0f7b4e !important;
    }
    table.cards-sm[data-page-key="projects"] tbody td.pj-start,
    table.cards-sm[data-page-key="projects"] tbody td.pj-end {
        font-size: 12px; color: #8094ae;
    }
    /* Inline captions so the dates read clearly — from the header, so they follow the UI culture. */
    table.cards-sm[data-page-key="projects"] tbody td.pj-start::before,
    table.cards-sm[data-page-key="projects"] tbody td.pj-end::before {
        content: attr(data-label) ": " !important; color: #b0b7c3;
    }
    /* Chips are nowrap everywhere else; in a half-width column a long stage name would overflow. */
    table.cards-sm[data-page-key="projects"] tbody td .chip {
        white-space: normal;
        max-width: 100%;
    }

    /* "Nhóm theo vai trò phụ trách" headers: a plain heading between the cards, not a card.
       Kept out of the captioned fallback above: projects.js's own draw handler labels every td
       by index, so this cell carries data-label="STT" and would read "STT: <group>". */
    table.cards-sm[data-page-key="projects"] tbody tr.crm-group-row {
        display: block;
        margin: 4px 0 6px;
        padding: 0;
        border: none;
        background: transparent;
        box-shadow: none;
    }
    table.cards-sm[data-page-key="projects"] tbody tr.crm-group-row > td {
        font-size: 13px;
        color: #364a63;
        padding: 8px 12px !important;
    }

    /* Empty-state row spans the full card width. */
    table.cards-sm[data-page-key="projects"] td.dataTables_empty {
        display: block !important;
        grid-column: 1 / -1 !important;
        text-align: center !important;
    }
}

/* ------------------------------------------------------------------ */
/*  Engineer listing — compact card: name row, a 3-metric stats row,    */
/*  projects, then actions. Scoped by [data-page-key="engineer"].       */
/* ------------------------------------------------------------------ */
@media (max-width: 767.98px) {
    table.cards-sm[data-page-key="engineer"] tbody tr {
        display: grid;
        grid-template-columns: 1fr 1fr 1fr;
        gap: 10px;
        padding: 12px 14px;
        align-items: start;
    }
    table.cards-sm[data-page-key="engineer"] tbody td {
        display: block !important;
        border: none !important;
        padding: 0 !important;
        text-align: left !important;
        white-space: normal !important;
        min-width: 0;
    }
    table.cards-sm[data-page-key="engineer"] tbody td::before {
        content: none !important;
    }
    /* Row 1 — name chip (left) · phone (right). */
    table.cards-sm[data-page-key="engineer"] tbody td:nth-child(1) {
        grid-column: 1 / -1;
        grid-row: 1;
        display: flex !important;
        justify-content: space-between;
        align-items: center;
        gap: 8px;
        padding-bottom: 8px !important;
        border-bottom: 1px solid #eef1f7 !important;
    }
    table.cards-sm[data-page-key="engineer"] tbody td:nth-child(1) > div { margin: 0 !important; }
    /* Specialty (col 2) is secondary — hidden in the compact card. */
    table.cards-sm[data-page-key="engineer"] tbody td:nth-child(2) {
        display: none !important;
    }
    /* Row 2 — three centered mini-stats: quality · success · rating. */
    table.cards-sm[data-page-key="engineer"] tbody td:nth-child(3),
    table.cards-sm[data-page-key="engineer"] tbody td:nth-child(4),
    table.cards-sm[data-page-key="engineer"] tbody td:nth-child(5) {
        grid-row: 2;
        display: flex !important;
        flex-direction: column;
        align-items: center;
        text-align: center;
        gap: 3px;
        font-size: 12px;
    }
    table.cards-sm[data-page-key="engineer"] tbody td:nth-child(3) { grid-column: 1; }
    table.cards-sm[data-page-key="engineer"] tbody td:nth-child(4) { grid-column: 2; }
    table.cards-sm[data-page-key="engineer"] tbody td:nth-child(5) { grid-column: 3; }
    table.cards-sm[data-page-key="engineer"] tbody td:nth-child(3) .badge {
        white-space: normal;
        line-height: 1.25;
    }
    table.cards-sm[data-page-key="engineer"] tbody td:nth-child(4) strong { font-size: 14px; }
    table.cards-sm[data-page-key="engineer"] tbody td:nth-child(5) .icon { font-size: 13px; }
    /* Row 3 — projects (full width). */
    table.cards-sm[data-page-key="engineer"] tbody td:nth-child(6) {
        grid-column: 1 / -1;
        grid-row: 3;
        padding-top: 8px !important;
        border-top: 1px solid #eef1f7 !important;
    }
    /* Row 4 — actions (full width). */
    table.cards-sm[data-page-key="engineer"] tbody td:nth-child(7) {
        grid-column: 1 / -1;
        grid-row: 4;
    }
    table.cards-sm[data-page-key="engineer"] tbody td:nth-child(7) .btn-group {
        width: 100%;
    }
    table.cards-sm[data-page-key="engineer"] tbody td:nth-child(7) .btn-group .btn {
        flex: 1;
    }
    /* Empty-state row spans the full card width. */
    table.cards-sm[data-page-key="engineer"] tbody td[colspan] {
        grid-column: 1 / -1 !important;
        text-align: center !important;
    }
}

/* ------------------------------------------------------------------ */
/*  Install + update banners (shared markup in _PwaInstall.cshtml)     */
/* ------------------------------------------------------------------ */
.crm-pwa-bar {
    position: fixed;
    left: 12px;
    right: 12px;
    bottom: calc(12px + env(safe-area-inset-bottom));
    z-index: 2000;
    display: none;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    border-radius: 14px;
    background: #10502f;
    color: #fff;
    box-shadow: 0 10px 30px rgba(0, 0, 0, .28);
    font-size: 14px;
    animation: crmPwaUp .28s ease-out;
}

.crm-pwa-bar.show {
    display: flex;
}

/* The "Add to Home Screen" install prompt is mobile-only — never on the full
   desktop site (Chrome fires beforeinstallprompt on desktop too). */
@media (min-width: 768px) {
    #crmInstall,
    #crmInstallIos {
        display: none !important;
    }
}

@keyframes crmPwaUp {
    from { transform: translateY(120%); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
}

.crm-pwa-ic {
    width: 40px;
    height: 40px;
    border-radius: 9px;
    background: #fff;
    padding: 4px;
    flex: 0 0 auto;
}

.crm-pwa-txt {
    flex: 1 1 auto;
    line-height: 1.3;
    min-width: 0;
}

.crm-pwa-txt b {
    display: block;
    font-weight: 600;
}

.crm-pwa-txt span {
    display: block;
    font-size: 12px;
    opacity: .85;
}

.crm-pwa-btn {
    flex: 0 0 auto;
    border: 0;
    border-radius: 999px;
    padding: 8px 16px;
    font-weight: 600;
    font-size: 13px;
    background: #fff;
    color: #10502f;
    cursor: pointer;
}

/* A 44 × 44 px target (BUG.17): the × was 12 × 15 px on the sign-in page, under the 24 px minimum and far under the 44 px
   a thumb needs on an iPhone. The glyph stays the same size; the button around it grows, and the bar's padding takes it. */
.crm-pwa-x {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    margin: -10px -10px -10px 0;
    border: 0;
    background: transparent;
    color: #fff;
    font-size: 22px;
    line-height: 1;
    opacity: .8;
    cursor: pointer;
    padding: 0;
}

/* Update banner uses an accent tint to read differently from "install". */
.crm-pwa-bar.update {
    background: #0b3f24;
}

.crm-pwa-bar.update .crm-pwa-btn {
    color: #0b3f24;
}

/* On wide screens keep the banner compact, docked bottom-right. */
@media (min-width: 768px) {
    .crm-pwa-bar {
        left: auto;
        right: 20px;
        max-width: 420px;
    }
}
