/* ==========================================================================
   COURSE PLAYER — hệ thiết kế cho trang học (student) và trang soạn (teacher)
   --------------------------------------------------------------------------
   Trang nào nạp file này thì KHÔNG nạp bootstrap.min.css.
   Mọi class đều mang tiền tố `lp-` để không đụng CSS cũ nếu lỡ nạp chung.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS
   -------------------------------------------------------------------------- */
/*
 * HỆ MÀU VÀ CHỮ LẤY TỪ **SAGE EDITION** (bản xuất thiết kế,
 * gfcourse_player_sage_edition).
 *
 * Nền sáng gần trắng ngả xám lục, điểm nhấn xanh sage trầm #426759, bo góc rất
 * lớn (24px cho thẻ, 48px cho khối lớn). Cảm giác học thuật, yên, ít tương phản
 * gắt — hợp với việc đọc lâu.
 *
 * BA TẦNG BỀ MẶT GIỮ NGUYÊN VAI TRÒ:
 *
 *   khung ngoài  --lp-chrome     topbar, sidebar — surface-container của bản gốc
 *   mặt đọc      --lp-ground / --lp-surface / --lp-surface-sub
 *   mảng đảo     --lp-invert     hàng khoá học, CTA cuối trang, mục đang học
 *
 * Đừng viết mã màu trực tiếp vào bất kỳ quy tắc nào bên dưới — mọi giá trị phải
 * đi qua token, nếu không nó sẽ không đổi theo giao diện sáng/tối.
 */
/*
 * BẢN SÁNG LẤY NGUYÊN VĂN. BẢN TỐI DO SUY RA.
 *
 * Sage Edition chỉ có một chế độ sáng. Bộ tối bên dưới suy từ chính nó theo luật
 * Material 3: GIỮ NGUYÊN SẮC, chỉ đổi độ sáng. Hai giá trị mấu chốt không phải
 * đoán — chúng có sẵn trong bảng gốc: `midnight-base: #0e1511` làm nền tối, và
 * `inverse-primary: #a8d0be` làm màu nhấn tối.
 *
 * Kiểm chứng sắc màu giữa hai chế độ: accent 157°→153°, ok 147°→147°,
 * warn 42°→42°, crit 0°→6°, edit 258°→258°. Lệch tối đa 6 độ, tức bật/tắt chế
 * độ tối không làm đổi màu thương hiệu.
 *
 * Toàn bộ 33 cặp chữ/nền đã tính tỉ lệ tương phản ở CẢ HAI chế độ, tất cả đạt
 * AA (≥4,5:1). Con số ghi kèm từng dòng.
 */
:root {
  /* --- khung ngoài --- */
  --lp-chrome: #EDECEB;
  --lp-chrome-alt: #E8E9E7;
  --lp-chrome-ink: #191C1B;
  /* 14,6:1 trên chrome */
  --lp-chrome-soft: #414945;
  /*  7,9:1 */
  --lp-chrome-rule: #C0C9C4;

  /* --- mặt đọc --- */
  --lp-ground: #F9F9F8;
  --lp-surface: #FFFFFF;
  --lp-surface-sub: #F3F4F3;
  --lp-ink: #191C1B;
  /* 16,3:1 trên ground */
  --lp-ink-soft: #414945;
  /*  8,8:1 */
  --lp-ink-faint: #5F6863;
  /*  5,5:1 — `outline` của bản gốc là #717974, chỉ đạt 4,0:1 nên hụt ngưỡng cho
     chữ cỡ thường; đậm thêm một nấc, giữ nguyên sắc */
  --lp-rule: #C0C9C4;
  --lp-rule-soft: #E2E3E2;

  /* --- điểm nhấn: xanh sage --- */
  --lp-accent: #426759;
  /* 6,0:1 trên ground */
  --lp-accent-ink: #FFFFFF;
  /* 6,3:1 trên accent */
  --lp-accent-sub: #C4ECD9;
  /* primary-container — nền của mục đang mở */

  /* --- mảng đảo --- */
  --lp-invert: #2D312F;
  --lp-invert-ink: #F1F1F1;
  /* 11,7:1 trên invert */
  --lp-invert-soft: #A9B0AC;
  /*  6,0:1 */

  /* --- trạng thái --- *
   * BẢNG GỐC CHỈ CÓ ĐỎ VÀ HỔ PHÁCH. Giao diện này cần thêm hai vai trò:
   *   ok    xanh lục — mục đã học xong
   *   edit  tím     — chế độ soạn của giáo viên
   *
   * `ok` phải phân biệt được với chính màu nhấn, vì màu nhấn CŨNG là xanh. Cách
   * tách: `ok` sáng và bão hoà hơn (147° · 39% bão hoà) so với nhấn (157° · 22%).
   * Trong bản thiết kế, dấu tích "đã xong" tô bằng đúng màu nhấn — ở đây tách ra
   * vì giao diện này còn dùng màu xanh cho nút và liên kết, ba thứ cùng màu thì
   * mất tín hiệu. */
  --lp-ok: #2F6B4A;
  /* 6,0:1 */
  --lp-ok-sub: #D7E6D9;
  --lp-warn: #7C5700;
  /* 6,2:1 — `warning-amber` gốc là #9c6e00, chỉ đạt 4,2:1 */
  --lp-warn-sub: #F5EBD6;
  --lp-crit: #BA1A1A;
  /* 6,1:1 — `error` của bản gốc, giữ nguyên */
  --lp-crit-sub: #FFDAD6;
  --lp-crit-ink: #FFFFFF;
  --lp-edit: #5E4A8C;
  /* 7,0:1 */
  --lp-edit-sub: #E8E3F5;
  --lp-edit-ink: #FFFFFF;

  /* Inter — font duy nhất của bản thiết kế, dùng cho cả tiêu đề lẫn thân bài.
     Đã kiểm tra có subset `vietnamese` phủ khối U+1EA0–1EF9. Tự host vì CSP đặt
     font-src 'self' data:. */
  --lp-f-display: "Inter", "Be Vietnam Pro", "Segoe UI", system-ui, sans-serif;
  --lp-f-body: "Inter", "Be Vietnam Pro", "Segoe UI", system-ui, -apple-system, sans-serif;
  --lp-f-data: ui-monospace, "Cascadia Mono", Consolas, "SF Mono", monospace;

  --lp-ease: cubic-bezier(0.4, 0, 0.2, 1);

  --lp-topbar-h: 60px;
  --lp-side-w: 300px;
  --lp-w-text: 68ch;

  /* Chiều cao ô nhập. Tách thành token vì đây là con số dễ phải chỉnh: trang
     đăng ký có bảy trường. */
  --lp-field-h: 56px;

  /* BO GÓC RẤT LỚN. Thang của bản gốc: 1.5rem thường · 3rem lớn · 4.5rem rất
     lớn · viên thuốc. Ba token dưới lấy ba nấc dùng nhiều nhất. */
  --lp-radius-sm: 12px;
  --lp-radius: 24px;
  --lp-radius-lg: 48px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --lp-chrome: #121A16;
    --lp-chrome-alt: #0E1511;
    --lp-chrome-ink: #E1E4E1;
    /* 13,8:1 trên chrome */
    --lp-chrome-soft: #BAC2BD;
    /*  9,7:1 */
    --lp-chrome-rule: #2A3430;

    --lp-ground: #0E1511;
    /* midnight-base — có sẵn trong bảng gốc */
    --lp-surface: #161E19;
    --lp-surface-sub: #1E2722;
    --lp-ink: #E1E4E1;
    /* 14,5:1 trên ground */
    --lp-ink-soft: #BAC2BD;
    /* 10,2:1 */
    --lp-ink-faint: #8B948E;
    /*  5,9:1 */
    --lp-rule: #2E3833;
    --lp-rule-soft: #1C2521;

    --lp-accent: #A8D0BE;
    /* 11,0:1 — inverse-primary, cũng có sẵn trong bảng gốc */
    --lp-accent-ink: #002117;
    /* 10,1:1 trên accent */
    --lp-accent-sub: #294F42;

    /* Đảo chiều: SÁNG hơn mặt nền, không tối hơn. */
    --lp-invert: #333B36;
    --lp-invert-ink: #E9ECEA;
    /*  9,7:1 trên invert */
    --lp-invert-soft: #A3ABA6;

    --lp-ok: #7FD1A4;
    --lp-ok-sub: #14291F;
    --lp-warn: #E0B44E;
    --lp-warn-sub: #2C2413;
    --lp-crit: #FFB4AB;
    --lp-crit-sub: #341614;
    --lp-crit-ink: #410002;
    --lp-edit: #C9B8F0;
    --lp-edit-sub: #231E33;
    --lp-edit-ink: #1F1633;
  }
}

/* Cùng bộ giá trị như khối trên, lặp lại để lựa chọn tường minh của người dùng
   thắng cả khi hệ điều hành đang ở chế độ sáng. */
:root[data-theme="dark"] {
  --lp-chrome: #121A16;
  --lp-chrome-alt: #0E1511;
  --lp-chrome-ink: #E1E4E1;
  --lp-chrome-soft: #BAC2BD;
  --lp-chrome-rule: #2A3430;

  --lp-ground: #0E1511;
  --lp-surface: #161E19;
  --lp-surface-sub: #1E2722;
  --lp-ink: #E1E4E1;
  --lp-ink-soft: #BAC2BD;
  --lp-ink-faint: #8B948E;
  --lp-rule: #2E3833;
  --lp-rule-soft: #1C2521;

  --lp-accent: #A8D0BE;
  --lp-accent-ink: #002117;
  --lp-accent-sub: #294F42;

  --lp-invert: #333B36;
  --lp-invert-ink: #E9ECEA;
  --lp-invert-soft: #A3ABA6;

  --lp-ok: #7FD1A4;
  --lp-ok-sub: #14291F;
  --lp-warn: #E0B44E;
  --lp-warn-sub: #2C2413;
  --lp-crit: #FFB4AB;
  --lp-crit-sub: #341614;
  --lp-crit-ink: #410002;
  --lp-edit: #C9B8F0;
  --lp-edit-sub: #231E33;
  --lp-edit-ink: #1F1633;
}

/* --------------------------------------------------------------------------
   1b. CẦU NỐI VỚI CSS CŨ
   --------------------------------------------------------------------------
   student.css / teacher.css / profile.css vẫn dùng biến của global.css, mà
   trang player KHÔNG nạp global.css (body rules của nó sẽ đá nhau với hệ mới).
   Ánh xạ lại sang token lp- để các khối cũ (mind map, thẻ bài học…) vừa còn
   chạy vừa tự đổi màu theo hệ mới, thay vì mất trắng biến và render trơ.
   -------------------------------------------------------------------------- */
:root {
  --primary: var(--lp-accent);
  --primary-hover: var(--lp-accent);
  --primary-light: var(--lp-accent-sub);
  --primary-gradient: linear-gradient(135deg, var(--lp-accent) 0%, var(--lp-accent) 100%);
  --secondary: var(--lp-accent);
  --white: var(--lp-surface);
  --background: var(--lp-ground);
  --text: var(--lp-ink);
  --text-muted: var(--lp-ink-soft);
  --text-light: var(--lp-ink-faint);
  --border: var(--lp-rule);
  --shadow-sm: none;
  --shadow-md: none;
  --shadow-lg: none;
  --shadow-glow: none;
  --radius-sm: var(--lp-radius-sm);
  --radius-md: var(--lp-radius);
  --radius-lg: var(--lp-radius);
  --transition-fast: .2s ease;
  --transition-normal: .25s ease;
}

/* --------------------------------------------------------------------------
   2. RESET / BASE
   -------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body.lp {
  margin: 0;
  background: var(--lp-ground);
  color: var(--lp-ink);
  font-family: var(--lp-f-body);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

.lp img,
.lp video,
.lp iframe {
  max-width: 100%;
}

.lp img,
.lp video {
  height: auto;
}

.lp :focus-visible {
  outline: 2px solid var(--lp-accent);
  outline-offset: 2px;
  border-radius: var(--lp-radius-sm);
}

@media (prefers-reduced-motion: reduce) {

  .lp *,
  .lp *::before,
  .lp *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

.lp-ico {
  width: 16px;
  height: 16px;
  flex: none;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.lp-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   3. TẦNG 1 — TOP BAR
   -------------------------------------------------------------------------- */
/*
 * Topbar và sidebar thuộc TẦNG KHUNG (tối). Bên trong hai vùng này, các token
 * mặt-sáng được ánh xạ lại sang bảng khung — nhờ vậy mọi component dùng chung
 * (nút, pill, menu…) tự hoạt động đúng ở cả hai thế giới mà không phải viết
 * lại từng cái một.
 */
.lp-topbar,
.lp-sidebar {
  --lp-surface: var(--lp-chrome);
  --lp-surface-sub: var(--lp-chrome-alt);
  --lp-ink: var(--lp-chrome-ink);
  --lp-ink-soft: var(--lp-chrome-soft);
  --lp-ink-faint: var(--lp-chrome-soft);
  --lp-rule: var(--lp-chrome-rule);
  --lp-rule-soft: var(--lp-chrome-rule);
  color: var(--lp-chrome-ink);
}

/*
 * KHỐI TRÊN TỪNG VIẾT CỨNG NĂM MÃ MÀU, NAY KHÔNG CÒN CÁI NÀO.
 *
 * Bản cũ chia hai thế giới: khung ngoài TỐI trong khi mặt đọc SÁNG. Vì hai nền
 * ngược chiều nhau nên khung ngoài phải mang bảng màu riêng — chữ mờ #8D939B,
 * đường kẻ #2A2E33, và một màu nhấn xanh nhạt #A9C2E8 khác hẳn màu nhấn của
 * trang.
 *
 * Luminous Midnight bỏ cách chia đó: khung ngoài và mặt đọc cùng chiều sáng,
 * chỉ khác nhau một nấc độ sáng bề mặt. Nên mọi giá trị viết cứng ở đây trở
 * thành sai — và sai theo kiểu tệ nhất: ở chế độ sáng, #A9C2E8 đặt trên nền
 * trắng chỉ còn 1,5:1, tức mục đang học ở sidebar gần như tàng hình.
 *
 * Giờ khối này chỉ còn làm một việc: đổi tên ba tầng bề mặt sang tầng chrome.
 * --lp-accent không bị ghi đè nữa, nó thừa hưởng thẳng từ :root và tự đúng ở
 * cả hai chế độ.
 */

.lp-topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  height: var(--lp-topbar-h);
  background: var(--lp-chrome);
  border-bottom: 1px solid var(--lp-chrome-rule);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 20px;
}

.lp-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--lp-f-display);
  font-size: 18px;
  letter-spacing: -.01em;
  color: var(--lp-ink);
  text-decoration: none;
}

.lp-brand .lp-mark {
  width: 26px;
  height: 26px;
  border-radius: var(--lp-radius-sm);
  flex: none;
  background: var(--lp-chrome-ink);
  color: var(--lp-chrome);
  display: grid;
  place-content: center;
  font-family: var(--lp-f-body);
  font-size: 13px;
  font-weight: 700;
}

.lp-burger {
  display: none;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex: none;
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius-sm);
  background: var(--lp-surface);
  color: var(--lp-ink-soft);
  cursor: pointer;
}

.lp-topnav {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 2px;
}

.lp-topnav a,
.lp-topnav .lp-topnav-btn {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 12px;
  border-radius: var(--lp-radius-sm);
  font-size: 13.5px;
  color: var(--lp-ink-soft);
  text-decoration: none;
  border: 0;
  background: transparent;
  font-family: var(--lp-f-body);
  cursor: pointer;
}

.lp-topnav a:hover,
.lp-topnav .lp-topnav-btn:hover {
  background: var(--lp-surface-sub);
  color: var(--lp-ink);
}

.lp-topnav a[aria-current],
.lp-topnav .lp-topnav-btn[data-lp-current] {
  background: var(--lp-accent-sub);
  color: var(--lp-accent);
  font-weight: 600;
}

.lp-caret {
  transition: transform .15s ease;
}

.lp-menu.is-open .lp-caret {
  transform: rotate(180deg);
}

.lp-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--lp-rule);
}

/* menu người dùng */
.lp-menu {
  position: relative;
}

.lp-menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 40;
  min-width: 208px;
  padding: 6px;
  background: var(--lp-surface);
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
  box-shadow: 0 8px 28px rgba(0, 0, 0, .14);
  display: none;
}

.lp-menu[open] .lp-menu-panel,
.lp-menu.is-open .lp-menu-panel {
  display: block;
}

.lp-menu-panel a,
.lp-menu-panel button {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 8px 10px;
  border-radius: var(--lp-radius-sm);
  font-size: 14px;
  color: var(--lp-ink);
  text-decoration: none;
  border: 0;
  background: transparent;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.lp-menu-panel a:hover,
.lp-menu-panel button:hover {
  background: var(--lp-surface-sub);
}

.lp-menu-panel .lp-danger {
  color: var(--lp-crit);
}

.lp-menu-sep {
  height: 1px;
  background: var(--lp-rule-soft);
  margin: 6px 0;
}

.lp-menu-label {
  padding: 6px 10px;
  font-family: var(--lp-f-data);
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--lp-ink-faint);
}

/* Nhãn chữ biến mất ở màn hình hẹp, nên MỌI mục nav phải mang aria-label —
   display:none gỡ phần tử khỏi cây khả truy cập, icon thì đã aria-hidden.
   Xem includes/player_topbar.php. */
@media (max-width: 1140px) {

  .lp-topnav a span,
  .lp-topnav .lp-topnav-btn span {
    display: none;
  }

  .lp-topnav a,
  .lp-topnav .lp-topnav-btn {
    padding: 7px 9px;
  }
}

@media (max-width: 1000px) {
  .lp-burger {
    display: flex;
  }
}

/* --------------------------------------------------------------------------
   3b. WIDGET TIẾN TRÌNH AI
   --------------------------------------------------------------------------
   Chuyển từ assets/css/global-ai-progress.css vào đây. Bản cũ tự dựng bảng màu
   riêng (#2563eb, chữ #172033) rồi đặt lên topbar tối, cho ra 1,29:1 — gần như
   không đọc được, đúng lúc giáo viên cần theo dõi tiến trình nhất. Nó cũng khoá
   dark mode vào [data-bs-theme] của Bootstrap, vốn đã bị gỡ khỏi dự án.

   Nằm trong .lp-topbar nên khối này thừa hưởng phép ánh xạ token của tầng khung:
   --lp-surface/-ink/-accent tự trỏ sang bảng màu tối và tự lật theo giao diện.
   -------------------------------------------------------------------------- */
