/* ═══════════════════════════════════════════════════════════════════════
   FptBook — hệ thiết kế dùng chung
   ═══════════════════════════════════════════════════════════════════════

   TẠI SAO LÀ FILE .css CHỨ KHÔNG NHÉT TRONG .cshtml

   Trước đây 513 dòng CSS nằm trong _Layout.cshtml, Ops và Docs mỗi trang một
   bộ riêng. Ba hệ quả đã trả giá:

   1. Razor nuốt `@`. Trong .cshtml phải viết `@@media`, quên một chỗ là lỗi
      biên dịch C# khó hiểu. Trong file .css thì `@media` viết bình thường —
      cạm bẫy đó biến mất hẳn.
   2. Trang `Layout = null` (10 trang) không thừa hưởng gì, nên mỗi lần đổi
      màu diện rộng là chúng lạc ra một kiểu. Giờ chúng chỉ cần <link> file này.
   3. Trình duyệt không cache được CSS nằm trong HTML. Tách ra thì tải một lần
      dùng cho mọi trang.

   ĐỌC BẢNG MÀU

   Nền giấy sáng, lấy từ portfolio. Có HAI bộ tên biến trỏ vào cùng màu:
   bộ `--bg/--surface/--text` (layout cũ dùng) và bộ `--canvas/--sheet/--ink`
   (trang Ops dùng). Giữ cả hai là cố ý — đổi tên sẽ phải sửa hơn 240 chỗ
   trong 39 view, rủi ro lớn hơn lợi ích.

   TƯƠNG PHẢN

   Mọi màu chữ ở đây đều đã đo trên nền giấy --surface (#f3f0ea):
     --text        16.9 : 1   chữ chính
     --text-muted   6.6 : 1   chữ phụ
     --text-dim     4.6 : 1   chữ mờ nhất — vừa đủ chuẩn WCAG AA (4.5:1)
   Không thêm màu chữ nào nhạt hơn --text-dim. Muốn nhạt hơn thì giảm cỡ
   chữ hoặc đổi cách trình bày, đừng giảm tương phản.

   CẤM: đặt màu chữ của nền sáng lên nền tối. Đó chính là lỗi cũ — thanh nav
   giữ nền tối rgba(10,10,10,.7) trong khi chữ đã đổi sang màu cho nền sáng,
   ra tương phản 1.8:1, gần như không đọc được.
   ═══════════════════════════════════════════════════════════════════════ */

:root {
    /* ── Nền, theo thứ tự từ ngoài vào trong ── */
    --bg: #cfcfc8;            /* canvas — nền ngoài cùng */
    --bg-soft: #ece8e0;
    --surface: #f3f0ea;       /* sheet — mặt thẻ, mặt card */
    --surface-hover: #e7e2d9;
    --surface-sunken: #e4e0d7; /* ô input, vùng lõm */

    /* ── Đường kẻ ── */
    --border: rgba(26, 26, 26, .14);
    --border-bright: rgba(26, 26, 26, .28);

    /* ── Chữ — xem phần TƯƠNG PHẢN ở đầu file ── */
    --text: #1a1a1a;
    --text-muted: #55554f;   /* thẻ 6.6:1 · canvas 4.8:1 — dùng ở đâu cũng được */
    /* CHỈ dùng --text-dim TRÊN MẶT THẺ. Trên nền canvas nó chỉ còn 3.3:1.
       Nền canvas đậm hơn mặt thẻ nên không đủ chỗ cho ba bậc chữ; ngoài thẻ
       thì bậc mờ nhất là --text-muted. */
    --text-dim: #6e6e68;     /* thẻ 4.6:1 · canvas 3.3:1 — KHÔNG đạt */

    /* ── Nhấn ── */
    --accent: #1f6f43;
    --accent-bright: #185536;
    --accent-bg: rgba(31, 111, 67, .10);
    --on-accent: #f3f0ea;

    /* ── Trạng thái ──
       Bốn màu này lấy nguyên từ portfolio, đúng như CLAUDE.md ghi. Dùng cho
       huy hiệu, viền, lát biểu đồ — tức là những chỗ nằm TRÊN MẶT THẺ. */
    --ok: #1f6f43;     --ok-bg: #dae1d6;
    --warn: #8a5a12;   --warn-bg: #e6ded0;
    --err: #a3372c;    --err-bg: #e9dad3;
    --info: #2b5f83;   --info-bg: #dbdfde;
    /* Bốn nền huy hiệu ở trên là màu ĐẶC, không phải rgba trong suốt — dù
       chúng chính là sắc độ 12% pha sẵn trên mặt giấy.
       Lý do: nền trong suốt lấy màu của thứ nằm dưới, nên cùng một huy hiệu
       đặt trong thẻ thì tương phản 6.0:1, đặt thẳng trên canvas tụt còn
       4.4:1 — dưới chuẩn. Đo được ở màn 375px. Màu đặc thì đặt ở đâu cũng
       cho ra một kết quả. */

    /* ── Bản đậm hơn, DÀNH RIÊNG CHO CHỮ ──

       Nền của app có hai tông: mặt thẻ --surface #f3f0ea (sáng) và nền canvas
       --bg #cfcfc8 (đậm hơn). Bốn màu trên đạt chuẩn trên mặt thẻ nhưng hụt
       trên canvas — đo bằng trình duyệt ở màn 375px:

                          trên canvas    cần
         --warn  #8a5a12     3.78 : 1    4.5
         --ok    #1f6f43     3.93 : 1    4.5
         --err   #a3372c     4.27 : 1    4.5

       Chữ có màu trạng thái mà đứng thẳng trên canvas (không trong thẻ) là có
       thật — dòng chú thích dưới tiêu đề Dashboard chẳng hạn.

       Không đụng vào bốn màu gốc: chúng là bảng màu chung với portfolio, ghi
       trong CLAUDE.md. Thay vào đó đậm thêm ~20% riêng cho chữ. Nhìn vẫn cùng
       một tông, mà đạt chuẩn trên CẢ HAI nền. */
    --ok-text: #1a5c38;    /* canvas 5.1 : 1   thẻ 7.1 : 1 */
    --warn-text: #6f4709;  /* canvas 5.2 : 1   thẻ 7.2 : 1 */
    --err-text: #8f2f26;   /* canvas 5.2 : 1   thẻ 7.2 : 1 */
    --info-text: #24506f;  /* canvas 5.5 : 1   thẻ 7.6 : 1 */

    --gradient: linear-gradient(135deg, #1a1a1a 0%, #1f4d3a 100%);

    /* ── Chữ ── */
    --serif: "Fraunces", "Iowan Old Style", Palatino, Georgia, serif;
    --sans: Inter, "Segoe UI", system-ui, -apple-system, sans-serif;
    --mono: "JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;

    /* ── Hình khối ── */
    --radius: 10px;
    --radius-lg: 14px;
    --shadow-sm: 0 1px 2px rgba(26, 26, 26, .06);
    --shadow: 0 4px 14px rgba(26, 26, 26, .09);
    --shadow-lg: 0 12px 32px rgba(26, 26, 26, .13);

    /* ── Kích thước điều hướng ── */
    --nav-h: 58px;
    --tabbar-h: 58px;

    /* Bí danh cho trang Ops. Cùng màu, khác tên. */
    --canvas: var(--bg);
    --sheet: var(--surface);
    --sheet-soft: var(--bg-soft);
    --ink: var(--text);
    --muted: var(--text-muted);
    --line: var(--border);
    --line-strong: var(--border-bright);
}

/* ═══════════════════════════════════════════════════════════════════════
   NỀN TẢNG
   ═══════════════════════════════════════════════════════════════════════ */

* { box-sizing: border-box; }

html {
    scroll-behavior: smooth;
    /* Chừa chỗ cho thanh nav dính khi nhảy tới #anchor, không thì tiêu đề
       mục bị thanh nav che mất. */
    scroll-padding-top: calc(var(--nav-h) + 12px);
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: var(--sans);
    font-size: 15px;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    /* Trên điện thoại phải chừa chỗ cho thanh tab dưới đáy, không thì nội dung
       cuối trang bị nó đè lên. env(safe-area-inset-bottom) là vạch home của
       iPhone — thiếu nó thanh tab bị vạch đó cắt ngang. */
    padding-bottom: 0;
}

h1, h2, h3, h4 {
    font-family: var(--serif);
    font-weight: 600;
    letter-spacing: -.01em;
    color: var(--text);
}

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

/* Ảnh không bao giờ được đẩy rộng hơn khung cha — nguyên nhân số một của
   thanh cuộn ngang trên điện thoại. */
img, svg, video, canvas { max-width: 100%; height: auto; }

/* Ghi đè Bootstrap: các lớp text-* mặc định của nó tính cho nền trắng. */
.text-muted, .text-secondary, .text-black-50 { color: var(--text-muted) !important; }
.text-dark { color: var(--text) !important; }

::selection { background: var(--accent); color: var(--on-accent); }

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 4px;
}

