/* ============================================================
   Be Vietnam Pro — tự host, subset vietnamese + latin, weight 400/500/600/700/800
   ============================================================ */
@font-face {
  font-family: 'Be Vietnam Pro';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/be-vietnam-pro-400-vietnamese.woff2') format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: 'Be Vietnam Pro';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/be-vietnam-pro-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Be Vietnam Pro';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/be-vietnam-pro-500-vietnamese.woff2') format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: 'Be Vietnam Pro';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/be-vietnam-pro-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Be Vietnam Pro';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/be-vietnam-pro-600-vietnamese.woff2') format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: 'Be Vietnam Pro';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/be-vietnam-pro-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Be Vietnam Pro';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/be-vietnam-pro-700-vietnamese.woff2') format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: 'Be Vietnam Pro';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/be-vietnam-pro-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Be Vietnam Pro';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('/fonts/be-vietnam-pro-800-vietnamese.woff2') format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: 'Be Vietnam Pro';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('/fonts/be-vietnam-pro-800-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ============================================================
   DESIGN TOKENS — 04_Design_System.md
   Lớp 1 (primitive) → lớp 2 (semantic). Component CHỈ dùng semantic.
   ============================================================ */
:root {
  /* --- Primitive: Slate --- */
  --slate-50:  #F8FAFC; --slate-100: #F1F5F9; --slate-200: #E2E8F0;
  --slate-300: #CBD5E1; --slate-400: #94A3B8; --slate-500: #64748B;
  --slate-600: #475569; --slate-700: #334155; --slate-800: #1E293B;
  --slate-900: #0F172A;
  /* --- Primitive: Green (hành động + thương hiệu) --- */
  --green-50: #E9F9EF; --green-100: #D9F2E3; --green-200: #A6E0BC;
  --green-400: #22C55E; --green-500: #16A34A; --green-600: #15803D; --green-700: #0F6B30;
  /* --- Primitive: Blue (primary hành động + thương hiệu FastClub) --- */
  --blue-50: #EFF6FF; --blue-100: #DBEAFE; --blue-200: #BFDBFE; --blue-300: #93C5FD;
  --blue-400: #60A5FA; --blue-500: #2563EB; --blue-600: #1D4ED8; --blue-700: #1E40AF;
  /* --- Primitive: Violet (accent icon tile) --- */
  --violet-500: #7C3AED; --violet-300: #C4B5FD;
  /* --- Primitive: Red (danger / money âm) --- */
  --red-50: #FEF2F2; --red-100: #FBDADA; --red-200: #F3A8A8;
  --red-400: #F87171; --red-500: #DC2626; --red-600: #B91C1C; --red-700: #8A1919;
  /* --- Primitive: Amber (accent ấm) --- */
  --amber-50: #FFF7ED; --amber-100: #FDE5D1; --amber-200: #FBC496;
  --amber-400: #FB923C; --amber-500: #F97316; --amber-600: #EA580C; --amber-700: #7C380B;

  /* --- Spacing (4px) --- */
  --space-2xs: .25rem; --space-xs: .5rem; --space-sm: .75rem; --space-md: 1rem;
  --space-lg: 1.5rem; --space-xl: 2rem; --space-2xl: 3rem; --space-3xl: 4rem;

  /* --- Radius --- */
  --radius-sm: 8px; --radius-md: 10px; --radius-lg: 16px;
  --radius-btn: 14px; --radius-card: 20px; --radius-pill: 999px;

  /* --- Content width --- */
  --w-narrow: 560px; --w-content: 720px; --w-wide: 960px;

  /* --- Motion --- */
  --motion-instant: 100ms; --motion-fast: 150ms; --motion-base: 250ms;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);

  /* --- Kích thước khung --- */
  --sidebar-width: 248px; --bottom-nav-height: 60px; --topbar-height: 56px;

  /* --- Sidebar TỐI (FastClub) — độc lập theme sáng/tối, luôn navy --- */
  --nav-bg:           linear-gradient(180deg, #0B1E40 0%, #0A1730 100%);
  --nav-text:         #C7D2E4;
  --nav-text-strong:  #F8FAFC;
  --nav-text-muted:   #8394B0;
  --nav-group-label:  #64789B;
  --nav-border:       rgba(148,163,184,.14);
  --nav-hover-bg:     rgba(148,163,184,.10);
  --nav-active-bg:    var(--blue-500);
  --nav-active-text:  #FFFFFF;
  --nav-brand-mark-bg: var(--blue-500);
}

/* ============================================================
   SEMANTIC — Light (mặc định) + [data-bs-theme="light"]
   ============================================================ */
:root,
[data-bs-theme="light"] {
  --surface:        #FFFFFF;
  --surface-sunken: var(--slate-50);
  --surface-muted:  var(--slate-100);
  --border:         var(--slate-200);
  --border-strong:  var(--slate-300);
  --text:           var(--slate-800);
  --text-strong:    var(--slate-900);
  --text-muted:     var(--slate-600);
  --text-disabled:  var(--slate-400);

  --action-primary:       var(--blue-500);
  --action-primary-hover: var(--blue-600);
  --action-secondary:     var(--green-500);

  --money-positive: var(--green-600);
  --money-negative: var(--red-500);
  --money-neutral:  var(--slate-800);

  --status-danger:  var(--red-500);
  --status-warning: var(--amber-500);
  --status-info:    var(--blue-500);

  --focus-ring: rgba(37, 99, 235, .38);

  --sidebar-active-bg:   var(--blue-100);
  --sidebar-active-text: var(--blue-700);

  --elevation-1: 0 1px 2px rgba(15,23,42,.04), 0 2px 6px rgba(15,23,42,.06);
  --elevation-2: 0 2px 4px rgba(15,23,42,.04), 0 8px 24px rgba(15,23,42,.08);
  --elevation-3: 0 8px 16px rgba(15,23,42,.08), 0 24px 48px rgba(15,23,42,.14);

  /* Badge soft — foreground đổi theo theme, background dùng rgba (chung 2 theme) */
  --badge-green-fg: #0F6B30; --badge-blue-fg: #1E40AF; --badge-red-fg: #8A1919;
  --badge-amber-fg: #7C380B; --badge-slate-fg: #475569;

  /* --- Ghi đè biến Bootstrap --- */
  --bs-primary: var(--action-primary);
  --bs-primary-rgb: 37, 99, 235;
  --bs-primary-text-emphasis: var(--blue-700);
  --bs-primary-bg-subtle: var(--blue-100);
  --bs-primary-border-subtle: var(--blue-200);
  --bs-success: var(--green-500);
  --bs-success-rgb: 22, 163, 74;
  --bs-danger: var(--red-500);
  --bs-danger-rgb: 220, 38, 38;
  --bs-warning: var(--amber-500);
  --bs-warning-rgb: 249, 115, 22;
  --bs-info: var(--blue-500);
  --bs-info-rgb: 37, 99, 235;
  --bs-body-bg: var(--surface-sunken);
  --bs-body-color: var(--text);
  --bs-secondary-color: var(--text-muted);
  --bs-border-color: var(--border);
  --bs-border-radius: var(--radius-md);
  --bs-border-radius-sm: var(--radius-sm);
  --bs-border-radius-lg: var(--radius-lg);
  --bs-body-font-family: 'Be Vietnam Pro', system-ui, -apple-system, 'Segoe UI', sans-serif;
}

/* ============================================================
   SEMANTIC — Dark
   ============================================================ */
[data-bs-theme="dark"] {
  --surface:        #1E293B;
  --surface-sunken: #0F172A;
  --surface-muted:  #334155;
  --border:         #334155;
  --border-strong:  #475569;
  --text:           #E2E8F0;
  --text-strong:    #F8FAFC;
  --text-muted:     #94A3B8;
  --text-disabled:  #64748B;

  --action-primary:       var(--blue-400);
  --action-primary-hover: var(--blue-300);
  --action-secondary:     var(--green-400);

  --money-positive: #4ADE80;
  --money-negative: #F87171;
  --money-neutral:  #E2E8F0;

  --status-danger:  #F87171;
  --status-warning: #FB923C;
  --status-info:    #60A5FA;

  --focus-ring: rgba(96, 165, 250, .45);

  --sidebar-active-bg:   rgba(59, 130, 246, .20);
  --sidebar-active-text: #93C5FD;

  --elevation-1: 0 1px 3px rgba(0,0,0,.40), 0 1px 2px rgba(0,0,0,.30);
  --elevation-2: 0 4px 12px rgba(0,0,0,.45), 0 2px 4px rgba(0,0,0,.35);
  --elevation-3: 0 16px 40px rgba(0,0,0,.55), 0 4px 12px rgba(0,0,0,.40);

  --badge-green-fg: #4ADE80; --badge-blue-fg: #93C5FD; --badge-red-fg: #FCA5A5;
  --badge-amber-fg: #FDBA74; --badge-slate-fg: #CBD5E1;

  --bs-primary: var(--action-primary);
  --bs-primary-rgb: 96, 165, 250;
  --bs-primary-text-emphasis: #93C5FD;
  --bs-primary-bg-subtle: rgba(59,130,246,.18);
  --bs-primary-border-subtle: rgba(59,130,246,.32);
  --bs-success: var(--green-400);
  --bs-success-rgb: 34, 197, 94;
  --bs-danger: #F87171;
  --bs-danger-rgb: 248, 113, 113;
  --bs-warning: #FB923C;
  --bs-warning-rgb: 251, 146, 60;
  --bs-info: #60A5FA;
  --bs-info-rgb: 96, 165, 250;
  --bs-body-bg: var(--surface-sunken);
  --bs-body-color: var(--text);
  --bs-secondary-color: var(--text-muted);
  --bs-border-color: var(--border);
  --bs-emphasis-color: var(--text-strong);
}

/* ============================================================
   BASE
   ============================================================ */
/* Luôn chừa chỗ cho thanh cuộn dọc — thiếu dòng này, trang có nội dung ngắn (không cần cuộn) sẽ
   nhích ngang vài px so với trang có nội dung dài (có thanh cuộn) vì layout mất/còn khác nhau bề
   rộng viewport khả dụng. Rõ nhất khi chuyển qua lại giữa các tab cùng một nhóm (VD: Cài đặt). */
html {
  scrollbar-gutter: stable;
}
/* scrollbar-gutter:stable chỉ áp dụng khi overflow ở trạng thái auto/scroll — Bootstrap Modal khoá
   cuộn nền bằng cách set body.style.overflow = 'hidden' (bootstrap.bundle.js ScrollBarHelper), làm
   "gutter" vừa chừa sẵn ở trên BIẾN MẤT đúng lúc đó, ĐỒNG THỜI Bootstrap còn tự cộng thêm
   padding-right = bề rộng thanh cuộn vào <body> để "bù" cho thanh cuộn biến mất — cộng dồn hai hiệu
   ứng này khiến bề rộng nội dung hụt hẳn một khoảng bằng bề rộng thanh cuộn (~15-17px) trong lúc
   modal mở, nội dung (căn giữa bằng margin auto trong .page-content) nhích ngang, rồi trả lại đúng vị
   trí cũ khi đóng modal — đã đo trực tiếp bằng CDP (BEFORE/AFTER getBoundingClientRect lệch, dừng
   lệch khi bỏ dòng padding-right này). Phần bù của Bootstrap thành thừa vì gutter đã tự lo chuyện
   này rồi — vô hiệu hoá nó bằng !important (thắng inline style Bootstrap tự set qua JS). */
body.modal-open {
  padding-right: 0 !important;
}
body {
  background: var(--surface-sunken);
  color: var(--text);
}
h1, h2, h3, h4, h5, h6 { font-weight: 700; color: var(--text-strong); }
h1 { font-size: 1.5rem; line-height: 2rem; letter-spacing: -.01em; }
h2 { font-size: 1.25rem; line-height: 1.75rem; }
h3 { font-size: 1.125rem; line-height: 1.625rem; font-weight: 600; }
a { color: var(--action-primary); }
a:hover { color: var(--action-primary-hover); }

/* Focus ring thống nhất — không bao giờ mất dấu focus */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
.form-control:focus-visible,
.form-select:focus-visible,
.stat-card:focus-visible,
.app-sidebar-nav .nav-link:focus-visible,
.app-bottom-nav-item:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--focus-ring);
}