.global-ai-progress-widget {
  position: relative;
  margin-inline: 4px;
}

.global-ai-progress-widget[hidden] {
  display: none !important;
}

/* Trạng thái chỉ đổi MÀU BÁO, không đổi màu nhấn của hệ. */
.global-ai-progress-widget {
  --ai-state: var(--lp-accent);
}

.global-ai-progress-widget.is-completed {
  --ai-state: var(--lp-ok);
}

.global-ai-progress-widget.is-failed {
  --ai-state: var(--lp-crit);
}

.global-ai-progress-details {
  position: relative;
}

.global-ai-progress-summary {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 34px;
  padding: 6px 12px;
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius-sm);
  background: var(--lp-surface-sub);
  color: var(--lp-ink);
  font-size: 13px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.global-ai-progress-summary::-webkit-details-marker {
  display: none;
}

.global-ai-progress-summary:hover {
  border-color: var(--ai-state);
}

.global-ai-progress-icon {
  color: var(--ai-state);
  font-size: 13px;
}

.global-ai-progress-widget.is-active .global-ai-progress-icon {
  animation: global-ai-progress-pulse 1.6s ease-in-out infinite;
}

.global-ai-progress-compact-label {
  white-space: nowrap;
  font-weight: 500;
}

#globalAiProgressPercent {
  min-width: 3.2ch;
  text-align: right;
  color: var(--ai-state);
  font-family: var(--lp-f-data);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.global-ai-progress-panel {
  position: absolute;
  z-index: 40;
  /* cùng thang với .lp-menu-panel */
  top: calc(100% + 6px);
  right: 0;
  width: min(21rem, calc(100vw - 2rem));
  padding: 15px 17px;
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
  background: var(--lp-surface);
  color: var(--lp-ink);
  box-shadow: 0 8px 28px rgba(0, 0, 0, .28);
}

.global-ai-progress-panel-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 6px;
  font-size: 13.5px;
  font-weight: 600;
}

#globalAiProgressText {
  min-height: 2.5em;
  margin: 0 0 11px;
  color: var(--lp-ink-soft);
  font-size: 13px;
  line-height: 1.5;
}

.global-ai-progress-track {
  height: 5px;
  overflow: hidden;
  border-radius: var(--lp-radius-sm);
  background: var(--lp-rule-soft);
}

#globalAiProgressBar {
  width: 0;
  height: 100%;
  border-radius: inherit;
  background: var(--ai-state);
  transition: width 260ms ease;
}

#globalAiProgressDetails {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  margin-top: 10px;
  color: var(--lp-accent);
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
}

#globalAiProgressDetails:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.pipeline-step {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 0;
  font-size: 13px;
  color: var(--lp-ink-soft);
  opacity: .45;
  transition: opacity .3s;
}

.pipeline-step.active {
  opacity: 1;
  color: var(--lp-ink);
}

.pipeline-step .step-icon {
  width: 28px;
  height: 28px;
  flex: none;
  font-size: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1px solid var(--lp-rule-soft);
  background: var(--lp-surface-sub);
  color: var(--lp-ink-faint);
}

.pipeline-step.active .step-icon {
  border-color: var(--lp-accent);
  background: var(--lp-accent-sub);
  color: var(--lp-accent);
}

@keyframes global-ai-progress-pulse {
  50% {
    opacity: .45;
    transform: scale(.9);
  }
}

/* 1000px cho khớp ngưỡng thu gọn của topbar. Bản cũ dùng 991.98px của Bootstrap,
   nên trong dải 992–1000px widget đã giãn hết bề ngang trong khi topbar vẫn nằm ngang. */
@media (max-width: 1000px) {
  .global-ai-progress-widget {
    margin-inline: 2px;
  }

  .global-ai-progress-compact-label {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   4. TẦNG 2 — SHELL + SIDEBAR
   -------------------------------------------------------------------------- */
.lp-shell {
  display: grid;
  grid-template-columns: var(--lp-side-w) minmax(0, 1fr);
}

.lp-shell.lp-no-side {
  grid-template-columns: minmax(0, 1fr);
}

.lp-sidebar {
  position: sticky;
  top: var(--lp-topbar-h);
  height: calc(100vh - var(--lp-topbar-h));
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--lp-chrome);
  border-right: 1px solid var(--lp-chrome-rule);
  padding-bottom: 40px;
}

.lp-course-head {
  padding: 18px 18px 16px;
  border-bottom: 1px solid var(--lp-rule);
}

.lp-eyebrow {
  font-family: var(--lp-f-data);
  font-size: 10px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--lp-ink-faint);
  margin: 0 0 6px;
}

.lp-course-head h2 {
  font-family: var(--lp-f-display);
  font-weight: 400;
  font-size: 19px;
  line-height: 1.25;
  margin: 0 0 14px;
}

.lp-course-head h2 a {
  color: inherit;
  text-decoration: none;
}

.lp-course-head h2 a:hover {
  color: var(--lp-accent);
}

.lp-pbar {
  height: 5px;
  border-radius: var(--lp-radius-sm);
  background: var(--lp-rule-soft);
  overflow: hidden;
}

.lp-pbar i {
  display: block;
  height: 100%;
  background: var(--lp-ok);
}

.lp-pmeta {
  display: flex;
  justify-content: space-between;
  margin-top: 7px;
  font-family: var(--lp-f-data);
  font-size: 11px;
  color: var(--lp-ink-faint);
  font-variant-numeric: tabular-nums;
}

.lp-mod {
  border-bottom: 1px solid var(--lp-rule-soft);
}

.lp-mod>summary {
  list-style: none;
  cursor: pointer;
  display: grid;
  grid-template-columns: 14px 1fr auto;
  gap: 10px;
  align-items: center;
  padding: 13px 18px;
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.35;
}

.lp-mod>summary::-webkit-details-marker {
  display: none;
}

.lp-mod>summary:hover {
  background: var(--lp-surface-sub);
}

.lp-mod>summary .lp-cnt {
  font-family: var(--lp-f-data);
  font-size: 11px;
  font-weight: 400;
  color: var(--lp-ink-faint);
  font-variant-numeric: tabular-nums;
}

.lp-mod>summary .lp-chev {
  width: 14px;
  height: 14px;
  color: var(--lp-ink-faint);
  transition: transform .15s ease;
}

.lp-mod[open]>summary .lp-chev {
  transform: rotate(90deg);
}

.lp-mod-items {
  padding: 0 10px 12px;
  display: grid;
  gap: 1px;
}

.lp-item {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--lp-radius-sm);
  font-size: 14px;
  line-height: 1.4;
  text-decoration: none;
  color: var(--lp-ink-soft);
  align-items: start;
}

.lp-item .lp-ico {
  margin-top: 3px;
  color: var(--lp-ink-faint);
}

.lp-item:hover {
  background: var(--lp-surface-sub);
  color: var(--lp-ink);
}

.lp-item.is-done {
  color: var(--lp-ink);
}

.lp-item.is-done .lp-ico {
  color: var(--lp-ok);
}

.lp-item.is-current {
  background: var(--lp-accent);
  color: var(--lp-accent-ink);
  font-weight: 600;
}

.lp-item.is-current .lp-ico {
  color: var(--lp-accent-ink);
}

.lp-item.is-current:hover {
  background: var(--lp-accent);
  color: var(--lp-accent-ink);
}

.lp-item.is-locked {
  color: var(--lp-ink-faint);
}

.lp-side-empty {
  padding: 22px 18px;
  font-size: 14px;
  color: var(--lp-ink-faint);
}

/* off-canvas dưới 1000px */
.lp-scrim {
  display: none;
}

@media (max-width: 1000px) {
  .lp-shell {
    grid-template-columns: minmax(0, 1fr);
  }

  .lp-sidebar {
    position: fixed;
    top: var(--lp-topbar-h);
    left: 0;
    width: 300px;
    z-index: 25;
    transform: translateX(-101%);
    transition: transform .2s ease;
  }

  body.lp-nav-open .lp-sidebar {
    transform: translateX(0);
    box-shadow: 0 8px 40px rgba(0, 0, 0, .28);
  }

  body.lp-nav-open .lp-scrim {
    display: block;
    position: fixed;
    inset: var(--lp-topbar-h) 0 0 0;
    background: rgba(0, 0, 0, .35);
    z-index: 24;
  }
}

/* --------------------------------------------------------------------------
   5. TẦNG 3 — CONTENT
   -------------------------------------------------------------------------- */
.lp-content {
  padding: 0 40px;
  min-width: 0;
  background: var(--lp-ground);
}

@media (max-width: 700px) {
  .lp-content {
    padding: 0 20px;
  }
}

.lp-crumb {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 22px 0 0;
  font-size: 13px;
  color: var(--lp-ink-faint);
}

.lp-crumb a {
  color: var(--lp-accent);
  text-decoration: none;
}

.lp-crumb a:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.lp-page-head {
  padding: 14px 0 22px;
  border-bottom: 1px solid var(--lp-rule);
  margin-bottom: 30px;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}

.lp-page-head>div {
  min-width: 0;
}

.lp-type-tag {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 16px;
  font-family: var(--lp-f-body);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--lp-ink-faint);
  border: 0;
  padding: 0;
}

.lp-type-tag .lp-ico {
  width: 13px;
  height: 13px;
}

.lp-type-tag.is-ok {
  color: var(--lp-ok);
  border-color: var(--lp-ok);
}

.lp-type-tag.is-warn {
  color: var(--lp-warn);
  border-color: var(--lp-warn);
}

.lp-type-tag.is-crit {
  color: var(--lp-crit);
  border-color: var(--lp-crit);
}

.lp-content h1 {
  font-family: var(--lp-f-display);
  font-weight: 500;
  font-size: clamp(34px, 5vw, 54px);
  line-height: 1.0;
  letter-spacing: -.03em;
  margin: 0;
  text-wrap: balance;
  max-width: 22ch;
}

/* lưới bài + rail */
.lp-article {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 296px;
  gap: 52px;
  max-width: 1180px;
  padding-bottom: 40px;
  align-items: start;
}

.lp-article.lp-wide {
  grid-template-columns: minmax(0, 1fr);
  max-width: 1180px;
}

@media (max-width: 1240px) {
  .lp-article {
    grid-template-columns: minmax(0, 1fr);
    gap: 36px;
    max-width: 900px;
  }
}

/* F-2 + F-3: chữ giới hạn 68ch, media chiếm trọn bề rộng cột */
.lp-prose>p,
.lp-prose>ul,
.lp-prose>ol,
.lp-prose>h2,
.lp-prose>h3,
.lp-prose>h4,
.lp-prose>blockquote {
  max-width: var(--lp-w-text);
}

.lp-prose>p {
  margin: 0 0 18px;
}

.lp-prose>ul,
.lp-prose>ol {
  margin: 0 0 18px;
  padding-left: 22px;
}

.lp-prose li {
  margin-bottom: 8px;
}

.lp-prose li>ul,
.lp-prose li>ol {
  margin-top: 8px;
}

/* phân cấp bằng màu + weight, cỡ chữ gần như không đổi */
.lp-prose h2 {
  font-family: var(--lp-f-display);
  font-weight: 400;
  font-size: 23px;
  line-height: 1.25;
  color: var(--lp-ink);
  margin: 36px 0 12px;
}

.lp-prose h3,
.lp-prose h4 {
  font-family: var(--lp-f-body);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--lp-ink);
  margin: 32px 0 10px;
}

.lp-prose> :first-child {
  margin-top: 0;
}

.lp-prose blockquote {
  margin: 0 0 18px;
  padding: 2px 0 2px 18px;
  border-left: 2px solid var(--lp-rule);
  color: var(--lp-ink-soft);
}

/* :not(.lp-btn) — nếu không, quy tắc này (0,2,0) sẽ thắng .lp-btn (0,1,0)
   và nút nằm trong bài viết bị tô chữ cùng màu nền, thành ô trống. */
.lp-prose a:not(.lp-btn) {
  color: var(--lp-accent);
  text-underline-offset: 3px;
}

.lp-prose img {
  border-radius: var(--lp-radius);
}

.lp-prose table {
  border-collapse: collapse;
  width: 100%;
  font-size: 14.5px;
}

.lp-prose table th,
.lp-prose table td {
  border: 1px solid var(--lp-rule);
  padding: 9px 12px;
  text-align: left;
}

.lp-prose table th {
  background: var(--lp-surface-sub);
  font-weight: 600;
}

.lp-prose pre {
  overflow-x: auto;
  background: var(--lp-surface-sub);
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
  padding: 16px 18px;
  font-family: var(--lp-f-data);
  font-size: 13px;
}

.lp-prose code {
  font-family: var(--lp-f-data);
  font-size: .88em;
  background: var(--lp-surface-sub);
  border: 1px solid var(--lp-rule-soft);
  padding: 1px 5px;
  border-radius: var(--lp-radius-sm);
}

.lp-prose pre code {
  background: none;
  border: 0;
  padding: 0;
}

.lp-lede {
  font-size: 17.5px;
  color: var(--lp-ink-soft);
}

/* bảng rộng — cuộn trong khung riêng, không đẩy trang */
.lp-tablewrap {
  overflow-x: auto;
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
  background: var(--lp-surface);
}

.lp-tablewrap table {
  border-collapse: collapse;
  width: 100%;
  font-size: 14px;
  min-width: 520px;
}

.lp-tablewrap th,
.lp-tablewrap td {
  text-align: left;
  padding: 11px 16px;
  border-bottom: 1px solid var(--lp-rule-soft);
  vertical-align: middle;
}

.lp-tablewrap thead th {
  font-family: var(--lp-f-data);
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--lp-ink-faint);
  font-weight: 400;
  background: var(--lp-surface-sub);
  border-bottom: 1px solid var(--lp-rule);
}

.lp-tablewrap tbody tr:last-child td {
  border-bottom: 0;
}

.lp-num {
  font-variant-numeric: tabular-nums;
  font-family: var(--lp-f-data);
}

/* --------------------------------------------------------------------------
   6. MEDIA
   -------------------------------------------------------------------------- */
.lp-video {
  width: 100%;
  aspect-ratio: 16 / 9;
  margin: 8px 0 26px;
  /* Nền đen là quy ước của khung phát video, không phải màu của hệ. */
  background: #000;
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
  overflow: hidden;
}

.lp-video video,
.lp-video iframe {
  width: 100%;
  height: 100%;
  display: block;
  border: 0;
}

.lp-video-empty {
  display: grid;
  place-content: center;
  gap: 12px;
  justify-items: center;
  background: var(--lp-surface-sub);
  color: var(--lp-ink-faint);
  height: 100%;
}

/* --------------------------------------------------------------------------
   7. RAIL + CARD
   -------------------------------------------------------------------------- */
.lp-rail {
  display: grid;
  gap: 18px;
  position: sticky;
  top: calc(var(--lp-topbar-h) + 24px);
}

@media (max-width: 1240px) {
  .lp-rail {
    position: static;
    max-width: var(--lp-w-text);
  }
}

.lp-card {
  background: var(--lp-surface);
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
  padding: 17px 19px;
}

.lp-card.lp-sub {
  background: var(--lp-surface-sub);
}

.lp-card>h4 {
  margin: 0 0 10px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--lp-accent);
  display: flex;
  align-items: center;
  gap: 8px;
}

.lp-card>p {
  margin: 0 0 11px;
  font-size: 14px;
  color: var(--lp-ink-soft);
  line-height: 1.6;
}

.lp-card>p:last-child {
  margin: 0;
}

.lp-kv {
  display: grid;
  gap: 9px;
  font-size: 13.5px;
  margin: 0;
}

.lp-kv>div {
  display: flex;
  justify-content: space-between;
  gap: 12px;
}

.lp-kv dt {
  color: var(--lp-ink-faint);
}

.lp-kv dd {
  margin: 0;
  font-family: var(--lp-f-data);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* --------------------------------------------------------------------------
   8. NÚT
   -------------------------------------------------------------------------- */
.lp-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  border: 1px solid var(--lp-accent);
  background: var(--lp-accent);
  color: var(--lp-accent-ink);
  font-family: inherit;
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.3;
  padding: 11px 22px;
  border-radius: var(--lp-radius-sm);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
}

.lp-btn:hover {
  filter: brightness(1.08);
}

.lp-btn:disabled,
.lp-btn[aria-disabled="true"] {
  opacity: .5;
  cursor: not-allowed;
  filter: none;
}

.lp-btn.lp-ghost {
  background: transparent;
  color: var(--lp-accent);
}

.lp-btn.lp-ghost:hover {
  background: var(--lp-accent-sub);
  filter: none;
}

.lp-btn.lp-quiet {
  background: var(--lp-surface);
  color: var(--lp-ink);
  border-color: var(--lp-rule);
}

.lp-btn.lp-quiet:hover {
  background: var(--lp-surface-sub);
  filter: none;
}

.lp-btn.lp-danger {
  background: var(--lp-crit);
  border-color: var(--lp-crit);
  color: var(--lp-crit-ink);
}

.lp-btn.lp-sm {
  font-size: 13px;
  padding: 7px 14px;
  font-weight: 500;
}

.lp-btn-row {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
}

/* --------------------------------------------------------------------------
   9. FORM
   -------------------------------------------------------------------------- */
.lp-field-group {
  display: grid;
  gap: 6px;
  margin-bottom: 18px;
}

.lp-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--lp-ink);
}

.lp-hint {
  font-size: 12.5px;
  color: var(--lp-ink-faint);
}

.lp-input,
.lp-textarea,
.lp-select {
  width: 100%;
  font-family: inherit;
  font-size: 15px;
  color: var(--lp-ink);
  background: var(--lp-surface);
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius-sm);
  padding: 10px 13px;
}

.lp-textarea {
  min-height: 120px;
  resize: vertical;
  line-height: 1.6;
}

.lp-input:focus,
.lp-textarea:focus,
.lp-select:focus {
  outline: none;
  border-color: var(--lp-accent);
  box-shadow: 0 0 0 3px var(--lp-accent-sub);
}