/* Bỏ hiệu ứng chuyển động cho người bật "giảm chuyển động" trong hệ điều
   hành. Không phải trang trí — với người bị rối loạn tiền đình, chuyển động
   lớn gây chóng mặt thật. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
}

/* Chỉ hiện cho trình đọc màn hình. Dùng cho nhãn của nút chỉ có icon. */
.sr-only {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* Nhảy thẳng tới nội dung, bỏ qua điều hướng. Hiện ra khi bấm Tab lần đầu. */
.skip-link {
    position: absolute; left: 8px; top: -60px; z-index: 200;
    background: var(--text); color: var(--bg);
    padding: 10px 16px; border-radius: 8px;
    font-weight: 600; text-decoration: none;
    transition: top .15s;
}
.skip-link:focus { top: 8px; color: var(--bg); }

/* ═══════════════════════════════════════════════════════════════════════
   KHUNG TRANG
   ═══════════════════════════════════════════════════════════════════════ */

.app-main {
    flex: 1;
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    padding: 24px 20px 48px;
}

@media (max-width: 1023.98px) {
    .app-main {
        padding: 16px 14px 24px;
        /* Chỗ cho thanh tab đáy + vạch home iPhone. */
        padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + 20px);
    }
}

/* Tiêu đề trang */
.page-head { margin-bottom: 22px; }
.page-head h1 { font-size: clamp(1.45rem, 4vw, 2rem); margin: 0 0 6px; }
.page-head p { color: var(--text-muted); margin: 0; font-size: .95rem; }

/* Hàng tiêu đề + hành động. Trên điện thoại xuống dòng thay vì tràn ngang —
   đây chính là lỗi nút "Thêm Sản phẩm" bị đẩy ra ngoài màn hình. */
.page-head-row {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 16px; flex-wrap: wrap; margin-bottom: 22px;
}
.page-head-row > .page-head { margin-bottom: 0; flex: 1 1 260px; min-width: 0; }
.page-head-actions { display: flex; gap: 8px; flex-wrap: wrap; }

@media (max-width: 575.98px) {
    .page-head-actions { width: 100%; }
    .page-head-actions > * { flex: 1 1 auto; justify-content: center; }
}

/* =====================================================================
   DIEU HUONG — MENU DOC BEN TRAI

   TAI SAO DOI TU THANH NGANG SANG MENU DOC

   Thanh ngang vo hai lan theo dung mot kieu: chu tran ra khoi khung roi ve
   de len nhom nut ben phai. O man 1364px do duoc chong nhau 101px — "Kho"
   nam duoi icon GitHub, "Khach hang" cut thanh "Khac".

   Toi sua hai lan bang cach do roi chinh moc breakpoint. Ca hai lan deu
   that bai, vi bai toan khong giai duoc theo huong do:

     - So muc KHONG co dinh. No doi theo quyen: phien Google co them muc
       "He thong" ma ban do cua toi thieu.
     - Nhan KHONG co dinh. "Khach hang" dai gap doi "Kho".
     - Be ngang thanh bi chan boi max-width cua chinh no, nen man hinh rong
       them cung khong giup gi.

   Ba bien so nhan nhau thi khong co con so nao tinh truoc duoc bang CSS.

   Menu doc thi chieu cao gan nhu vo han — them bao nhieu muc, nhan dai bao
   nhieu cung khong het cho. Day la bo han CA MOT LOP LOI, khong phai va
   them mot truong hop nua.

   MOT khoi markup, hai cach hoat dong:
     >=1024px  cot co dinh ben trai, cuon rieng
     <1024px   truot vao tu trai khi bam menu, co lop phu nen
   ===================================================================== */

/* flex-direction: row PHAI ghi ro. Quy tac .app-shell cu o phan KHUNG TRANG
   dat flex-direction: column (hoi bo cuc thanh ngang, khi shell chi la mot
   cot doc). Khong ghi de thi sidebar va cot noi dung XEP CHONG len nhau theo
   chieu doc thay vi nam canh nhau — do duoc .app-col o top:820, dung ngay
   duoi sidebar cao 820px. */
/* Dat .icon-btn TRUOC cac quy tac an/hien nut.
   CSS cung do uu tien thi quy tac viet SAU thang. De .icon-btn o cuoi khoi
   thi "display: inline-flex" cua no de len "display: none" trong
   @media(min-width:1024px) cua .sidebar-close va .sidebar-toggle — nut X va
   nut ba gach van hien tren man rong du da bao an. Do duoc: ca hai ra
   display "flex" thay vi "none". */
.icon-btn {
    width: 38px; height: 38px; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 9px; border: 1px solid transparent;
    background: transparent; color: var(--text-muted);
    text-decoration: none; cursor: pointer; font-size: 1.05rem;
    transition: color .15s, background-color .15s, border-color .15s;
}
.icon-btn:hover { color: var(--text); background: var(--surface-hover); border-color: var(--border); }

.app-shell { min-height: 100vh; display: flex; flex-direction: row; align-items: flex-start; }

.sidebar {
    width: 252px; flex-shrink: 0;
    background: var(--surface);
    border-right: 1px solid var(--border);
    display: flex; flex-direction: column;

    /* Duoi 1024px: tam truot phu len trang. */
    position: fixed; top: 0; left: 0; bottom: 0; z-index: 150;
    transform: translateX(-100%);
    transition: transform .22s ease;
    overflow-y: auto; overscroll-behavior: contain;
}
.sidebar.is-open { transform: translateX(0); box-shadow: var(--shadow-lg); }

@media (min-width: 1024px) {
    /* sticky + 100vh: menu dung yen khi cuon noi dung, va tu cuon rieng khi
       danh sach muc dai hon man hinh. */
    .sidebar { position: sticky; height: 100vh; transform: none; box-shadow: none; }
}

.sidebar-backdrop {
    position: fixed; inset: 0; z-index: 140;
    background: rgba(26, 26, 26, .42);
    opacity: 0; pointer-events: none; transition: opacity .2s;
}
.sidebar-backdrop.is-open { opacity: 1; pointer-events: auto; }
@media (min-width: 1024px) { .sidebar-backdrop { display: none; } }

.sidebar-brand {
    display: flex; align-items: center; gap: 8px;
    padding: 14px 14px 10px;
    position: sticky; top: 0; background: var(--surface); z-index: 1;
}
.sidebar-close { margin-left: auto; }
@media (min-width: 1024px) { .sidebar-close { display: none; } }

.brand {
    display: flex; align-items: center; gap: 10px; min-width: 0;
    font-family: var(--serif); font-weight: 600; font-size: 1rem;
    letter-spacing: -.01em; color: var(--text); text-decoration: none;
}
.brand-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.brand-dot {
    width: 28px; height: 28px; border-radius: 8px; flex-shrink: 0;
    background: var(--gradient); color: var(--on-accent);
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: 800; font-size: .82rem; font-family: var(--sans);
}