/* Input ≥16px trên mobile — chống Safari iOS auto-zoom */
.form-control, .form-select { font-size: 1rem; background: var(--surface); color: var(--text); }

/* ============================================================
   TYPOGRAPHY UTILITIES
   ============================================================ */
.text-app-muted { color: var(--text-muted) !important; }
.text-caption {
  font-size: .75rem; line-height: 1rem; font-weight: 600;
  letter-spacing: .02em; text-transform: uppercase; color: var(--text-muted);
}

/* Số tiền — luôn tabular-nums, và không bao giờ bẻ dòng: "1.575.000" rớt chữ "₫"
   xuống dòng dưới đọc như hai con số khác nhau. */
.money { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* white-space cùng lý do với .money ở trên: chuỗi chữ số không có chỗ ngắt, nên chỗ DUY NHẤT bẻ
   được là khoảng trắng trước "₫" — bẻ ở đó làm "1.575.000" và "₫" nằm hai dòng, đọc như hai con số. */
.money-hero {
  font-size: 1.75rem; line-height: 2.25rem; font-weight: 700;
  font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--money-neutral);
}
.money-lg {
  font-size: 1.25rem; line-height: 1.75rem; font-weight: 700;
  font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--money-neutral);
}
.money-pos { color: var(--money-positive) !important; }
.money-neg { color: var(--money-negative) !important; }
.money-neutral { color: var(--money-neutral) !important; }

/* ============================================================
   BADGE — soft (thay bg-* đặc mặc định Bootstrap)
   ============================================================ */
.badge-soft {
  display: inline-flex; align-items: center; gap: .25rem;
  padding: .2rem .55rem; border-radius: var(--radius-pill);
  font-size: .75rem; font-weight: 600; line-height: 1.2; white-space: nowrap;
}
.badge-soft.is-green { background: rgba(22,163,74,.14);  color: var(--badge-green-fg); }
.badge-soft.is-blue  { background: rgba(37,99,235,.14);  color: var(--badge-blue-fg); }
.badge-soft.is-red   { background: rgba(220,38,38,.14);  color: var(--badge-red-fg); }
.badge-soft.is-amber { background: rgba(249,115,22,.16); color: var(--badge-amber-fg); }
.badge-soft.is-slate { background: rgba(100,116,139,.16); color: var(--badge-slate-fg); }

/* Chấm trạng thái bên trong chip (VD "Đang sinh hoạt"). Màu kế thừa currentColor của chip. */
.badge-soft .dot { width: .5rem; height: .5rem; border-radius: 50%; background: currentColor; flex: none; }

/* Chữ màu theo status (VD giờ buổi tập ở màn Lịch) — dùng chung biến màu với .badge-soft cho nhất quán. */
.text-status-green { color: var(--badge-green-fg); }
.text-status-amber { color: var(--badge-amber-fg); }
.text-status-slate { color: var(--badge-slate-fg); }
/* Cố ý KHÔNG dùng .text-danger của Bootstrap cho việc này: nó ghim cứng #dc3545 ở CẢ hai theme
   (chỉ nền mới đổi theo data-bs-theme), nên trên nền tối chữ tụt tương phản. Biến ở đây có sẵn
   bản sáng/tối. */
.text-status-red   { color: var(--badge-red-fg); }

/* Chấm tròn chú thích màu status (VD legend phía trên bảng Lịch). */
.legend-dot { display: inline-block; width: .6rem; height: .6rem; border-radius: 50%; }
.legend-dot.is-green { background: var(--badge-green-fg); }
.legend-dot.is-amber { background: var(--badge-amber-fg); }
.legend-dot.is-slate { background: var(--badge-slate-fg); }