.lp-input::placeholder,
.lp-textarea::placeholder {
  color: var(--lp-ink-faint);
}

/* ô nhập + nút gửi liền khối */
.lp-inline-field {
  display: flex;
  gap: 8px;
  align-items: center;
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius-sm);
  padding: 4px 4px 4px 14px;
  background: var(--lp-surface);
}

.lp-inline-field:focus-within {
  border-color: var(--lp-accent);
  box-shadow: 0 0 0 3px var(--lp-accent-sub);
}

.lp-inline-field input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  font-family: inherit;
  font-size: 15px;
  color: var(--lp-ink);
  padding: 9px 0;
}

.lp-inline-field input:focus {
  outline: none;
}

.lp-inline-field button {
  border: 0;
  background: var(--lp-accent);
  color: var(--lp-accent-ink);
  font-family: var(--lp-f-data);
  font-size: 12.5px;
  padding: 9px 18px;
  border-radius: var(--lp-radius-sm);
  cursor: pointer;
}

/* --------------------------------------------------------------------------
   10. KHỐI TƯƠNG TÁC / PHẢN HỒI AI
   -------------------------------------------------------------------------- */
.lp-engage {
  margin: 34px 0 0;
  max-width: var(--lp-w-text);
}

.lp-engage>h3 {
  font-family: var(--lp-f-body);
  font-size: 16.5px;
  font-weight: 600;
  color: var(--lp-accent);
  margin: 0 0 6px;
}

.lp-engage>p {
  margin: 0 0 14px;
  font-size: 15px;
  color: var(--lp-ink-soft);
}

.lp-ai {
  margin-top: 16px;
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
  padding: 18px 20px;
  background: var(--lp-surface-sub);
}

.lp-ai .lp-tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 11px;
  font-family: var(--lp-f-data);
  font-size: 10px;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--lp-accent);
  border: 1px solid var(--lp-accent);
  border-radius: var(--lp-radius-sm);
  padding: 2px 8px;
}

.lp-ai h4 {
  margin: 0 0 8px;
  font-size: 15.5px;
  font-weight: 600;
}

.lp-ai p {
  margin: 0 0 10px;
  font-size: 15px;
  color: var(--lp-ink-soft);
}

.lp-ai p:last-child {
  margin: 0;
}

/* --------------------------------------------------------------------------
   10b. LỜI GIẢNG (TRANSCRIPT) — thanh ẩn/hiện
   -------------------------------------------------------------------------- */
.lp-transcript {
  margin: 10px 0 22px;
  max-width: var(--lp-w-text);
}

.lp-transcript-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

.lp-transcript-body {
  border-left: 2px solid var(--lp-rule);
  padding-left: 16px;
  font-size: 15.5px;
  line-height: 1.75;
  /* văn nói dài, cần thoáng hơn văn viết */
  color: var(--lp-ink-soft);
}

/* Ẩn bằng thuộc tính chứ không bằng class: trạng thái nằm ngay trên phần tử,
   nên script và CSS không thể lệch nhau. */
.lp-transcript[data-collapsed] .lp-transcript-body {
  display: none;
}

/* Không hoạt ảnh chiều cao: nội dung dài hàng nghìn chữ, animate height sẽ giật.
   Đổi trạng thái tức thì là đúng với một nút ẩn/hiện. */
.lp-results {
  display: flex;
  align-items: center;
  gap: 40px;
  flex-wrap: wrap;
  padding: 26px;
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
  background: var(--lp-surface);
  margin-bottom: 30px;
}

.lp-ring {
  position: relative;
  width: 120px;
  height: 120px;
  flex: none;
}

.lp-ring svg {
  transform: rotate(-90deg);
  display: block;
}

.lp-ring b {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  font-family: var(--lp-f-data);
  font-size: 25px;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
}

.lp-stat {
  display: grid;
  gap: 1px;
}

.lp-stat b {
  font-family: var(--lp-f-data);
  font-size: 29px;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}

.lp-stat span {
  font-size: 12.5px;
  color: var(--lp-ink-faint);
}

.lp-qlist {
  display: grid;
  gap: 12px;
  max-width: var(--lp-w-text);
}

.lp-qcard {
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
  background: var(--lp-surface);
  padding: 16px 18px;
}

.lp-qhead {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.lp-qnum {
  width: 28px;
  height: 28px;
  flex: none;
  display: grid;
  place-content: center;
  background: var(--lp-ink);
  color: var(--lp-ground);
  font-family: var(--lp-f-data);
  font-size: 12.5px;
  border-radius: var(--lp-radius-sm);
}

.lp-qscore {
  font-family: var(--lp-f-data);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.lp-qscore.is-full {
  color: var(--lp-ok);
}

.lp-qscore.is-part {
  color: var(--lp-warn);
}

.lp-qscore.is-zero {
  color: var(--lp-crit);
}

.lp-pill {
  font-family: var(--lp-f-data);
  font-size: 10px;
  letter-spacing: .1em;
  text-transform: uppercase;
  border: 1px solid var(--lp-rule);
  color: var(--lp-ink-faint);
  border-radius: var(--lp-radius-sm);
  padding: 2px 8px;
  white-space: nowrap;
}

.lp-pill.is-ok {
  border-color: var(--lp-ok);
  color: var(--lp-ok);
}

.lp-pill.is-warn {
  border-color: var(--lp-warn);
  color: var(--lp-warn);
}

.lp-pill.is-crit {
  border-color: var(--lp-crit);
  color: var(--lp-crit);
}

.lp-pill.is-accent {
  border-color: var(--lp-accent);
  color: var(--lp-accent);
}

/* thang chấm */
.lp-rubric {
  display: grid;
  gap: 1px;
  background: var(--lp-rule);
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
  overflow: hidden;
  max-width: var(--lp-w-text);
  margin: 8px 0 22px;
}

.lp-rubric>div {
  background: var(--lp-surface);
  padding: 15px 18px;
}

.lp-rubric h5 {
  margin: 0 0 7px;
  font-size: 13px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 9px;
}

.lp-rubric h5 i {
  width: 8px;
  height: 8px;
  border-radius: var(--lp-radius-sm);
  flex: none;
  font-style: normal;
}

.lp-rubric ul {
  margin: 0;
  padding-left: 20px;
  font-size: 14px;
  color: var(--lp-ink-soft);
}

.lp-rubric li {
  margin-bottom: 5px;
}

/* --------------------------------------------------------------------------
   12. THÔNG BÁO / TRẠNG THÁI RỖNG
   -------------------------------------------------------------------------- */
.lp-alert {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 13px 16px;
  border-radius: var(--lp-radius);
  border: 1px solid var(--lp-rule);
  background: var(--lp-surface-sub);
  font-size: 14.5px;
  margin-bottom: 20px;
  max-width: var(--lp-w-text);
}

.lp-alert p {
  margin: 0;
}

.lp-alert.is-ok {
  border-color: var(--lp-ok);
  background: var(--lp-ok-sub);
  color: var(--lp-ink);
}

.lp-alert.is-warn {
  border-color: var(--lp-warn);
  background: var(--lp-warn-sub);
  color: var(--lp-ink);
}

.lp-alert.is-crit {
  border-color: var(--lp-crit);
  background: var(--lp-crit-sub);
  color: var(--lp-ink);
}

.lp-empty {
  display: grid;
  gap: 10px;
  justify-items: center;
  text-align: center;
  padding: 56px 24px;
  border: 1px dashed var(--lp-rule);
  border-radius: var(--lp-radius);
  color: var(--lp-ink-faint);
}

.lp-empty h3 {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
  color: var(--lp-ink);
}

.lp-empty p {
  margin: 0;
  font-size: 14.5px;
  max-width: 44ch;
}

/* --------------------------------------------------------------------------
   13. PAGER
   -------------------------------------------------------------------------- */
.lp-pager {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  padding: 26px 0 56px;
  margin-top: 10px;
  border-top: 1px solid var(--lp-rule);
  max-width: 1180px;
}

@media (max-width: 620px) {
  .lp-pager {
    grid-template-columns: minmax(0, 1fr);
  }
}

.lp-pgbtn {
  display: grid;
  gap: 3px;
  padding: 13px 18px;
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
  background: var(--lp-surface);
  text-decoration: none;
}

.lp-pgbtn:hover {
  border-color: var(--lp-accent);
}

.lp-pgbtn em {
  font-style: normal;
  font-family: var(--lp-f-data);
  font-size: 10px;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--lp-ink-faint);
}

.lp-pgbtn b {
  font-weight: 600;
  font-size: 14.5px;
  color: var(--lp-ink);
  line-height: 1.35;
}

.lp-pgbtn.lp-next {
  text-align: right;
}

.lp-pgbtn.is-empty {
  visibility: hidden;
}

/* --------------------------------------------------------------------------
   14. CHẾ ĐỘ SOẠN (chỉ giáo viên)
   -------------------------------------------------------------------------- */
.lp-editbar {
  position: sticky;
  top: var(--lp-topbar-h);
  z-index: 28;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding: 10px 40px;
  background: var(--lp-edit-sub);
  border-bottom: 1px solid var(--lp-edit);
}

@media (max-width: 700px) {
  .lp-editbar {
    padding: 10px 20px;
  }
}

.lp-editbar .lp-editbar-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--lp-f-data);
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--lp-edit);
  font-weight: 600;
}

.lp-editbar .lp-editbar-actions {
  margin-left: auto;
  display: flex;
  gap: 10px;
  align-items: center;
}

.lp-editbar .lp-btn {
  border-color: var(--lp-edit);
  background: var(--lp-edit);
  color: var(--lp-edit-ink);
}

.lp-editbar .lp-btn.lp-quiet {
  background: var(--lp-surface);
  color: var(--lp-ink);
  border-color: var(--lp-rule);
}

.lp-dirty {
  font-family: var(--lp-f-data);
  font-size: 11.5px;
  color: var(--lp-ink-soft);
  font-variant-numeric: tabular-nums;
}

.lp-dirty.is-dirty {
  color: var(--lp-warn);
}

.lp-dirty.is-saved {
  color: var(--lp-ok);
}

/* vùng có thể sửa — chỉ hiện khi bật chế độ soạn */
[data-lp-edit] {
  border-radius: var(--lp-radius-sm);
}

body.lp-editing [data-lp-edit] {
  outline: 1px dashed var(--lp-edit);
  outline-offset: 3px;
  cursor: text;
  transition: outline-color .15s ease, background-color .15s ease;
}

body.lp-editing [data-lp-edit]:hover {
  outline-style: solid;
  background: var(--lp-edit-sub);
}

body.lp-editing [data-lp-edit]:focus {
  outline: 2px solid var(--lp-edit);
  outline-offset: 3px;
  background: var(--lp-surface);
}

body.lp-editing [data-lp-edit].is-changed {
  outline-color: var(--lp-warn);
  outline-style: solid;
}

body.lp-editing [data-lp-edit][data-lp-empty]:empty::before {
  content: attr(data-lp-empty);
  color: var(--lp-ink-faint);
  font-style: italic;
}

/* sắp xếp lại item trong sidebar */
body.lp-editing .lp-item {
  cursor: grab;
}

body.lp-editing .lp-item.is-dragging {
  opacity: .45;
}

body.lp-editing .lp-item.is-dropzone {
  box-shadow: inset 0 2px 0 var(--lp-edit);
}

.lp-grip {
  display: none;
}

body.lp-editing .lp-grip {
  display: block;
  color: var(--lp-ink-faint);
  width: 14px;
  height: 14px;
  flex: none;
}

/* chỉ hiện khi đang ở chế độ soạn */
.lp-edit-only {
  display: none;
}

body.lp-editing .lp-edit-only {
  display: block;
}

body.lp-editing .lp-edit-only.lp-row,
body.lp-editing .lp-edit-only.lp-btn-row {
  display: flex;
}

body.lp-editing .lp-edit-only.lp-inline {
  display: inline-flex;
}

/* vùng kéo-thả tệp */
.lp-dropzone {
  margin: 14px 0 22px;
  padding: 22px;
  border: 1px dashed var(--lp-rule);
  border-radius: var(--lp-radius);
  background: var(--lp-surface-sub);
  display: grid;
  gap: 10px;
  justify-items: center;
  text-align: center;
  color: var(--lp-ink-soft);
  font-size: 14px;
  transition: border-color .15s ease, background-color .15s ease;
  max-width: var(--lp-w-text);
}

.lp-dropzone.is-over {
  border-color: var(--lp-edit);
  border-style: solid;
  background: var(--lp-edit-sub);
}

.lp-dropzone.is-busy {
  opacity: .6;
  pointer-events: none;
}

.lp-dropzone p {
  margin: 0;
}

.lp-dropzone input[type="file"] {
  display: none;
}

/* nút xoá trên từng dòng tài liệu */
.lp-rowdel {
  border: 1px solid var(--lp-rule);
  background: var(--lp-surface);
  color: var(--lp-crit);
  border-radius: var(--lp-radius-sm);
  padding: 5px 9px;
  cursor: pointer;
  line-height: 0;
}

.lp-rowdel:hover {
  border-color: var(--lp-crit);
  background: var(--lp-crit-sub);
}

/* thao tác bài học trong sidebar */
.lp-side-actions {
  display: none;
  padding: 12px 14px;
  border-top: 1px solid var(--lp-rule);
}

body.lp-editing .lp-side-actions {
  display: block;
}

body.lp-editing .lp-mod>summary {
  position: relative;
}

.lp-mod-tools {
  display: none;
  gap: 4px;
  align-items: center;
}

body.lp-editing .lp-mod-tools {
  display: flex;
}

.lp-mod-tools button {
  border: 0;
  background: transparent;
  color: var(--lp-ink-faint);
  cursor: pointer;
  padding: 3px;
  border-radius: var(--lp-radius-sm);
  line-height: 0;
}

.lp-mod-tools button:hover {
  background: var(--lp-rule-soft);
  color: var(--lp-crit);
}

.lp-mod-tools .lp-drag {
  cursor: grab;
}

.lp-mod.is-dragging {
  opacity: .45;
}

.lp-mod.is-dropbefore {
  box-shadow: inset 0 2px 0 var(--lp-edit);
}

/* thanh lưu ở cuối trang — dính đáy màn hình khi đang soạn */
.lp-savebar {
  position: sticky;
  bottom: 0;
  z-index: 26;
  margin: 0 -40px;
  padding: 14px 40px;
  background: var(--lp-surface);
  border-top: 1px solid var(--lp-edit);
  display: none;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  box-shadow: 0 -4px 20px rgba(0, 0, 0, .08);
}

@media (max-width: 700px) {
  .lp-savebar {
    margin: 0 -20px;
    padding: 14px 20px;
  }
}

body.lp-editing .lp-savebar {
  display: flex;
}

.lp-savebar .lp-savebar-hint {
  font-size: 13.5px;
  color: var(--lp-ink-soft);
  flex: 1;
  min-width: 180px;
}

.lp-savebar .lp-btn-row {
  margin-left: auto;
}

.lp-savebar .lp-btn {
  border-color: var(--lp-edit);
  background: var(--lp-edit);
  color: var(--lp-edit-ink);
}

.lp-savebar .lp-btn.lp-quiet {
  background: var(--lp-surface);
  color: var(--lp-ink);
  border-color: var(--lp-rule);
}

.lp-savebar .lp-btn:disabled {
  opacity: .45;
}

/* toast lưu */
.lp-toast {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 18px;
  border-radius: var(--lp-radius);
  background: var(--lp-surface);
  border: 1px solid var(--lp-rule);
  box-shadow: 0 8px 30px rgba(0, 0, 0, .18);
  font-size: 14px;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .18s ease, transform .18s ease;
  pointer-events: none;
}

.lp-toast.is-on {
  opacity: 1;
  transform: translateY(0);
}

.lp-toast.is-ok {
  border-color: var(--lp-ok);
  color: var(--lp-ok);
}

.lp-toast.is-crit {
  border-color: var(--lp-crit);
  color: var(--lp-crit);
}

/* hộp thoại */
.lp-dialog {
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
  background: var(--lp-surface);
  color: var(--lp-ink);
  padding: 0;
  max-width: 560px;
  width: calc(100vw - 40px);
  box-shadow: 0 20px 60px rgba(0, 0, 0, .28);
}

.lp-dialog::backdrop {
  background: rgba(15, 23, 42, 0.55);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
}