.sidebar-nav { flex: 1; padding: 4px 10px 12px; display: flex; flex-direction: column; gap: 1px; }

.side-label {
    padding: 14px 10px 5px;
    font-size: .68rem; font-weight: 700; letter-spacing: .12em;
    text-transform: uppercase; color: var(--text-dim);
}

.side-link {
    display: flex; align-items: center; gap: 11px;
    padding: 9px 11px; border-radius: 9px;
    font-size: .9rem; font-weight: 500;
    color: var(--text-muted); text-decoration: none;
    /* Nhan dai thi cat bang dau ba cham — KHONG bao gio tran ra ngoai cot,
       vi cot co be ngang co dinh. Day la diem khac can ban voi thanh ngang. */
    white-space: nowrap; overflow: hidden;
    transition: color .15s, background-color .15s;
}
.side-link span { overflow: hidden; text-overflow: ellipsis; }
.side-link i { font-size: 1.05rem; width: 20px; text-align: center; flex-shrink: 0; color: var(--text-dim); }
.side-link:hover { background: var(--surface-hover); color: var(--text); }
.side-link.is-active {
    background: var(--bg-soft); color: var(--text); font-weight: 600;
    box-shadow: inset 3px 0 0 var(--accent);
}
.side-link.is-active i { color: var(--accent); }

/* So mon trong gio. Dat SAU .side-link span vi quy tac do co cung do uu tien
   va se de len neu viet truoc — badge se bi cat bang dau ba cham thay vi hien
   con so. flex-shrink: 0 de nhan dai cua muc khac khong bop no lai. */
.side-badge {
    margin-left: auto; flex-shrink: 0;
    min-width: 20px; padding: 1px 6px;
    border-radius: 999px;
    background: var(--accent); color: var(--surface);
    font-size: .7rem; font-weight: 700; line-height: 1.5;
    text-align: center; overflow: visible;
}

.sidebar-foot {
    padding: 10px 10px calc(12px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--border);
    position: sticky; bottom: 0; background: var(--surface);
}

.user-card {
    display: flex; align-items: center; gap: 10px; width: 100%;
    padding: 8px 10px; border-radius: 10px;
    background: var(--bg-soft); border: 1px solid var(--border);
    color: var(--text-muted); cursor: pointer; text-align: left;
    transition: background-color .15s, border-color .15s;
}
.user-card:hover { background: var(--surface-hover); border-color: var(--border-bright); }
.user-card-text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.user-card-name { font-size: .84rem; font-weight: 600; color: var(--text); }
.user-card-role { font-size: .72rem; color: var(--text-dim); }
.user-card > i { font-size: .75rem; flex-shrink: 0; }

/* Số phiên bản (FB-056): chân menu và trang đăng nhập, cả hai nền đều là #f3f0ea (6.6:1). */
.app-version {
    margin-top: 8px;
    font-size: .72rem; color: var(--text-muted); text-align: center;
    font-variant-numeric: tabular-nums;
}

.avatar {
    width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
    background: var(--gradient); color: var(--on-accent);
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: .82rem;
}

/* ---- Cot noi dung ben phai ---- */
.app-col { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 100vh; }

.topbar {
    position: sticky; top: 0; z-index: 100;
    height: var(--nav-h); flex-shrink: 0;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    display: flex; align-items: center; gap: 10px;
    padding: 0 16px;
}
.topbar-title {
    font-family: var(--serif); font-weight: 600; font-size: 1rem;
    color: var(--text); min-width: 0;
}
.sidebar-toggle { display: inline-flex; }
@media (min-width: 1024px) { .sidebar-toggle { display: none; } }


/* ═══════════════════════════════════════════════════════════════════════
   MENU THẢ XUỐNG

   Bản cũ: nền rgba(18,18,18,.95) tối kèm chữ --text-muted của nền sáng
   → 3.3:1, không đạt chuẩn. Giờ nền giấy, chữ đủ đậm.
   ═══════════════════════════════════════════════════════════════════════ */

.menu {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    padding: 6px;
    min-width: 240px;
}
.menu .dropdown-item,
.menu-item {
    display: flex; align-items: center; gap: 10px;
    padding: 9px 12px; border-radius: 8px;
    font-size: .9rem; font-weight: 500;
    color: var(--text-muted); text-decoration: none;
    background: transparent; border: 0; width: 100%; text-align: left;
    transition: color .15s, background-color .15s;
}
.menu .dropdown-item:hover, .menu-item:hover,
.menu .dropdown-item:focus, .menu-item:focus {
    background: var(--surface-hover); color: var(--text);
}
.menu .dropdown-item i, .menu-item i {
    font-size: 1rem; width: 18px; text-align: center;
    color: var(--text-dim); flex-shrink: 0;
}
.menu .dropdown-item:hover i, .menu-item:hover i { color: var(--accent); }

.menu-label {
    padding: 10px 12px 5px;
    font-size: .68rem; font-weight: 700; letter-spacing: .12em;
    text-transform: uppercase; color: var(--text-dim);
}
.menu-sep { height: 1px; background: var(--border); margin: 5px 8px; border: 0; }
.menu-text { padding: 4px 12px; font-size: .8rem; color: var(--text-dim); }

/* ═══════════════════════════════════════════════════════════════════════
   THANH TAB ĐÁY — chỉ dưới 992px

   Năm mục. Không hơn: quá năm thì mỗi ô hẹp dưới 64px, bấm nhầm liên tục.
   Mục thứ năm là "Thêm" mở ngăn trượt chứa phần còn lại.
   ═══════════════════════════════════════════════════════════════════════ */

.tabbar {
    display: none;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 120;
    background: var(--surface);
    border-top: 1px solid var(--border);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    box-shadow: 0 -2px 12px rgba(26, 26, 26, .07);
}
@media (max-width: 1023.98px) { .tabbar { display: flex; } }