/* Ô ngày bấm-được (Owner/Admin) — bấm vùng trống mở modal tạo buổi đột xuất. Dấu "+" mờ hiện khi
   rê chuột (desktop có hover); màn hình cảm ứng không hiện nhưng cả ô vẫn chạm được. `position:
   relative` để neo dấu "+" tuyệt đối vào góc phải-trên ô. */
.lich-day--clickable { position: relative; cursor: pointer; }
.lich-day--clickable::after {
    content: "\002B"; /* dấu + */
    position: absolute; top: 2px; right: 6px;
    font-size: .95rem; line-height: 1; font-weight: 700;
    color: var(--bs-primary); opacity: 0; pointer-events: none;
    transition: opacity .12s ease-in-out;
}
@media (hover: hover) {
    .lich-day--clickable:hover::after { opacity: .55; }
}

/* ============================================================
   CARD & COMPONENT
   ============================================================ */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--elevation-1);
}
.app-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
  box-shadow: var(--elevation-1);
}

/* Radius mới theo DESIGN_RULES — card mềm hơn, nút/ô nhập bo 14px */
.card, .app-card, .stat-card, .empty-state, .auth-card { border-radius: var(--radius-card); }
.btn { border-radius: var(--radius-btn); }
.form-control, .form-select { border-radius: var(--radius-btn); padding: .625rem .85rem; }

/* Tom Select — ô tìm kiếm cho mọi select.form-select (CLAUDE.md § 2). tom-select.bootstrap5.css tự
   đọc --bs-body-bg/--bs-border-color, nhưng --bs-body-bg ở app này trỏ --surface-sunken (nền TRANG,
   dòng 196/257) chứ không phải --surface (nền Ô NHẬP mà .form-control/.form-select dùng ở dòng 310)
   — không override thì ô Tom Select lệch màu nền so với mọi input khác trên cùng form. */
.ts-wrapper.form-select .ts-control {
  background: var(--surface);
  color: var(--text);
  border-color: var(--border);
  border-radius: var(--radius-btn);
  padding: .625rem .85rem;
}
.ts-wrapper.form-select.is-invalid .ts-control {
  border-color: var(--bs-danger);
}
.ts-dropdown {
  background: var(--surface);
  color: var(--text);
  border-color: var(--border);
  /* dropdownParent: 'body' (layout.html) append .ts-dropdown làm con trực tiếp của <body> — CSS mặc
     định của tom-select.bootstrap5.css chỉ đặt z-index: 10 cho selector này (bản có class
     ".form-select" đi kèm mới lên 1000, nhưng Tom Select KHÔNG tự copy class đó sang dropdown trừ khi
     bật copyClassesToDropdown, mặc định false). Bootstrap modal ở app này dùng --bs-modal-zindex:
     1055 ⇒ thiếu dòng này, danh sách tìm kiếm bị modal đè lên, thấy list nhưng bấm chọn không ăn
     (bug thật đã gặp: mở modal "Tạo buổi tập đột xuất", không chọn được Sân). +5 để chắc chắn nổi
     trên modal dù giá trị --bs-modal-zindex có đổi. */
  z-index: calc(var(--bs-modal-zindex, 1055) + 5);
}
.ts-dropdown .option.active {
  background: var(--surface-muted);
}

/* Statistic Card — cả card là link về nguồn (PP-3) */
.stat-card {
  display: block; height: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
  box-shadow: var(--elevation-1);
  text-decoration: none; color: inherit;
  transition: box-shadow var(--motion-fast) var(--ease-standard),
              border-color var(--motion-fast) var(--ease-standard),
              transform var(--motion-fast) var(--ease-standard);
}
.stat-card:hover {
  border-color: var(--border-strong);
  box-shadow: var(--elevation-2);
  transform: translateY(-1px);
  color: inherit;
}
.stat-card__label {
  display: flex; align-items: center; gap: .4rem;
  font-size: .75rem; font-weight: 600; letter-spacing: .02em;
  text-transform: uppercase; color: var(--text-muted);
  margin-bottom: var(--space-xs);
}
.stat-card__label i { font-size: 1rem; }
.stat-card__value { margin-bottom: var(--space-2xs); }
.stat-card__meta { font-size: .875rem; color: var(--text-muted); }
.stat-card__meta .arrow { color: var(--action-primary); }

/* Thẻ CLB đang chờ duyệt (BR-MEM-13, Đ8) — không click được, không giống link thường. */
.stat-card--locked {
  opacity: .6;
  cursor: default;
}
.stat-card--locked:hover {
  border-color: var(--border);
  box-shadow: var(--elevation-1);
  transform: none;
}

/* Đầu card có ô icon bo góc màu (kiểu FastClub) */
.stat-card__head { display: flex; align-items: center; gap: .75rem; margin-bottom: var(--space-sm); }
.stat-card__icon {
  width: 2.75rem; height: 2.75rem; border-radius: 12px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center; font-size: 1.3rem;
}
/* Biến thể nhỏ cho hàng chỉ số THAM KHẢO (Báo cáo tài chính): giữ nguyên bộ màu is-* bên dưới,
   chỉ hạ kích thước để cụm nhãn không lấn chỗ của số tiền ở khổ máy tính bảng. */