/* Theme UI Confirmation Modal */
.lp-confirm-card {
  padding: 28px 24px 22px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.lp-confirm-icon {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 16px;
  flex-shrink: 0;
  transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);
}
.lp-confirm-icon.is-danger {
  background: #fee2e2;
  border: 1px solid #fecaca;
  color: #dc2626;
}
.lp-confirm-icon.is-info {
  background: var(--lp-accent-sub, #f0fdfa);
  border: 1px solid var(--lp-accent, #ccfbf1);
  color: var(--lp-accent, #0d9488);
}
.lp-confirm-icon.is-warn {
  background: #fffbeb;
  border: 1px solid #fde68a;
  color: #d97706;
}
.lp-confirm-title {
  margin: 0 0 8px;
  font-family: var(--lp-f-display);
  font-weight: 700;
  font-size: 18px;
  color: var(--lp-ink);
  line-height: 1.35;
}
.lp-confirm-desc {
  margin: 0 0 16px;
  font-size: 13.5px;
  color: var(--lp-ink-soft);
  line-height: 1.55;
  word-break: break-word;
}
.lp-confirm-warning {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  background: #fffbeb;
  border: 1px solid #fde68a;
  border-radius: 10px;
  padding: 10px 14px;
  font-size: 12px;
  color: #92400e;
  text-align: left;
  line-height: 1.45;
  margin-bottom: 20px;
  width: 100%;
  box-sizing: border-box;
}
.lp-confirm-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
}
.lp-confirm-actions .lp-btn {
  flex: 1;
  padding: 10px 18px;
  font-size: 13.5px;
}


.lp-dialog-head {
  padding: 18px 22px 14px;
  border-bottom: 1px solid var(--lp-rule);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.lp-dialog-head h3 {
  margin: 0;
  font-family: var(--lp-f-display);
  font-weight: 400;
  font-size: 21px;
}

.lp-dialog-body {
  padding: 20px 22px;
}

.lp-dialog-foot {
  padding: 14px 22px 18px;
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  flex-wrap: wrap;
}

.lp-x {
  border: 0;
  background: transparent;
  color: var(--lp-ink-faint);
  cursor: pointer;
  padding: 4px;
  border-radius: var(--lp-radius-sm);
  line-height: 0;
}

.lp-x:hover {
  background: var(--lp-surface-sub);
  color: var(--lp-ink);
}

/* một mục học trong trang xem lại & chấm bài */
.lp-reviewitem {
  padding: 16px 0;
  border-top: 1px solid var(--lp-rule-soft);
}

.lp-reviewitem:first-of-type {
  border-top: 0;
}

/* Mục có bài nộp được tách hẳn ra: trong một module hai mươi mục, chỗ cần đọc
   phải nhìn thấy ngay chứ không phải dò từ trên xuống. */
.lp-reviewitem.has-work {
  border-left: 2px solid var(--lp-accent);
  padding-left: 14px;
  margin-left: -16px;
}

.lp-reviewitem h4 {
  margin: 16px 0 6px;
  font-size: 14px;
  font-weight: 600;
}

.lp-quote {
  margin: 0;
  padding: 10px 14px;
  border-left: 2px solid var(--lp-rule);
  background: var(--lp-surface-sub);
  border-radius: 0 var(--lp-radius-sm) var(--lp-radius-sm) 0;
  font-size: 14px;
  line-height: 1.55;
  white-space: normal;
  overflow-wrap: anywhere;
}

/* thanh tiến độ mảnh, dùng cho danh sách mảng kiến thức */
.lp-bar {
  display: block;
  height: 6px;
  border-radius: 999px;
  background: var(--lp-surface-sub);
  overflow: hidden;
}

.lp-bar-fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--lp-accent);
  /* 0% vẫn phải thấy được vạch nền, nên fill không có min-width giả tạo. */
  transition: width .25s ease;
}

/* thẻ phân loại khoá học */
.lp-tagcloud {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  min-height: 30px;
}

.lp-tagchip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 6px 4px 11px;
  border: 1px solid var(--lp-rule);
  border-radius: 999px;
  background: var(--lp-surface-sub);
  font-size: 13px;
  line-height: 1.2;
}

/* Thẻ AI đề xuất mà chưa duyệt: viền đứt để phân biệt ngay từ xa với thẻ đã chốt. */
.lp-tagchip.is-pending {
  border-style: dashed;
  background: transparent;
  color: var(--lp-ink-faint);
}

.lp-tagchip-text {
  font-family: var(--lp-f-mono, ui-monospace, monospace);
  letter-spacing: .01em;
}

.lp-tagchip-flag {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--lp-ink-faint);
}

.lp-tagchip-btn {
  border: 0;
  background: transparent;
  color: var(--lp-ink-faint);
  cursor: pointer;
  padding: 2px;
  border-radius: 999px;
  line-height: 0;
}

.lp-tagchip-btn:hover {
  background: var(--lp-surface);
  color: var(--lp-ink);
}

/* bộ chọn loại mục — bảy thẻ bấm, thay cho ô gõ tay */
.lp-typepick {
  max-width: 640px;
}

.lp-typegrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 10px;
}

.lp-typecard {
  display: grid;
  grid-template-columns: 20px 1fr;
  grid-template-rows: auto auto;
  column-gap: 10px;
  row-gap: 3px;
  align-items: start;
  text-align: left;
  padding: 12px 14px;
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius-sm);
  background: var(--lp-surface);
  color: var(--lp-ink);
  font: inherit;
  cursor: pointer;
}

.lp-typecard:hover:not(:disabled),
.lp-typecard:focus-visible {
  border-color: var(--lp-accent);
  background: var(--lp-surface-sub);
}

.lp-typecard:disabled {
  opacity: .5;
  cursor: default;
}

.lp-typecard .lp-ico {
  grid-row: 1 / span 2;
  margin-top: 2px;
  color: var(--lp-ink-faint);
}

.lp-typecard-name {
  font-weight: 600;
  font-size: 15px;
}

.lp-typecard-hint {
  font-size: 13px;
  line-height: 1.4;
  color: var(--lp-ink-faint);
}

/* --------------------------------------------------------------------------
   14b. LỚP LAYOUT LAUNCHFOLIO — số đo bê nguyên từ bản gốc
   --------------------------------------------------------------------------
   Đo trực tiếp trên https://plain-site-720560.framer.app/ :
     cột nội dung 1025px (đệm ngang 44px) · section đệm dọc 128px, gap 64px
     hero đệm trên 144px · display 64px/0.95/500/-3% · tiêu đề section 54px/1.0
     hàng dự án: nền đen bo 12px đệm 32px · vỏ nhóm: #F0F0F0 bo 16 đệm 6px
     thẻ lưới: trắng bo 16px · CTA cuối: đen tràn viền chữ khổng lồ
   -------------------------------------------------------------------------- */

/* cột nội dung chuẩn LaunchFolio */
.lp-lf {
  width: 100%;
  max-width: 1025px;
  margin: 0 auto;
  padding-left: 44px;
  padding-right: 44px;
}

@media (max-width: 700px) {
  .lp-lf {
    padding-left: 20px;
    padding-right: 20px;
  }
}

/* section: đệm dọc 128, các khối con cách nhau 64 */
.lp-sec {
  padding: 128px 0;
  display: flex;
  flex-direction: column;
  gap: 64px;
}

.lp-sec.lp-sec-tight {
  padding: 64px 0;
  gap: 32px;
}

@media (max-width: 900px) {
  .lp-sec {
    padding: 72px 0;
    gap: 40px;
  }
}

/* hero */
.lp-hero {
  padding-top: 144px;
  display: flex;
  flex-direction: column;
  gap: 32px;
}

@media (max-width: 900px) {
  .lp-hero {
    padding-top: 96px;
  }
}

/* thang chữ display — đúng số đo gốc */
.lp-display {
  font-family: var(--lp-f-display);
  font-size: clamp(40px, 6.2vw, 64px);
  line-height: 0.95;
  font-weight: 500;
  letter-spacing: -0.03em;
  margin: 0;
  text-wrap: balance;
}

.lp-sec-title {
  font-family: var(--lp-f-display);
  font-size: clamp(34px, 5vw, 54px);
  line-height: 1.0;
  font-weight: 500;
  letter-spacing: -0.03em;
  margin: 0;
  text-wrap: balance;
}

/* nhãn nhỏ chữ hoa — 12px, giãn cách, kèm số thứ tự (01) */
.lp-label {
  font-family: var(--lp-f-body);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--lp-ink-faint);
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
}

.lp-label .lp-label-num {
  color: var(--lp-ink);
  font-family: var(--lp-f-data);
}

/* đầu section: nhãn trên, tiêu đề 54px dưới */
.lp-sec-head {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.lp-sec-head .lp-row {
  justify-content: space-between;
  align-items: flex-end;
}

/* HÀNG DỰ ÁN — component chủ lực: nền đen, bo 12, đệm 32.
   Dùng cho: khoá học trong danh sách, module, mục nổi bật. */
.lp-projrow {
  display: flex;
  flex-direction: column;
  gap: 20px;
  background: var(--lp-invert);
  color: var(--lp-invert-ink);
  border-radius: var(--lp-radius);
  padding: 32px;
  text-decoration: none;
  transition: transform .18s ease;
}

.lp-projrow:hover {
  transform: translateY(-2px);
}

.lp-projrow .lp-projrow-top {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  flex-wrap: wrap;
}

.lp-projrow h3 {
  margin: 0;
  font-size: clamp(22px, 2.6vw, 30px);
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.1;
  color: var(--lp-invert-ink);
}

.lp-projrow .lp-projrow-meta {
  display: flex;
  gap: 24px;
  font-size: 12px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--lp-invert-soft);
}

.lp-projrow .lp-projrow-meta b {
  color: var(--lp-invert-ink);
  font-weight: 500;
}

/* VỎ NHÓM — pricing container gốc: nền chìm bo 16 đệm 6, thẻ con trắng bo 12.
   Dùng cho: nhóm module, bảng gói, khối gộp nhiều thẻ. */
.lp-shellcard {
  background: var(--lp-surface-sub);
  border-radius: var(--lp-radius-lg);
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.lp-shellcard>.lp-shellcard-item {
  background: var(--lp-surface);
  border-radius: var(--lp-radius);
  padding: 24px 28px;
}

.lp-shellcard>.lp-shellcard-item.lp-dark {
  background: var(--lp-invert);
  color: var(--lp-invert-ink);
}

/* lưới thẻ 3 cột kiểu testimonial: trắng bo 16 */
.lp-grid3 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
}

@media (max-width: 980px) {
  .lp-grid3 {
    grid-template-columns: minmax(0, 1fr);
  }
}

.lp-grid3>* {
  background: var(--lp-surface);
  border-radius: var(--lp-radius-lg);
  padding: 28px;
}

/* CTA cuối trang: đen tràn viền, chữ khổng lồ */
.lp-endcta {
  background: var(--lp-invert);
  color: var(--lp-invert-ink);
  margin: 0 -40px;
  padding: 64px 44px 128px;
  display: flex;
  flex-direction: column;
  gap: 24px;
}

@media (max-width: 700px) {
  .lp-endcta {
    margin: 0 -20px;
    padding: 48px 20px 96px;
  }
}

/* trong cột .lp-lf (đệm 44px) thì thoát lề phải là -44px, không phải -40px */
.lp-lf .lp-endcta {
  margin: 0 -44px;
  padding-left: 44px;
  padding-right: 44px;
}

@media (max-width: 700px) {
  .lp-lf .lp-endcta {
    margin: 0 -20px;
    padding-left: 20px;
    padding-right: 20px;
  }
}

.lp-endcta .lp-display {
  color: var(--lp-invert-ink);
}

.lp-endcta .lp-label {
  color: var(--lp-invert-soft);
}

.lp-endcta .lp-btn {
  background: var(--lp-invert-ink);
  color: var(--lp-invert);
  border-color: var(--lp-invert-ink);
}

/* số liệu lớn kiểu (07) Stats */
.lp-bignum {
  font-family: var(--lp-f-display);
  font-size: clamp(44px, 6vw, 72px);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.0;
}

/* --------------------------------------------------------------------------
   15. TIỆN ÍCH
   -------------------------------------------------------------------------- */
.lp-stack {
  display: grid;
  gap: 18px;
}

.lp-stack-sm {
  display: grid;
  gap: 10px;
}

.lp-row {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
}

.lp-spacer {
  flex: 1;
}

.lp-muted {
  color: var(--lp-ink-soft);
}

.lp-faint {
  color: var(--lp-ink-faint);
}

.lp-mono {
  font-family: var(--lp-f-data);
  font-variant-numeric: tabular-nums;
}

.lp-mb0 {
  margin-bottom: 0 !important;
}

.lp-grid-cards {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
}

/* --------------------------------------------------------------------------
   16. MÔ HÌNH eCORNELL: CALLOUT / TAB THỰC HÀNH / THANH BƯỚC / HOÀN THÀNH
   -------------------------------------------------------------------------- */

/* Callout cột phải — khối chú giải nội dung (Ý chính, Tải công cụ),
   viền nhấn bên trái theo đúng dáng callout của eCornell. */
.lp-callout {
  background: var(--lp-surface);
  border: 1px solid var(--lp-rule);
  border-left: 3px solid var(--lp-accent);
  border-radius: var(--lp-radius);
  padding: 16px 18px;
}

.lp-callout h4 {
  margin: 0 0 10px;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.lp-callout p {
  margin: 0 0 12px;
  font-size: 14px;
  color: var(--lp-ink-soft);
}

.lp-callout ul {
  margin: 0;
  padding-left: 18px;
  font-size: 14px;
  color: var(--lp-ink-soft);
}

.lp-callout li {
  margin-bottom: 7px;
}

/* Tab Thực hành / Góc nhìn chuyên gia. Tab khoá là <button disabled> và
   phần nội dung của nó KHÔNG được server render — CSS chỉ lo dáng vẻ. */
.lp-tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--lp-rule);
  margin: 6px 0 20px;
}

.lp-tab {
  appearance: none;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  padding: 9px 14px;
  font: inherit;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--lp-ink-soft);
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 7px;
}

.lp-tab.is-active {
  color: var(--lp-accent);
  border-bottom-color: var(--lp-accent);
}

.lp-tab[disabled] {
  cursor: not-allowed;
  opacity: .55;
}

.lp-tabpane {
  display: none;
}

.lp-tabpane.is-active {
  display: block;
}

/* Thanh bước của activity: chấm tròn + đường nối dọc. */
.lp-steps {
  margin: 4px 0 10px;
}

.lp-step {
  position: relative;
  padding: 0 0 26px 28px;
}

.lp-step::before {
  content: '';
  position: absolute;
  left: 7px;
  top: 22px;
  bottom: 2px;
  width: 2px;
  background: var(--lp-rule);
}

.lp-step:last-child::before {
  display: none;
}

.lp-step-dot {
  position: absolute;
  left: 0;
  top: 3px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid var(--lp-accent);
  background: var(--lp-surface);
}

.lp-step.is-done .lp-step-dot {
  background: var(--lp-accent);
}

.lp-step h4 {
  margin: 0 0 12px;
  font-size: 15.5px;
}

/* Nút hoàn thành nằm cạnh pager ở chân trang, thay cho thẻ cũ trên rail. */
.lp-complete-bar {
  display: flex;
  justify-content: flex-end;
  margin: 28px 0 6px;
}

/* ==========================================================================
   BÁO ĐANG CHUYỂN TRANG
   ==========================================================================

   Vấn đề: mấy thao tác dưới đây là ĐIỀU HƯỚNG TRANG, không phải AJAX. Người dùng
   bấm, trình duyệt POST, PHP gọi model — và trang cũ đứng im. Tín hiệu duy nhất
   là cái vòng xoay bé tí trên tab, thứ chẳng ai nhìn. Với AI thì mỗi lời gọi có
   thể thử lần lượt 6 mô hình AI, mỗi model tới 15–45 giây, nên
   chờ hàng phút là chuyện bình thường.

   Cách chữa: phủ một lớp lên TRANG CŨ ngay lúc gửi đi. Trang cũ vẫn hiển thị cho
   tới khi trang mới về, nên lớp phủ này sống đúng quãng chờ đó — chỗ mà không
   một dòng JS nào của trang đích có thể với tới.

   Loader lấy từ https://uiverse.io/dovatgabriel (Uiverse.io, MIT).
   Đổi hai chỗ: đặt tiền tố `lp-`, và buộc màu vào currentColor thay vì #0d0909
   cứng — nền tối thì chấm đen là chấm vô hình.
   ========================================================================== */

.lp-dot-wave {
  --uib-size: 50px;
  --uib-speed: 0.6s;
  display: flex;
  flex-flow: row nowrap;
  align-items: center;
  justify-content: space-between;
  width: var(--uib-size);
  height: calc(var(--uib-size) * 0.17);
  padding-top: calc(var(--uib-size) * 0.34);
}

.lp-dot-wave__dot {
  flex-shrink: 0;
  width: calc(var(--uib-size) * 0.17);
  height: calc(var(--uib-size) * 0.17);
  border-radius: 50%;
  background-color: currentColor;
  will-change: transform;
}

.lp-dot-wave__dot:nth-child(1) {
  animation: lp-dot-jump var(--uib-speed) ease-in-out calc(var(--uib-speed) * -0.45) infinite;
}

.lp-dot-wave__dot:nth-child(2) {
  animation: lp-dot-jump var(--uib-speed) ease-in-out calc(var(--uib-speed) * -0.3) infinite;
}

.lp-dot-wave__dot:nth-child(3) {
  animation: lp-dot-jump var(--uib-speed) ease-in-out calc(var(--uib-speed) * -0.15) infinite;
}

.lp-dot-wave__dot:nth-child(4) {
  animation: lp-dot-jump var(--uib-speed) ease-in-out infinite;
}

@keyframes lp-dot-jump {

  0%,
  100% {
    transform: translateY(0);
  }

  50% {
    transform: translateY(-200%);
  }
}

/*
 * GIẢM CHUYỂN ĐỘNG: vẫn phải nhấp nháy.
 * Người tắt hiệu ứng chuyển động không phải là người muốn "loader đứng hình" —
 * bốn chấm bất động thì đúng nghĩa là màn hình đơ. Bỏ cú nhảy, giữ nhịp mờ tỏ.
 */
@media (prefers-reduced-motion: reduce) {
  .lp-dot-wave__dot {
    animation-name: lp-dot-fade;
  }
}

@keyframes lp-dot-fade {

  0%,
  100% {
    opacity: 0.25;
  }

  50% {
    opacity: 1;
  }
}

/* --- lớp phủ --- */
.lp-page-busy {
  position: fixed;
  inset: 0;
  /* Trên tất cả: menu xổ (60), sidebar (40), scrim (30). */
  z-index: 9000;
  display: grid;
  place-items: center;
  padding: 24px;
  background: color-mix(in srgb, var(--lp-surface) 82%, transparent);
  /* backdrop-filter chỉ là gia vị; thiếu nó lớp phủ vẫn đục nhờ nền ở trên. */
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  /* Chặn luôn cú bấm thứ hai: người sốt ruột bấm lại là gửi thêm một lượt chấm. */
  cursor: progress;
}

.lp-page-busy__box {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  max-width: 380px;
  padding: 28px 32px;
  border-radius: var(--lp-radius);
  border: 1px solid var(--lp-line, rgba(0, 0, 0, .12));
  background: var(--lp-surface);
  box-shadow: 0 18px 48px rgba(0, 0, 0, .18);
  text-align: center;
  color: var(--lp-ink);
}

.lp-page-busy__msg {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.45;
}

/*
 * Dòng trấn an, hiện muộn.
 * Quá 15 giây thì người ta bắt đầu nghĩ máy chết. Lúc đó nói thẳng còn phải chờ
 * bao lâu — im lặng mới là thứ khiến người ta bấm F5 giữa chừng.
 */
.lp-page-busy__note {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--lp-ink-faint, #68737F);
  opacity: 0;
  transition: opacity 400ms;
}

.lp-page-busy.is-slow .lp-page-busy__note {
  opacity: 1;
}