.tabbar-item {
    flex: 1 1 0; min-width: 0;
    height: var(--tabbar-h);
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 3px; padding: 6px 2px;
    color: var(--text-dim); text-decoration: none;
    background: transparent; border: 0; cursor: pointer;
    font-size: .68rem; font-weight: 600; line-height: 1.1;
    transition: color .15s;
}
.tabbar-item i { font-size: 1.25rem; }
.tabbar-item span {
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tabbar-item:hover { color: var(--text-muted); }
.tabbar-item.is-active { color: var(--accent); }
.tabbar-item.is-active i { transform: translateY(-1px); }

/* Huy hiệu số món trên icon giỏ (thanh tab đáy). <i> làm mốc định vị;
   cỡ chữ đặt lại vì <i> mang font-size 1.25rem của icon. Viền màu nền để
   huy hiệu tách khỏi nét icon khi chồng lên nhau. */
.tabbar-item i { position: relative; }
.tabbar-badge {
    position: absolute; top: -5px; left: 58%;
    min-width: 17px; height: 17px; padding: 0 4px;
    border-radius: 999px;
    background: var(--accent); color: var(--surface);
    font-family: inherit; font-style: normal;
    font-size: .62rem; font-weight: 700; line-height: 17px;
    text-align: center; white-space: nowrap;
    box-shadow: 0 0 0 2px var(--surface);
}

/* ── POS: tìm hàng khi có nhiều món ──
   Hàng nút lọc loại hàng cuộn ngang TRONG khung của nó (overflow-x: auto), không
   bao giờ đẩy trang tràn ra ngoài. Trên 10 loại thì view đổi sang danh sách thả
   xuống. Chữ dùng --text-muted (6.6:1 trên mặt thẻ), nút đang chọn là --surface
   trên --text (16.9:1). */
.pos-count { font-family: var(--sans); font-size: .8rem; font-weight: 500; color: var(--text-muted); white-space: nowrap; }
.pos-chips {
    display: flex; gap: .4rem; overflow-x: auto;
    padding: .75rem 1.25rem 0; scrollbar-width: thin;
}
.pos-chip {
    flex: 0 0 auto;
    border: 1px solid var(--border); background: var(--surface); color: var(--text-muted);
    border-radius: 999px; padding: .3rem .85rem;
    font-size: .85rem; font-weight: 500; cursor: pointer;
    transition: background-color .15s, color .15s;
}
.pos-chip:hover { color: var(--text); background: var(--surface-hover); }
.pos-chip.is-active { background: var(--text); color: var(--surface); border-color: var(--text); }
.pos-empty { padding: 2rem 1rem; text-align: center; color: var(--text-muted); }

/* ═══════════════════════════════════════════════════════════════════════
   TAB TRONG TRANG — dùng cho Ops, Dashboard, Docs
   ═══════════════════════════════════════════════════════════════════════ */

.tabs {
    display: flex; gap: 4px;
    /* Nhiều tab hơn bề ngang thì cuộn ngang TRONG thanh tab, không đẩy cả
       trang cuộn ngang theo. */
    overflow-x: auto; overscroll-behavior-x: contain;
    scrollbar-width: none; -ms-overflow-style: none;
    padding: 4px 0; margin-bottom: 18px;
    border-bottom: 1px solid var(--border);
}
.tabs::-webkit-scrollbar { display: none; }

.tabs a, .tabs button {
    flex-shrink: 0;
    padding: 8px 14px; border-radius: 999px; border: 0; background: transparent;
    font-size: .875rem; font-weight: 500; font-family: inherit;
    color: var(--text-muted); text-decoration: none; cursor: pointer;
    white-space: nowrap;
    transition: color .15s, background-color .15s;
}
.tabs a:hover, .tabs button:hover { background: var(--surface-hover); color: var(--text); }
.tabs a.is-active, .tabs button.is-active {
    background: var(--text); color: var(--surface); font-weight: 600;
}

/* ── Lọc danh mục ở /Shop: chip, đặt lên trên .tabs ──

   Mục không chọn của .tabs chỉ là chữ mờ không viền, không ai biết bấm được, và
   điện thoại không có hover để gợi ý (FB-046). Mọi quy tắc đều có .cat-filter nên
   .tabs của Blog, Ops, Docs không đổi.

   THỨ TỰ CÓ NGHĨA. `.cat-filter a` và `.tabs a` cùng độ ưu tiên, nên khối này phải
   đứng SAU khối .tabs, không thì chip nhận border:0. Trong khối, .is-active phải
   đứng sau :hover: ngược lại thì chip đang chọn khi rê chuột thành chữ sáng trên
   nền sáng. CategoryFilterCssTests ghim thứ tự này.

   Tương phản, tính bằng số:
     chữ --text trên --surface             15.30 : 1
     chữ --text trên --surface-hover       13.49 : 1
     chữ --surface trên --text (đang chọn) 15.30 : 1
     nhãn --text-muted trên canvas          4.79 : 1   (--text-dim chỉ 3.28 : 1)
     viền --text-muted với canvas           4.79 : 1   (--border 1.30, --border-bright 1.76: không đủ 3 : 1)
     vòng focus --accent-bright với canvas  5.61 : 1 */
.cat-filter-hint {
    display: flex; align-items: center; gap: 6px;
    margin: 0 0 4px;
    font-size: .85rem; color: var(--text-muted);
}
/* padding 6px: .tabs có overflow-x nên cắt mọi thứ vượt khỏi khung, vòng focus
   cần 3px nét + 2px khoảng cách. */
.cat-filter { gap: 8px; padding: 6px; }
.cat-filter a {
    display: inline-flex; align-items: center; justify-content: center;
    box-sizing: border-box; min-height: 44px; max-width: 240px; padding: 0 16px;
    border: 1px solid var(--text-muted);
    background: var(--surface); color: var(--text);
    cursor: pointer;
}
/* Tên quá dài không được rộng hơn thanh, không thì không có vị trí cuộn nào thấy trọn
   chip (đo: tên 50 ký tự rộng 363px, thanh 347px ở bề ngang 375). text-overflow không
   tác dụng lên chữ trần trong inline-flex nên phải có span; tên đầy đủ nằm ở title. */
.cat-filter .cat-chip-text {
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cat-filter a:hover { background: var(--surface-hover); border-color: var(--text); color: var(--text); }
.cat-filter a:focus-visible { outline: 3px solid var(--accent-bright); outline-offset: 2px; }
.cat-filter a.is-active {
    background: var(--text); border-color: var(--text); color: var(--surface); font-weight: 700;
}

/* Tên danh mục ở /Categories là link sang trang sửa. Mũi tên nằm sẵn trên trang vì
   điện thoại không có hover; gạch chân chỉ dưới phần chữ, không kéo qua mũi tên. */
.cat-name-link {
    display: inline-flex; align-items: center; gap: 6px;
    min-height: 44px; max-width: 100%;
    color: var(--text); text-decoration: none; cursor: pointer;
}
.cat-name-link:hover { color: var(--text); }
.cat-name-text { min-width: 0; overflow-wrap: anywhere; }
.cat-name-link:hover .cat-name-text,
.cat-name-link:focus-visible .cat-name-text { text-decoration: underline; text-underline-offset: 3px; }
.cat-name-link .bi { flex-shrink: 0; font-size: .8em; color: var(--text-muted); }

/* ═══════════════════════════════════════════════════════════════════════
   THẺ
   ═══════════════════════════════════════════════════════════════════════ */

.card-p {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 20px;
}
.card-p + .card-p { margin-top: 16px; }
.card-head {
    display: flex; align-items: center; gap: 10px;
    margin: 0 0 14px; font-size: 1.05rem;
}
.card-head i { color: var(--accent); }

/* Lưới thẻ tự co. auto-fit + minmax là cách duy nhất tự xuống hàng theo bề
   ngang thật mà không cần một cái @media nào. min() để trên màn 320px cột
   không bị ép rộng hơn màn hình. */
.grid {
    display: grid; gap: 16px;
    grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
}
.grid-sm { grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr)); }
.grid-lg { grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr)); }

/* Ô số liệu */
.stat { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 18px; }
.stat-label {
    font-size: .72rem; font-weight: 700; letter-spacing: .1em;
    text-transform: uppercase; color: var(--text-dim); margin-bottom: 8px;
}
.stat-value {
    font-family: var(--serif); font-size: clamp(1.5rem, 5vw, 2.1rem);
    font-weight: 600; line-height: 1.15; letter-spacing: -.02em;
    /* Số dài (doanh thu) không được đẩy vỡ thẻ. */
    overflow-wrap: anywhere;
}
.stat-sub { font-size: .82rem; color: var(--text-muted); margin-top: 6px; }

/* ═══════════════════════════════════════════════════════════════════════
   BẢNG → THẺ TRÊN ĐIỆN THOẠI

   Bảng 7 cột không bao giờ vừa màn hình 375px. Hai lớp phòng vệ:

   1. .table-wrap — cuộn ngang trong khung riêng. Luôn dùng, cho mọi bảng.
   2. Dưới 768px, bảng có class .table-cards đổi hẳn thành danh sách thẻ,
      mỗi hàng một thẻ, nhãn cột lấy từ thuộc tính data-label của <td>.

   Cách 2 cần <td data-label="Tên cột">. Thiếu data-label thì hàng vẫn đọc
   được, chỉ mất nhãn — hỏng nhẹ, không vỡ layout.
   ═══════════════════════════════════════════════════════════════════════ */

.table-wrap {
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
}