.stat-card__icon--sm { width: 2rem; height: 2rem; border-radius: 9px; font-size: 1rem; }
.stat-card__icon.is-blue   { background: rgba(37,99,235,.12);  color: var(--blue-600); }
.stat-card__icon.is-green  { background: rgba(22,163,74,.12);  color: var(--green-600); }
.stat-card__icon.is-amber  { background: rgba(249,115,22,.14); color: var(--amber-600); }
.stat-card__icon.is-violet { background: rgba(124,58,237,.12); color: var(--violet-500); }
.stat-card__icon.is-red    { background: rgba(220,38,38,.12);  color: var(--red-500); }
[data-bs-theme="dark"] .stat-card__icon.is-blue   { color: #93C5FD; }
[data-bs-theme="dark"] .stat-card__icon.is-green  { color: #4ADE80; }
[data-bs-theme="dark"] .stat-card__icon.is-amber  { color: #FDBA74; }
[data-bs-theme="dark"] .stat-card__icon.is-violet { color: var(--violet-300); }
[data-bs-theme="dark"] .stat-card__icon.is-red    { color: #FCA5A5; }

/* Club pill — bộ chọn CLB góc phải header (kiểu FastClub) */
.page-header__aside { display: flex; align-items: center; gap: .6rem; }
.club-pill {
  display: inline-flex; align-items: center; gap: .55rem;
  padding: .5rem .85rem; border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--surface); color: var(--text); text-decoration: none;
  font-weight: 600; font-size: .9rem; box-shadow: var(--elevation-1);
}
.club-pill:hover { border-color: var(--border-strong); color: var(--text); }
.club-pill .lead-ic { color: var(--action-primary); }
.club-pill .chev { color: var(--text-muted); font-size: .8rem; }
.club-pill__logo { width: 1.1rem; height: 1.1rem; border-radius: 50%; object-fit: cover; }
.club-list__logo { width: 1.5rem; height: 1.5rem; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
/* Biến thể chỉ-hiển-thị: định danh CLB trong header trang, không bấm được (đổi CLB dùng switcher navbar). */
.club-pill--static { cursor: default; }
.club-pill--static:hover { border-color: var(--border); color: var(--text); }

/* Page Header — thay link "← Về…" đặt lệch */
.page-header { margin-bottom: var(--space-xl); }
/* Hàng trên header: breadcrumb (trái) + club-pill định danh CLB (phải) — dùng CHUNG cho MỌI trang
   trong CLB qua fragment `page :: pageHeader`, để tên CLB đang xem luôn hiện, không chỉ Dashboard.
   flex-wrap: pill rớt xuống dòng dưới trên màn hẹp thay vì chèn ép breadcrumb. */
.page-header__top {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-sm); flex-wrap: wrap; margin-bottom: var(--space-2xs);
}
.page-header__top .page-header__crumb { margin-bottom: 0; }
.page-header__top .club-pill { margin-left: auto; }
/* Breadcrumb — "thanh menu" đường dẫn: mọi cấp cha bấm được để quay lại, cấp hiện tại là chữ mờ.
   Dùng flex + wrap để chuỗi dài (VD Buổi tập › Chi tiết buổi › Điểm danh) tự xuống dòng trên mobile. */
.page-header__crumb {
  display: flex; flex-wrap: wrap; align-items: center; gap: .375rem;
  font-size: .8125rem; color: var(--text-muted); margin-bottom: var(--space-2xs);
}
.page-header__crumb a { color: var(--action-primary); text-decoration: none; font-weight: 500; }
.page-header__crumb a:hover { text-decoration: underline; }
.page-header__crumb .sep { color: var(--text-muted); opacity: .55; }
.page-header__crumb .current { color: var(--text-muted); }
.page-header__row {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: var(--space-md); flex-wrap: wrap; margin-top: var(--space-2xs);
}
/* Tiêu đề trang to & đậm hơn — nhịp thị giác giống mockup FastClub */
.page-header__title { margin: 0; font-size: 1.75rem; line-height: 2.25rem; font-weight: 800; letter-spacing: -.02em; }
.page-header__subtitle { font-size: .9rem; color: var(--text-muted); margin-top: var(--space-2xs); max-width: 60ch; }

/* ============================================================
   NAV-PILLS — tab dạng segmented (Báo cáo, Sân, Cài đặt…)
   Active = viên xanh đặc (đã map --bs-primary). Track nền chìm.
   ============================================================ */
.nav-pills {
  display: inline-flex; flex-wrap: wrap; gap: .25rem;
  background: var(--surface-muted); padding: .3rem;
  border-radius: var(--radius-md); border: 1px solid var(--border);
}
.nav-pills .nav-link {
  color: var(--text-muted); font-weight: 600; font-size: .9rem;
  padding: .45rem 1rem; border-radius: var(--radius-sm);
}
.nav-pills .nav-link:hover:not(.active) { color: var(--text); background: var(--surface); }
.nav-pills .nav-link.active {
  background: var(--action-primary); color: #fff;
  box-shadow: 0 4px 10px rgba(37,99,235,.28);
}

/* App Alert — soft, kèm hành động bên phải */
.app-alert {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-sm); flex-wrap: wrap;
  padding: var(--space-md); border-radius: var(--radius-md);
  border: 1px solid transparent; font-size: .95rem;
  margin-bottom: var(--space-md);
}
.app-alert__body { display: flex; align-items: center; gap: .5rem; }
.app-alert.is-info    { background: rgba(37,99,235,.10);  border-color: rgba(37,99,235,.22);  color: var(--badge-blue-fg); }
.app-alert.is-success { background: rgba(22,163,74,.10);  border-color: rgba(22,163,74,.22);  color: var(--badge-green-fg); }
.app-alert.is-warning { background: rgba(249,115,22,.12); border-color: rgba(249,115,22,.26); color: var(--badge-amber-fg); }
.app-alert.is-danger  { background: rgba(220,38,38,.10);  border-color: rgba(220,38,38,.24);  color: var(--badge-red-fg); }

/* Empty State — biến màn trống thành điểm khởi đầu */
.empty-state {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--elevation-1);
  padding: var(--space-2xl) var(--space-xl); text-align: center;
}
.empty-state__mark {
  display: flex; align-items: center; justify-content: center;
  width: 3.5rem; height: 3.5rem; margin: 0 auto var(--space-md);
  border-radius: 50%; font-size: 1.6rem; line-height: 1;
  background: rgba(37,99,235,.10); color: var(--action-primary);
}
.empty-state__title { margin-bottom: var(--space-xs); }
.empty-state__desc { color: var(--text-muted); margin-bottom: var(--space-lg); }

/* ============================================================
   Bọc nội dung trang — đẩy phải khi có sidebar (>=992px),
   chừa chỗ bottom-nav (<992px)
   ============================================================ */
.page-content { padding-top: var(--space-lg); }
/* Bề rộng nội dung — QUY ƯỚC: MỌI màn trong CLB dùng content-wide (960) cho đồng nhất bề rộng.
   (Trước đây các màn *sua* dùng content-default(720) nên trông "bé hơn" màn danh sách — theo yêu
    cầu đồng bộ, đã gộp về cùng một size 960.)
     • content-wide  (960): MỌI màn trong CLB — list, bảng tiền, dashboard, VÀ các màn *sua*.
     • content-default(720): còn định nghĩa để dùng lại nếu cần trang một cột hẹp (hiện không màn nào dùng).
     • content-narrow (560): dành cho auth/shell ngoài CLB.
   🔴 Bảng dữ liệu KHÔNG được dùng content-default — nó co bảng lại hẹp hơn các màn khác (bug đã từng gặp ở
      bang-chia-tien). Thêm màn mới ⇒ content-wide. */
.page-content .content-narrow  { max-width: var(--w-narrow); }
.page-content .content-default { max-width: var(--w-content); }
.page-content .content-wide    { max-width: var(--w-wide); }

@media (min-width: 992px) {
  .page-content { margin-left: var(--sidebar-width); padding-top: var(--space-xl); }
}
@media (max-width: 991.98px) {
  .page-content {
    padding-bottom: calc(var(--bottom-nav-height) + env(safe-area-inset-bottom) + var(--space-md));
  }
}

/* ============================================================
   Topbar tối giản (<992px)
   ============================================================ */
.app-topbar-mobile {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: .5rem 1rem;
  min-height: var(--topbar-height);
}

/* ============================================================
   Sidebar trái cố định (>=992px)
   ============================================================ */
.app-sidebar {
  position: fixed; top: 0; left: 0; bottom: 0;
  width: var(--sidebar-width);
  background: var(--nav-bg);
  border-right: 1px solid var(--nav-border);
  padding: var(--space-md) 0 0;
  z-index: 1030;
}
.app-sidebar-brand { padding: 0 var(--space-md) var(--space-md); }
.app-brand {
  display: flex; align-items: center; gap: .6rem;
  font-weight: 800; font-size: 1.1rem; color: var(--text-strong);
  text-decoration: none;
}
/* Logo mark: ô bo góc màu xanh — dùng chung sidebar + topbar mobile */
.app-brand .app-brand-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.2rem; height: 2.2rem; border-radius: 11px;
  background: var(--nav-brand-mark-bg); font-size: 1.15rem; flex: 0 0 auto;
  box-shadow: 0 4px 10px rgba(37,99,235,.35);
}
/* Cỡ mặc định logo SVG (auth/entry — không có ô tile): xanh thương hiệu */
.brand-svg { width: 1.4rem; height: 1.4rem; color: var(--action-primary); flex: 0 0 auto; vertical-align: -.2em; }
/* Trong ô tile sidebar/topbar/entry: trắng, khớp tile */
.app-brand .app-brand-mark .brand-svg { width: 1.35rem; height: 1.35rem; color: #fff; }
.app-brand-text { display: flex; flex-direction: column; line-height: 1.12; }
.app-brand-name { font-weight: 800; font-size: 1.05rem; }
.app-brand-sub  { font-size: .7rem; font-weight: 500; }
/* Trong sidebar tối: chữ sáng */
.app-sidebar .app-brand-name { color: var(--nav-text-strong); }
.app-sidebar .app-brand-sub  { color: var(--nav-text-muted); }

/* Club switcher — base SÁNG (dùng trong offcanvas menu mobile) */
.app-club-switch {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  margin: 0 var(--space-sm) var(--space-sm);
  padding: .55rem .7rem;
  border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--surface-sunken); color: var(--text);
  text-decoration: none; font-size: .9rem;
}
.app-club-switch:hover { border-color: var(--border-strong); color: var(--text); }
.app-club-switch .label { display: inline-flex; align-items: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-club-switch i { color: var(--text-muted); }
.app-club-switch__logo { width: 1.1rem; height: 1.1rem; border-radius: 50%; object-fit: cover; margin-right: .4rem; flex: 0 0 auto; }
/* Trong sidebar TỐI: đổi sang nền/chữ sáng cho hợp navy */
.app-sidebar .app-club-switch {
  border-color: var(--nav-border); background: var(--nav-hover-bg); color: var(--nav-text);
}
.app-sidebar .app-club-switch:hover { border-color: var(--border-strong); color: var(--nav-text-strong); background: rgba(148,163,184,.16); }
.app-sidebar .app-club-switch i { color: var(--nav-text-muted); }

.app-sidebar-nav { flex: 1 1 auto; overflow-y: auto; padding: 0 var(--space-xs); }
.app-sidebar-group-label {
  padding: var(--space-md) var(--space-sm) var(--space-2xs);
  font-size: .6875rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--nav-group-label);
}
.app-sidebar-nav .nav-link {
  color: var(--nav-text); padding: .6rem .75rem; margin: 2px 0;
  border-radius: var(--radius-md); display: flex; align-items: center; gap: .7rem;
  font-size: .9375rem; font-weight: 500;
  transition: background var(--motion-fast) var(--ease-standard), color var(--motion-fast) var(--ease-standard);
}
.app-sidebar-nav .nav-link i { font-size: 1.1rem; color: var(--nav-text-muted); width: 1.2rem; text-align: center; }
.app-sidebar-nav .nav-link:hover { background: var(--nav-hover-bg); color: var(--nav-text-strong); }
.app-sidebar-nav .nav-link:hover i { color: var(--nav-text-strong); }
.app-sidebar-nav .nav-link.active {
  background: var(--nav-active-bg);
  color: var(--nav-active-text);
  font-weight: 600;
  box-shadow: 0 6px 14px rgba(37,99,235,.35);
}
.app-sidebar-nav .nav-link.active i { color: var(--nav-active-text); }