/* ==========================================================================
   NÚT QUAY LẠI TRÊN THANH TRÊN CÙNG
   ==========================================================================

   Đặt ngoài cùng bên trái, trước cả tên thương hiệu — đó là chỗ người ta đã quen
   tìm nút quay lại suốt hai chục năm nay, và cũng là chỗ ngón cái với tới được
   trên điện thoại.

   Là <a href> chứ không phải <button>: nút thì không mở được tab mới, không sao
   chép được địa chỉ, không hiện đích đến khi rê chuột. Trang cha là một địa chỉ
   thật thì phải nói ra bằng một liên kết thật.
   ========================================================================== */

.lp-back {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 34px;
  padding: 0 10px;
  flex: none;
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius-sm);
  background: var(--lp-surface);
  color: var(--lp-ink-soft);
  font-size: 13.5px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 140ms, color 140ms, border-color 140ms;
}

.lp-back:hover,
.lp-back:focus-visible {
  background: var(--lp-surface-sub);
  color: var(--lp-ink);
  border-color: var(--lp-ink-faint);
}

.lp-back .lp-ico {
  width: 15px;
  height: 15px;
}

/*
 * Hẹp thì bỏ chữ, giữ mũi tên.
 * Dưới 640px thanh trên cùng đã chật; chữ "Quay lại" ăn mất chỗ của tên trang.
 * Nhãn cho trình đọc màn hình nằm ở aria-label chứ KHÔNG ở <span> này — span bị
 * display:none là bay khỏi cây khả truy cập, đúng cái bẫy mà lpNavItem đã ghi.
 */
@media (max-width: 640px) {
  .lp-back span {
    display: none;
  }

  .lp-back {
    width: 34px;
    padding: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .lp-back {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   17. LỚP LUMINOUS MIDNIGHT — nét nhận dạng của hệ thiết kế
   --------------------------------------------------------------------------
   Khối token ở mục 1 đã đổi MÀU và CHỮ. Khối này đổi HÌNH và ÁNH SÁNG.

   Đặt ở CUỐI FILE là có chủ ý: mọi quy tắc dưới đây ghi đè quy tắc cùng độ đặc
   hiệu ở trên, nên gỡ nguyên mục 17 là quay về hình dạng cũ mà không phải lần
   ngược từng dòng. Không dùng !important ở bất cứ đâu trong mục này.

   Sáu nét lấy từ DESIGN.md:

     1. bo góc kiểu viên thuốc     thang 8/16/24/32/48, nút bo tròn hoàn toàn
     2. tiêu đề Unbounded          rộng, hình học, giãn chữ âm
     3. nhãn kỹ thuật              chữ hoa nhỏ giãn 0.05em, kiểu bảng điều khiển
     4. độ nổi bằng ĐỘ SÁNG        không bóng đổ; viền trên mảnh "hứng sáng"
     5. quầng sáng khi focus       mờ 20px ở 10% độ đục — bản gốc gọi là "neon hum"
     6. thanh tiến độ dày, nạp sáng  12px, bo tròn hết, chuyển sắc lam
   -------------------------------------------------------------------------- */

/* --- 17.1 Thang chữ ---------------------------------------------------------
 * DESIGN.md đặt: display 56/800, headline-lg 40/700, headline-md 24/600,
 * body 16–18/400 dòng 1.6, nhãn 14/600 giãn 0.05em viết hoa.
 *
 * Unbounded RỘNG hơn hẳn một font sans thường ở cùng cỡ chữ. Bộ số cũ căn cho
 * Be Vietnam Pro, giữ nguyên thì tiêu đề tràn dòng. Hai chỉnh sửa:
 *   giãn chữ  về -0.02em theo đúng bản gốc, kéo các chữ cái sát lại
 *   cân dòng  text-wrap: balance để dòng cuối không trơ một từ
 * -------------------------------------------------------------------------- */
.lp-display {
  font-size: clamp(38px, 5.4vw, 56px);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.02em;
}

.lp-sec-title,
.lp-content h1 {
  font-size: clamp(30px, 4vw, 40px);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.lp-course-head h2,
.lp-prose h2 {
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.015em;
}

.lp-prose h2 {
  font-size: 24px;
}

/*
 * Thân bài dòng 1.6 — bản gốc ghi rõ lý do: nền tối cần khoảng thở lớn hơn nền
 * sáng thì chữ mới không dính vào nhau.
 */
.lp-prose p,
.lp-prose li {
  line-height: 1.6;
}

/*
 * Tên thương hiệu: Unbounded ở cỡ nhỏ vẫn đọc được vì nó là một từ ngắn và
 * người ta nhận ra bằng hình dáng, không bằng đọc.
 */
.lp-brand {
  font-weight: 700;
  letter-spacing: -0.01em;
}

.lp-brand .lp-mark {
  color: var(--lp-accent);
}

/* --- 17.2 Nhãn kỹ thuật ----------------------------------------------------
 * Bản gốc gọi kiểu này là "instrument panel": chữ hoa, giãn rộng, nét đậm. Nó
 * là thứ phân biệt giao diện điều khiển với giao diện tiêu dùng.
 * Bản cũ đặt eyebrow bằng font mono 10px; DESIGN.md đặt bằng font thân bài 14px
 * nét 600 giãn 0.05em.
 * -------------------------------------------------------------------------- */
.lp-eyebrow,
.lp-label {
  font-family: var(--lp-f-body);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.lp-eyebrow {
  color: var(--lp-accent);
  margin: 0 0 10px;
}

.lp-label {
  color: var(--lp-ink);
}

/* --- 17.3 Nút --------------------------------------------------------------
 * Bản gốc: nút chính bo tròn HOÀN TOÀN, nền xanh băng, chữ tối, rê chuột thì có
 * quầng sáng nhẹ bên ngoài. Nút phụ là "ghost": viền 1.5px, không tô nền.
 *
 * Bản cũ dùng filter: brightness(1.08) khi rê chuột. Trên nền xanh băng vốn đã
 * rất sáng thì hiệu ứng đó gần như không thấy — thay bằng quầng sáng, đúng thứ
 * bản gốc mô tả.
 * -------------------------------------------------------------------------- */
.lp-btn {
  border-radius: 999px;
  font-weight: 600;
  letter-spacing: 0.01em;
  padding: 12px 26px;
  transition: box-shadow .3s var(--lp-ease), background .3s var(--lp-ease),
    border-color .3s var(--lp-ease), color .3s var(--lp-ease);
}

.lp-btn:hover {
  filter: none;
  box-shadow: 0 0 20px color-mix(in srgb, var(--lp-accent) 45%, transparent);
}

/* Nút phụ = ghost: viền 1.5px, nền trong suốt. */
.lp-btn.lp-quiet {
  background: transparent;
  border-width: 1.5px;
  border-color: var(--lp-ink-faint);
  color: var(--lp-ink);
}

.lp-btn.lp-quiet:hover {
  border-color: var(--lp-accent);
  color: var(--lp-accent);
  box-shadow: none;
  background: transparent;
}

.lp-btn.lp-ghost:hover {
  background: var(--lp-accent-sub);
  box-shadow: none;
}

.lp-btn.lp-danger:hover {
  box-shadow: 0 0 20px color-mix(in srgb, var(--lp-crit) 45%, transparent);
}

.lp-btn.lp-sm {
  padding: 7px 16px;
}

/* --- 17.4 Quầng sáng khi focus ---------------------------------------------
 * Bản gốc: "soft, 20px outer blur in the primary color at a very low 10%
 * opacity, creating a neon hum effect".
 *
 * KHÔNG thay outline bằng quầng sáng. Quầng mờ không phải chỉ báo focus đạt
 * chuẩn — nó nhòe, và người dùng bàn phím cần một đường viền rõ. Ở đây quầng
 * sáng CỘNG THÊM vào outline 2px vốn có ở mục 2, không thay thế.
 * -------------------------------------------------------------------------- */
.lp :focus-visible {
  box-shadow: 0 0 20px color-mix(in srgb, var(--lp-accent) 22%, transparent);
}

/* --- 17.5 Ô nhập -----------------------------------------------------------
 * Bản gốc: ô cao 60px, nền bề mặt sâu, khi focus thì cả đường viền phát sáng.
 *
 * 60px là con số của bản gốc và giữ nguyên ở đây. Nếu biểu mẫu dài thấy trống
 * quá — trang đăng ký có bảy trường, tức hơn 400px chỉ riêng ô nhập — thì đổi
 * một dòng --lp-field-h bên dưới, mọi ô đi theo.
 * -------------------------------------------------------------------------- */
.lp-input,
.lp-select {
  height: var(--lp-field-h);
  padding: 0 18px;
}

.lp-input,
.lp-textarea,
.lp-select {
  background: var(--lp-surface-sub);
  border-radius: var(--lp-radius-sm);
  font-size: 15px;
  transition: border-color .3s var(--lp-ease), box-shadow .3s var(--lp-ease);
}

.lp-textarea {
  padding: 16px 18px;
}

.lp-input:focus,
.lp-textarea:focus,
.lp-select:focus,
.lp-inline-field:focus-within {
  border-color: var(--lp-accent);
  box-shadow: 0 0 18px color-mix(in srgb, var(--lp-accent) 25%, transparent);
}

/* --- 17.6 Thẻ: độ nổi bằng ánh sáng ----------------------------------------
 * Bản gốc nói thẳng: thẻ KHÔNG có bóng đổ. Nó nổi lên nhờ nền sáng hơn một nấc,
 * cộng một vệt sáng mảnh ở CẠNH TRÊN, giả nguồn sáng chiếu từ phía trên xuống.
 *
 * Vệt sáng làm bằng inset box-shadow 1px chứ không phải border, để nó không
 * cộng vào kích thước hộp và không phá lưới.
 * -------------------------------------------------------------------------- */
.lp-card {
  border-radius: var(--lp-radius);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--lp-accent) 20%, transparent);
}

/* --- 17.7 Thanh tiến độ ----------------------------------------------------
 * Bản gốc: dày 12px, bo tròn hết, rãnh màu lam đêm, phần chạy chuyển sắc từ lam
 * phụ sang lam chính — "appearing to charge with light".
 * -------------------------------------------------------------------------- */
.lp-bar,
.lp-pbar {
  height: 12px;
  border-radius: 999px;
  background: var(--lp-accent-sub);
  overflow: hidden;
}

.lp-bar-fill,
.lp-pbar i {
  border-radius: 999px;
  background: linear-gradient(90deg,
      color-mix(in srgb, var(--lp-accent) 55%, var(--lp-accent-sub)) 0%,
      var(--lp-accent) 100%);
}

/*
 * Thanh tiến độ trong sidebar hẹp hơn — 12px ở đó chiếm chỗ của tên chương.
 */
.lp-sidebar .lp-pbar {
  height: 6px;
}

/* --- 17.8 Thẻ nhãn ---------------------------------------------------------
 * Bản gốc: viên thuốc nhỏ, nền là màu nhấn ở 15% độ đục, chữ sáng. Nền bán
 * trong suốt chứ không phải màu đặc — nhờ vậy nó nổi trên mọi tầng bề mặt.
 * -------------------------------------------------------------------------- */
.lp-tagchip,
.lp-pill {
  border-radius: 999px;
  background: color-mix(in srgb, var(--lp-accent) 15%, transparent);
  border-color: color-mix(in srgb, var(--lp-accent) 30%, transparent);
  color: var(--lp-ink);
}

.lp-pill {
  font-family: var(--lp-f-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  padding: 3px 11px;
}

/* --- 17.9 Mục đang học -----------------------------------------------------
 * Trong ảnh mẫu, mục đang học ở sidebar là một viên thuốc tô xanh băng.
 *
 * Bản gốc để chữ #52677a trên nền #cfe5fc — đo được 4,54:1, vừa sát mép AA ở
 * phần tử điều hướng quan trọng nhất màn hình. Ở đây dùng --lp-accent-ink
 * (#1D3244) cho 10,2:1. Mắt thường không thấy khác, người mắt kém thì có.
 * -------------------------------------------------------------------------- */
.lp-item.is-current {
  border-radius: var(--lp-radius);
}

/*
 * KHÔNG thêm vệt sáng cạnh trên cho mục đang học, dù thẻ thường thì có.
 * Vệt sáng đó mô phỏng ánh sáng hắt lên một BỀ MẶT; mục đang học lại được tô
 * đặc bằng chính màu nhấn, nên vệt sáng trên nền đó không đọc ra là ánh sáng,
 * chỉ thành một đường kẻ mờ. Nó cũng buộc phải viết cứng màu trắng — thứ mà
 * chú thích đầu tệp cấm.
 */

/* --- 17.10 Bóng đổ ---------------------------------------------------------
 * DESIGN.md: "Depth is conveyed through Tonal Layering rather than physical
 * shadows."
 *
 * Không xoá hẳn. Những khối dưới đây đều là lớp NỔI trên nội dung — menu, hộp
 * thoại, toast, ngăn kéo. Bỏ bóng thì trên nền tối chúng dính liền vào trang,
 * vì chênh lệch độ sáng giữa các tầng bề mặt chỉ khoảng 1,1:1.
 *
 * Cách xử lý: hạ bóng xuống rất nhạt để tách khỏi nền, rồi cộng thêm vệt sáng
 * cạnh trên — đúng ngôn ngữ "hứng sáng" của bản gốc.
 * -------------------------------------------------------------------------- */
.lp-menu-panel,
.global-ai-progress-panel,
.lp-dialog,
.lp-toast,
.lp-page-busy__box {
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--lp-accent) 20%, transparent),
    0 18px 44px rgba(0, 0, 0, .34);
}

.lp-savebar {
  box-shadow: 0 -12px 30px rgba(0, 0, 0, .22);
}

/* --- 17.11 Nhịp chuyển động ------------------------------------------------
 * Bản gốc dùng cubic-bezier(0.4, 0, 0.2, 1) cho thanh tiến độ và các chuyển
 * cảnh. --lp-ease ở mục 1 giữ đúng đường cong đó.
 * Khối @media (prefers-reduced-motion) ở mục 2 vẫn cắt toàn bộ như cũ.
 * -------------------------------------------------------------------------- */
.lp-item,
.lp-typecard,
.lp-tagchip,
.lp-pill,
.lp-card {
  transition: background .3s var(--lp-ease), border-color .3s var(--lp-ease),
    color .3s var(--lp-ease), box-shadow .3s var(--lp-ease);
}

/*
 * DỰ PHÒNG CHO TRÌNH DUYỆT KHÔNG CÓ color-mix().
 *
 * color-mix() có từ Chrome 111 / Safari 16.2 / Firefox 113. Trình duyệt cũ hơn
 * sẽ bỏ qua cả khai báo chứa nó — với nền và viền thì hậu quả là mất màu hoàn
 * toàn, thẻ nhãn thành trong suốt không viền. Khối này đặt giá trị đặc làm nền
 * trước, khối trên đè lên khi trình duyệt hiểu.
 */
@supports not (color: color-mix(in srgb, red 50%, transparent)) {

  .lp-tagchip,
  .lp-pill {
    background: var(--lp-accent-sub);
    border-color: var(--lp-rule);
  }

  .lp-card,
  .lp-item.is-current {
    box-shadow: none;
  }

  .lp-btn:hover {
    background: var(--lp-accent);
    filter: brightness(1.1);
  }
}

/* --------------------------------------------------------------------------
   18. RAIL ĐIỀU HƯỚNG + THANH TAB ĐÁY
   --------------------------------------------------------------------------
   Khung của bản thiết kế Stitch: rail cố định 256px bên trái, nội dung lùi vào
   đúng bằng đó; dưới 900px rail ẩn và một hàng tab hiện ở đáy màn hình.

   TÊN LỚP LÀ .lp-navrail, KHÔNG PHẢI .lp-rail.
   Mục 7 đã có sẵn một .lp-rail khác — cột phụ dính (sticky) bên phải trong trang
   mục học. Đặt trùng tên thì quy tắc position:fixed;width:256px;height:100vh ở
   đây đè lên nó và phá bố cục trang đang học. Đã dính đúng lỗi này một lần.

   RAIL NẰM NGOÀI .lp-shell, KHÔNG NẰM TRONG.
   .lp-shell đã là lưới hai cột cho sidebar CÂY BÀI HỌC — thứ chỉ 6/27 trang có.
   Rail thì mọi trang đều có. Nhét chung một lưới nghĩa là trang có sidebar
   thành ba cột còn trang không có thành hai, và mọi số đo phải rẽ nhánh theo.
   Để rail ở position:fixed rồi đẩy <body> sang phải thì cả hai loại trang dùng
   chung một quy tắc.
   -------------------------------------------------------------------------- */

.lp {
  --lp-navrail-w: 256px;
  --lp-tabbar-h: 64px;
}

.lp-navrail {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 45;
  width: var(--lp-navrail-w);
  height: 100vh;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 18px 14px;
  background: var(--lp-chrome);
  border-right: 1px solid var(--lp-chrome-rule);
  color: var(--lp-chrome-ink);
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Rail mượn phép ánh xạ token của tầng khung, giống topbar và sidebar. */
.lp-navrail {
  --lp-surface: var(--lp-chrome);
  --lp-surface-sub: var(--lp-chrome-alt);
  --lp-ink: var(--lp-chrome-ink);
  --lp-ink-soft: var(--lp-chrome-soft);
  --lp-ink-faint: var(--lp-chrome-soft);
  --lp-rule: var(--lp-chrome-rule);
}

.lp-navrail-brand {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px 18px;
  color: var(--lp-chrome-ink);
  text-decoration: none;
  border-bottom: 1px solid var(--lp-chrome-rule);
  margin-bottom: 10px;
}

.lp-navrail-brand .lp-ico {
  width: 26px;
  height: 26px;
  flex: none;
  color: var(--lp-accent);
}

.lp-navrail-brand span {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.lp-navrail-brand strong {
  font-family: var(--lp-f-display);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.2;
}

.lp-navrail-brand small {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--lp-chrome-soft);
}

.lp-navrail-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/*
 * Mục đang mở là một viên thuốc tô nền — đúng cách bản thiết kế đánh dấu vị trí
 * hiện tại. Dùng --lp-accent-sub chứ không phải --lp-accent: nền nhấn đặc ở đây
 * quá nặng cho một mục điều hướng, và nó cũng tranh chỗ với nút hành động chính
 * của trang.
 */
.lp-navrail-link {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  border-radius: 999px;
  color: var(--lp-chrome-soft);
  font-size: 14.5px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  font-family: var(--lp-f-body);
  border: none;
  background: transparent;
  cursor: pointer;
  text-align: left;
  transition: background .25s var(--lp-ease), color .25s var(--lp-ease);
}

.lp-navrail-link .lp-ico {
  width: 19px;
  height: 19px;
  flex: none;
}

.lp-navrail-link:hover {
  background: var(--lp-chrome-alt);
  color: var(--lp-chrome-ink);
}

.lp-navrail-link.is-current {
  background: var(--lp-accent-sub);
  color: var(--lp-accent);
}

/* --- đẩy nội dung sang phải để chừa chỗ cho rail --- *
 * CHỈ đẩy khi rail THẬT SỰ có mặt.
 *
 * player_rail.php thoát sớm với khách chưa đăng nhập, nên trang đăng nhập và
 * trang giới thiệu không có rail. Nếu đẩy vô điều kiện thì hai trang đó chừa
 * một dải trắng 256px bên trái mà không có gì trong đó.
 *
 * Lớp lp-has-rail do player_head.php gắn, cùng lúc và cùng điều kiện với việc
 * rail được dựng — một nguồn sự thật, không phải hai chỗ đoán nhau. */
body.lp.lp-has-rail {
  padding-left: var(--lp-navrail-w);
}

/*
 * Topbar là sticky nên nó nằm trong luồng của <body> và tự lùi theo padding.
 * Nhưng .lp-sidebar (cây bài học) thì sticky bên trong lưới .lp-shell, và
 * .lp-savebar dùng margin âm để tràn hết bề rộng vùng đọc — cả hai đã tính theo
 * hộp cha, nên padding của body không phá gì.
 */

/* --- thanh tab đáy: chỉ hiện khi rail ẩn --- */
.lp-tabbar {
  display: none;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 45;
  height: var(--lp-tabbar-h);
  /* Vùng an toàn của máy có thanh gạt dưới đáy (iPhone). Không có thì bằng 0. */
  padding-bottom: env(safe-area-inset-bottom, 0);
  background: var(--lp-chrome);
  border-top: 1px solid var(--lp-chrome-rule);
}

.lp-tab {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-width: 0;
  padding: 8px 4px;
  color: var(--lp-chrome-soft);
  text-decoration: none;
  font-size: 10.5px;
  font-weight: 600;
  line-height: 1.15;
  text-align: center;
}

.lp-tab .lp-ico {
  width: 21px;
  height: 21px;
  flex: none;
}

.lp-tab span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

.lp-tab.is-current {
  color: var(--lp-accent);
}

@media (max-width: 900px) {
  .lp-navrail {
    display: none;
  }

  body.lp.lp-has-rail {
    padding-left: 0;
    /* Chừa chỗ cho thanh đáy, cộng vùng an toàn — nếu không thì nội dung cuối
       trang và nút gửi biểu mẫu nằm khuất dưới thanh. */
    padding-bottom: calc(var(--lp-tabbar-h) + env(safe-area-inset-bottom, 0px));
  }

  .lp-tabbar {
    display: flex;
  }

  /*
   * .lp-savebar của chế độ soạn cũng neo ở đáy. Đẩy nó lên trên thanh tab, nếu
   * không hai thanh chồng lên nhau và nút Lưu bị che.
   */
  .lp-savebar {
    bottom: calc(var(--lp-tabbar-h) + env(safe-area-inset-bottom, 0px));
  }
}

@media (prefers-reduced-motion: reduce) {
  .lp-navrail-link {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   19. THÀNH PHẦN CỦA CÁC TRANG THIẾT KẾ MỚI
   --------------------------------------------------------------------------
   Các bản thiết kế Stitch dùng đi dùng lại một nhóm khối cố định. Dựng ở đây
   một lần thay vì viết lại trong từng trang.

   Vì sao không đặt trong CSS riêng của từng trang: các trang này nằm ở hai vai
   trò (học viên, giáo viên) và ba thư mục khác nhau. Mỗi trang một bản là sáu
   bản sẽ trôi khỏi nhau — đúng chuyện đã xảy ra với danh sách điều hướng.
   -------------------------------------------------------------------------- */

/* --- 19.1 Đầu trang: lời chào lớn + một dòng dẫn ---------------------------
 * Bản thiết kế bỏ hẳn breadcrumb và thẻ phân loại của bản cũ. Chỉ còn một lời
 * chào cỡ rất lớn và một câu nói rõ người học đang dở việc gì.
 * -------------------------------------------------------------------------- */
.lp-head {
  margin: 8px 0 30px;
}

.lp-head h1 {
  font-family: var(--lp-f-display);
  font-size: clamp(30px, 5vw, 52px);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -0.03em;
  color: var(--lp-ink);
  margin: 0;
  text-wrap: balance;
}

.lp-head p {
  margin: 12px 0 0;
  font-size: 16px;
  color: var(--lp-ink-soft);
  max-width: 60ch;
}

/* Tên khóa học trong dòng dẫn được nhấn — bản gốc in đậm và đổi màu. */
.lp-head p strong {
  color: var(--lp-ink);
  font-weight: 700;
}

/* --- 19.2 Nhãn nhỏ + tiêu đề mục ------------------------------------------ */
.lp-sect {
  margin: 36px 0 16px;
}

.lp-sect .lp-eyebrow {
  margin-bottom: 4px;
}

.lp-sect h2 {
  font-family: var(--lp-f-display);
  font-size: clamp(19px, 2.2vw, 24px);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--lp-ink);
  margin: 0;
}

/* Hàng tiêu đề có nút ở mép phải ("Xem tất cả"). */
.lp-sect-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

/* --- 19.3 Khối media lớn của bài đang học ----------------------------------
 * Ảnh bìa hoặc khung video, bo góc, có nút phát tròn ở giữa.
 * -------------------------------------------------------------------------- */
.lp-stage {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--lp-radius);
  overflow: hidden;
  background: var(--lp-surface-sub);
  border: 1px solid var(--lp-rule);
  text-decoration: none;
}

.lp-stage img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/*
 * Nút phát. Là phần tử TRANG TRÍ (aria-hidden ở markup) vì cả khối .lp-stage đã
 * là một liên kết có tên — nếu để nó tự mang nhãn thì trình đọc màn hình đọc
 * thành hai chỗ bấm chồng nhau.
 */
.lp-stage-play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: 76px;
  height: 76px;
  border-radius: 50%;
  background: var(--lp-accent);
  color: var(--lp-accent-ink);
  transition: transform .3s var(--lp-ease);
}

.lp-stage:hover .lp-stage-play {
  transform: translate(-50%, -50%) scale(1.06);
}

.lp-stage-play .lp-ico {
  width: 28px;
  height: 28px;
}

/* Nhãn thời lượng / loại nội dung dưới khung media. */
.lp-stage-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  font-size: 14px;
  color: var(--lp-ink-soft);
}

.lp-stage-meta .lp-ico {
  width: 16px;
  height: 16px;
  color: var(--lp-accent);
}

/* --- 19.4 Cây nội dung khóa học ở sidebar ----------------------------------
 * Ba trạng thái: đã xong (dấu tích tô đặc), đang học (vòng tròn có chấm giữa),
 * chưa mở (ổ khóa). Ba trạng thái phải phân biệt được KHÔNG CHỈ bằng màu —
 * mỗi cái có một hình riêng, để người mù màu vẫn đọc được.
 * -------------------------------------------------------------------------- */
.lp-toc {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.lp-toc-title {
  font-family: var(--lp-f-display);
  font-size: 16px;
  font-weight: 700;
  color: var(--lp-chrome-ink);
  margin: 0 0 14px;
  padding: 0 12px;
}

.lp-toc-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 11px 12px;
  border-radius: var(--lp-radius);
  color: var(--lp-chrome-soft);
  text-decoration: none;
  transition: background .25s var(--lp-ease), color .25s var(--lp-ease);
}

.lp-toc-item:hover {
  background: var(--lp-chrome-alt);
  color: var(--lp-chrome-ink);
}

.lp-toc-mark {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  flex: none;
  margin-top: 2px;
  border-radius: 50%;
  border: 1.5px solid currentColor;
}

.lp-toc-mark .lp-ico {
  width: 12px;
  height: 12px;
}

.lp-toc-body {
  min-width: 0;
}

.lp-toc-name {
  display: block;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.35;
}

.lp-toc-meta {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  color: var(--lp-chrome-soft);
}

/* đã xong — dấu tích tô đặc */
.lp-toc-item.is-done .lp-toc-mark {
  background: var(--lp-ok);
  border-color: var(--lp-ok);
  color: var(--lp-chrome);
}

/* đang học — viên thuốc tô nền, chấm đặc ở giữa vòng tròn */
.lp-toc-item.is-current {
  background: var(--lp-accent-sub);
  color: var(--lp-accent);
}

.lp-toc-item.is-current .lp-toc-meta {
  color: inherit;
  opacity: .82;
}

.lp-toc-item.is-current .lp-toc-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
}