.table-premium {
    width: 100%;
    color: var(--text);
    border-collapse: separate;
    border-spacing: 0 10px;
}
.table-premium tr { background: var(--surface); }
.table-premium th, .table-premium td {
    border: none; padding: 14px 16px;
    vertical-align: middle; background: transparent;
}
.table-premium thead tr { background: transparent; }
.table-premium thead th {
    color: var(--text-muted); font-weight: 700;
    text-transform: uppercase; font-size: .72rem; letter-spacing: .1em;
    padding-bottom: 4px; white-space: nowrap;
}
.table-premium tbody tr { transition: background-color .2s; }
.table-premium tbody tr:hover { background: var(--surface-hover); }
.table-premium td:first-child, .table-premium th:first-child {
    border-top-left-radius: 12px; border-bottom-left-radius: 12px; padding-left: 18px;
}
.table-premium td:last-child, .table-premium th:last-child {
    border-top-right-radius: 12px; border-bottom-right-radius: 12px; padding-right: 18px;
}

@media (max-width: 767.98px) {
    .table-cards, .table-cards tbody, .table-cards tr, .table-cards td { display: block; width: 100%; }
    .table-cards thead { display: none; }

    .table-cards tr {
        background: var(--surface);
        border: 1px solid var(--border);
        border-radius: var(--radius-lg);
        padding: 6px 4px;
        margin-bottom: 12px;
    }
    .table-cards td {
        display: flex; align-items: flex-start; justify-content: space-between;
        gap: 14px; padding: 9px 14px !important;
        border-radius: 0 !important;
        text-align: right;
        min-width: 0;
    }
    .table-cards td + td { border-top: 1px solid var(--border); }
    .table-cards td::before {
        content: attr(data-label);
        flex: 0 0 auto; max-width: 45%;
        text-align: left;
        font-size: .72rem; font-weight: 700; letter-spacing: .08em;
        text-transform: uppercase; color: var(--text-dim);
        padding-top: 2px;
    }
    /* Ô không có nhãn (ảnh, nút thao tác) chiếm trọn bề ngang. */
    .table-cards td[data-label=""]::before,
    .table-cards td:not([data-label])::before { display: none; }
    .table-cards td:not([data-label]) { justify-content: flex-end; }

    /* Giá trị dài (tên sản phẩm) xuống dòng theo TỪ, không cắt giữa chữ.
       "CÁ NỤC GAI" xếp dọc từng chữ là do ô quá hẹp — giờ ô rộng cả hàng. */
    .table-cards td > * { min-width: 0; overflow-wrap: break-word; }
}

/* Bảng lịch sử kho trong cửa sổ nhập kho. Cửa sổ chỉ rộng 500px cho tới 992px
   (modal-lg của Bootstrap) nên 7 cột không lọt: đo ở 768, bảng 585px trong khung
   466px, cột Ghi chú nằm hẳn ngoài khung. .table-cards chỉ bật dưới 768px vì nó
   nhìn bề ngang màn hình chứ không nhìn cửa sổ, nên khoảng giữa làm lại ở đây.
   Chữ liền dài (dán mã lô, đường link) thì tràn ở mọi bề ngang nếu không có anywhere;
   break-word không đủ vì nó không làm cột co lại khi bảng tính bề rộng. */
.stock-history-note { overflow-wrap: anywhere; }

@media (min-width: 768px) and (max-width: 991.98px) {
    .stock-history-table, .stock-history-table tbody, .stock-history-table tr, .stock-history-table td { display: block; width: 100%; }
    .stock-history-table thead { display: none; }

    .stock-history-table tr {
        background: var(--surface);
        border: 1px solid var(--border);
        border-radius: var(--radius-lg);
        padding: 6px 4px;
        margin-bottom: 12px;
    }
    .stock-history-table td {
        display: flex; align-items: flex-start; justify-content: space-between;
        gap: 14px; padding: 9px 14px !important;
        border-radius: 0 !important;
        text-align: right;
        min-width: 0;
    }
    .stock-history-table td + td { border-top: 1px solid var(--border); }
    .stock-history-table td::before {
        content: attr(data-label);
        flex: 0 0 auto; max-width: 45%;
        text-align: left;
        font-size: .72rem; font-weight: 700; letter-spacing: .08em;
        text-transform: uppercase; color: var(--text-dim);
        padding-top: 2px;
    }
    .stock-history-table td:not([data-label])::before { display: none; }
    .stock-history-table td:not([data-label]) { justify-content: center; }
}

/* ═══════════════════════════════════════════════════════════════════════
   BIỂU MẪU
   ═══════════════════════════════════════════════════════════════════════ */

.form-premium, .form-control, .form-select {
    background: var(--surface-sunken);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 10px 14px;
    font-family: inherit;
    /* 16px là ngưỡng: nhỏ hơn thì Safari trên iPhone TỰ PHÓNG TO trang khi
       chạm vào ô nhập, và không thu lại. Đây là lý do form trên iPhone hay
       bị "nhảy" — không phải lỗi layout. */
    font-size: 16px;
    width: 100%;
    transition: border-color .15s, box-shadow .15s, background-color .15s;
}
@media (min-width: 768px) {
    .form-premium, .form-control, .form-select { font-size: .95rem; }
}
/* Ô nhập có nền --surface-sunken, đậm hơn mặt thẻ, nên --text-dim ở đây
   xuống dưới chuẩn. Chữ gợi ý là chữ để ĐỌC, không phải trang trí. */
.form-premium::placeholder, .form-control::placeholder { color: var(--text-muted); opacity: 1; }
.form-premium:focus, .form-control:focus, .form-select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-bg);
    background: var(--surface);
}
.form-label {
    display: block; margin-bottom: 6px;
    font-size: .82rem; font-weight: 600; color: var(--text-muted);
}

/* Hàng ô tìm kiếm + nút. Trên điện thoại nút xuống dòng, không bị ép hẹp. */
.search-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.search-row > .form-premium, .search-row > .form-control { flex: 1 1 200px; min-width: 0; width: auto; }

/* ═══════════════════════════════════════════════════════════════════════
   NÚT

   Cao tối thiểu 44px trên cảm ứng. Đây là kích thước vùng chạm mà Apple và
   Google đều khuyến nghị; nhỏ hơn thì tỷ lệ bấm trượt tăng rõ rệt.
   ═══════════════════════════════════════════════════════════════════════ */

.btn-gradient, .btn-premium, .btn-outline-premium, .btn-ghost {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    padding: 10px 18px; min-height: 42px;
    border-radius: var(--radius);
    font-family: inherit; font-size: .92rem; font-weight: 600;
    text-decoration: none; cursor: pointer; white-space: nowrap;
    transition: transform .15s, box-shadow .15s, background-color .15s, border-color .15s, color .15s;
}
@media (max-width: 767.98px) {
    .btn-gradient, .btn-premium, .btn-outline-premium, .btn-ghost { min-height: 44px; }
}

.btn-gradient { background: var(--gradient); color: var(--on-accent); border: 1px solid transparent; }
.btn-gradient:hover { transform: translateY(-1px); box-shadow: var(--shadow); color: var(--on-accent); }

.btn-premium { background: var(--text); color: var(--surface); border: 1px solid var(--text); }
.btn-premium:hover {
    transform: translateY(-1px); box-shadow: var(--shadow);
    background: var(--accent-bright); border-color: var(--accent-bright); color: var(--surface);
}

.btn-outline-premium { background: transparent; color: var(--text); border: 1px solid var(--border-bright); }
.btn-outline-premium:hover { background: var(--surface); border-color: var(--text-muted); color: var(--text); }

.btn-ghost { background: transparent; color: var(--text-muted); border: 1px solid transparent; }
.btn-ghost:hover { background: var(--surface-hover); color: var(--text); }

.btn-gradient:disabled, .btn-premium:disabled, .btn-outline-premium:disabled,
.btn-gradient[disabled], .btn-premium[disabled], .btn-outline-premium[disabled] {
    background: var(--surface-hover); color: var(--text-dim);
    border-color: var(--border); box-shadow: none; transform: none;
    cursor: not-allowed;
}