.app-sidebar-footer {
  padding: var(--space-sm);
  margin-top: var(--space-xs);
  border-top: 1px solid var(--nav-border);
  display: flex; flex-direction: column; gap: var(--space-xs);
}

/* Hồ sơ người dùng cuối sidebar */
.app-user {
  display: flex; align-items: center; gap: .6rem;
  padding: .5rem; border-radius: var(--radius-md);
  text-decoration: none; color: var(--nav-text);
}
.app-user:hover { background: var(--nav-hover-bg); color: var(--nav-text-strong); }
.app-user__avatar {
  width: 2.2rem; height: 2.2rem; border-radius: 50%; flex: 0 0 auto;
  background: rgba(148,163,184,.18); color: var(--nav-text-strong);
  display: inline-flex; align-items: center; justify-content: center; font-size: 1.05rem;
  overflow: hidden;
}
.app-user__avatar img { width: 100%; height: 100%; object-fit: cover; }
.app-user__meta { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.app-user__name { font-weight: 600; font-size: .85rem; color: var(--nav-text-strong);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 130px; }
.app-user__role { font-size: .72rem; color: var(--nav-text-muted); }
.app-user__chev { margin-left: auto; color: var(--nav-text-muted); font-size: .8rem; }

/* 🔴 Hai nút [Giao diện] [Đăng xuất] phải rộng BẰNG NHAU, nhưng hai flex item lại khác
   loại: một bên là chính <button>, bên kia là <form> bọc nút (form bắt buộc — đăng xuất
   là POST có CSRF). Với flex:1 1 0 Chrome vẫn chia lệch 117.3px/99.3px (đo thật), mà nút
   hẹp hơn lại là nút có chữ dài hơn (cần 102.4px) ⇒ "Đăng xuất" gãy 2 dòng còn "Giao diện"
   1 dòng, hai nút cao bằng nhau nhưng trông lệch hẳn. Grid 2 cột 1fr chia đúng bằng nhau
   bất kể item là thẻ gì; minmax(0,1fr) để cột không bị nội dung đẩy phình ra. */
.app-sidebar-footer-actions {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .3rem;
}
.app-sidebar-footer .app-theme-toggle,
.app-sidebar-footer .btn-logout {
  display: inline-flex; align-items: center; justify-content: center; gap: .3rem;
  background: rgba(148,163,184,.08); border: 1px solid var(--nav-border);
  color: var(--nav-text); border-radius: var(--radius-md);
  padding: .45rem .35rem; font-size: .8rem; width: 100%; cursor: pointer;
  /* 🔴 CHỮ PHẢI NẰM 1 DÒNG. Hai lớp bảo vệ:
     1. nowrap — chặn gãy dòng, kể cả khi ai đó đổi nhãn dài hơn (lúc đó lỗi lộ ra bằng
        cách tràn viền, thấy ngay, chứ không âm thầm làm hai nút cao lệch nhau).
     2. Nới chỗ: gap .4→.3rem, padding ngang .5→.35rem ⇒ nhãn dài nhất ("Đăng xuất" +
        icon) chỉ cần 93.6px trong cột 108.8px — dư 15.2px thay vì 5.9px. Nhờ vậy vẫn
        vừa 1 dòng cả khi cỡ chữ gốc trình duyệt lớn hơn 16px (zoom, hệ điều hành đặt
        font to) — trường hợp trước đây sẽ tràn. */
  white-space: nowrap;
}
.app-sidebar-footer .app-theme-toggle:hover,
.app-sidebar-footer .btn-logout:hover { background: var(--nav-hover-bg); color: var(--nav-text-strong); border-color: var(--border-strong); }

/* ============================================================
   Sidebar collapse (desktop >=992px). Trạng thái ở <html class="sidebar-collapsed">,
   áp trước paint từ localStorage (layout.html) để không nháy.
   ============================================================ */
.app-sidebar-brand { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
.app-sidebar-collapse-btn {
  flex: none; background: transparent; border: none; color: var(--nav-text-muted);
  padding: .3rem; border-radius: var(--radius-md); cursor: pointer; line-height: 0;
}
.app-sidebar-collapse-btn:hover { background: var(--nav-hover-bg); color: var(--nav-text-strong); }
.collapse-ic { display: inline-flex; }
.collapse-ic--open { display: none; }
html.sidebar-collapsed .collapse-ic--close { display: none; }
html.sidebar-collapsed .collapse-ic--open  { display: inline-flex; }

@media (min-width: 992px) {
  html.sidebar-collapsed { --sidebar-width: 76px; }
  html.sidebar-collapsed .app-sidebar { width: 76px; }
  html.sidebar-collapsed .page-content { margin-left: 76px; }

  /* Ẩn nhãn/khối chữ; chừa nút collapse (để mở lại) + icon. */
  html.sidebar-collapsed .app-brand,
  html.sidebar-collapsed .app-club-switch,
  html.sidebar-collapsed .app-sidebar-group-label,
  html.sidebar-collapsed .app-user__meta,
  html.sidebar-collapsed .app-user__chev,
  html.sidebar-collapsed .app-sidebar-nav .nav-link > span,
  html.sidebar-collapsed .app-theme-toggle > span,
  html.sidebar-collapsed .btn-logout > span { display: none; }

  /* Căn giữa các phần tử còn lại trong rail hẹp. */
  html.sidebar-collapsed .app-sidebar-brand { justify-content: center; }
  html.sidebar-collapsed .app-sidebar-nav .nav-link { justify-content: center; padding: .6rem; }
  html.sidebar-collapsed .app-user { justify-content: center; }
  /* Rail hẹp: xếp dọc — grid 1 cột (trước là flex-direction: column). */
  html.sidebar-collapsed .app-sidebar-footer-actions { grid-template-columns: 1fr; }
}

/* Nút ghost — nền trong suốt, hover nền chìm (dùng cho trigger menu "…") */
.btn-ghost { background: transparent; border: 1px solid transparent; color: var(--text-muted); }
.btn-ghost:hover { background: var(--surface-muted); color: var(--text); }
.min-w-0 { min-width: 0; }

/* Nút đổi theme sáng/tối (mặc định — dùng trên topbar mobile sáng) */
.app-theme-toggle {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text-muted); border-radius: var(--radius-md);
  padding: .35rem .6rem; font-size: .85rem; cursor: pointer;
}
.app-theme-toggle:hover { border-color: var(--border-strong); color: var(--text); }

/* ============================================================
   Bottom-nav cố định đáy (<992px)
   ============================================================ */
.app-bottom-nav {
  position: fixed; left: 0; right: 0; bottom: 0;
  display: flex; background: var(--surface);
  border-top: 1px solid var(--border);
  padding-bottom: env(safe-area-inset-bottom);
  z-index: 1030;
}
.app-bottom-nav-item {
  flex: 1 1 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: .15rem;
  min-height: 56px; padding: .5rem 0;
  color: var(--text-muted); background: none; border: none;
  font-size: .7rem; text-decoration: none;
}
.app-bottom-nav-item i { font-size: 1.25rem; }
.app-bottom-nav-item.active { color: var(--action-primary); }

/* Offcanvas menu (mobile) dùng token */
.offcanvas { background: var(--surface); color: var(--text); }
.offcanvas .offcanvas-header { border-bottom: 1px solid var(--border); }

/* ============================================================
   Bảng — list-card: bảng >=768px, card xếp chồng <768px.
   Cần <td data-label="..."> trong HTML.
   ============================================================ */
/* Bảng dữ liệu — thoáng, hover nhẹ, bỏ viền dọc, header kiểu caption in hoa. */
.table { color: var(--text); margin: 0; }
.table > thead > tr > th {
  font-size: .7rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-muted); border-bottom: 1px solid var(--border);
  padding: .85rem 1rem; white-space: nowrap;
}
.table > tbody > tr > td { padding: .85rem 1rem; border-bottom: 1px solid var(--border); vertical-align: middle; }
.table > tbody > tr:last-child > td { border-bottom: 0; }
.table.table-hover > tbody > tr:hover > td,
.app-card .table > tbody > tr:hover > td { background: var(--surface-sunken); }
.table > :not(caption) > * > * { box-shadow: none; } /* bỏ đường kẻ mặc định Bootstrap */