/* chưa mở — mờ đi và không bấm được */
.lp-toc-item.is-locked {
  opacity: .55;
  cursor: not-allowed;
}

/* --- 19.5 Thẻ có ảnh ------------------------------------------------------- */
.lp-mcard {
  display: flex;
  flex-direction: column;
  background: var(--lp-surface);
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  transition: border-color .25s var(--lp-ease), transform .25s var(--lp-ease);
}

.lp-mcard:hover {
  border-color: var(--lp-accent);
  transform: translateY(-2px);
}

.lp-mcard-media {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--lp-surface-sub);
  overflow: hidden;
}

.lp-mcard-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.lp-mcard-tag {
  position: absolute;
  top: 10px;
  right: 10px;
  padding: 4px 12px;
  border-radius: 999px;
  background: var(--lp-accent);
  color: var(--lp-accent-ink);
  font-size: 12px;
  font-weight: 700;
  max-width: calc(100% - 20px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lp-mcard-body {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 16px 18px 18px;
  flex: 1;
}

.lp-mcard-body h3 {
  font-family: var(--lp-f-display);
  font-size: 19px;
  font-weight: 700;
  line-height: 1.25;
  color: var(--lp-ink);
  margin: 0;
}

.lp-mcard-body p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--lp-ink-soft);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.lp-mcard-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: auto;
  padding-top: 12px;
  font-size: 13px;
  color: var(--lp-ink-faint);
}

/* Thẻ "thêm mới" — ô cuối hàng, viền đứt. */
.lp-mcard.is-add {
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 32px 24px;
  border-style: dashed;
  background: var(--lp-surface-sub);
  text-align: center;
}

.lp-mcard.is-add .lp-ico {
  width: 40px;
  height: 40px;
  color: var(--lp-ink-faint);
}

/* --- 19.6 Hàng tiến độ ----------------------------------------------------- */
.lp-prow {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 13px 0;
  border-bottom: 1px solid var(--lp-rule-soft);
}

.lp-prow:last-child {
  border-bottom: none;
}

.lp-prow-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}

.lp-prow-name {
  font-size: 15px;
  font-weight: 600;
  color: var(--lp-ink);
}

.lp-prow-pct {
  font-size: 15px;
  font-weight: 700;
  color: var(--lp-ink-soft);
  /* Số căn cột: các phần trăm xếp dọc nhau, chữ số không cùng bề rộng thì
     chúng nhảy qua nhảy lại theo từng hàng. */
  font-variant-numeric: tabular-nums;
}

/* --- 19.7 Huy hiệu --------------------------------------------------------- */
.lp-badges {
  display: flex;
  gap: 22px;
  flex-wrap: wrap;
}

.lp-badge {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: 68px;
  text-align: center;
}

.lp-badge-ring {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--lp-accent-sub);
  color: var(--lp-accent);
}

.lp-badge-ring .lp-ico {
  width: 24px;
  height: 24px;
}

.lp-badge span {
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.25;
  color: var(--lp-ink-soft);
}

/* Huy hiệu chưa đạt — xám và mờ, nhưng VẪN HIỆN để người học biết đích tiếp theo. */
.lp-badge.is-off .lp-badge-ring {
  background: var(--lp-surface-sub);
  color: var(--lp-ink-faint);
}

.lp-badge.is-off span {
  color: var(--lp-ink-faint);
}

/* --- 19.8 Trạng thái rỗng --------------------------------------------------
 * Vòng tròn lớn có icon · tiêu đề · một đoạn giải thích · một nút lối ra.
 * Khác bản cũ ở chỗ có LỐI RA — bản cũ chỉ có chữ, người dùng đọc xong đứng đó.
 * -------------------------------------------------------------------------- */
.lp-blank {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 60px 24px;
  border: 1px dashed var(--lp-rule);
  border-radius: var(--lp-radius);
  text-align: center;
}

.lp-blank-ico {
  display: grid;
  place-items: center;
  width: 92px;
  height: 92px;
  border-radius: 50%;
  background: var(--lp-surface-sub);
  color: var(--lp-ink-faint);
}

.lp-blank-ico .lp-ico {
  width: 38px;
  height: 38px;
}

.lp-blank h3 {
  font-family: var(--lp-f-display);
  font-size: 20px;
  font-weight: 700;
  color: var(--lp-ink);
  margin: 0;
}

.lp-blank p {
  margin: 0;
  max-width: 46ch;
  font-size: 15px;
  line-height: 1.55;
  color: var(--lp-ink-soft);
}

/* --- 19.9 Lưới ------------------------------------------------------------- */
.lp-grid-3 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
}

.lp-grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
}

@media (max-width: 1000px) {
  .lp-grid-3 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 700px) {

  .lp-grid-3,
  .lp-grid-2 {
    grid-template-columns: minmax(0, 1fr);
  }

  .lp-head {
    margin-bottom: 22px;
  }

  .lp-stage-play {
    width: 58px;
    height: 58px;
  }

  .lp-blank {
    padding: 40px 18px;
  }

  .lp-blank-ico {
    width: 72px;
    height: 72px;
  }
}

@media (prefers-reduced-motion: reduce) {

  .lp-mcard,
  .lp-toc-item,
  .lp-stage-play {
    transition: none;
  }

  .lp-mcard:hover {
    transform: none;
  }

  .lp-stage:hover .lp-stage-play {
    transform: translate(-50%, -50%);
  }
}

/* --------------------------------------------------------------------------
   20. SIDEBAR KHOÁ HỌC THEO BẢN THIẾT KẾ
   --------------------------------------------------------------------------
   Bản thiết kế Stitch (gfcourse_player) vẽ mỗi mục thành: một DẤU TRÒN trạng
   thái bên trái, rồi tên mục, rồi một dòng phụ nhỏ. Mục đang mở là một viên
   thuốc tô nền.

   Ghi đè các quy tắc .lp-item ở mục 4 thay vì sửa tại chỗ — gỡ nguyên mục 20 là
   quay về hình dạng cũ. Cấu trúc markup (details/summary, data-lp-key, nút kéo
   thả của chế độ soạn) giữ nguyên không đụng tới.
   -------------------------------------------------------------------------- */

.lp-item {
  grid-template-columns: 22px minmax(0, 1fr);
  gap: 12px;
  padding: 10px 12px;
  border-radius: var(--lp-radius);
  align-items: start;
}

/* --- dấu tròn trạng thái --- */
.lp-item-mark {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  margin-top: 1px;
  border-radius: 50%;
  border: 1.5px solid currentColor;
  color: var(--lp-ink-faint);
  flex: none;
}

.lp-item-mark .lp-ico {
  width: 12px;
  height: 12px;
  margin: 0;
  color: inherit;
}

/*
 * ĐÃ XONG — vòng tròn tô đặc màu "xong", dấu tích đảo màu bên trong.
 * Đây là trạng thái người học liếc qua nhiều nhất, nên nó phải đọc được ở tầm
 * mắt lướt: khối đặc dễ thấy hơn một đường viền.
 */
.lp-item.is-done .lp-item-mark {
  background: var(--lp-ok);
  border-color: var(--lp-ok);
  color: var(--lp-chrome);
}

/*
 * ĐANG MỞ — viên thuốc tô nền. Dấu tròn lúc này đảo màu theo nền viên thuốc
 * chứ không giữ màu nhấn, nếu không nó chìm nghỉm vào chính nền đó.
 */
.lp-item.is-current .lp-item-mark {
  border-color: currentColor;
  color: inherit;
}

/* --- hai dòng chữ --- */
.lp-item-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.lp-item-name {
  font-size: 14px;
  line-height: 1.35;
}

.lp-item-meta {
  font-size: 11.5px;
  line-height: 1.3;
  color: var(--lp-ink-faint);
}

/* Trong viên thuốc, dòng phụ theo màu chữ chính chứ không giữ màu mờ — trên nền
   nhấn thì màu mờ tụt xuống dưới ngưỡng đọc được. */
.lp-item.is-current .lp-item-meta {
  color: inherit;
  opacity: .8;
}

.lp-item.is-done .lp-item-name {
  color: var(--lp-ink);
}

/* --- đầu sidebar --- */
.lp-course-head h2 {
  font-size: 17px;
  line-height: 1.3;
}

/*
 * Thanh tiến độ ở sidebar mỏng hơn thanh trong nội dung. Mục 17 đặt .lp-pbar dày
 * 12px theo bản thiết kế, nhưng ở cột hẹp 300px thì 12px chiếm mất chỗ của tên
 * chương. Mục 17 đã hạ xuống 6px cho .lp-sidebar; nhắc lại đây để ai đọc mục 20
 * không tưởng là thiếu.
 */

/* --------------------------------------------------------------------------
   21. LƯỚI BENTO CỦA BẢNG ĐIỀU KHIỂN
   --------------------------------------------------------------------------
   Bản thiết kế b_ng_i_u_khi_n_h_c_vi_n_sage_edition xếp phần trên thành lưới 12
   cột: thẻ năng lực chiếm 8, cột số liệu chiếm 4 và tự chia đôi theo chiều dọc.
   -------------------------------------------------------------------------- */

.lp-bento {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 24px;
  align-items: stretch;
}

.lp-bento-main {
  grid-column: span 8;
}

.lp-bento-side {
  grid-column: span 4;
  display: flex;
  flex-direction: column;
  gap: 24px;
}