/* Nút biểu tượng trong bảng */
.btn-action {
    width: 38px; height: 38px; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 9px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text-muted);
    padding: 0; text-decoration: none; cursor: pointer;
    transition: color .15s, background-color .15s, border-color .15s;
}
.btn-action:hover { border-color: var(--accent); background: var(--accent-bg); color: var(--accent); }
.btn-action-edit:hover { border-color: var(--info); background: var(--info-bg); color: var(--info); }
.btn-action-delete:hover { border-color: var(--err); background: var(--err-bg); color: var(--err); }
.btn-action i { font-size: 1rem; }

.btn-row { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }

/* ═══════════════════════════════════════════════════════════════════════
   HUY HIỆU TRẠNG THÁI

   Không bao giờ chỉ dùng màu để phân biệt trạng thái — khoảng 8% nam giới
   khó phân biệt đỏ với xanh lá. Mỗi huy hiệu có chấm dẫn ở đầu và chữ
   riêng, màu chỉ là lớp thông tin thứ ba.
   ═══════════════════════════════════════════════════════════════════════ */

.badge-p {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 11px; border-radius: 999px;
    font-size: .78rem; font-weight: 600; white-space: nowrap;
    border: 1px solid transparent;
}
.badge-p::before {
    content: ""; width: 6px; height: 6px; border-radius: 50%;
    background: currentColor; flex-shrink: 0;
}
.badge-ok   { color: var(--ok-text);   background: var(--ok-bg);   border-color: rgba(31,111,67,.22); }
.badge-warn { color: var(--warn-text); background: var(--warn-bg); border-color: rgba(138,90,18,.22); }
.badge-err  { color: var(--err-text);  background: var(--err-bg);  border-color: rgba(163,55,44,.22); }
.badge-info { color: var(--info-text); background: var(--info-bg); border-color: rgba(43,95,131,.22); }
.badge-mute { color: var(--text-muted); background: var(--bg-soft); border-color: var(--border); }

/* ═══════════════════════════════════════════════════════════════════════
   TRỐNG RỖNG
   ═══════════════════════════════════════════════════════════════════════ */

.empty {
    text-align: center; padding: 48px 20px;
    background: var(--surface); border: 1px dashed var(--border-bright);
    border-radius: var(--radius-lg); color: var(--text-muted);
}
.empty i { font-size: 2.2rem; color: var(--text-dim); display: block; margin-bottom: 12px; }
.empty h3 { font-size: 1.05rem; margin: 0 0 6px; }
.empty p { margin: 0 0 16px; font-size: .9rem; }

/* ═══════════════════════════════════════════════════════════════════════
   CHÂN TRANG
   ═══════════════════════════════════════════════════════════════════════ */

.app-footer {
    background: var(--bg);
    border-top: 1px solid var(--border);
    padding: 28px 20px 24px;
    /* Chân trang nằm trên canvas chứ không trên thẻ, nên không được dùng
       --text-dim (3.3:1 ở đó). */
    color: var(--text-muted); font-size: .85rem;
}
.app-footer-inner {
    max-width: 1180px; margin: 0 auto;
    display: flex; justify-content: space-between; flex-wrap: wrap; gap: 10px;
}
.app-footer a { color: var(--text-muted); text-decoration: none; }
.app-footer a:hover { color: var(--text); }

@media (max-width: 1023.98px) {
    /* Chân trang nằm dưới thanh tab thì không ai thấy. Đẩy lên. */
    .app-footer { padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + 20px); }
}

/* ═══════════════════════════════════════════════════════════════════════
   TIỆN ÍCH
   ═══════════════════════════════════════════════════════════════════════ */