/* Bo góc bảng khớp card mà KHÔNG dùng overflow:hidden — nếu bọc overflow:hidden thì dropdown "…"
   trong hàng bị cắt mất. Chỉ bo 4 ô góc để nền hover không tràn ra ngoài góc bo của card. */
.app-card > .list-card > table > thead > tr > th:first-child { border-top-left-radius: var(--radius-card); }
.app-card > .list-card > table > thead > tr > th:last-child  { border-top-right-radius: var(--radius-card); }
.app-card > .list-card > table > tbody > tr:last-child > td:first-child { border-bottom-left-radius: var(--radius-card); }
.app-card > .list-card > table > tbody > tr:last-child > td:last-child  { border-bottom-right-radius: var(--radius-card); }

@media (max-width: 767.98px) {
  .list-card table thead { display: none; }
  .list-card table, .list-card tbody, .list-card tr, .list-card td { display: block; width: 100%; }
  .list-card tbody tr {
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    margin-bottom: .75rem; padding: .5rem .75rem;
    background: var(--surface);
  }
  .list-card td {
    display: flex; justify-content: space-between; align-items: center;
    gap: .5rem; border: none !important; padding: .35rem 0 !important;
    text-align: right !important;
  }
  .list-card td[data-label]::before {
    content: attr(data-label);
    font-weight: 600; color: var(--text-muted); text-align: left;
  }
  .list-card td:not([data-label]) { justify-content: flex-start; }
  .list-card tfoot tr {
    display: block; background: var(--sidebar-active-bg);
    border-radius: var(--radius-md); padding: .5rem .75rem; font-weight: 700;
  }
  .list-card tfoot td { display: flex; justify-content: space-between; border: none !important; }
}

/* ============================================================
   Bảng "khóa 1 dòng" — table-nowrap.
   Ngày giờ, số tiền, tên người là dữ liệu atomic: bẻ dòng giữa chúng bắt mắt
   phải ghép lại mới đọc được, và làm chiều cao các dòng so le trông như lỗi.
   Mặc định khóa cả bảng 1 dòng, rồi mở lại đúng cột chữ tự do bằng .col-wrap;
   .col-grow cho cột đó nuốt hết phần rộng dư (chỉ dùng khi có ĐÚNG MỘT cột chữ
   tự do — nhiều cột cùng grow thì trình duyệt lại chia đều, vô nghĩa).
   Đánh dấu bằng class trên <th>/<td> chứ không nth-child: thêm/bớt cột sau này
   không âm thầm dịch quy tắc sang nhầm cột.
   ============================================================ */
@media (min-width: 768px) {
  .table-nowrap > thead > tr > th, .table-nowrap > tbody > tr > td { white-space: nowrap; }
  .table-nowrap .col-wrap { white-space: normal; }
  .table-nowrap .col-grow { width: 100%; }
}

/* ============================================================
   Danh sách Khách gộp trong một dòng công nợ (BR-EXP-06)
   Mỗi khách một dòng, tên trái — tiền phải, để mắt dò thẳng xuống cột tiền.
   ============================================================ */
.guest-list { list-style: none; margin: 0; padding: 0; }
.guest-list li {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: .75rem; font-size: .875rem; padding: .1rem 0;
}
.guest-list li + li { border-top: 1px dashed var(--border); padding-top: .25rem; margin-top: .15rem; }
.guest-list__name { color: var(--text-muted); }
.guest-list__amount { white-space: nowrap; }

@media (max-width: 767.98px) {
  /* Trong chế độ card, <td> đã là flex "nhãn | nội dung" — danh sách phải co lại thành cột bên phải,
     không giãn hết chiều ngang làm tên khách dính vào nhãn "Khách đi cùng". */
  .list-card .guest-list { min-width: 60%; }
}

/* ============================================================
   Vùng chạm điểm danh >=44px trên mobile (OQ-43)
   ============================================================ */
@media (max-width: 991.98px) {
  .attendance-row .btn { min-height: 44px; min-width: 96px; font-size: .95rem; }
  .attendance-row { padding-top: .6rem; padding-bottom: .6rem; }
}

/* ============================================================
   Bảng điểm danh — grid 4 cột: Tên · Giới tính · Trình độ · Trạng thái.
   🔴 Mỗi dòng VẪN là <div> (KHÔNG phải <tr>) để không đụng cơ chế HTMX swap
   từng dòng của nút tick (xem chú thích trong attendance/fragments.html — <tr>
   trong <div> response sẽ bị trình duyệt nuốt mất khi htmx parse). Cột cố định
   px + cột Tên co giãn (1fr) ⇒ các dòng độc lập vẫn thẳng hàng nhau. Bọc trong
   .attendance-scroll (overflow-x) + min-width ⇒ cuộn ngang khi màn hẹp.
   ============================================================ */
.attendance-scroll { overflow-x: auto; }
.attendance-grid {
  display: grid;
  grid-template-columns: minmax(7rem, 1fr) 4.5rem 6.5rem 8.5rem;
  align-items: center;
  gap: .5rem;
  min-width: 28rem;
}
.attendance-grid__name { min-width: 0; }        /* cho phép cột Tên co lại thay vì tràn grid */
/* 🔴 Nút trạng thái phải RỘNG BẰNG NHAU ở cả 3 state. Để nút tự co theo chữ thì
   "Chưa điểm danh" (14 ký tự) to gấp ~2,5 lần "Vắng" ⇒ cột Trạng thái nhấp nhô
   theo từng dòng, và mỗi lần tick nút lại nhảy kích thước ngay dưới ngón tay.
   Cho ô chiếm trọn bề rộng cột (8.5rem, đủ chứa nhãn dài nhất) và nút/badge
   width:100% ⇒ mọi state cùng một khung, chỉ đổi màu và chữ. */