/*
 * Hai ô số liệu chia đều chiều cao của cột, để mép dưới của chúng thẳng hàng với
 * mép dưới thẻ năng lực bên cạnh — bản thiết kế căn như vậy.
 */
.lp-bento-side>.lp-card {
  flex: 1;
}

.lp-card-title {
  font-family: var(--lp-f-display);
  font-size: 22px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--lp-ink);
  margin: 0 0 20px;
}

/* --- ô số liệu --- */
.lp-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  text-align: center;
}

.lp-stat .lp-eyebrow {
  margin: 0;
}

.lp-stat-num {
  font-family: var(--lp-f-display);
  font-size: clamp(36px, 5vw, 48px);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--lp-ink);
}

/*
 * NHÃN "CHƯA NỐI DỮ LIỆU".
 *
 * Ô giờ học đang là số cứng vì hệ thống không ghi thời gian học. Để một con số
 * bịa mà không đánh dấu gì thì học viên đọc nó thành sự thật — đây đúng là cái
 * bẫy đã gỡ ở phần khoá học sinh từ tài liệu. Nhãn nhỏ, không phá bố cục, nhưng
 * đọc được.
 */
.lp-stat-warn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 2px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--lp-warn);
}

.lp-stat-warn::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

/* --- cột các hàng tiến độ --- */
.lp-prows {
  display: flex;
  flex-direction: column;
}

.lp-prow-note {
  font-size: 12px;
  color: var(--lp-ink-faint);
}

/* Thanh mảnh dùng trong thẻ khoá học — 12px của mục 17 quá dày cho chân thẻ. */
.lp-bar-thin {
  height: 5px;
}

.lp-mcard-prog {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: auto;
  padding-top: 14px;
}

.lp-mcard-prog .lp-mcard-foot {
  margin-top: 0;
  padding-top: 0;
}

/* Ô "khám phá khoá học mới" — bản thiết kế cho nó cùng chiều cao với thẻ thật. */
.lp-mcard.is-add h3 {
  font-family: var(--lp-f-display);
  font-size: 18px;
  font-weight: 600;
  color: var(--lp-ink-soft);
  margin: 0;
}

.lp-mcard.is-add p {
  margin: 0;
  font-size: 14px;
}

@media (max-width: 1000px) {

  .lp-bento-main,
  .lp-bento-side {
    grid-column: span 12;
  }

  /* Hai ô số liệu nằm ngang khi cột đã trải hết bề ngang. */
  .lp-bento-side {
    flex-direction: row;
  }
}

@media (max-width: 700px) {
  .lp-bento-side {
    flex-direction: column;
  }
}

/* Thẻ nhãn tô màu nhấn — dùng khi khoá không có ảnh bìa nên không có chỗ đặt
   nhãn nổi trên ảnh. */
.lp-pill-accent {
  align-self: flex-start;
  background: var(--lp-accent-sub);
  border-color: var(--lp-accent-sub);
  color: var(--lp-accent);
  margin-bottom: 2px;
}

/* Thẻ không có ảnh thì phần nội dung tự giãn cho đủ chiều cao hàng. */
.lp-mcard>.lp-mcard-body:first-child {
  padding-top: 20px;
}

/* --------------------------------------------------------------------------
   22. THẺ TỔNG QUAN KHOÁ HỌC (trang soạn của giáo viên)
   -------------------------------------------------------------------------- */

.lp-course-card {
  display: flex;
  gap: 24px;
  padding: 24px;
  margin-bottom: 24px;
  background: var(--lp-surface);
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
}

.lp-course-thumb {
  flex: 0 0 33%;
  max-width: 280px;
  aspect-ratio: 4 / 3;
  border-radius: var(--lp-radius-sm);
  overflow: hidden;
  background: var(--lp-surface-sub);
  border: 1px solid var(--lp-rule);
}

.lp-course-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.lp-course-info {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
  flex: 1;
}

.lp-course-info>.lp-pill {
  align-self: flex-start;
}

.lp-course-desc {
  margin: 0;
  font-size: 15px;
  line-height: 1.55;
  color: var(--lp-ink-soft);
}

/*
 * Bốn ô số liệu, chia đều một hàng. Dùng <dl> chứ không phải <div>: đây đúng là
 * các cặp tên–giá trị, và trình đọc màn hình đọc ra được quan hệ đó.
 */
.lp-course-stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
  margin: auto 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--lp-rule);
}

.lp-course-stats dt {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--lp-ink-faint);
  margin-bottom: 4px;
}

.lp-course-stats dd {
  margin: 0;
  font-family: var(--lp-f-display);
  font-size: 20px;
  font-weight: 600;
  color: var(--lp-ink);
  font-variant-numeric: tabular-nums;
}

/* --- bảng thống kê nhanh --- */
.lp-quickstats {
  margin-bottom: 24px;
}

.lp-quickstats h3 {
  margin: 0 0 6px;
  font-family: var(--lp-f-display);
  font-size: 18px;
  font-weight: 600;
  color: var(--lp-ink);
}

/* Con số cần chú ý (bài chờ chấm) — đỏ, nhưng vẫn cùng cỡ để không hét lên. */
.lp-prow-alert {
  color: var(--lp-crit);
}

@media (max-width: 900px) {
  .lp-course-card {
    flex-direction: column;
  }

  .lp-course-thumb {
    flex: none;
    max-width: none;
    aspect-ratio: 16 / 9;
  }

  .lp-course-stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* --------------------------------------------------------------------------
   23. XƯỞNG SINH NỘI DUNG BẰNG AI
   --------------------------------------------------------------------------
   Dùng chung cho ba trang: sinh khoá học bằng AI, phân tích video lớn, và sinh
   từ tài liệu. Cả ba đều là "tải nguồn lên → chọn tham số → chạy", nên bản thiết
   kế sinh_kh_a_h_c_t_ng_b_ng_ai áp được cho cả ba.

   Bố cục: lưới 12 cột — vùng thả tệp chiếm 8, cột tham số chiếm 4.
   -------------------------------------------------------------------------- */

.lp-gen {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 24px;
  align-items: start;
}

.lp-gen-main {
  grid-column: span 8;
}

.lp-gen-side {
  grid-column: span 4;
  display: flex;
  flex-direction: column;
  gap: 24px;
}

/* --- khung có thanh tiêu đề --- */
.lp-panel {
  background: var(--lp-surface);
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
  overflow: hidden;
}

.lp-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 16px 20px;
  background: var(--lp-surface-sub);
  border-bottom: 1px solid var(--lp-rule);
}

.lp-panel-head h2,
.lp-panel-head h3 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-family: var(--lp-f-display);
  font-size: 18px;
  font-weight: 600;
  color: var(--lp-ink);
}

.lp-panel-head .lp-ico {
  width: 20px;
  height: 20px;
  color: var(--lp-accent);
}

.lp-panel-body {
  padding: 20px;
}

/* --- vùng kéo thả --- *
 * Viền đứt vẽ bằng background SVG chứ không bằng border-style: dashed, vì
 * border dashed không cho chỉnh độ dài nét và khoảng hở — ở bo góc 24px thì
 * nét mặc định của trình duyệt gãy vụn rất xấu. Đây cũng là cách bản thiết kế
 * làm.
 *
 * Màu nét nằm trong data-URI nên KHÔNG đọc được biến CSS. Hai màu viết cứng ở
 * đây là ngoại lệ duy nhất của mục này; chúng khớp với --lp-rule (#C0C9C4) và
 * --lp-accent (#426759) của bảng sáng. Ở chế độ tối có khối ghi đè riêng bên
 * dưới.
 * -------------------------------------------------------------------------- */
.lp-drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 340px;
  padding: 40px 24px;
  border-radius: var(--lp-radius);
  background-color: var(--lp-surface);
  background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' rx='24' ry='24' stroke='%23C0C9C4' stroke-width='2' stroke-dasharray='8,8'/%3e%3c/svg%3e");
  text-align: center;
  cursor: pointer;
  transition: background-color .3s var(--lp-ease);
}

.lp-drop:hover,
.lp-drop.is-over {
  background-color: var(--lp-surface-sub);
  background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' rx='24' ry='24' stroke='%23426759' stroke-width='2' stroke-dasharray='8,8'/%3e%3c/svg%3e");
}

:root[data-theme="dark"] .lp-drop,
:root:not([data-theme="light"]) .lp-drop {
  background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' rx='24' ry='24' stroke='%232E3833' stroke-width='2' stroke-dasharray='8,8'/%3e%3c/svg%3e");
}

:root[data-theme="dark"] .lp-drop:hover,
:root[data-theme="dark"] .lp-drop.is-over,
:root:not([data-theme="light"]) .lp-drop:hover,
:root:not([data-theme="light"]) .lp-drop.is-over {
  background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' rx='24' ry='24' stroke='%23A8D0BE' stroke-width='2' stroke-dasharray='8,8'/%3e%3c/svg%3e");
}

.lp-drop-ring {
  display: grid;
  place-items: center;
  width: 80px;
  height: 80px;
  margin-bottom: 12px;
  border-radius: 50%;
  background: var(--lp-surface-sub);
  border: 1px solid var(--lp-rule);
  color: var(--lp-ink-faint);
  transition: color .3s var(--lp-ease), border-color .3s var(--lp-ease);
}

.lp-drop:hover .lp-drop-ring,
.lp-drop.is-over .lp-drop-ring {
  color: var(--lp-accent);
  border-color: var(--lp-accent);
}

.lp-drop-ring .lp-ico,
.lp-drop-ring i {
  width: 34px;
  height: 34px;
  font-size: 30px;
}

.lp-drop h3,
.lp-drop h4 {
  margin: 0;
  font-family: var(--lp-f-display);
  font-size: 20px;
  font-weight: 600;
  color: var(--lp-ink);
}

.lp-drop p {
  margin: 0;
  max-width: 42ch;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--lp-ink-soft);
}

/* Trạng thái đã chọn tệp — viền liền, nền nhấn nhạt. */
.lp-drop.has-file {
  background-image: none;
  border: 1px solid var(--lp-accent);
  background-color: var(--lp-accent-sub);
}

/* --- nhóm nút chọn dạng viên thuốc --- */
.lp-pillset {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/*
 * Radio thật nằm dưới, ẩn bằng opacity chứ KHÔNG bằng display:none —
 * display:none gỡ hẳn phần tử khỏi cây khả truy cập và người dùng bàn phím
 * không Tab tới được. Cùng bẫy đã ghi ở auth-form.css.
 */
.lp-pillset label {
  position: relative;
  cursor: pointer;
}

.lp-pillset input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.lp-pillset span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 9px 18px;
  border-radius: 999px;
  border: 1px solid var(--lp-rule);
  background: var(--lp-surface);
  color: var(--lp-ink-soft);
  font-size: 14px;
  font-weight: 500;
  transition: background .25s var(--lp-ease), border-color .25s var(--lp-ease),
    color .25s var(--lp-ease);
}

.lp-pillset label:hover span {
  border-color: var(--lp-accent);
  color: var(--lp-ink);
}

.lp-pillset input:checked+span {
  background: var(--lp-accent-sub);
  border-color: var(--lp-accent-sub);
  color: var(--lp-accent);
  font-weight: 600;
}

.lp-pillset input:focus-visible+span {
  outline: 2px solid var(--lp-accent);
  outline-offset: 2px;
}

/* --- nút chạy, chiếm hết bề ngang cột --- */
.lp-btn-hero {
  width: 100%;
  justify-content: center;
  padding: 16px 24px;
  font-size: 15px;
  font-weight: 700;
}

@media (max-width: 1000px) {

  .lp-gen-main,
  .lp-gen-side {
    grid-column: span 12;
  }
}

@media (max-width: 700px) {
  .lp-drop {
    min-height: 240px;
    padding: 28px 18px;
  }

  .lp-drop-ring {
    width: 64px;
    height: 64px;
  }
}

@media (prefers-reduced-motion: reduce) {

  .lp-drop,
  .lp-drop-ring,
  .lp-pillset span {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   24. ĐẦU TRANG HỒ SƠ
   --------------------------------------------------------------------------
   Bản thiết kế trang_c_nh_n_gi_ng_vi_n: một dải nền rộng, ảnh đại diện tròn đè
   lên mép dưới của dải, rồi tên · trạng thái · các viên thuốc số liệu, và nút
   hành động ở mép phải.

   Dùng chung cho hồ sơ giáo viên và học viên — cùng một trang, khác dữ liệu.
   -------------------------------------------------------------------------- */

.lp-prof {
  margin-bottom: 24px;
  background: var(--lp-surface);
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
  overflow: hidden;
}

/*
 * Dải nền là mảng màu chuyển sắc, KHÔNG phải ảnh — bảng users không có cột ảnh
 * bìa nên không có gì để đọc ra. Xem chú thích ở pages/profile.php.
 */
.lp-prof-banner {
  height: 168px;
  background:
    radial-gradient(120% 140% at 15% 0%, var(--lp-accent-sub), transparent 62%),
    linear-gradient(120deg, var(--lp-surface-sub), var(--lp-accent-sub));
}

.lp-prof-body {
  display: flex;
  align-items: flex-end;
  gap: 20px;
  padding: 0 24px 22px;
  /* Kéo ngược lên để ảnh đại diện đè lên mép dưới dải nền — chi tiết đặc trưng
     của bản thiết kế. */
  margin-top: -56px;
  flex-wrap: wrap;
}

.lp-prof-avatar {
  position: relative;
  width: 128px;
  height: 128px;
  flex: none;
  border-radius: 50%;
  /* Viền dày cùng màu nền để tách ảnh khỏi dải nền phía sau. */
  border: 4px solid var(--lp-surface);
  background: var(--lp-surface-sub);
  overflow: visible;
}

.lp-prof-avatar img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  display: block;
}

.lp-prof-cam {
  position: absolute;
  right: 2px;
  bottom: 2px;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 2px solid var(--lp-surface);
  background: var(--lp-accent);
  color: var(--lp-accent-ink);
  cursor: pointer;
  font-size: 13px;
}

.lp-prof-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-bottom: 4px;
}

.lp-prof-main>.lp-pill {
  align-self: flex-start;
}

.lp-prof-main h1 {
  margin: 0;
  font-family: var(--lp-f-display);
  font-size: clamp(26px, 3.6vw, 38px);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.02em;
  color: var(--lp-ink);
}

.lp-prof-status {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  font-size: 14.5px;
  color: var(--lp-ink-soft);
}

.lp-prof-status.is-empty {
  color: var(--lp-ink-faint);
}

/* --- viên thuốc số liệu --- */
.lp-prof-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 6px;
}

.lp-prof-stat {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 6px 16px;
  border-radius: 999px;
  border: 1px solid var(--lp-rule);
  background: var(--lp-surface-sub);
  font-family: inherit;
  font-size: 13.5px;
  color: var(--lp-ink-soft);
  cursor: pointer;
  transition: border-color .25s var(--lp-ease), background .25s var(--lp-ease);
}

/* Ô điểm đánh giá không bấm được — nó không mở danh sách nào. */
.lp-prof-stat.is-static {
  cursor: default;
}

.lp-prof-stat:not(.is-static):hover {
  border-color: var(--lp-accent);
  background: var(--lp-accent-sub);
}

.lp-prof-stat b {
  font-family: var(--lp-f-display);
  font-size: 17px;
  font-weight: 700;
  color: var(--lp-ink);
  font-variant-numeric: tabular-nums;
}

.lp-prof-act {
  flex: none;
  padding-bottom: 4px;
}