.stack   { display: flex; flex-direction: column; gap: 12px; }
.row-flex{ display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.truncate{ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.hide-sm { display: none; }
@media (min-width: 768px) { .hide-sm { display: revert; } .only-sm { display: none; } }

/* ═══════════════════════════════════════════════════════════════════════
   BÍ DANH TƯƠNG THÍCH

   Layout cũ đặt tên .user-avatar; layout mới gọi là .avatar. Giữ bí danh
   thay vì sửa view, vì view khác có thể còn dùng — và một class thiếu định
   nghĩa hỏng ÂM THẦM: chữ vẫn hiện, chỉ mất hình tròn và màu nền, không có
   lỗi nào báo ra.
   ═══════════════════════════════════════════════════════════════════════ */

.user-avatar {
    width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
    background: var(--gradient); color: var(--on-accent);
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: .8rem;
}

/* ═══════════════════════════════════════════════════════════════════════
   HIỆU ỨNG DI CHUỘT — chỉ cho thiết bị THẬT SỰ có chuột

   Trên màn cảm ứng, :hover dính lại sau khi chạm: thẻ nhấc lên 5px rồi ở
   nguyên đó tới khi chạm chỗ khác. Nhìn như lỗi. (hover: hover) loại điện
   thoại và máy tính bảng ra khỏi các quy tắc này.
   ═══════════════════════════════════════════════════════════════════════ */

@media (hover: none) {
    .dashboard-card:hover,
    .table-premium tbody tr:hover,
    .btn-gradient:hover, .btn-premium:hover, .btn-outline-premium:hover {
        transform: none !important;
    }
}

/* ═══════════════════════════════════════════════════════════════════════
   KHUNG BIỂU ĐỒ

   Chart.js với maintainAspectRatio:false lấy chiều cao từ thẻ cha. Cha phải
   có position:relative và chiều cao xác định, nếu không canvas cao 0 và
   biểu đồ "mất tích" dù dữ liệu đúng.
   ═══════════════════════════════════════════════════════════════════════ */

.chart-box { position: relative; width: 100%; height: 300px; }

@media (max-width: 767.98px) {
    /* Chú giải chuyển xuống dưới trên điện thoại nên cần thêm chỗ, không thì
       vòng tròn bị ép còn bằng đầu ngón tay. */
    .chart-box { height: 360px; }
}

/* ═══════════════════════════════════════════════════════════════════════
   GHI ĐÈ MÀU NGỮ NGHĨA CỦA BOOTSTRAP

   Bootstrap chọn màu cho nền TRẮNG. Trên nền giấy #f3f0ea chúng hỏng nặng —
   đo thật trên nền này:

     .text-warning  #ffc107   1.4 : 1   gần như vô hình  (21 chỗ)
     .text-info     #0dcaf0   1.9 : 1   gần như vô hình
     .text-success  #198754   3.9 : 1   dưới chuẩn
     .text-danger   #dc3545   4.5 : 1   sát mép
     .text-primary  #0d6efd   4.5 : 1   sát mép

   Bảng màu portfolio, đo trên cùng nền, đều 5.2–6.1 : 1. Ghi đè ở ĐÂY một
   lần thay vì sửa 128 chỗ trong 39 view: ít rủi ro hơn, và trang viết sau
   này lỡ dùng class Bootstrap thì vẫn tự đúng màu.
   ═══════════════════════════════════════════════════════════════════════ */

/* Dung ban --*-text (dam hon) chu KHONG dung mau goc: cac lop nay hay duoc
   dat tran tren nen canvas, cho mau goc khong dat chuan. */
.text-success { color: var(--ok-text) !important; }
.text-warning { color: var(--warn-text) !important; }
.text-danger  { color: var(--err-text) !important; }
.text-primary { color: var(--info-text) !important; }
.text-info    { color: var(--info-text) !important; }

.bg-success-subtle { background-color: var(--ok-bg) !important; }
.bg-warning-subtle { background-color: var(--warn-bg) !important; }
.bg-danger-subtle  { background-color: var(--err-bg) !important; }
.bg-primary-subtle,
.bg-info-subtle    { background-color: var(--info-bg) !important; }

/* Huy hiệu Bootstrap trên nền giấy */
.badge.bg-success-subtle { color: var(--ok-text) !important; }
.badge.bg-warning-subtle { color: var(--warn-text) !important; }
.badge.bg-danger-subtle  { color: var(--err-text) !important; }
.badge.bg-primary-subtle,
.badge.bg-info-subtle    { color: var(--info-text) !important; }
.badge.bg-warning { background-color: var(--warn-bg) !important; color: var(--warn-text) !important; }
/* Khách nợ là trạng thái duy nhất còn việc phải đòi, nên nổi hơn "Đã huỷ" cùng màu. */
.badge-debt-glow { box-shadow: 0 0 8px rgba(163, 55, 44, .25); }

/* Hộp thông báo */
.alert {
    border-radius: var(--radius-lg);
    border: 1px solid var(--border);
    padding: 14px 16px;
}
.alert-success { background: var(--ok-bg)   !important; border-color: rgba(31,111,67,.25)  !important; color: var(--ok-text)   !important; }
.alert-info    { background: var(--info-bg) !important; border-color: rgba(43,95,131,.25)  !important; color: var(--info-text) !important; }
.alert-warning { background: var(--warn-bg) !important; border-color: rgba(138,90,18,.25)  !important; color: var(--warn-text) !important; }
.alert-danger  { background: var(--err-bg)  !important; border-color: rgba(163,55,44,.25)  !important; color: var(--err-text)  !important; }

/* Nút phụ. Mặc định của Bootstrap là xám #6c757d, chọi với tông giấy. */
.btn-outline-secondary {
    color: var(--text-muted) !important;
    border-color: var(--border-bright) !important;
    background: transparent !important;
}
.btn-outline-secondary:hover {
    color: var(--text) !important;
    background: var(--surface-hover) !important;
    border-color: var(--text-muted) !important;
}

/* Bootstrap dựng .card cho nền trắng. */
.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    color: var(--text);
}

/* Ô nhập ghép (input-group-text) — nền trắng mặc định thành vệt sáng chói
   cạnh ô nhập màu giấy trũng. */
.input-group-text {
    background: var(--bg-soft);
    border-color: var(--border);
    color: var(--text-muted);
}

/* Bảng của Bootstrap đặt --bs-table-bg trắng, đè lên nền giấy của hàng. */
.table { --bs-table-bg: transparent; color: var(--text); }
.table > :not(caption) > * > * { background-color: transparent; }

/* ═══════════════════════════════════════════════════════════════════════
   HỘP THOẠI (MODAL)

   .modal-content của Bootstrap mặc định nền trắng. Có 9 hộp thoại trong 7
   view, phần lớn từng bị nhét nền tối rgba(22,22,22,.95) bằng style inline
   — dấu tích của theme cũ. Gom về một chỗ ở đây.
   ═══════════════════════════════════════════════════════════════════════ */

.modal-content {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    color: var(--text);
    box-shadow: var(--shadow-lg);
}
.modal-header, .modal-footer { border-color: var(--border); }
.modal-backdrop.show { opacity: .45; }

/* Trên điện thoại, hộp thoại dán sát đáy màn hình như bảng kéo lên (sheet):
   ngón cái với tới nút được, và không bị thanh địa chỉ của trình duyệt che.
   Hộp thoại canh giữa màn hình cao là kiểu của máy tính để bàn. */
@media (max-width: 575.98px) {
    .modal-dialog {
        margin: 0; position: absolute; bottom: 0; left: 0; right: 0;
        max-width: 100%;
    }
    .modal-content {
        border-radius: var(--radius-lg) var(--radius-lg) 0 0;
        border-bottom: 0;
        max-height: 92vh; overflow-y: auto;
        padding-bottom: env(safe-area-inset-bottom, 0px);
    }
}

/* Bootstrap dựng cái này cho thanh nav tối. Trên nền giấy phải lật lại,
   không thì ra menu đen chữ xám — đúng lỗi cũ, 3.3:1. */
.dropdown-menu-dark {
    background: var(--surface) !important;
    border: 1px solid var(--border) !important;
    color: var(--text) !important;
    box-shadow: var(--shadow-lg);
}
.dropdown-menu-dark .dropdown-item { color: var(--text-muted) !important; }
.dropdown-menu-dark .dropdown-item:hover,
.dropdown-menu-dark .dropdown-item:focus {
    background: var(--surface-hover) !important; color: var(--text) !important;
}
.dropdown-menu-dark .dropdown-divider { border-color: var(--border) !important; }

/* Phân trang */
.page-link {
    background: var(--surface) !important;
    border-color: var(--border) !important;
    color: var(--text) !important;
}
.page-link:hover { background: var(--surface-hover) !important; }
.page-item.active .page-link {
    background: var(--text) !important;
    border-color: var(--text) !important;
    color: var(--surface) !important;
}
.page-item.disabled .page-link { color: var(--text-dim) !important; opacity: .6; }

/* Tab của Bootstrap */
.nav-tabs { border-bottom-color: var(--border); }
.nav-tabs .nav-link { color: var(--text-muted); border: 0; border-bottom: 2px solid transparent; }
.nav-tabs .nav-link:hover { color: var(--text); border-bottom-color: var(--border-bright); }
.nav-tabs .nav-link.active {
    color: var(--text); background: transparent;
    border-bottom-color: var(--accent); font-weight: 600;
}

/* Nút đóng của Bootstrap là ảnh SVG MÀU TRẮNG nhúng sẵn — trên nền giấy nó
   tàng hình. filter đảo màu là cách duy nhất đổi được mà không phải tự vẽ
   lại icon. */
.btn-close { filter: invert(1) grayscale(100%) brightness(.35); opacity: .7; }
.btn-close:hover { opacity: 1; }

/* ═══════════════════════════════════════════════════════════════════════
   THÔNG BÁO KẾT QUẢ

   Dùng cho _Alerts.cshtml — khối hiện ở đầu nội dung mỗi trang sau khi làm
   một việc gì đó (lưu, xoá, đăng nhập, vào phòng share…).

   Không tự tắt sau vài giây. Thông báo lỗi mà tự biến mất thì người đọc
   chậm, người vừa ngước lên, hoặc người dùng trình đọc màn hình sẽ không kịp
   biết chuyện gì đã xảy ra.
   ═══════════════════════════════════════════════════════════════════════ */

.alert-stack { display: flex; flex-direction: column; gap: 10px; margin-bottom: 20px; }

.alert-p {
    display: flex; align-items: flex-start; gap: 12px;
    padding: 13px 14px;
    border: 1px solid;
    border-left-width: 4px;      /* vạch dày bên trái: nhận ra loại thông báo
                                    ngay cả khi không phân biệt được màu */
    border-radius: var(--radius);
    font-size: .92rem;
    background: var(--surface);
}
.alert-p > i { font-size: 1.05rem; line-height: 1.5; flex-shrink: 0; }
.alert-body { flex: 1; min-width: 0; overflow-wrap: anywhere; }
/* Email Google dài không có chỗ ngắt từng làm /MyOrders tràn ngang ở 375px (FB-045). */
.my-orders-email { overflow-wrap: anywhere; }
.alert-label { display: block; font-weight: 700; font-size: .78rem; letter-spacing: .04em; }
.alert-text { color: var(--text); }

.alert-ok   { border-color: rgba(31,111,67,.35);  background: var(--ok-bg); }
.alert-ok   > i, .alert-ok .alert-label   { color: var(--ok-text); }
.alert-err  { border-color: rgba(163,55,44,.35);  background: var(--err-bg); }
.alert-err  > i, .alert-err .alert-label  { color: var(--err-text); }
.alert-warn { border-color: rgba(138,90,18,.35);  background: var(--warn-bg); }
.alert-warn > i, .alert-warn .alert-label { color: var(--warn-text); }
.alert-info { border-color: rgba(43,95,131,.35);  background: var(--info-bg); }
.alert-info > i, .alert-info .alert-label { color: var(--info-text); }

.alert-close {
    flex-shrink: 0; width: 30px; height: 30px;
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent; border: 0; border-radius: 7px;
    color: var(--text-muted); cursor: pointer; font-size: .8rem;
}
.alert-close:hover { background: rgba(26,26,26,.07); color: var(--text); }

/* Thông báo ngay dưới ô nhập — dùng cho kiểm tra tại chỗ, không cần tải lại
   trang. Ví dụ: gõ sai mã phòng share. */
.field-msg {
    display: none;
    align-items: flex-start; gap: 8px;
    margin-top: 10px; padding: 10px 12px;
    border-radius: var(--radius); border: 1px solid;
    font-size: .88rem; text-align: left;
}
.field-msg.is-shown { display: flex; }
.field-msg i { flex-shrink: 0; line-height: 1.5; }
.field-msg.err  { background: var(--err-bg);  border-color: rgba(163,55,44,.35);  color: var(--err-text); }
.field-msg.ok   { background: var(--ok-bg);   border-color: rgba(31,111,67,.35);  color: var(--ok-text); }
.field-msg.warn { background: var(--warn-bg); border-color: rgba(138,90,18,.35); color: var(--warn-text); }
.field-msg.info { background: var(--info-bg); border-color: rgba(43,95,131,.35); color: var(--info-text); }

/* Nút đang chờ xử lý. Không có trạng thái này thì người dùng bấm lại nhiều
   lần vì tưởng chưa ăn — tạo ra đơn trùng. */
.is-busy { position: relative; pointer-events: none; opacity: .72; }
.is-busy::after {
    content: ""; width: 14px; height: 14px; margin-left: 8px;
    border: 2px solid currentColor; border-right-color: transparent;
    border-radius: 50%; display: inline-block;
    animation: spin .6s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ═══════════════════════════════════════════════════════════════════════
   THẺ SẢN PHẨM — gian hàng công khai

   Khác thẻ ở trang quản lý: ở đây người xem là NGƯỜI MUA, nên ảnh to, giá
   nổi, và nút thêm vào giỏ luôn nằm cuối thẻ ở cùng một độ cao dù mô tả
   dài ngắn khác nhau.
   ═══════════════════════════════════════════════════════════════════════ */

.shop-card {
    display: flex; flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    transition: border-color .15s, box-shadow .15s, transform .15s;
}
@media (hover: hover) {
    .shop-card:hover { border-color: var(--border-bright); box-shadow: var(--shadow); transform: translateY(-2px); }
}
/* Món hết hàng vẫn hiện — khách biết là có bán, hôm khác quay lại. Nhưng
   làm nhạt đi để mắt lướt qua phần còn mua được trước. */
.shop-card.is-out { opacity: .72; }

.shop-thumb {
    display: block; position: relative;
    aspect-ratio: 4 / 3; background: var(--bg-soft);
    overflow: hidden;
}
.shop-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.shop-thumb-empty {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    color: var(--text-dim); font-size: 2rem;
}
.shop-flag {
    position: absolute; top: 10px; left: 10px;
    background: var(--err-bg); color: var(--err-text);
    border: 1px solid rgba(163,55,44,.3);
    padding: 3px 10px; border-radius: 999px;
    font-size: .74rem; font-weight: 700;
}

.shop-body { padding: 14px; display: flex; flex-direction: column; gap: 8px; flex: 1; }

.shop-name { font-size: 1rem; margin: 0; line-height: 1.3; }
.shop-name a { color: var(--text); text-decoration: none; }
.shop-name a:hover { color: var(--accent); }

.shop-desc {
    margin: 0; font-size: .85rem; color: var(--text-muted);
    /* Cắt đúng hai dòng để mọi thẻ cao bằng nhau — mô tả dài ngắn khác nhau
       mà không cắt thì hàng thẻ so le, nút bấm mỗi cái một chỗ. */
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden;
}

.shop-price-row {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px; flex-wrap: wrap;
    /* margin-top:auto đẩy giá + nút xuống đáy thẻ, nên chúng thẳng hàng
       ngang qua mọi thẻ dù nội dung trên khác nhau. */
    margin-top: auto;
}
.shop-price {
    font-family: var(--serif); font-size: 1.15rem; font-weight: 600;
    color: var(--accent);
}
.shop-price small { font-size: .78rem; color: var(--text-muted); font-family: var(--sans); }

.shop-buy { display: flex; gap: 8px; }
.shop-buy input { width: 78px; flex: 0 0 auto; }
.shop-buy button { flex: 1; }

/* ═══════════════════════════════════════════════════════════════════════
   BLOG — trang đọc và form soạn bài
   ═══════════════════════════════════════════════════════════════════════ */

/* Form soạn bài: nội dung bên trái, các lựa chọn bên phải. Dưới 900px thì
   xếp dọc, phần nội dung lên trước — người viết quan tâm chữ trước, ảnh bìa
   và trạng thái tính sau. */
.editor-grid { display: grid; gap: 16px; grid-template-columns: 1fr; }
@media (min-width: 900px) { .editor-grid { grid-template-columns: minmax(0, 1fr) 320px; } }

/* Nút Lưu thứ hai ở cuối form, chỉ cho màn hình dưới 1024px. */
.form-end-actions { display: none; }
@media (max-width: 1023.98px) {
    .form-end-actions { display: flex; justify-content: flex-end; margin-top: 16px; }
}
@media (max-width: 575.98px) {
    .form-end-actions > * { flex: 1 1 auto; justify-content: center; }
}

.char-count { text-align: right; font-size: .78rem; color: var(--text-dim); margin-top: 4px; }

.radio-row {
    display: flex; align-items: flex-start; gap: 10px;
    padding: 10px; border-radius: var(--radius);
    border: 1px solid var(--border); cursor: pointer;
    transition: border-color .15s, background-color .15s;
}
.radio-row + .radio-row { margin-top: 8px; }
.radio-row:hover { background: var(--surface-hover); }
.radio-row:has(input:checked) { border-color: var(--accent); background: var(--accent-bg); }
.radio-row input { margin-top: 3px; flex-shrink: 0; }
.radio-row span { display: flex; flex-direction: column; }
.radio-row small { color: var(--text-muted); font-size: .8rem; }

.cover-box {
    position: relative; width: 100%; aspect-ratio: 16 / 9;
    background: var(--bg-soft);
    border: 1px dashed var(--border-bright); border-radius: var(--radius);
    overflow: hidden;
    display: flex; align-items: center; justify-content: center;
}
.cover-box img { width: 100%; height: 100%; object-fit: cover; }
.cover-empty {
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    color: var(--text-muted); text-align: center; padding: 12px;
}
.cover-empty i { font-size: 1.8rem; color: var(--text-dim); }
.cover-empty small { font-size: .76rem; color: var(--text-dim); }

/* ── Trang đọc bài ── */
.post { max-width: 720px; margin: 0 auto; }
.post-title {
    font-size: clamp(1.6rem, 5vw, 2.4rem);
    line-height: 1.2; margin: 10px 0 8px;
}
.post-meta { color: var(--text-muted); font-size: .88rem; margin: 0 0 20px; }
.post-cover {
    width: 100%; border-radius: var(--radius-lg);
    border: 1px solid var(--border); margin-bottom: 22px;
}
.post-lead {
    font-size: 1.1rem; color: var(--text-muted);
    padding-left: 14px; border-left: 3px solid var(--accent);
    margin: 0 0 22px;
}

.post-body {
    /* pre-line giữ nguyên xuống dòng và đoạn mà người viết gõ, nhưng gộp
       khoảng trắng thừa. Đây là thứ cho phép ô soạn thảo nhận văn bản THUẦN
       mà vẫn ra bài đọc được — không cần nhận HTML, nên không có đường cho
       script lạ chạy trên trang công khai. */
    white-space: pre-line;
    font-size: 1.02rem; line-height: 1.75;
    overflow-wrap: break-word;
}

/* Dòng chữ dài quá thì mỏi mắt. ~70 ký tự một dòng là khoảng dễ đọc nhất,
   .post đã giới hạn 720px cho đúng khoảng đó. */