.attendance-grid__status { justify-self: stretch; min-width: 0; }
.attendance-grid__status > .btn,
.attendance-grid__status > .badge-soft {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  white-space: nowrap;
}

/* Tablet (576–992px): quy tắc vùng chạm ở trên bơm chữ nút lên .95rem ⇒ "Chưa điểm danh"
   rộng 120.3px, KHÔNG vừa phần lòng 118px của cột 8.5rem (đo được: tràn 2.3px). Nới cột
   riêng cho dải này thay vì nới cho cả desktop (desktop chữ 14px, 8.5rem đã dư 7.2px). */
@media (min-width: 576px) and (max-width: 991.98px) {
  .attendance-grid { grid-template-columns: minmax(7rem, 1fr) 4.5rem 6.5rem 9.25rem; }
}

/* Điện thoại: mọi nút trạng thái rộng bằng nhau ⇒ cột phải ôm được NHÃN DÀI NHẤT. Trên
   mobile nhãn PENDING rút còn "Chưa" (xem attendance/fragments.html), nhãn dài nhất trở
   thành "Có mặt" = 47.2px ⇒ cột 4.5rem (72px) là đủ, thay vì 7.75rem như khi giữ nguyên
   "Chưa điểm danh". Nhờ vậy tổng hàng còn ~416px, vừa màn 430px — trước đó 468px nên bảng
   cuộn ngang và tên người bị cắt cụt. Chiều cao chạm 44px (OQ-43) giữ nguyên.
   🔴 min-width: 0 là BẮT BUỘC: min-width 28rem (448px) ở khối gốc sẽ giữ hàng rộng 448px
   dù các cột đã co lại ⇒ vẫn cuộn ngang, thu cột thành vô nghĩa. */
@media (max-width: 575.98px) {
  /* Cột Trình độ 6.5rem → 5.5rem: đủ để hàng vừa màn 375px (iPhone SE/mini) chứ không chỉ
     390px. Trình độ là free text nên giá trị dài sẽ xuống dòng — chấp nhận cao thêm 1 dòng
     để đổi lấy việc KHÔNG cuộn ngang, vì cuộn ngang cắt cụt cột Tên (lỗi đang gặp). */
  .attendance-grid { grid-template-columns: minmax(6rem, 1fr) 4.5rem 5.5rem 4.5rem; min-width: 0; }
  /* "TRẠNG THÁI" rộng ~73px, nhỉnh hơn cột 72px vài px ⇒ mặc định gãy 2 dòng, đội cao hàng
     tiêu đề từ 33px lên 49px. Bỏ letter-spacing .02em (10 ký tự ⇒ tiết kiệm ~2.4px) là vừa
     đúng 1 dòng mà không phải tràn ra ngoài cột. */
  .attendance-grid--head { letter-spacing: normal; }
  .attendance-grid--head > span { white-space: nowrap; }
  .attendance-row .btn { font-size: .8125rem; min-width: 0; padding-left: .35rem; padding-right: .35rem; }
}

/* Nhãn form — đồng nhất mọi màn */
.form-label { font-weight: 600; font-size: .875rem; color: var(--text); margin-bottom: .35rem; }
.form-text { color: var(--text-muted); }

/* ============================================================
   AUTH & ENTRY — vỏ tối giản căn giữa (chưa đăng nhập, KHÔNG sidebar).
   Dùng cho: đăng nhập/đăng ký/quên-đặt lại MK, nhận lời mời (claim).
   ============================================================ */
.auth-shell {
  min-height: 100vh;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  padding: var(--space-2xl) var(--space-md);
  background: var(--surface-sunken);
}
.auth-topbar { position: fixed; top: var(--space-md); right: var(--space-md); z-index: 10; }
.auth-container { width: 100%; max-width: 400px; }
.auth-brand {
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  font-weight: 800; font-size: 1.25rem; color: var(--text-strong);
  text-decoration: none; margin-bottom: var(--space-lg);
}
.auth-brand .app-brand-mark { font-size: 1.4rem; }
.auth-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--elevation-2);
  padding: var(--space-xl);
}
.auth-card__title { font-size: 1.25rem; margin-bottom: var(--space-2xs); }
.auth-card__subtitle { font-size: .875rem; color: var(--text-muted); margin-bottom: var(--space-lg); }
.auth-links {
  display: flex; justify-content: space-between; gap: var(--space-sm);
  margin-top: var(--space-md); font-size: .875rem; flex-wrap: wrap;
}
.auth-alt { margin-top: var(--space-md); font-size: .875rem; color: var(--text-muted); text-align: center; }
.auth-footer { margin-top: var(--space-lg); font-size: .8125rem; color: var(--text-muted); text-align: center; }

/* Entry header — trang SAU đăng nhập nhưng CHƯA chọn CLB (danh sách CLB) — không có sidebar. */
.entry-header {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-md);
  padding: var(--space-sm) var(--space-md);
  background: var(--surface); border-bottom: 1px solid var(--border);
}
.entry-header .entry-actions { display: flex; align-items: center; gap: var(--space-sm); }
/* Biến thể cho khu quản trị hệ thống: header có THÊM một cụm nav 5 mục ở giữa, nên ba nhóm con
   không đủ chỗ trên một hàng ở màn điện thoại. Không có flex-wrap ⇒ tràn ngang 465px trên viewport
   390px (đo bằng CDP 2026-08-08). Đặt riêng chứ không sửa .entry-header chung, vì các trang entry
   hiện có chỉ có brand + 2 nút và đang vừa khít. */
.entry-header--platform { flex-wrap: wrap; row-gap: var(--space-sm); }
.entry-header--platform > * { min-width: 0; }
.entry-content { max-width: var(--w-wide); margin: 0 auto; padding: var(--space-xl) var(--space-md); }

/* ============================================================
   STEP FLOW — trục hành động buổi tập: Điểm danh → Chi phí → Chốt sổ (M-TSK-1).
   Mảnh, không phô: chỉ để dẫn thứ tự, không cạnh tranh với nội dung.
   ============================================================ */