@media (max-width: 700px) {
  .lp-prof-banner {
    height: 120px;
  }

  .lp-prof-body {
    margin-top: -44px;
    padding: 0 16px 18px;
    gap: 14px;
  }

  .lp-prof-avatar {
    width: 96px;
    height: 96px;
  }

  /* Nút hành động trải hết bề ngang khi đã xuống dòng riêng. */
  .lp-prof-act,
  .lp-prof-act .lp-btn {
    width: 100%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .lp-prof-stat {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   25. THẺ HỌC VIÊN Ở MÀN HÌNH CHẤM BÀI
   -------------------------------------------------------------------------- */

.lp-picker {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 240px;
}

.lp-picker .lp-select {
  border-radius: 999px;
}

.lp-scard {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 20px;
  background: var(--lp-surface);
  border: 1px solid var(--lp-rule);
  border-radius: var(--lp-radius);
  text-decoration: none;
  color: inherit;
  transition: border-color .25s var(--lp-ease), background .25s var(--lp-ease);
}

.lp-scard:hover {
  border-color: var(--lp-accent);
  background: var(--lp-surface-sub);
}

.lp-scard-top {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

/*
 * Ảnh đại diện, hoặc chữ cái đầu khi chưa có ảnh. Nền đổi màu theo việc còn
 * chờ hay không — nhưng trạng thái KHÔNG chỉ dựa vào màu: thẻ nhãn bên cạnh
 * viết rõ "Chờ chấm" / "Đã xong".
 */
.lp-scard-face {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  flex: none;
  border-radius: 50%;
  overflow: hidden;
  background: var(--lp-surface-sub);
  border: 1px solid var(--lp-rule);
  font-family: var(--lp-f-display);
  font-size: 17px;
  font-weight: 700;
  color: var(--lp-ink-soft);
}

.lp-scard-face.is-pending {
  background: var(--lp-accent-sub);
  color: var(--lp-accent);
  border-color: var(--lp-accent-sub);
}

.lp-scard-face img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.lp-scard-who {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1;
}

.lp-scard-who strong {
  font-size: 15.5px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--lp-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lp-scard-who small {
  font-size: 12.5px;
  color: var(--lp-ink-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lp-scard-flag {
  flex: none;
  padding: 3px 10px;
  border-radius: var(--lp-radius-sm);
  border: 1px solid var(--lp-rule);
  background: var(--lp-surface-sub);
  font-size: 11.5px;
  font-weight: 600;
  color: var(--lp-ink-soft);
  white-space: nowrap;
}

.lp-scard-flag.is-pending {
  background: var(--lp-warn-sub);
  border-color: var(--lp-warn-sub);
  color: var(--lp-warn);
}

.lp-scard-mid {
  flex: 1;
}

.lp-scard-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-top: 14px;
  border-top: 1px solid var(--lp-rule);
}

.lp-scard-note {
  font-size: 12.5px;
  color: var(--lp-ink-faint);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .lp-scard {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   26. CON CHUỘT HAMSTER CHẠY BÁNH XE — chỉ báo đang chờ dùng chung

   Nguồn: https://uiverse.io/Nawsome/wet-mayfly-23 (MIT).

   ĐÃ ĐỔI SO VỚI BẢN GỐC: mọi selector được bọc dưới .lp-hamster. Bản gốc khai
   .wheel, .spoke, .hamster ở tầng cao nhất — ba tên quá phổ thông để thả vào
   một biểu định kiểu dùng chung cho 27 trang; chỉ cần một trang khác có phần tử
   tên .wheel là nó lĩnh trọn animation của bánh xe. Nội dung khai báo giữ
   nguyên từng giá trị.

   THAY CHO BỐN VÒNG QUAY RIÊNG. Trước đây ai_generator (.aig-spinner),
   generate_tests (.gt-spinner), ai_large_video (.lv-spin) và lớp phủ chờ toàn
   cục (.lp-dot-wave) mỗi chỗ một kiểu, mà cả bốn đều nói cùng một điều.
   -------------------------------------------------------------------------- */
.lp-hamster {
  --dur: 0.8s;
  position: relative;
  width: 12em;
  height: 12em;
  font-size: 14px;
  margin: 0 auto;
}

.lp-hamster,
.lp-hamster * {
  animation-duration: var(--dur) !important;
}

.lp-hamster .wheel,
.lp-hamster .hamster,
.lp-hamster .hamster div,
.lp-hamster .spoke {
  position: absolute;
}

.lp-hamster .wheel,
.lp-hamster .spoke {
  border-radius: 50%;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.lp-hamster .wheel {
  background: radial-gradient(100% 100% at center, hsla(0, 0%, 60%, 0) 47.8%, hsl(0, 0%, 60%) 48%);
  z-index: 2;
}

.lp-hamster .hamster {
  animation: lp-hamster var(--dur) ease-in-out infinite;
  top: 50%;
  left: calc(50% - 3.5em);
  width: 7em;
  height: 3.75em;
  transform: rotate(4deg) translate(-0.8em, 1.85em);
  transform-origin: 50% 0;
  z-index: 1;
}

.lp-hamster .hamster__head {
  animation: lp-hamsterHead var(--dur) ease-in-out infinite;
  background: hsl(30, 90%, 55%);
  border-radius: 70% 30% 0 100% / 40% 25% 25% 60%;
  box-shadow: 0 -0.25em 0 hsl(30, 90%, 80%) inset, 0.75em -1.55em 0 hsl(30, 90%, 90%) inset;
  top: 0;
  left: -2em;
  width: 2.75em;
  height: 2.5em;
  transform-origin: 100% 50%;
}

.lp-hamster .hamster__ear {
  animation: lp-hamsterEar var(--dur) ease-in-out infinite;
  background: hsl(0, 90%, 85%);
  border-radius: 50%;
  box-shadow: -0.25em 0 hsl(30, 90%, 55%) inset;
  top: -0.25em;
  right: -0.25em;
  width: 0.75em;
  height: 0.75em;
  transform-origin: 50% 75%;
}

.lp-hamster .hamster__eye {
  animation: lp-hamsterEye var(--dur) linear infinite;
  background-color: hsl(0, 0%, 0%);
  border-radius: 50%;
  top: 0.375em;
  left: 1.25em;
  width: 0.5em;
  height: 0.5em;
}

.lp-hamster .hamster__nose {
  background: hsl(0, 90%, 75%);
  border-radius: 35% 65% 85% 15% / 70% 50% 50% 30%;
  top: 0.75em;
  left: 0;
  width: 0.2em;
  height: 0.25em;
}

.lp-hamster .hamster__body {
  animation: lp-hamsterBody var(--dur) ease-in-out infinite;
  background: hsl(30, 90%, 90%);
  border-radius: 50% 30% 50% 30% / 15% 60% 40% 40%;
  box-shadow: 0.1em 0.75em 0 hsl(30, 90%, 55%) inset, 0.15em -0.5em 0 hsl(30, 90%, 80%) inset;
  top: 0.25em;
  left: 2em;
  width: 4.5em;
  height: 3em;
  transform-origin: 17% 50%;
  transform-style: preserve-3d;
}

.lp-hamster .hamster__limb--fr,
.lp-hamster .hamster__limb--fl {
  clip-path: polygon(0 0, 100% 0, 70% 80%, 60% 100%, 0% 100%, 40% 80%);
  top: 2em;
  left: 0.5em;
  width: 1em;
  height: 1.5em;
  transform-origin: 50% 0;
}

.lp-hamster .hamster__limb--fr {
  animation: lp-hamsterFRLimb var(--dur) linear infinite;
  background: linear-gradient(hsl(30, 90%, 80%) 80%, hsl(0, 90%, 75%) 80%);
  transform: rotate(15deg) translateZ(-1px);
}

.lp-hamster .hamster__limb--fl {
  animation: lp-hamsterFLLimb var(--dur) linear infinite;
  background: linear-gradient(hsl(30, 90%, 90%) 80%, hsl(0, 90%, 85%) 80%);
  transform: rotate(15deg);
}

.lp-hamster .hamster__limb--br,
.lp-hamster .hamster__limb--bl {
  border-radius: 0.75em 0.75em 0 0;
  clip-path: polygon(0 0, 100% 0, 100% 30%, 70% 90%, 70% 100%, 30% 100%, 40% 90%, 0% 30%);
  top: 1em;
  left: 2.8em;
  width: 1.5em;
  height: 2.5em;
  transform-origin: 50% 30%;
}

.lp-hamster .hamster__limb--br {
  animation: lp-hamsterBRLimb var(--dur) linear infinite;
  background: linear-gradient(hsl(30, 90%, 80%) 90%, hsl(0, 90%, 75%) 90%);
  transform: rotate(-25deg) translateZ(-1px);
}

.lp-hamster .hamster__limb--bl {
  animation: lp-hamsterBLLimb var(--dur) linear infinite;
  background: linear-gradient(hsl(30, 90%, 90%) 90%, hsl(0, 90%, 85%) 90%);
  transform: rotate(-25deg);
}

.lp-hamster .hamster__tail {
  animation: lp-hamsterTail var(--dur) linear infinite;
  background: hsl(0, 90%, 85%);
  border-radius: 0.25em 50% 50% 0.25em;
  box-shadow: 0 -0.2em 0 hsl(0, 90%, 75%) inset;
  top: 1.5em;
  right: -0.5em;
  width: 1em;
  height: 0.5em;
  transform: rotate(30deg) translateZ(-1px);
  transform-origin: 0.25em 0.25em;
}

.lp-hamster .spoke {
  animation: lp-spoke var(--dur) linear infinite;
  background: radial-gradient(100% 100% at center, hsl(0, 0%, 60%) 4.8%, hsla(0, 0%, 60%, 0) 5%),
    linear-gradient(hsla(0, 0%, 55%, 0) 46.9%, hsl(0, 0%, 65%) 47% 52.9%, hsla(0, 0%, 65%, 0) 53%) 50% 50% / 99% 99% no-repeat;
}

@keyframes lp-hamster {

  from,
  to {
    transform: rotate(4deg) translate(-0.8em, 1.85em);
  }

  50% {
    transform: rotate(0) translate(-0.8em, 1.85em);
  }
}

@keyframes lp-hamsterHead {

  from,
  25%,
  50%,
  75%,
  to {
    transform: rotate(0);
  }

  12.5%,
  37.5%,
  62.5%,
  87.5% {
    transform: rotate(8deg);
  }
}

@keyframes lp-hamsterEye {

  from,
  90%,
  to {
    transform: scaleY(1);
  }

  95% {
    transform: scaleY(0);
  }
}

@keyframes lp-hamsterEar {

  from,
  25%,
  50%,
  75%,
  to {
    transform: rotate(0);
  }

  12.5%,
  37.5%,
  62.5%,
  87.5% {
    transform: rotate(12deg);
  }
}

@keyframes lp-hamsterBody {

  from,
  25%,
  50%,
  75%,
  to {
    transform: rotate(0);
  }

  12.5%,
  37.5%,
  62.5%,
  87.5% {
    transform: rotate(-2deg);
  }
}

@keyframes lp-hamsterFRLimb {

  from,
  25%,
  50%,
  75%,
  to {
    transform: rotate(50deg) translateZ(-1px);
  }

  12.5%,
  37.5%,
  62.5%,
  87.5% {
    transform: rotate(-30deg) translateZ(-1px);
  }
}

@keyframes lp-hamsterFLLimb {

  from,
  25%,
  50%,
  75%,
  to {
    transform: rotate(-30deg);
  }

  12.5%,
  37.5%,
  62.5%,
  87.5% {
    transform: rotate(50deg);
  }
}

@keyframes lp-hamsterBRLimb {

  from,
  25%,
  50%,
  75%,
  to {
    transform: rotate(-60deg) translateZ(-1px);
  }

  12.5%,
  37.5%,
  62.5%,
  87.5% {
    transform: rotate(20deg) translateZ(-1px);
  }
}

@keyframes lp-hamsterBLLimb {

  from,
  25%,
  50%,
  75%,
  to {
    transform: rotate(20deg);
  }

  12.5%,
  37.5%,
  62.5%,
  87.5% {
    transform: rotate(-60deg);
  }
}

@keyframes lp-hamsterTail {

  from,
  25%,
  50%,
  75%,
  to {
    transform: rotate(30deg) translateZ(-1px);
  }

  12.5%,
  37.5%,
  62.5%,
  87.5% {
    transform: rotate(10deg) translateZ(-1px);
  }
}

@keyframes lp-spoke {
  from {
    transform: rotate(0);
  }

  to {
    transform: rotate(-1turn);
  }
}

/*
 * Người đã tắt hiệu ứng chuyển động vẫn cần biết là hệ thống đang chạy. Dừng
 * hẳn con chuột thì nó thành một bức tranh tĩnh, đọc ra là "đã đơ". Giữ đúng
 * một chuyển động chậm ở nan bánh xe: đủ để nói "còn sống", không nhấp nháy.
 */
@media (prefers-reduced-motion: reduce) {

  .lp-hamster .hamster,
  .lp-hamster .hamster div {
    animation: none;
  }

  .lp-hamster .spoke {
    animation-duration: 4s;
  }
}

/* --- bong bóng thoại của con chuột ------------------------------------------
   Thuần CSS, KHÔNG dùng BlobSpeech của feral-blob. Component đó là React và nằm
   trong gói 319KB; kéo cả gói về chỉ để hiện một câu trên màn hình chờ là đắt
   gấp nhiều lần thứ nó thay thế. Hình dạng dựng lại bằng bo góc + một tam giác
   xoay làm đuôi.
   -------------------------------------------------------------------------- */
.lp-hamster-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
}

.lp-hamster-say {
  position: relative;
  max-width: 260px;
  margin: 0 0 14px;
  padding: 10px 18px;
  border-radius: 18px;
  border: 1px solid var(--lp-rule);
  background: var(--lp-surface);
  color: var(--lp-ink);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.35;
  text-align: center;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .08);
}

/*
 * Đuôi bong bóng: một hình vuông xoay 45°, KHÔNG phải border-triangle.
 *
 * Mẹo border cho ra tam giác đặc, không mang được đường viền 1px của bong bóng —
 * trên nền sáng thì bong bóng có viền mà cái đuôi thì không, nhìn như bị dán
 * thêm. Hình vuông xoay thì nhận viền ở hai cạnh dưới, và một khối nền phủ lên
 * chỗ giáp ranh để không thấy vạch ngang cắt qua.
 */
.lp-hamster-say::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -6px;
  width: 11px;
  height: 11px;
  transform: translateX(-50%) rotate(45deg);
  background: var(--lp-surface);
  border-right: 1px solid var(--lp-rule);
  border-bottom: 1px solid var(--lp-rule);
  border-bottom-right-radius: 3px;
}

/* --------------------------------------------------------------------------
   27. NỀN SHADER — canvas WebGL trôi chậm dưới toàn bộ ứng dụng

   assets/js/lp-shader.js dựng canvas này lúc chạy (nạp từ player_foot.php).
   Thuật toán từ bản xuất Stitch; màu đọc từ token lúc chạy.
   -------------------------------------------------------------------------- */
.lp-shader {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  /*
   * -1 đặt canvas DƯỚI mọi nội dung nhưng TRÊN nền của <html>. Thứ tự vẽ:
   * nền html (dự phòng) → canvas → nội dung. Vì thế body phải trong suốt khi
   * shader chạy — xem quy tắc dưới.
   */
  z-index: -1;
  pointer-events: none;
  /*
   * Nền của CHÍNH canvas (2026-09-26). lp-shader.js tạo ngữ cảnh alpha:true nên
   * bộ đệm chưa vẽ / vừa bị xoá khi zoom / mất ngữ cảnh GPU là trong suốt — và lộ
   * ra màu này, không bao giờ lộ màu đen. Đừng bỏ, đừng đổi sang màu tối cố định.
   */
  background: var(--lp-ground);
}

/*
 * Chỉ trong suốt khi JS ĐÃ dựng được canvas (lớp lp-has-shader do chính
 * lp-shader.js gắn). Không có WebGL, tắt JS, hay shader lỗi giữa chừng thì lớp
 * này không bao giờ xuất hiện và body giữ nguyên nền --lp-ground như cũ.
 */
body.lp.lp-has-shader {
  background: transparent;
}

/* Nền dự phòng nằm ở html: hở ra ở overscroll và khi canvas chưa kịp vẽ. */
html {
  background: var(--lp-ground);
}

@media print {
  .lp-shader {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   28. CODE BLOCK & RICH MARKDOWN STYLES (Master Doc & Course Content)
   -------------------------------------------------------------------------- */
/*
 * Sáu cấp heading và highlight dưới đây thuộc nội dung NGUỒN, không phải tiêu
 * đề khung player. Trước đây renderer đã sinh đúng h1..h6/mark nhưng CSS chỉ
 * chăm h2..h4; vì thế Heading 1 trông như tiêu đề trang còn Heading 5/6 và chữ
 * tô sáng gần như biến mất. Dùng class semantic do parser sinh cùng tag chuẩn
 * giúp cả nội dung cũ lẫn nội dung vừa bóc Word/PDF có cùng hệ phân cấp, không
 * phải suy lại cấu trúc bằng cỡ chữ ở trình duyệt.
 */
.lp-prose h1,
.lp-prose h2,
.lp-prose .gdoc-subh1,
.lp-prose .gdoc-subh2 {
  max-width: var(--lp-w-text);
  margin: 36px 0 12px;
  padding: 12px 16px;
  border-left: 4px solid var(--lp-accent);
  border-radius: 0 var(--lp-radius-sm) var(--lp-radius-sm) 0;
  background: var(--lp-accent-sub);
  font-family: var(--lp-f-display);
  font-size: 24px;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -.015em;
  color: var(--lp-ink);
}

.lp-prose h3,
.lp-prose .gdoc-subh3 {
  padding-bottom: 8px;
  border-bottom: 1px solid var(--lp-rule);
  color: var(--lp-accent);
}

.lp-prose h5,
.lp-prose h6,
.lp-prose .gdoc-subh5,
.lp-prose .gdoc-subh6 {
  max-width: var(--lp-w-text);
  margin: 24px 0 10px;
  font-family: var(--lp-f-body);
  color: var(--lp-ink);
  font-weight: 700;
}

.lp-prose h6,
.lp-prose .gdoc-subh6 {
  font-size: .95em;
  letter-spacing: .01em;
}

.lp-prose strong,
.lp-prose b {
  font-weight: 700;
  color: var(--lp-ink);
}

.lp-prose mark,
.lp-prose .gdoc-highlight {
  padding: .08em .22em;
  border-radius: 4px;
  background: var(--lp-warn-sub);
  color: var(--lp-ink);
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

.gdoc-code-card {
  margin: 16px 0 20px;
  background: #0f172a;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
  border: 1px solid #1e293b;
}
.gdoc-code-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: #1e293b;
  padding: 6px 14px;
  border-bottom: 1px solid #334155;
}
.gdoc-code-badge {
  font-family: Consolas, Menlo, Monaco, monospace;
  font-size: 11px;
  font-weight: 700;
  color: #38bdf8;
  letter-spacing: 0.5px;
}
.gdoc-copy-btn {
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: #cbd5e1;
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.15s ease;
}
.gdoc-copy-btn:hover {
  background: rgba(255, 255, 255, 0.18);
  color: #ffffff;
}
.gdoc-code-pre {
  margin: 0;
  padding: 14px 18px;
  overflow-x: auto;
  background: transparent;
  font-family: Consolas, Menlo, Monaco, monospace;
  font-size: 13.5px;
  line-height: 1.6;
  color: #e2e8f0;
  tab-size: 4;
}
.gdoc-code-pre code {
  font-family: inherit;
  color: inherit;
  background: transparent;
  padding: 0;
  border: none;
}
.gdoc-inline-code {
  font-family: Consolas, Menlo, Monaco, monospace;
  font-size: 0.88em;
  background: var(--lp-surface-sub, #f1f5f9);
  color: var(--lp-ink, #0f172a);
  padding: 2px 6px;
  border-radius: 4px;
  border: 1px solid var(--lp-rule, #e2e8f0);
}
.gdoc-subh3 {
  font-size: 16.5px;
  font-weight: 700;
  color: var(--lp-ink, #0f172a);
  margin: 22px 0 10px;
}
.gdoc-subh4 {
  font-size: 14.5px;
  font-weight: 700;
  color: var(--lp-ink, #1e293b);
  margin: 18px 0 8px;
}
.gdoc-para-text {
  margin: 0 0 14px;
  line-height: 1.85;
  text-align: justify;
  text-indent: 1.25cm;
}
.gdoc-bullet-item, .gdoc-num-item {
  display: flex;
  gap: 8px;
  margin-bottom: 6px;
  line-height: 1.7;
}
.gdoc-bullet-dot {
  color: var(--lp-accent, #0d9488);
  font-weight: bold;
}
.gdoc-num-idx {
  color: var(--lp-accent, #0d9488);
  font-weight: 700;
  min-width: 20px;
}