.step-flow { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; margin-bottom: var(--space-lg); }
.step-flow__item {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .35rem .7rem; border-radius: var(--radius-pill);
  font-size: .8125rem; font-weight: 600;
  background: var(--surface-muted); color: var(--text-muted);
  border: 1px solid var(--border);
}
.step-flow__item .num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.2rem; height: 1.2rem; border-radius: 50%;
  background: var(--border-strong); color: var(--surface); font-size: .7rem; font-weight: 700;
}
.step-flow__item.is-done { background: rgba(22,163,74,.12); color: var(--badge-green-fg); border-color: rgba(22,163,74,.24); }
.step-flow__item.is-done .num { background: var(--action-primary); color: #fff; }
.step-flow__item.is-current { background: var(--sidebar-active-bg); color: var(--sidebar-active-text); border-color: var(--action-primary); }
.step-flow__item.is-current .num { background: var(--action-primary); color: #fff; }
.step-flow__sep { color: var(--text-disabled); }

/* Hàng nút hành động theo trạng thái buổi */
.action-bar { display: flex; flex-wrap: wrap; gap: var(--space-xs); align-items: center; margin-bottom: var(--space-lg); }

/* ============================================================
   Các trang CÔNG KHAI của một buổi tập — /chia-se/{token} (thẻ "vé mời" + bảng chia tiền)
   VÀ /vote/{token}. Markup chung ở templates/fragments/buoi-hero.html.
   Điểm nhấn DUY NHẤT: khối hero WHEN (ngày + giờ). Còn lại giữ yên.

   🔴 Tiền tố `share-` là DẤU VẾT LỊCH SỬ, không phải ranh giới module: nhóm này ra đời khi chỉ
   trang chia sẻ dùng, nay trang vote dùng chung y hệt. Giữ tên vì đổi là 17 chỗ ở đây cộng 3
   template, sót một chỗ là vỡ layout mà không báo lỗi — xem VT-5 trong
   docs/superpowers/specs/2026-07-28-vote-dung-chung-template-chia-se-design.md.
   ============================================================ */
.share-hero {
  padding: var(--space-lg);
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  background: linear-gradient(135deg, rgba(22,163,74,.12), rgba(37,99,235,.10));
}
.share-hero.is-cancelled { background: var(--surface-muted); }
.share-eyebrow {
  display: flex; align-items: center; gap: .4rem;
  font-weight: 700; color: var(--text-strong);
}
.share-eyebrow .app-brand-mark { font-size: 1.1rem; }
/* Ngày + giờ chung một hàng — pill giờ neo bên phải, xuống hàng riêng khi màn quá hẹp cho cả hai. */
.share-hero__when {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; column-gap: .6rem; row-gap: .35rem;
  margin-top: var(--space-sm);
}
.share-hero__date {
  font-size: 1.35rem; line-height: 1.25; font-weight: 800;
  color: var(--text-strong);
}
.share-hero.is-cancelled .share-hero__date { text-decoration: line-through; color: var(--text-muted); }
.share-time {
  display: inline-flex; align-items: center; gap: .4rem; flex: none;
  padding: .3rem .7rem; border-radius: var(--radius-pill);
  background: var(--surface); border: 1px solid var(--border);
  font-weight: 700; font-variant-numeric: tabular-nums;
}
.share-loc { margin-top: var(--space-md); color: var(--text); }
.share-loc__label { display: flex; align-items: flex-start; gap: .5rem; }
.share-loc__label > .bi { color: var(--action-primary); margin-top: .15rem; flex: none; }
.share-slots { margin-top: var(--space-md); }
.share-slots__label { display: flex; align-items: center; gap: .4rem; }
.share-people li { display: flex; align-items: center; gap: .55rem; padding: .35rem 0; }
.share-people li + li { border-top: 1px solid var(--border); }
/* Avatar chữ-cái tái dùng (danh sách thành viên…). 6 tông từ palette, chọn theo hash tên. */
.avatar {
  flex: none; width: 2.5rem; height: 2.5rem; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: .85rem; line-height: 1; letter-spacing: .01em;
  user-select: none;
}
.avatar--c0 { background: rgba(37,99,235,.14);  color: var(--badge-blue-fg); }
.avatar--c1 { background: rgba(22,163,74,.14);  color: var(--badge-green-fg); }
.avatar--c2 { background: rgba(249,115,22,.16); color: var(--badge-amber-fg); }
.avatar--c3 { background: rgba(124,58,237,.14); color: var(--violet-500); }
.avatar--c4 { background: rgba(220,38,38,.12);  color: var(--badge-red-fg); }
.avatar--c5 { background: rgba(100,116,139,.16); color: var(--badge-slate-fg); }
[data-bs-theme="dark"] .avatar--c3 { color: var(--violet-300); }

/* Khối thông tin thành viên ở đầu trang công nợ công khai (/chia-se/{token} loại DEBT) — avatar to
   hơn bản .avatar mặc định (2.5rem, dùng ở danh sách bảng), phóng qua wrapper riêng thay vì sửa
   fragment gốc để không ảnh hưởng chỗ khác đang dùng cỡ nhỏ (member/thanh-vien.html). */
.debt-member__avatar { display: flex; justify-content: center; margin-bottom: var(--space-sm); }
.debt-member__avatar .avatar { width: 4.5rem; height: 4.5rem; font-size: 1.5rem; }
.debt-member__name { font-size: 1.5rem; font-weight: 800; color: var(--text-strong); margin: 0 0 var(--space-2xs); }
.debt-member__meta { display: flex; flex-wrap: wrap; justify-content: center; gap: .4rem; margin: var(--space-xs) 0 var(--space-sm); }

.share-avatar {
  flex: none; width: 2rem; height: 2rem; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: .8rem;
  background: rgba(22,163,74,.14); color: var(--badge-green-fg);
}
.share-avatar.is-guest { background: rgba(37,99,235,.14); color: var(--badge-blue-fg); }
.share-empty { padding: .35rem 0; }

/* Trang bảng chia tiền công khai — cùng khung "vé mời", nhưng điểm nhấn là TIỀN.
   .share-split dùng lại .share-people (avatar + gạch ngăn) và chỉ thêm cột tiền bên phải. */
.share-split li { align-items: flex-start; padding: .55rem 0; }
.share-split__who { flex: 1 1 auto; min-width: 0; }
.share-split__money { flex: none; text-align: right; }

/* Một dòng "nhãn + giá trị + nút chép" trong popup Mã thanh toán.
   .copy-field__value dùng break-all: số tài khoản/tên chủ TK dài không được đẩy nút chép ra khỏi popup. */
.copy-field {
  display: flex; align-items: center; gap: var(--space-sm);
  padding: var(--space-sm) 0;
}
.copy-field + .copy-field { border-top: 1px solid var(--border); }
.copy-field__text { flex: 1 1 auto; min-width: 0; }
.copy-field__label { font-size: .8rem; color: var(--text-muted); }
/* white-space: normal — gỡ nowrap mà .money áp lên số tài khoản: ở đây break-all mới
   là hành vi đúng, nowrap sẽ đẩy nút chép văng khỏi popup. */
.copy-field__value { font-weight: 700; color: var(--text-strong); word-break: break-all; white-space: normal; }
.copy-btn { flex: none; white-space: nowrap; }
.copy-btn__text { margin-left: .3rem; }

.qr-box {
  padding: var(--space-md);
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  background: var(--surface-muted);
}
/* Nền trắng cố định: QR ngân hàng là ảnh đen-trên-trắng, để nó trong suốt ở giao diện tối thì
   các ô đen chìm vào nền và app ngân hàng không quét được. */
.qr-box__img {
  display: block; margin: 0 auto var(--space-sm);
  max-width: 260px; width: 100%; height: auto;
  background: #fff; padding: var(--space-xs); border-radius: var(--radius-sm);
}

/* ============================================================
   Thanh phân trang dùng chung (fragments/ui :: pagination)
   ============================================================ */
/* margin-bottom: thanh phân trang là phần tử CUỐI của trang (nằm sau .card) — không có nó thì dòng
   "Hiển thị 1–10 trong tổng số N" dính sát mép dưới viewport, khó đọc. Trên <992px khoảng này cộng
   thêm vào padding-bottom chừa chỗ bottom-nav của .page-content, vẫn cách đều. */
.pagination-bar {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-md);
  justify-content: space-between; margin-top: var(--space-md); margin-bottom: var(--space-lg);
}
.pagination-bar__info { color: var(--text-muted); font-size: .875rem; }
.pagination-bar__pages { display: flex; align-items: center; gap: .25rem; list-style: none; margin: 0; padding: 0; }
.pagination-bar__btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 2.25rem; height: 2.25rem; padding: 0 .5rem;
  border: 1px solid var(--border); border-radius: var(--radius-btn);
  background: var(--surface); color: var(--text); text-decoration: none;
  font-size: .875rem; font-weight: 600; font-variant-numeric: tabular-nums;
}
.pagination-bar__btn:hover { border-color: var(--border-strong); color: var(--text); }
.pagination-bar__btn.is-active {
  background: var(--action-primary); border-color: var(--action-primary); color: #fff;
}
.pagination-bar__btn.is-disabled { opacity: .4; pointer-events: none; }
.pagination-bar__ellipsis { padding: 0 .35rem; color: var(--text-muted); }
.pagination-bar__size .btn-ghost { border: 1px solid var(--border); }
@media (max-width: 575.98px) {
  .pagination-bar { justify-content: center; }
  .pagination-bar__info { width: 100%; text-align: center; order: 3; }
}

/* Tôn trọng prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
