/* CHOTSALE PLATFORM — biểu định kiểu của bề mặt quản trị nền tảng.
 *
 * §1 CSP: TỆP NÀY TỪNG LÀ MỘT KHỐI <style> NỘI TUYẾN, VÀ NÓ ĐÃ LÀM HỎNG TOÀN BỘ PORTAL.
 * `style-src 'self'` không cho phép style nội tuyến — trình duyệt chặn cả khối <style> lẫn mọi thuộc tính
 * style="...", nên trang hiện ra không có bố cục nào. Câu trả lời đúng là đưa CSS ra một tệp cùng origin,
 * KHÔNG phải nới CSP bằng 'unsafe-inline': nới một lần cho CSS là mở đường cho mọi thứ nội tuyến về sau.
 *
 * FULL-V1 Phase 0: Portal có HỆ TOKEN RIÊNG (`--pf-*`) thay vì mượn token của Control Center.
 * Hai lý do, và lý do thứ hai mới là lý do thật:
 *   1. đây là một sản phẩm khác, cho một người dùng khác, với mật độ thông tin khác;
 *   2. mượn token nghĩa là một thay đổi giao diện của Customer App có thể lặng lẽ đổi giao diện trang quản
 *      trị.
 *
 * §3 (08A) TỆP NÀY LÀ BIỂU ĐỊNH KIỂU DUY NHẤT CỦA PORTAL. Trước 08A, khung trang còn nạp
 * `/cc-static/cc.css` để mượn vài lớp tiện ích — nhưng trên host Portal thật đường dẫn đó trả **404**, nên
 * những lớp ấy chưa bao giờ tới nơi và 45 nút của bề mặt quản trị hiển thị bằng kiểu mặc định của trình
 * duyệt. Link đã được gỡ và phần còn thiếu (`.btn` và các biến thể) được định nghĩa ngay trong tệp này.
 *
 * QUY TẮC KỂ TỪ ĐÂY: một lớp mà markup của Portal dùng thì phải có định nghĩa Ở ĐÂY. Không mượn nữa —
 * `test_platform_portal_asset_08a` (mục C) khẳng định điều đó bằng cách đối chiếu mọi `class="…"` trong hai
 * tệp view với các bộ chọn của tệp này.
 */

/* ================================================================= TOKEN */
:root{
  --pf-brand:#4338ca; --pf-brand-d:#3730a3; --pf-brand-050:#eef2ff; --pf-brand-100:#e0e7ff;
  --pf-link:#4338ca;
  --pf-ink:#0f172a; --pf-ink-2:#334155; --pf-muted:#64748b; --pf-muted-2:#94a3b8;
  --pf-line:#e2e8f0; --pf-line-2:#f1f5f9; --pf-bg:#f8fafc; --pf-card:#fff;
  --pf-ok:#15803d; --pf-ok-bg:#dcfce7; --pf-warn:#92400e; --pf-warn-bg:#fef3c7;
  --pf-no:#b91c1c; --pf-no-bg:#fee2e2; --pf-off:#475569; --pf-off-bg:#f1f5f9;
  /* 09C — ĐỐI SOÁT có màu RIÊNG, không mượn `warn` cũng không mượn `no`.
   * Tiền ĐÃ VÀO, nên tô nó đỏ như một lần thất bại là mời người trực kết luận "không thu được" rồi đi đòi
   * khách trả lần nữa — một khoản thu hai lần bắt đầu từ đúng một màu sai. Nhưng nó cũng phải nổi hơn
   * `pending`, vì có tiền thật đang treo. Tím: khẩn trương mà không phải báo lỗi. */
  --pf-review:#6d28d9; --pf-review-bg:#ede9fe; --pf-review-line:#c4b5fd;
  /* FULL-V2 — thanh bên SÁNG. Mọi luật của `.pf-side` đều lấy màu từ bốn token này, nên lật giao
   * diện là sửa Ở ĐÂY chứ không phải chồng một khối ghi đè ở cuối tệp. Chồng luật là đúng cái bẫy
   * "luật sau đè luật trước" mà kho này đã trả giá nhiều lần: hai nguồn sự thật cho cùng một thuộc
   * tính, và nguồn thắng là nguồn đứng sau chứ không phải nguồn đúng. */
  --pf-nav:#fff; --pf-nav-2:#eef2f7; --pf-nav-ink:#334155; --pf-nav-ink-2:#94a3b8;
  --pf-font:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --pf-r:14px; --pf-r-sm:8px; --pf-r-pill:999px;
  --pf-sh:0 1px 2px rgba(15,23,42,.04),0 1px 3px rgba(15,23,42,.06);
  --pf-sh-2:0 8px 24px rgba(15,23,42,.10);
  --pf-side-w:248px; --pf-side-w-min:64px; --pf-head-h:56px;
}

*{box-sizing:border-box}
body.pf{margin:0;background:var(--pf-bg);color:var(--pf-ink);font-family:var(--pf-font);font-size:14px}

/* ================================================================= KHUNG */
.pf-app{display:flex;min-height:100vh}
.pf-side{width:var(--pf-side-w);background:var(--pf-nav);color:var(--pf-nav-ink);flex:0 0 auto;
  border-right:1px solid var(--pf-line);
  display:flex;flex-direction:column;transition:width .15s ease}
.pf-logo{display:flex;align-items:center;gap:10px;height:var(--pf-head-h);padding:0 16px;
  border-bottom:1px solid var(--pf-line);color:var(--pf-ink);font-weight:700;white-space:nowrap;
  overflow:hidden}
.pf-logo .pf-mark{flex:0 0 auto;width:28px;height:28px;border-radius:var(--pf-r-sm);background:var(--pf-brand);
  display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:800}
.pf-logo .pf-word{font-size:14px;line-height:1.15}
.pf-logo .pf-word small{display:block;font-weight:400;color:var(--pf-nav-ink-2);font-size:10px;
  letter-spacing:.08em;text-transform:uppercase}
.pf-side nav{padding:10px 8px;flex:1;overflow-y:auto;overflow-x:hidden}
.pf-navgroup{color:var(--pf-nav-ink-2);font-size:10px;letter-spacing:.08em;text-transform:uppercase;
  padding:14px 12px 6px;white-space:nowrap;overflow:hidden}
.pf-side a{display:flex;align-items:center;gap:11px;padding:8px 12px;color:var(--pf-nav-ink);
  text-decoration:none;border-radius:var(--pf-r-sm);font-size:13px;white-space:nowrap;overflow:hidden}
.pf-side a:hover{background:var(--pf-nav-2);color:var(--pf-ink)}
.pf-side a.on{background:var(--pf-brand-050);color:var(--pf-brand);font-weight:650}
.pf-side a .pf-i{flex:0 0 18px;width:18px;text-align:center;opacity:.9;font-size:13px}
.pf-who{padding:10px 14px;border-top:1px solid var(--pf-line);font-size:11px;color:var(--pf-nav-ink-2);
  white-space:nowrap;overflow:hidden}
.pf-who b{display:block;color:var(--pf-ink);font-size:12px;font-weight:600;text-overflow:ellipsis;overflow:hidden}

/* thu gọn: chỉ còn biểu tượng. `title` trên mỗi mục giữ lại nhãn cho chuột và cho trình đọc màn hình. */
.pf-app.is-min .pf-side{width:var(--pf-side-w-min)}
.pf-app.is-min .pf-word,.pf-app.is-min .pf-navgroup,.pf-app.is-min .pf-side a span:not(.pf-i),
.pf-app.is-min .pf-who,.pf-app.is-min .pf-logout button span{display:none}
.pf-app.is-min .pf-side a{justify-content:center;padding:9px 0}
.pf-app.is-min .pf-logo{justify-content:center;padding:0}

.pf-main{flex:1;min-width:0;display:flex;flex-direction:column}

/* ================================================================= HEADER */
.pf-head{height:var(--pf-head-h);background:var(--pf-card);border-bottom:1px solid var(--pf-line);
  display:flex;align-items:center;gap:12px;padding:0 18px;position:sticky;top:0;z-index:20}
.pf-burger{border:1px solid var(--pf-line);background:var(--pf-card);border-radius:var(--pf-r-sm);
  width:32px;height:32px;cursor:pointer;color:var(--pf-ink-2);font-size:14px;line-height:1;flex:0 0 auto}
.pf-burger:hover{background:var(--pf-line-2)}
.pf-crumb{display:flex;align-items:center;gap:7px;font-size:13px;color:var(--pf-muted);min-width:0}
.pf-crumb a{color:var(--pf-muted);text-decoration:none}
.pf-crumb a:hover{color:var(--pf-brand)}
.pf-crumb b{color:var(--pf-ink);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pf-crumb .pf-sep{color:var(--pf-muted-2)}
.pf-grow{flex:1}
.pf-search{position:relative;flex:0 1 300px;min-width:0}
.pf-search input{width:100%;border:1px solid var(--pf-line);border-radius:var(--pf-r-pill);
  padding:7px 12px 7px 32px;font-size:13px;font-family:inherit;background:var(--pf-bg);color:var(--pf-ink)}
.pf-search input:focus{outline:2px solid var(--pf-brand-100);border-color:var(--pf-brand);background:#fff}
.pf-search .pf-sicon{position:absolute;left:11px;top:50%;transform:translateY(-50%);color:var(--pf-muted-2);
  font-size:12px;pointer-events:none}
.pf-hbtn{position:relative;border:1px solid var(--pf-line);background:var(--pf-card);border-radius:var(--pf-r-sm);
  width:32px;height:32px;cursor:pointer;color:var(--pf-ink-2);font-size:13px;flex:0 0 auto}
.pf-hbtn:hover{background:var(--pf-line-2)}
.pf-badge{position:absolute;top:-5px;right:-5px;min-width:16px;height:16px;padding:0 4px;border-radius:8px;
  background:var(--pf-no);color:#fff;font-size:10px;line-height:16px;font-weight:700}
.pf-acct{display:flex;align-items:center;gap:8px;border:1px solid var(--pf-line);background:var(--pf-card);
  border-radius:var(--pf-r-pill);padding:3px 10px 3px 3px;cursor:pointer;font-family:inherit;font-size:12px;
  color:var(--pf-ink-2);max-width:220px}
.pf-acct:hover{background:var(--pf-line-2)}
.pf-avatar{width:24px;height:24px;border-radius:50%;background:var(--pf-brand);color:#fff;font-size:10px;
  font-weight:700;display:flex;align-items:center;justify-content:center;flex:0 0 auto}
.pf-acct .pf-mail{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pf-pop{position:absolute;top:calc(var(--pf-head-h) - 6px);right:18px;background:var(--pf-card);
  border:1px solid var(--pf-line);border-radius:var(--pf-r);box-shadow:var(--pf-sh-2);min-width:230px;
  padding:6px;z-index:30}
.pf-pop[hidden]{display:none}
.pf-pop .pf-pophead{padding:8px 10px;border-bottom:1px solid var(--pf-line-2);font-size:12px;
  color:var(--pf-muted);word-break:break-all}
.pf-pop .pf-pophead b{display:block;color:var(--pf-ink);font-size:13px}
.pf-pop a,.pf-pop button{display:block;width:100%;text-align:left;border:0;background:0;padding:8px 10px;
  border-radius:var(--pf-r-sm);font-size:13px;color:var(--pf-ink-2);cursor:pointer;font-family:inherit;
  text-decoration:none}
.pf-pop a:hover,.pf-pop button:hover{background:var(--pf-line-2);color:var(--pf-ink)}
.pf-pop form{margin:0}
.pf-pop .pf-danger{color:var(--pf-no)}

/* ================================================================= NỘI DUNG */
.pf-wrap{padding:22px;max-width:1240px;width:100%}
/* FULL-V2 — `.pf-title`/`.pf-lede` LÀ CÁCH 30 TRANG CON MANG DIỆN MẠO CỦA TRANG CHỦ.
 * Trang chủ dùng `.pf-pagehead`; ba tệp view còn lại dùng hai lớp này ở 30 chỗ. Đổi markup từng chỗ
 * là sửa to, rủi ro, và mỗi chỗ một cấu trúc bao quanh khác nhau. Đổi KIỂU của hai lớp này thì một
 * chỗ sửa, 30 trang đổi theo — và đó chính là nguyên tắc 'nói chung một bộ lớp' mà bài kiểm C1 ghim:
 * phong cách chung phải được bảo đảm bằng CẤU TRÚC, không bằng việc mỗi trang tự nhớ chép lại. */
.pf-title{margin:0 0 4px;font-size:22px;line-height:1.25;font-weight:700;letter-spacing:-.01em;
  color:var(--pf-ink)}
.pf-lede{margin:0 0 18px;color:var(--pf-muted);font-size:13.5px;max-width:760px}
.pf-card{background:var(--pf-card);border:1px solid var(--pf-line);border-radius:var(--pf-r);
  box-shadow:var(--pf-sh);margin-bottom:18px}
.pf-card>h2{margin:0;padding:14px 18px;border-bottom:1px solid var(--pf-line-2);font-size:13.5px;
  font-weight:700;display:flex;align-items:center;gap:10px}
.pf-card>.pf-b{padding:18px}
.pf-grid{display:grid;gap:14px}
.pf-g4{grid-template-columns:repeat(4,1fr)} .pf-g3{grid-template-columns:repeat(3,1fr)}
.pf-g2{grid-template-columns:repeat(2,1fr)}
.pf-kpi{background:var(--pf-card);border:1px solid var(--pf-line);border-radius:var(--pf-r);padding:14px 16px;
  box-shadow:var(--pf-sh)}
.pf-kpi .k{color:var(--pf-muted);font-size:12px;display:flex;align-items:center;gap:6px}
.pf-kpi .v{font-size:25px;font-weight:700;margin:5px 0 2px;letter-spacing:-.02em}
.pf-kpi .d{font-size:11px;color:var(--pf-muted-2);line-height:1.4}
.pf-hint{border:0;background:var(--pf-brand-050);color:var(--pf-brand-d);width:15px;height:15px;
  border-radius:var(--pf-r-pill);font-size:10px;cursor:help;line-height:15px;padding:0;font-family:inherit}

.pf-tw{overflow-x:auto}
.pf-tw table{width:100%;border-collapse:collapse;font-size:13px}
.pf-tw th{text-align:left;color:var(--pf-muted);font-size:11px;font-weight:600;letter-spacing:.03em;
  text-transform:uppercase;padding:9px 16px;border-bottom:1px solid var(--pf-line);white-space:nowrap}
.pf-tw td{padding:11px 16px;border-bottom:1px solid var(--pf-line-2);vertical-align:middle}
.pf-tw tbody tr:hover{background:var(--pf-brand-050)}
.pf-tw a{color:var(--pf-brand-d);text-decoration:none}
.pf-tw a:hover{text-decoration:underline}

.pf-pill{display:inline-block;padding:2px 9px;border-radius:var(--pf-r-pill);font-size:11px;font-weight:600;
  white-space:nowrap}
.pf-ok{background:var(--pf-ok-bg);color:var(--pf-ok)}
/* 22D1 — SỐ TIỀN TIẾT KIỆM. Dùng màu "ok" đã có sẵn thay vì thêm một biến màu mới: tiết kiệm là một con
 * số tốt, và Portal đã có đúng một màu cho ý đó. Thêm biến thứ hai cùng nghĩa là mở đường cho hai sắc
 * xanh hơi khác nhau cùng xuất hiện trên một màn hình. */
.pf-save{color:var(--pf-ok)}
.pf-warn{background:var(--pf-warn-bg);color:var(--pf-warn)}
.pf-no{background:var(--pf-no-bg);color:var(--pf-no)}
.pf-off{background:var(--pf-off-bg);color:var(--pf-off)}
.pf-brandpill{background:var(--pf-brand-100);color:var(--pf-brand-d)}

.kv{display:flex;justify-content:space-between;gap:16px;padding:9px 0;border-bottom:1px solid var(--pf-line-2);
  font-size:13px}
.kv:last-child{border-bottom:0}
.kv .k{color:var(--pf-muted)}

.pf-tabs{display:flex;gap:2px;overflow-x:auto;border-bottom:1px solid var(--pf-line);margin-bottom:18px;
  padding-bottom:0}
.pf-tabs a{padding:9px 13px;font-size:13px;color:var(--pf-muted);text-decoration:none;white-space:nowrap;
  border-bottom:2px solid transparent;border-radius:var(--pf-r-sm) var(--pf-r-sm) 0 0}
.pf-tabs a:hover{color:var(--pf-ink);background:var(--pf-line-2)}
.pf-tabs a.on{color:var(--pf-brand-d);border-bottom-color:var(--pf-brand);font-weight:600}
.pf-tabs a.soon{color:var(--pf-muted-2)}

/* ================================================================= TRẠNG THÁI */
.pf-state{text-align:center;padding:34px 20px;color:var(--pf-muted);font-size:13px}
.pf-state .pf-icon{font-size:26px;display:block;margin-bottom:10px;opacity:.5}
.pf-state-err{background:var(--pf-warn-bg);color:var(--pf-warn);border-radius:var(--pf-r)}
.pf-state-deny{background:var(--pf-no-bg);color:var(--pf-no);border-radius:var(--pf-r);font-weight:600}
.pf-sk{background:linear-gradient(90deg,var(--pf-line-2) 25%,#fff 50%,var(--pf-line-2) 75%);
  background-size:200% 100%;animation:pf-sh 1.2s infinite;border-radius:var(--pf-r-sm);height:13px}
@keyframes pf-sh{0%{background-position:200% 0}100%{background-position:-200% 0}}
.pf-soon{border:1px dashed var(--pf-line);border-radius:var(--pf-r);padding:26px 20px;text-align:center;
  color:var(--pf-muted);background:var(--pf-card)}
.pf-soon b{display:block;color:var(--pf-ink);font-size:14px;margin-bottom:6px}
.pf-soon .pf-phase{display:inline-block;margin-top:12px;padding:3px 10px;border-radius:var(--pf-r-pill);
  background:var(--pf-brand-050);color:var(--pf-brand-d);font-size:11px;font-weight:600}

/* ================================================================= BIỂU MẪU */
.pf-filters{display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;margin-bottom:16px}
.pf-filters label,.pf-form label{display:block;font-size:11px;color:var(--pf-muted);margin-bottom:4px;
  font-weight:600;text-transform:uppercase;letter-spacing:.03em}
.pf-filters input,.pf-filters select,.pf-form input{border:1px solid var(--pf-line);
  border-radius:var(--pf-r-sm);padding:7px 10px;font-size:13px;font-family:inherit;background:var(--pf-card);
  color:var(--pf-ink)}
.pf-filters input:focus,.pf-filters select:focus,.pf-form input:focus{outline:2px solid var(--pf-brand-100);
  border-color:var(--pf-brand)}
.pf-form{max-width:380px}
.pf-form label{margin-top:14px}
.pf-form input{width:100%}
.pf-form .btn{margin-top:18px}
.pf-pager{margin-top:16px;display:flex;gap:8px}
.pf-logout{margin:10px 8px 0;padding-top:10px;border-top:1px solid var(--pf-line)}
.pf-logout button{width:100%;background:0;border:1px solid var(--pf-line);color:var(--pf-nav-ink);
  border-radius:var(--pf-r-sm);padding:8px 12px;font-size:13px;font-family:inherit;cursor:pointer;
  display:flex;align-items:center;gap:11px;white-space:nowrap;overflow:hidden}
.pf-logout button:hover{background:var(--pf-nav-2);color:var(--pf-ink)}

/* ================================================================= ĐĂNG NHẬP */
.pf-auth{display:flex;align-items:center;justify-content:center;min-height:100vh;width:100%;
  background:var(--pf-nav);padding:16px}
.pf-box{background:var(--pf-card);border-radius:14px;padding:30px;width:100%;max-width:396px;
  box-shadow:var(--pf-sh-2)}
.pf-box .pf-logo{border:0;height:auto;padding:0 0 18px;color:var(--pf-ink)}
.pf-box .pf-logo .pf-word small{color:var(--pf-muted-2)}
.pf-box h1{margin:0 0 6px;font-size:19px}
.pf-box label{display:block;font-size:11px;color:var(--pf-muted);margin:15px 0 4px;font-weight:600;
  text-transform:uppercase;letter-spacing:.03em}
.pf-box input{width:100%;border:1px solid var(--pf-line);border-radius:var(--pf-r-sm);padding:9px 11px;
  font-size:13px;font-family:inherit}
.pf-box input:focus{outline:2px solid var(--pf-brand-100);border-color:var(--pf-brand)}
.pf-box .btn{width:100%;margin-top:20px;padding:10px}
.pf-otp{letter-spacing:.5em;text-align:center;font-size:20px}
.pf-sub{margin:0;color:var(--pf-muted);font-size:13px}
.pf-note{background:var(--pf-brand-050);border-left:3px solid var(--pf-brand);padding:11px 14px;
  border-radius:0 var(--pf-r-sm) var(--pf-r-sm) 0;font-size:12px;color:var(--pf-ink-2);margin:15px 0 0}
.pf-err{background:var(--pf-no-bg);color:var(--pf-no);padding:10px 13px;border-radius:var(--pf-r-sm);
  font-size:13px;margin:15px 0 0}

.pf-mt-3{margin-top:12px} .pf-mt-4{margin-top:16px} .pf-mt-5{margin-top:18px} .pf-center{text-align:center}
.muted{color:var(--pf-muted)} .small{font-size:12px}

/* ================================================================= RESPONSIVE */
@media(max-width:1100px){ .pf-g4{grid-template-columns:repeat(2,1fr)} }
@media(max-width:900px){
  .pf-side{position:fixed;left:-100%;top:0;bottom:0;z-index:40;width:var(--pf-side-w);transition:left .18s}
  .pf-app.is-open .pf-side{left:0;box-shadow:var(--pf-sh-2)}
  .pf-app.is-min .pf-side{width:var(--pf-side-w)}
  .pf-app.is-min .pf-word,.pf-app.is-min .pf-navgroup,.pf-app.is-min .pf-side a span:not(.pf-i),
  .pf-app.is-min .pf-who,.pf-app.is-min .pf-logout button span{display:revert}
  .pf-app.is-min .pf-side a{justify-content:flex-start;padding:8px 12px}
  .pf-scrim{position:fixed;inset:0;background:rgba(15,23,42,.45);z-index:35}
  .pf-scrim[hidden]{display:none}
  .pf-search{display:none}
  .pf-wrap{padding:14px}
  .pf-g4,.pf-g3,.pf-g2{grid-template-columns:1fr}
  .pf-acct .pf-mail{display:none}
  .pf-crumb .pf-hideS{display:none}
}
@media(max-width:560px){
  .pf-head{padding:0 12px;gap:8px}
  .pf-title{font-size:18px}
}

/* ================================================================= 4A-07 · DANH MỤC GÓI / ADD-ON
 *
 * Không lớp nào ở đây là style nội tuyến, và đó không phải sở thích: `style-src 'self'` mà
 * `PortalKernel::harden()` đặt sẽ chặn cả `<style>` lẫn `style="..."`, nên một quy tắc viết thẳng vào
 * markup sẽ làm trang mất bố cục trên production đúng như sự cố HARDENING-02.
 */

/* Form nhiều trường: lưới hai cột trên màn rộng. `.pf-form` gốc là một cột rộng 380px — đủ cho form đăng
 * nhập, nhưng form phiên bản có tám trường và sẽ thành một dải dọc dài hơn màn hình. */
.pf-form.pf-grid,.pf-wrap .pf-form{max-width:none}
.pf-wrap .pf-form{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:0 18px}
.pf-wrap .pf-form>div{min-width:0}
.pf-wrap .pf-form select{border:1px solid var(--pf-line);border-radius:var(--pf-r-sm);padding:8px 10px;
  font:inherit;font-size:13px;background:#fff;color:var(--pf-ink);width:100%}
.pf-wrap .pf-form select:focus{outline:2px solid var(--pf-brand-100);border-color:var(--pf-brand)}
.pf-wrap .pf-form .muted{display:block;margin-top:4px}

/* Ô đánh dấu có nhãn dài — `is_free` là ô quan trọng nhất của cả màn hình, nên nó KHÔNG bị nhồi vào lưới
 * cùng các ô nhập: nó đứng riêng, có khung, và có câu giải thích bên dưới. */
.pf-check{background:var(--pf-brand-050);border:1px solid var(--pf-line);border-radius:var(--pf-r-sm);
  padding:11px 13px}
.pf-check label{font-size:13px;color:var(--pf-ink);display:flex;align-items:center;gap:8px;margin:0}
.pf-check .muted{margin-top:6px}

/* ================================================================= 08A · HỆ NÚT, TỰ CHỨA
 *
 * VÌ SAO KHỐI NÀY TỒN TẠI. Portal từng nạp `/cc-static/cc.css` để mượn `.btn` của Control Center, và
 * `.btn` KHÔNG hề được định nghĩa ở tệp này — chỉ có ba biến thể phụ (`.pf-form .btn`, `.pf-box .btn`,
 * `.btn.pf-primary`) giả định một nền đã có sẵn.
 *
 * Nhưng trên host Portal thật, `/cc-static/cc.css` trả **404**: ROOT-04 cố ý cho Portal chiếm mọi đường dẫn
 * của host, và Portal chỉ phục vụ `/portal-static/*`. Nghĩa là cái nền ấy CHƯA BAO GIỜ tới nơi — 45 nút của
 * bề mặt quản trị đang hiển thị bằng kiểu mặc định của trình duyệt trên production, lặng lẽ, từ trước
 * ticket này.
 *
 * Nên gỡ cái link chết đi thì phải mang theo cái nền: một bề mặt quản trị KHÔNG được phụ thuộc vào biểu
 * định kiểu của sản phẩm khác. Toàn bộ khối này dựng bằng token `--pf-*` có sẵn, không thêm token mới.
 */

.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  padding:8px 14px;min-height:36px;                 /* thấp hơn cc.css (40px): Portal là màn hình dày đặc */
  border:1px solid var(--pf-line);border-radius:var(--pf-r-sm);
  background:var(--pf-card);color:var(--pf-ink-2);
  font:inherit;font-size:13px;font-weight:600;line-height:1.25;
  text-align:center;text-decoration:none;white-space:normal;max-width:100%;
  cursor:pointer;transition:background .12s,border-color .12s,color .12s;
}
.btn:hover{background:var(--pf-line-2);border-color:var(--pf-muted-2);text-decoration:none}
.btn:active{background:var(--pf-line)}

/* BÀN PHÍM PHẢI NHÌN THẤY ĐƯỢC TIÊU ĐIỂM. `:focus-visible` chứ không phải `:focus`, nên chuột không để lại
 * viền sau mỗi cú bấm, còn người dùng Tab thì luôn biết mình đang ở đâu — trên một bề mặt có thao tác phát
 * hành giá và gỡ gói, "đang ở nút nào" không phải chi tiết trang trí. */
.btn:focus-visible{outline:2px solid var(--pf-brand);outline-offset:2px}

/* CHÍNH — đúng một nút mỗi trang ghi.
 *
 * MỘT TÊN DUY NHẤT, và việc dọn nó là một phát hiện của ticket này. Năm nút quan trọng nhất của luồng vào
 * (Đăng nhập, MFA, ghi danh MFA, mời nhân sự, đổi mật khẩu) mang `class="btn pri"` — nhưng `.pri` không tồn
 * tại ở portal.css LẪN cc.css. Chúng chưa bao giờ là nút chính, kể cả những ngày cc.css còn tải được.
 *
 * Cách sửa là đổi năm chỗ markup sang `pf-primary`, KHÔNG phải định nghĩa thêm `.pri` — thêm bí danh thứ hai
 * cho cùng một khái niệm là cách lần sau có người dùng nhầm tên rồi lại không có gì bắt được. */
.btn.pf-primary{background:var(--pf-brand);border-color:var(--pf-brand);color:#fff}
.btn.pf-primary:hover{background:var(--pf-brand-d);border-color:var(--pf-brand-d)}
/* Nut PHU (Huy / quay lai). Vien mo, nen trong suot: no phai doc nhu mot loi thoat, khong canh
   tranh thi giac voi hanh dong chinh dung canh no. */
.btn.ghost{background:0;border-color:var(--pf-line);color:var(--pf-muted)}
.btn.ghost:hover{background:var(--pf-line-2);border-color:var(--pf-muted-2);color:var(--pf-ink-2)}

/* PHÁ HỦY — lưu trữ phiên bản, gỡ gói, thu hồi phiên, đặt lại MFA. Chưa markup nào dùng lớp này; nó được
 * định nghĩa để một thao tác phá hủy có đường trông khác một thao tác đọc, thay vì cả hai cùng là nút
 * trắng. Việc gắn nó vào từng nút là một thay đổi giao diện riêng, không thuộc ticket gỡ link này. */
.btn.pf-danger{color:var(--pf-no);border-color:#fecaca;background:var(--pf-card)}
.btn.pf-danger:hover{background:var(--pf-no-bg);border-color:var(--pf-no)}
.btn.pf-danger:active{background:#fecaca}

/* VÒNG TIÊU ĐIỂM RIÊNG CHO NÚT NGUY HIỂM.
 *
 * `.btn:focus-visible` phía trên vẽ vòng màu chàm — đặt quanh một nút đỏ thì vừa lệch nghĩa vừa khó thấy.
 * Người dùng bàn phím phải nhận ra mình đang đứng trên "Đặt lại MFA" chứ không phải nút bên cạnh, nên vòng
 * tiêu điểm của nút nguy hiểm mang đúng màu của nó.
 *
 * MÀU KHÔNG PHẢI TÍN HIỆU DUY NHẤT, và đó là chủ ý: mọi nút ở nhóm này đều mang nhãn nói thẳng hành động
 * ("Lưu trữ", "Gỡ gói", "Thu hồi", "Khóa tài khoản", "Đặt lại MFA") và đều hỏi lại trước khi chạy. Người
 * không phân biệt được đỏ với xám vẫn đọc được nhãn và vẫn nhận được câu hỏi xác nhận.
 *
 * Tương phản (WCAG, trên nền thẻ trắng): chữ #b91c1c ⇒ 6.5:1; khi hover trên nền #fee2e2 ⇒ 5.4:1. Cả hai
 * vượt ngưỡng AA 4.5:1. */
.btn.pf-danger:focus-visible{outline:2px solid var(--pf-no);outline-offset:2px}

/* NHỎ — `class="btn xs"` là HAI lớp, nên bộ chọn là `.btn.xs`, không phải `.btn-xs`: một bộ chọn gạch nối
 * sẽ không khớp hàng nào và 29 nút vẫn giữ nguyên kích thước đầy đủ. */
.btn.xs{min-height:0;padding:4px 9px;font-size:12px;gap:5px}

/* VÔ HIỆU HÓA — dùng thuộc tính `disabled` thật, không phải một lớp trông giống vô hiệu hóa. Nút "Chuyển
 * sang công khai" của một gói chưa phát hành đi qua đúng đường này, và `pointer-events:none` để một cú bấm
 * không gửi được form mà cổng quyền phía sau sẽ từ chối. */
.btn[disabled]{opacity:.5;cursor:not-allowed;pointer-events:none}

/* Form một nút nằm chung dòng với nội dung khác. */
form.pf-inline{display:inline}
label.pf-inline{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--pf-ink-2);
  margin:0;text-transform:none;letter-spacing:0}

/* Danh sách "điều gì sẽ xảy ra" trên trang xác nhận. */
.pf-list{margin:8px 0 0;padding-left:18px}
.pf-list li{margin:4px 0;line-height:1.5}

/* =========================================================================================================
 * 09C — BILLING
 * ========================================================================================================= */

/* TIÊU ĐỀ TRONG THẺ. `h2` mặc định của trình duyệt quá to cho một thẻ nội dung. */
.pf-h2{margin:0 0 10px;font-size:14px;font-weight:650;color:var(--pf-ink);letter-spacing:-.01em}

/* SỐ TIỀN. Chữ số dạng bảng (`tabular-nums`) để các hàng thẳng cột — khi đọc một cột tiền, mắt so sánh độ
 * dài chuỗi số, và chữ số rộng khác nhau làm hỏng phép so sánh đó. */
.pf-money{font-variant-numeric:tabular-nums;white-space:nowrap;font-weight:600;color:var(--pf-ink)}
.pf-cur{font-weight:400;font-size:11px;color:var(--pf-muted)}

/* Ô số căn phải — áp cho cả `th` để tiêu đề thẳng hàng với số bên dưới. */
.pf-num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}

/* Định danh kỹ thuật đã cắt ngắn (mã giao dịch, mã sự kiện, băm payload, mã lý do). */
.pf-code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;
  background:var(--pf-line-2);border:1px solid var(--pf-line);border-radius:var(--pf-r-sm);
  padding:1px 5px;color:var(--pf-ink-2);white-space:nowrap}

/* Ô trạng thái ĐỐI SOÁT — xem lý do màu riêng ở phần token phía trên. */
.pf-pill.pf-review{background:var(--pf-review-bg);color:var(--pf-review)}

/* KHỐI CẢNH BÁO. `.pf-note` đã tồn tại cho ghi chú trung tính; đây là bậc cao hơn, dùng khi có tiền treo. */
.pf-alert{border:1px solid var(--pf-line);border-left:3px solid var(--pf-muted-2);
  background:var(--pf-line-2);border-radius:var(--pf-r-sm);padding:10px 12px;font-size:13px;
  line-height:1.6;color:var(--pf-ink-2)}
.pf-alert b{color:var(--pf-ink)}
.pf-alert-review{border-left-color:var(--pf-review);background:var(--pf-review-bg);
  border-color:var(--pf-review-line)}
.pf-alert-review b{color:var(--pf-review)}

/* Thẻ chứa hàng đợi đối soát trên trang tổng quan — viền trái để nó tách khỏi các ô thống kê. */
.pf-card-review{border-left:3px solid var(--pf-review)}

/* Hàng bảng cần đối soát. Nền RẤT nhạt: nó phải đọc được là "khác" khi lướt mắt qua bảng, nhưng không
 * được nuốt mất chữ trong hàng. */
.pf-row-review td{background:var(--pf-review-bg)}
.pf-tw tbody tr.pf-row-review:hover td{background:var(--pf-review-line)}

/* DÒNG THỜI GIAN. Một danh sách có thứ tự, không phải một bảng: các mốc không có cột chung nào ngoài thời
 * điểm, và ép chúng vào bảng sẽ tạo ra những ô trống không mang nghĩa gì. */
.pf-timeline{list-style:none;margin:0;padding:0}
.pf-timeline li{position:relative;padding:6px 0 6px 18px;font-size:13px;line-height:1.5;
  border-left:2px solid var(--pf-line);margin-left:4px}
.pf-timeline li:before{content:"";position:absolute;left:-5px;top:12px;width:8px;height:8px;
  border-radius:var(--pf-r-pill);background:var(--pf-muted-2)}
.pf-tl-ok:before{background:var(--pf-ok)}
.pf-tl-warn:before{background:var(--pf-warn)}
.pf-tl-no:before{background:var(--pf-no)}
.pf-tl-off:before{background:var(--pf-muted-2)}
.pf-tl-at{font-variant-numeric:tabular-nums;color:var(--pf-muted);font-size:12px}
.pf-tl-label{color:var(--pf-ink-2);font-weight:500}

/* 375×812 — bảng billing rộng hơn mọi bảng khác của Portal (tới 11 cột), nên `.pf-tw` phải cuộn ngang
 * được và thân trang thì KHÔNG. `.pf-tw` đã có `overflow:auto`; ở đây chỉ siết lại khoảng đệm để nhiều cột
 * còn đọc được trên máy hẹp. */
@media (max-width:560px){
  .pf-tw th,.pf-tw td{padding:8px 8px}
  .pf-code{font-size:10px}
  .pf-money{font-size:12px}

  /* 22D1 — BẢNG THÀNH THẺ TRÊN MÀN HẸP, THAY VÌ ĐUA VỚI TỪNG PIXEL.
   *
   * 22D đã siết bề rộng ô nhập và cho khóa entitlement xuống dòng. Nó ĐỦ ở 375px — và chỉ đủ ở đó. Quét
   * 320→400px trên Chrome thật đo được biên mỏng đến mức nào:
   *
   *     375px  0 bảng tràn        ← nơi 22D được nghiệm thu
   *     370px  1 bảng tràn  +2px
   *     365px  3 bảng tràn  +4/+7/+4
   *     360px  3 bảng tràn  +9/+12/+9   ← đúng hình dạng Owner báo: MỘT bảng giá + HAI bảng tính năng
   *     320px  4 bảng tràn  tới +52px
   *
   * Tức bản sửa cũ vượt qua bài kiểm bằng 5px dự trữ. Bất cứ thứ gì ăn mất 5px đó — một thanh cuộn hiện
   * hình, một phông chữ hệ thống rộng hơn, một máy 360px — đều đưa ô nhập chính ra ngoài màn hình trở lại.
   * Đua với từng pixel trên một bảng bảy cột là một ván không thắng được.
   *
   * NÊN Ở MÀN HẸP, BẢNG THÔI LÀM BẢNG. Mỗi hàng thành một thẻ xếp dọc; nhãn cột đọc ra từ `data-label` của
   * chính ô đó, nên nhãn chỉ tồn tại MỘT BẢN (trong markup) thay vì một bản trong `<thead>` cho màn rộng
   * và một bản trong CSS cho màn hẹp — hai bản sẽ trôi khỏi nhau.
   *
   * KHÔNG CÒN CHIỀU NGANG ĐỂ TRÀN, nên phép đo "khối nào đang giấu nội dung" đúng bằng 0 ở MỌI bề rộng,
   * không phải chỉ ở 375.
   *
   * NEO VÀO `.pf-stack`, KHÔNG PHẢI `.pf-tw`. Portal có những bảng khác — hóa đơn 11 cột, nhật ký — mà
   * dạng thẻ sẽ làm dài ra vô ích và ở đó cuộn ngang mới là đúng. Chỉ ba bảng của trình sửa giá mang lớp
   * này. Đây cũng là bài học 08B: một luật không được neo đúng chỗ sẽ sơn lại thứ không ai định sơn. */
  .pf-stack table,.pf-stack tbody,.pf-stack tr,.pf-stack td{display:block;width:auto}
  .pf-stack thead{display:none}
  .pf-stack tr{padding:10px 2px;border-bottom:1px solid var(--pf-line)}
  .pf-stack tr:last-child{border-bottom:0}
  .pf-stack td{border:0;padding:3px 0}
  /* NHÃN LÀ MỘT DÒNG RIÊNG, KHÔNG PHẢI MỘT CỘT FLEX.
   *
   * Bản đầu đặt `display:flex` lên chính ô để nhãn và giá trị nằm cùng dòng. Chrome thật bác bỏ: nội dung
   * của ô là `<b>Nhãn</b><br><code>khoa.rat.dai</code>`, và trong một flex container thì `<b>` với `<code>`
   * thành HAI CỘT cạnh nhau — `<br>` không còn ngắt được gì. Bề rộng tối thiểu của ô vì thế cộng dồn cả
   * hai, và hai bảng tính năng vẫn tràn dưới 365px (đo được: +3px ở 360, +27px ở 320).
   *
   * Nhãn xếp trên, giá trị xếp dưới thì không còn bề rộng tối thiểu nào để cộng dồn. Cao hơn vài pixel mỗi
   * hàng, và đó là cái giá đúng để trả. */
  .pf-stack td[data-label]::before{content:attr(data-label);display:block;
    color:var(--pf-muted);font-size:11px;font-weight:600;letter-spacing:.03em;text-transform:uppercase}
  /* Ô nhập chiếm nốt phần còn lại: ở dạng thẻ không còn cột nào để tranh, nên không cần siết bề rộng. */
  .pf-stack input[type=text],.pf-stack input:not([type]){width:100%;min-width:0;box-sizing:border-box}
  .pf-stack code{overflow-wrap:anywhere}
}

/* 22D1-HOTFIX — KHÓA ĐỊNH DANH DÀI PHẢI NGẮT ĐƯỢC, Ở MỌI BỀ RỘNG.
 *
 * `.pf-keyref` chỉ nằm trên bảng TRA CỨU KHÓA entitlement (`PortalPages::entitlementKeyReference()`), nơi
 * mỗi ô mang một chuỗi như `feature.crm.renurture_leads` — một "từ" không có chỗ ngắt, nên bề rộng tối
 * thiểu của cột bằng nguyên chiều dài chuỗi. Đo trên Chrome thật ở `/plans`: ba bảng này cần hơn khung
 * +3…+48px ở 375px và +63px ở 360px, và người đọc phải cuộn ngang bên trong khối mới thấy hết mã.
 *
 * VÌ SAO KHÔNG DÙNG `.pf-tw td code` NHƯ PHƯƠNG ÁN RỘNG. Ticket cho phép nó "nếu audit xác nhận không làm
 * hỏng các bảng .pf-tw khác, đặc biệt invoice/billing" — và audit KHÔNG xác nhận được điều đó:
 * `PortalBillingPages` đặt `<code class="pf-code">` trong ô bảng ở 14 chỗ (mã giao dịch, `reason_code`).
 * `overflow-wrap:anywhere` thay đổi cả bề rộng TỐI THIỂU của ô, nên nó sẽ phân bố lại cột của bảng billing
 * kể cả khi không có gì tràn. Một lớp chỉ sống trên bảng tra cứu khóa thì không với tới chúng được.
 *
 * NGOÀI `@media` CÓ CHỦ Ý. Khuyết điểm không dừng ở 560px: cùng ba bảng ấy vẫn tràn ở mọi bề rộng nhỏ hơn
 * chiều dài chuỗi. Đặt luật trong khối hẹp sẽ để lại đúng khuyết điểm này ở dải 560–900px. Đã đo desktop
 * 1366px trước và sau: không một pixel nào đổi, vì ở đó cột đã đủ rộng nên không có gì để ngắt. */
.pf-keyref td code{overflow-wrap:anywhere}

/* 22E1 — NỘI DUNG CHUYỂN KHOẢN PHẢI HIỆN ĐỦ TRÊN MÁY HẸP.
 *
 * `CSINV202609000001` là một "từ" không có chỗ ngắt, nên ở 360–390px nó đẩy ô ra rộng hơn khung và người
 * dùng phải cuộn ngang mới đọc hết — đúng lúc họ cần chép chính xác từng ký tự.
 *
 * NGẮT BẰNG CSS, KHÔNG CHÈN KÝ TỰ VÀO GIÁ TRỊ. Một `<wbr>` hay một khoảng trắng "mềm" nhét vào giữa mã sẽ
 * đi thẳng vào clipboard khi người dùng bôi đen và chép — và ngân hàng sẽ nhận một nội dung không khớp
 * hóa đơn nào. `overflow-wrap` chỉ đổi chỗ XUỐNG DÒNG khi vẽ; giá trị trong DOM không đổi một ký tự, nên
 * chép ra vẫn nguyên mã.
 *
 * Neo vào đúng ba ô dữ liệu chuyển khoản (`data-bt`), không nới cho cả trang. */
[data-bt="reference"],[data-bt="account"],[data-bt="amount"]{overflow-wrap:anywhere;word-break:normal}

/* 22E1-CORR — LUẬT TRÊN KHÔNG BAO GIỜ ĂN, VÀ THỦ PHẠM LỚN NHẤT KHÔNG PHẢI MÃ CK.
 *
 * VÌ SAO 22E1 KHÔNG ĐÓNG ĐƯỢC LỖI NÓ NHẮM TỚI. `overflow-wrap` chỉ chọn CHỖ ngắt cho một dòng đã được
 * phép ngắt — nó không cấp quyền ngắt. `.pf-quota th,.pf-quota td` đặt `white-space:nowrap`, tức cấm ngắt
 * ngay từ đầu; cấm rồi thì không còn chỗ nào để `overflow-wrap` chọn. Ngoại lệ duy nhất đang có là
 * `td:first-child`, mà ô mang mã CK KHÔNG phải ô đầu hàng — ô đầu là `<th>Nội dung chuyển khoản</th>`.
 * Nên luật trên là mã chết kể từ lúc được viết ra, và bài kiểm của 22E1 báo PASS vì nó đo sai phạm vi.
 *
 * THỦ PHẠM LỚN HƠN LÀ ĐOẠN VĂN. Ô ấy còn chứa một câu chú thích dài ("Giữ nguyên nội dung này. Ngân hàng
 * có thể thêm chữ của họ…"). Dưới `nowrap`, CẢ CÂU nằm trên một dòng duy nhất và tự nó kéo bảng ra
 * ~747px — rộng gấp nhiều lần 18 ký tự của mã. Chỉ nới cho `<b data-bt>` thì bảng vẫn tràn y như cũ, và
 * đó là lý do bản sửa này nhắm hai thứ chứ không một.
 *
 * `nowrap` của `.pf-quota` sinh ra để giữ GIÁ TRỊ NGẮN (ngày, số tiền, trạng thái) khỏi bị bẻ đôi giữa
 * chừng. Nó chưa bao giờ có nghĩa cho văn xuôi, cũng không cho một mã dài hơn khung. Hai ngoại lệ dưới
 * đây trả quyền xuống dòng cho đúng hai thứ đó và không đụng tới ô nào khác.
 *
 * PHẠM VI LÀ CẢ BẢNG, VÀ ĐO MỚI CHO THẤY VÌ SAO. Bản sửa đầu của khối này chỉ nới cho `<b data-bt>` và
 * `<p>`; đo lại ở 360px thì bảng co từ 747px xuống 382px nhưng VẪN tràn khung 298px, và mã CK vẫn khuất
 * đúng 12px. Lý do: `th` "Nội dung chuyển khoản" cũng `nowrap` và một mình nó đòi 172px, còn cột giá trị
 * đòi 210px vì "Ngân hàng TMCP Quân Đội (MB)" và tên chủ tài khoản cũng là VĂN XUÔI bị cấm ngắt. Nới cho
 * hai phần tử mà bỏ sót bốn ô còn lại thì bảng vẫn không lọt.
 *
 * `.pf-bt` CHỨ KHÔNG PHẢI `.pf-quota` TRẦN. `.pf-quota` còn phục vụ các bảng Hóa đơn / Thanh toán / Đăng
 * ký, nơi mỗi hàng là một BẢN GHI và `nowrap` đang giữ ngày, số tiền, trạng thái nằm gọn một dòng — nới
 * chỗ đó là đổi bố cục bốn trang không ai yêu cầu. Bảng chuyển khoản khác hẳn về thể loại: nó là bảng
 * NHÃN–GIÁ TRỊ đọc dọc, hai cột, mỗi ô một câu. Một lớp riêng nói đúng sự khác biệt ấy và không với tới
 * các bảng kia.
 *
 * Số tiền là ngoại lệ ngược: nó NGẮN và phải đọc liền một mạch, nên nó giữ `nowrap` để không bị tách
 * "1.200.000" khỏi "₫". */
.pf-quota.pf-bt th,.pf-quota.pf-bt td{white-space:normal}
.pf-quota.pf-bt [data-bt="amount"]{white-space:nowrap}

@media (max-width:560px){
  /* Giữ khối này để các luật hẹp phía dưới (nếu có) vẫn có chỗ đứng. */
  .pf-keyref td:first-child{word-break:break-word}
}

/* =========================================================================================================
 * 09D — LỰA CHỌN QUYẾT ĐỊNH ĐỐI SOÁT
 * ========================================================================================================= */

/* Mỗi lựa chọn là một THẺ có hai dòng: tên quyết định, và câu nói ĐIỀU GÌ KHÔNG XẢY RA khi chọn nó.
 * Dòng thứ hai quan trọng ngang dòng thứ nhất — nó là thứ ngăn người đối soát tưởng mình đang ra lệnh cho
 * hệ thống — nên nó được cho chỗ đứng riêng chứ không nhét vào một `title` mà không ai rê chuột vào. */
.pf-choices{display:grid;gap:8px;grid-template-columns:1fr}
@media (min-width:720px){ .pf-choices{grid-template-columns:1fr 1fr} }
.pf-choice{display:grid;grid-template-columns:auto 1fr;gap:2px 10px;align-items:start;
  border:1px solid var(--pf-line);border-radius:var(--pf-r-sm);padding:10px 12px;cursor:pointer;
  background:var(--pf-card);margin:0;text-transform:none;letter-spacing:0}
.pf-choice:hover{border-color:var(--pf-review-line);background:var(--pf-review-bg)}
.pf-choice input{grid-row:1 / span 2;align-self:center;margin:0}
.pf-choice-t{font-size:13px;font-weight:600;color:var(--pf-ink)}
.pf-choice-d{font-size:12px;line-height:1.5;color:var(--pf-muted)}
/* Lựa chọn đang chọn phải NHÌN THẤY được: một nhóm radio không có phản hồi thị giác là một nhóm mà người
 * dùng phải nheo mắt tìm chấm nào đang đậm. */
.pf-choice:has(input:checked){border-color:var(--pf-review);background:var(--pf-review-bg)}
.pf-choice:has(input:checked) .pf-choice-t{color:var(--pf-review)}

/* =========================================================================================================
 * 11B-3 — FORM MUA HÀNG: SẢN PHẨM, CHU KỲ, GIÁ SNAPSHOT, TỔNG TIỀN
 * ========================================================================================================= */

/* `.pf-form` gốc chỉ tạo kiểu cho `input`, nên `select` của form mua hàng sẽ thừa hưởng kiểu mặc định của
 * trình duyệt và cao thấp lệch hẳn so với ô kề bên. Kéo `select` và `textarea` vào cùng luật. */
.pf-form select,.pf-form textarea{border:1px solid var(--pf-line);border-radius:var(--pf-r-sm);
  padding:8px 10px;font:inherit;font-size:13px;color:var(--pf-ink);background:var(--pf-card);width:100%;
  box-sizing:border-box}
.pf-form select:focus{outline:2px solid var(--pf-brand-100);border-color:var(--pf-brand)}

/* Form mua hàng rộng hơn form một cột thường: nó có hai nhóm sản phẩm và một dòng tổng tiền. Nhưng bề rộng
 * là TRẦN chứ không phải sàn — ở 375px nó co lại theo khung, không đẩy trang trượt ngang. */
#ck-form{max-width:520px}

/* GÓI và TIỆN ÍCH là HAI NHÓM TÁCH BẠCH, không phải một danh sách phẳng. Từ 11B-3 add-on mua riêng được,
 * nên gộp chung một khối sẽ nói sai rằng phải chọn gói trước. */
.ck-group{border:1px solid var(--pf-line);border-radius:var(--pf-r-sm);padding:12px 14px 14px;
  margin:16px 0 0;min-width:0}
.ck-group legend{font-size:11px;font-weight:600;color:var(--pf-muted);text-transform:uppercase;
  letter-spacing:.04em;padding:0 6px}
.ck-group > label:first-of-type{margin-top:0}

/* Mỗi add-on là một hàng: tên bên trái, giá bên phải. `min-width:0` trên phần tên là thứ giữ cho một tên
 * dài co lại thay vì đẩy giá tràn khỏi khung ở màn hình hẹp. */
.ck-addon{display:flex;align-items:center;gap:8px;margin:8px 0 0;text-transform:none;letter-spacing:0;
  font-size:13px;color:var(--pf-ink)}
.ck-addon input{width:auto;flex:none;margin:0}
.ck-addon-name{flex:1 1 auto;min-width:0;overflow-wrap:anywhere}
.ck-addon-price{flex:none;font-variant-numeric:tabular-nums;color:var(--pf-muted);font-size:12px}
.ck-line{margin:10px 0 0;font-size:12px}

/* Tổng tiền là con số người dùng quyết định dựa trên nó, nên nó được đứng riêng chứ không lẫn vào chú thích. */
.ck-total{margin:16px 0 0;padding-top:12px;border-top:1px solid var(--pf-line);font-size:13px;
  color:var(--pf-muted);display:flex;justify-content:space-between;gap:10px;flex-wrap:wrap}
.ck-total b{font-size:16px;color:var(--pf-ink);font-variant-numeric:tabular-nums}

/* Hóa đơn: mỗi hóa đơn là một THẺ có nhóm dòng, không phải một hàng bảng phẳng. */
.pf-inv{border:1px solid var(--pf-line);border-radius:var(--pf-r-sm);background:var(--pf-card);
  padding:12px 14px;margin:0 0 12px}
.pf-inv-h{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;
  margin-bottom:10px}
.pf-inv-g{margin:10px 0 0;min-width:0}
.pf-inv-g h3{font-size:11px;font-weight:600;color:var(--pf-muted);text-transform:uppercase;
  letter-spacing:.04em;margin:0 0 6px}
/* Bảng dòng hóa đơn cuộn ngang TRONG `.pf-inv-g`. Một thời tôi cho CẢ `.pf-inv-g` LẪN `table` cùng
 * `overflow-x:auto` — hai khung cuộn lồng nhau, và cái lồng trong khiến trang trượt ngang 5px ở 375px.
 * Một khung cuộn là đủ; hai khung là một cái thừa và là cái gây lỗi. */
.pf-inv-g table{width:100%}
.pf-inv-f{display:flex;gap:12px;flex-wrap:wrap;justify-content:space-between;margin-top:12px;
  padding-top:10px;border-top:1px solid var(--pf-line);font-size:12px;color:var(--pf-muted)}
.pf-inv-total b{font-size:14px;color:var(--pf-ink);font-variant-numeric:tabular-nums}
/* TÊN RIÊNG, KHÔNG MƯỢN `.pf-badge`.
 *
 * `.pf-badge` ĐÃ TỒN TẠI ở đầu tệp này với nghĩa khác hẳn: một bong bóng đếm thông báo, `position:absolute;
 * top:-5px; right:-5px`. Dùng lại tên đó cho chip trạng thái hóa đơn thì `position` và `right` của nó vẫn
 * áp — và chip bị đẩy ra ngoài thẻ đúng 5px, khiến trang trượt ngang ở 375px. Ghi đè từng thuộc tính sẽ
 * chữa triệu chứng; đổi tên mới là bỏ hẳn vụ va chạm. */
.pf-status{display:inline-block;font-size:11px;font-weight:600;padding:3px 9px;border-radius:999px;
  border:1px solid var(--pf-line);color:var(--pf-muted);background:var(--pf-line-2);white-space:nowrap}
.pf-status-paid{color:#0a6b3d;background:#e6f6ed;border-color:#a9dcc1}
.pf-status-pending{color:#8a5a00;background:#fdf3e0;border-color:#efd6a3}
.pf-status-failed,.pf-status-void,.pf-status-expired{color:#8a1c1c;background:#fdeaea;border-color:#f0b9b9}

/* 375px: thẻ hóa đơn không được đẩy trang trượt ngang. `.pf-inv` có viền + đệm, nên bề rộng của nó phải
 * TÍNH CẢ hai thứ đó — nếu không 375px nội dung + 2×14px đệm + 2px viền = 405px và trang tràn. */
.pf-inv,.ck-group{box-sizing:border-box;max-width:100%}
.pf-wrap{min-width:0}

/* =========================================================================================================
 * `.pf-quota` — BẢNG DỮ LIỆU CỦA KHU VỰC THANH TOÁN KHÁCH HÀNG
 * =========================================================================================================
 *
 * Class này được dùng từ 11A trên trang Hóa đơn, Thanh toán và Đăng ký, nhưng KHÔNG được định nghĩa ở bất
 * kỳ stylesheet nào — nên tới trước 11B-3 mọi bảng ấy render bằng kiểu mặc định của trình duyệt. Không bài
 * curl nào thấy được (curl không dựng layout); phép đo bắt được nó là `scrollWidth > clientWidth` ở 375px
 * trên Chrome thật. Cùng loại defect mà 08A từng gặp: một trang không có style, im lặng.
 */
.pf-quota{width:100%;border-collapse:collapse;font-size:13px;color:var(--pf-ink)}
.pf-quota th,.pf-quota td{padding:7px 10px;text-align:left;border-bottom:1px solid var(--pf-line);
  white-space:nowrap}
.pf-quota th{font-size:11px;font-weight:600;color:var(--pf-muted);text-transform:uppercase;
  letter-spacing:.04em;background:var(--pf-line-2)}
.pf-quota td:first-child{white-space:normal;overflow-wrap:anywhere}
.pf-quota tr:last-child td{border-bottom:0}
/* Bảng rộng hơn khung thì CUỘN TRONG KHUNG CỦA NÓ, không đẩy cả trang trượt ngang. */
.pf-scroll,.pf-inv-g{overflow-x:auto;max-width:100%}

/* Header/footer của thẻ hóa đơn: KHÔNG dùng `space-between` cho hai phần tử không co được.
 *
 * `space-between` đẩy phần tử cuối ra sát mép phải; khi tổng bề rộng vừa đúng chạm giới hạn, huy hiệu trạng
 * thái thò ra ngoài thẻ thay vì xuống dòng — đo được ở 375px là `scrollWidth` 380 so với `clientWidth` 375.
 * Cho số hóa đơn co giãn và huy hiệu giữ nguyên kích thước thì bố cục tự đúng ở mọi bề rộng. */
.pf-inv-h,.pf-inv-f{justify-content:flex-start;gap:6px 10px}
.pf-inv-h > b{flex:1 1 auto;min-width:0;overflow-wrap:anywhere}
.pf-inv-h > .pf-status{flex:0 0 auto;max-width:100%}
.pf-inv-f > span{flex:0 1 auto;min-width:0}
.pf-inv-f > .pf-inv-total{margin-left:auto}

/* 19B — ảnh QR chuyển khoản. Giới hạn theo khung để ở 375px nó không đẩy trang trượt ngang. */
.bt-qr{max-width:100%;height:auto;display:block;border:1px solid var(--pf-line);border-radius:var(--pf-r-sm)}

/* =============================================================================================
   CHOTSALE-SAAS-SIGNUP-LOGIN-HUMAN-UX-21A — trang công khai: đăng ký, hoàn tất, đăng ký tư vấn.
   =============================================================================================

   KHÔNG GIAN TÊN RIÊNG `.su-*`. Đã đo trước khi thêm: 0 tên `su-` tồn tại trong portal.css và cc.css.
   Đây là bài học `.pf-badge` của 11B-3 — một tên trùng với một quy tắc `position:absolute` đã có ở nơi
   khác sẽ sửa lại bố cục của trang này theo cách không ai đọc CSS ra được.

   THIẾT KẾ CHO MÀN HÌNH HẸP TRƯỚC. Phần lớn người bán hàng mở link từ điện thoại: mặc định là MỘT CỘT, và
   `.su-grid` chỉ tách hai cột từ 640px trở lên. Làm ngược lại (hai cột rồi gấp xuống) là cách sinh ra một
   trang tràn ngang trên điện thoại mà máy bàn không bao giờ thấy.
   ============================================================================================= */

/* 22A — PHÔNG ĐẶT Ở ĐÂY, VÀ ĐÂY LÀ MỘT LỖI THẬT ĐÃ ĐO ĐƯỢC.
   `portal.css` chỉ có MỘT luật đặt phông cho `<body>`: `body.pf{…font-family:var(--pf-font)…}`. Các trang
   công khai và billing phát `<body class="su-body">` / `<body class="pf-public">` — không phải `pf` — nên
   luật đó KHÔNG BAO GIỜ khớp và `font-family` rơi về mặc định của trình duyệt, tức một phông có chân.
   Đo trong Chrome thật trước khi sửa: `getComputedStyle(document.body).fontFamily` = `"Times New Roman"`
   trên `/pricing`, `/signup` và `/tu-van`.
   Vá ở GỐC: mọi trang mang `.su-body` — signup, pricing, tư vấn, và toàn bộ billing — khỏi cùng một lúc. */
body.su-body { margin: 0; background: #f4f6fb; color: #1b2333;
  font-family: var(--pf-font); font-size: 15px; line-height: 1.5;
  -webkit-font-smoothing: antialiased; }
.su-wrap { max-width: 720px; margin: 0 auto; padding: 32px 16px 56px; }
.su-card { background: #fff; border: 1px solid #e3e8f2; border-radius: 16px;
  box-shadow: 0 10px 30px rgba(20,32,64,.07); padding: 28px 24px; }

.su-top { text-align: center; margin-bottom: 20px; }
.su-brand { display: inline-flex; align-items: center; gap: 10px; text-decoration: none;
  color: inherit; margin-bottom: 14px; }
.su-logo { border-radius: 8px; display: block; }
.su-brandname { font-weight: 800; font-size: 19px; letter-spacing: .4px; }
.su-dot { color: #e8492f; }

.su-h1 { font-size: 26px; line-height: 1.25; margin: 6px 0 8px; }
.su-lede { color: #5a6479; margin: 0; font-size: 15px; }
/* 22B — gói khách đã chọn từ bảng giá. Nhãn trạng thái, không phải nút: không có gì để bấm ở đây. */
.su-choice { display: inline-block; margin: 0 0 10px; padding: 5px 12px; border-radius: 999px;
  background: #eef3ff; color: #1f4fc4; font-size: 14px; }

.su-alert { background: #fdecea; border: 1px solid #f5c2bb; color: #93261a;
  border-radius: 10px; padding: 10px 12px; margin: 0 0 16px; font-size: 14px; }

.su-form { margin: 0; }
.su-group { border: 0; padding: 0; margin: 0 0 4px; }
.su-group legend { font-weight: 700; font-size: 13px; text-transform: uppercase;
  letter-spacing: .6px; color: #7b8496; padding: 0; margin-bottom: 10px; }

/* Một cột trên điện thoại; hai cột khi có chỗ. */
.su-grid { display: grid; grid-template-columns: 1fr; gap: 0 14px; }
@media (min-width: 640px) { .su-grid { grid-template-columns: 1fr 1fr; } }

.su-f { margin: 0 0 14px; display: flex; flex-direction: column; }
.su-f label { font-size: 14px; font-weight: 600; margin-bottom: 6px; }
.su-req { color: #e8492f; margin-left: 3px; }
.su-f input, .su-f textarea { font: inherit; font-size: 15px; padding: 11px 12px;
  border: 1px solid #d3daea; border-radius: 10px; background: #fff; color: inherit;
  width: 100%; box-sizing: border-box; }
.su-f input:focus, .su-f textarea:focus { outline: 2px solid #2f6df6; outline-offset: 1px;
  border-color: #2f6df6; }
.su-f textarea { resize: vertical; }
.su-bad input, .su-bad textarea { border-color: #e8492f; }
.su-hint { font-size: 12.5px; color: #7b8496; margin-top: 5px; }
.su-err { color: #c0392b; font-size: 13px; margin: 5px 0 0; }

.su-more { border: 1px solid #e3e8f2; border-radius: 12px; padding: 0; margin: 4px 0 18px;
  background: #fafbfe; }
.su-more > summary { cursor: pointer; padding: 13px 14px; font-weight: 600; font-size: 14.5px;
  list-style: revert; }
.su-opt { color: #7b8496; font-weight: 400; }
.su-morebody { padding: 4px 14px 2px; border-top: 1px solid #e9edf6; }
.su-note { font-size: 13.5px; color: #5a6479; margin: 12px 0 14px; }

.su-btn { display: block; width: 100%; box-sizing: border-box; font: inherit; font-size: 16px;
  font-weight: 700; padding: 13px 18px; border: 0; border-radius: 10px; cursor: pointer;
  background: #e8492f; color: #fff; text-align: center; text-decoration: none; }
.su-btn:hover { background: #cf3a22; }
.su-btn-a { display: inline-block; width: auto; min-width: 220px; }

.su-alt { text-align: center; font-size: 14.5px; color: #5a6479; margin: 16px 0 0; }
.su-foot { text-align: center; font-size: 14px; color: #6b7386; margin: 18px 0 0; }

.su-done { text-align: center; }
.su-tick { width: 54px; height: 54px; line-height: 54px; border-radius: 50%; margin: 4px auto 6px;
  background: #e6f6ec; color: #17864a; font-size: 27px; font-weight: 700; }
.su-steps { text-align: left; margin: 20px auto 24px; max-width: 420px; padding-left: 22px;
  color: #3b445a; font-size: 15px; line-height: 1.75; }

/* ---------------------------------------------------------------------------------------------
   21A2 — COMBOBOX "Ngành hàng" / "Gói quan tâm".

   Danh sách định vị TUYỆT ĐỐI so với `.su-f` (đã `position: relative`), nên nó NỔI LÊN TRÊN thay vì
   đẩy các ô bên dưới xuống. Một danh sách đẩy layout sẽ làm nút "Tạo tài khoản" nhảy đi ngay lúc
   người dùng định bấm — và trên điện thoại thì đẩy luôn trang dài thêm 300px.

   `.su-combo-list` khi chưa nâng cấp bằng JS vẫn mang thuộc tính `hidden` của HTML, nên không cần
   một luật CSS nào để giấu nó: không có JavaScript thì không có danh sách, và ô vẫn là một trường
   văn bản dùng được.
   --------------------------------------------------------------------------------------------- */
.su-combo { position: relative; }
.su-combo-box { position: relative; display: block; }
.su-combo-box input { padding-right: 40px; }

.su-combo-arrow { position: absolute; right: 1px; top: 1px; bottom: 1px; width: 36px;
  display: flex; align-items: center; justify-content: center; font-size: 13px;
  background: transparent; border: 0; border-radius: 0 10px 10px 0; cursor: pointer;
  color: #5a6479; padding: 0; }
.su-combo-arrow:hover { color: #1b2333; background: #eef2fb; }
.su-combo-arrow:focus-visible { outline: 2px solid #2f6df6; outline-offset: -2px; }
.su-combo-open .su-combo-arrow > span { transform: rotate(180deg); display: block; }

.su-combo-list { position: absolute; z-index: 30; left: 0; right: 0; top: 100%; margin: 4px 0 0;
  padding: 4px; list-style: none; max-height: 240px; overflow-y: auto;
  background: #fff; border: 1px solid #d3daea; border-radius: 10px;
  box-shadow: 0 12px 28px rgba(20,32,64,.14); }
.su-combo-list li { padding: 9px 11px; border-radius: 7px; cursor: pointer; font-size: 15px; }
.su-combo-list li[aria-selected="true"] { font-weight: 700; }
.su-combo-list li.su-combo-active { background: #eef2fb; }

/* =============================================================================================
   CHOTSALE-PRICING-HUMAN-UI-21B — trang bảng giá công khai.
   =============================================================================================

   VÌ SAO KHÔNG DÙNG LẠI `.pf-plan*`: những lớp đó KHÔNG TỒN TẠI. Trang giá cũ tham chiếu
   `.pf-plans`, `.pf-plan`, `.pf-price`, `.pf-per`, `.pf-limits`, `.btn-primary`, `.note`,
   `.pf-public` — đo được 0 luật cho cả tám, trong cả `portal.css` lẫn `cc.css`. Stylesheet tải
   200 và không có gì để áp; đó là toàn bộ lý do trang trông như HTML thô, và vì sao Network
   hoàn toàn sạch. Đặt tên mới `.pr-*` (đã đo: 0 trùng) thay vì "sửa" những lớp chưa từng có.

   NỀN VÀ THẺ DÙNG CHUNG BIẾN VỚI `/signup` (`.su-body` vẫn là lớp của `<body>`), nên hai trang
   không trôi khỏi nhau mỗi lần một bên được sửa.

   MỘT CỘT TRƯỚC. Lưới chỉ tách cột từ 640px, rồi 1024px. Làm ngược lại là cách sinh ra một
   trang tràn ngang trên điện thoại mà máy bàn không bao giờ thấy.
   ============================================================================================= */

.pr-wrap { max-width: 1160px; margin: 0 auto; padding: 36px 16px 64px; }

.pr-top { text-align: center; margin-bottom: 30px; }
.pr-h1 { font-size: 32px; line-height: 1.2; margin: 10px 0 10px; }
.pr-lede { color: #5a6479; margin: 0 auto; font-size: 16px; max-width: 520px; }

.pr-section { margin: 0 0 40px; }
.pr-h2 { font-size: 22px; margin: 0 0 4px; }
.pr-sub { color: #5a6479; font-size: 14.5px; margin: 0 0 18px; }
.pr-addons { border-top: 1px solid #e3e8f2; padding-top: 30px; }

.pr-grid { display: grid; grid-template-columns: 1fr; gap: 18px; align-items: stretch; }
@media (min-width: 640px) { .pr-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) {
  .pr-grid { grid-template-columns: repeat(3, 1fr); }
  /* Bốn gói trên một hàng khi có đủ chỗ; hai gói kéo dài hết chiều ngang trông rỗng. */
  .pr-grid.pr-n4 { grid-template-columns: repeat(4, 1fr); }
  .pr-grid.pr-n2 { grid-template-columns: repeat(2, 1fr); max-width: 720px; margin: 0 auto; }
  .pr-grid.pr-n1 { grid-template-columns: 1fr; max-width: 380px; margin: 0 auto; }
}

.pr-card { position: relative; display: flex; flex-direction: column;
  background: #fff; border: 1px solid #e3e8f2; border-radius: 16px; padding: 24px 20px 20px;
  box-shadow: 0 8px 24px rgba(20,32,64,.06); }
.pr-card-badged { border-color: #e8492f; box-shadow: 0 12px 30px rgba(232,73,47,.13); }
.pr-badge { position: absolute; top: -11px; left: 20px; background: #e8492f; color: #fff;
  font-size: 12px; font-weight: 700; letter-spacing: .3px; padding: 4px 10px; border-radius: 999px; }

.pr-name { font-size: 20px; margin: 0 0 6px; }
.pr-desc { color: #5a6479; font-size: 14px; margin: 0 0 14px; }

.pr-price { margin: 10px 0 4px; display: flex; flex-wrap: wrap; align-items: baseline; gap: 7px; }
.pr-amount { font-size: 30px; font-weight: 800; letter-spacing: -.5px; }
.pr-tbd { font-size: 22px; }
.pr-per { color: #7b8496; font-size: 14px; }
.pr-trial { color: #17864a; font-size: 13.5px; font-weight: 600; margin: 2px 0 0; }

.pr-cycles { list-style: none; margin: 12px 0 0; padding: 10px 0 0; border-top: 1px dashed #e3e8f2;
  font-size: 14px; }
.pr-cycles li { display: flex; justify-content: space-between; gap: 12px; padding: 3px 0; }
.pr-cyc { color: #5a6479; }

.pr-limits { list-style: none; margin: 16px 0 18px; padding: 0; font-size: 14.5px; }
.pr-limits li { display: flex; justify-content: space-between; gap: 12px;
  padding: 7px 0; border-bottom: 1px solid #f1f4fa; }
.pr-limits li:last-child { border-bottom: 0; }
.pr-lk { color: #4a5368; }
.pr-lv { font-weight: 700; white-space: nowrap; }

/* `margin-top: auto` đẩy CTA xuống đáy thẻ, nên các nút thẳng hàng dù quyền lợi dài ngắn khác nhau. */
.pr-cta { margin: auto 0 0; padding-top: 16px; }
.pr-btn { display: block; box-sizing: border-box; width: 100%; text-align: center;
  font: inherit; font-size: 15.5px; font-weight: 700; padding: 12px 16px;
  border: 1px solid #d3daea; border-radius: 10px; background: #fff; color: #1b2333;
  text-decoration: none; cursor: pointer; }
.pr-btn:hover { border-color: #b9c3db; background: #f7f9fe; }
.pr-btn-primary { background: #e8492f; border-color: #e8492f; color: #fff; }
.pr-btn-primary:hover { background: #cf3a22; border-color: #cf3a22; color: #fff; }
.pr-btn:focus-visible { outline: 2px solid #2f6df6; outline-offset: 2px; }

.pr-empty { background: #fff; border: 1px solid #e3e8f2; border-radius: 16px;
  padding: 28px 22px; text-align: center; }
.pr-note { color: #5a6479; font-size: 14.5px; margin: 8px 0 0; }
.pr-foot { text-align: center; color: #6b7386; font-size: 14.5px; margin: 8px 0 0; }

/* =============================================================================================
   CHOTSALE-CUSTOMER-BILLING-UX-22A — khu vực gói & thanh toán của KHÁCH.

   Không gian tên `.bl-*` (đã đo: 0 trùng). Dùng CHUNG nền/phông/màu chữ với `/signup` và
   `/pricing` qua lớp `.su-body` — không chép lại giá trị màu, mà dùng chung một luật; đó là
   nghĩa thực của "cùng design system".

   MỘT CỘT TRƯỚC: lưới chỉ tách cột từ 720px. Trang này có bảng tiền, và bảng là thứ dễ đẩy
   trang tràn ngang nhất trên màn 375px — nên mỗi bảng nằm trong hộp cuộn riêng của nó thay vì
   kéo giãn cả trang.
   ============================================================================================= */

.bl-wrap { max-width: 980px; margin: 0 auto; padding: 24px 16px 56px; }

.bl-top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 18px; }
.bl-back { font-size: 14px; color: #5a6479; text-decoration: none; }
.bl-back:hover { color: #1b2333; text-decoration: underline; }

.bl-tabs { display: flex; flex-wrap: wrap; gap: 6px; border-bottom: 1px solid #e3e8f2;
  padding-bottom: 10px; margin-bottom: 20px; }
.bl-tab { font-size: 14.5px; font-weight: 600; padding: 8px 13px; border-radius: 9px;
  color: #4a5368; text-decoration: none; }
.bl-tab:hover { background: #eef2fb; color: #1b2333; }
.bl-tab-on { background: #1b2333; color: #fff; }
.bl-tab-on:hover { background: #1b2333; color: #fff; }

.bl-h1 { font-size: 26px; margin: 0 0 18px; }
.bl-h2 { font-size: 19px; margin: 0 0 4px; }
.bl-h3 { font-size: 15.5px; margin: 0 0 6px; }
.bl-sub { color: #5a6479; font-size: 14.5px; margin: 0 0 16px; }
.bl-hint { color: #5a6479; font-size: 14px; margin: 6px 0 0; }

.bl-card { background: #fff; border: 1px solid #e3e8f2; border-radius: 16px;
  box-shadow: 0 8px 24px rgba(20,32,64,.06); padding: 22px 20px; margin: 0 0 20px; }

.bl-planhead { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 2px; }

/* Chip trạng thái. `review` có màu RIÊNG — tiền đã vào, hóa đơn chưa đóng; tô như thất bại là
   mời người trực đi đòi khách trả lần nữa (bài học 09C). */
.bl-chip { display: inline-block; font-size: 12.5px; font-weight: 700; padding: 4px 11px;
  border-radius: 999px; white-space: nowrap; }
.bl-chip-ok { background: #dcfce7; color: #15803d; }
.bl-chip-warn { background: #fef3c7; color: #92400e; }
.bl-chip-no { background: #fee2e2; color: #b91c1c; }
.bl-chip-off { background: #f1f5f9; color: #475569; }
.bl-chip-review { background: #ede9fe; color: #6d28d9; }

.bl-facts { display: grid; grid-template-columns: 1fr; gap: 0; margin: 16px 0 0; }
@media (min-width: 720px) { .bl-facts { grid-template-columns: 1fr 1fr; gap: 0 24px; } }
.bl-facts > div { display: flex; justify-content: space-between; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid #f1f4fa; }
.bl-facts dt { color: #4a5368; font-size: 14.5px; margin: 0; }
.bl-facts dd { margin: 0; font-weight: 700; font-size: 14.5px; text-align: right; }

.bl-money { margin: 16px 0 0; padding: 12px 14px; background: #fafbfe;
  border: 1px solid #e9edf6; border-radius: 10px; font-size: 14.5px; }

/* 22E1-B — KHỐI TRẠNG THÁI GÓI KHI NGƯỜI ĐÃ ĐĂNG NHẬP BẤM MỘT GÓI TRÊN BẢNG GIÁ.
   Dòng hạn dùng là thứ người đọc tới đây để tìm, nên nó to hơn chữ thường và KHÔNG xám:
   một dòng ngày tháng màu xám đọc như chú thích, trong khi nó là câu trả lời. */
.bl-status { border-color: #d7dfef; }
.bl-st-when { font-size: 16px; font-weight: 700; color: #1b2333; margin: 12px 0 0;
  /* Ngày tháng và dấu `·` phải xuống dòng được: "Còn 12 ngày · Hết hạn ngày 01/10/2026" dài hơn
     một màn 320px, và một dòng không ngắt được sẽ kéo ngang cả trang. */
  overflow-wrap: anywhere; }

.bl-upsell { margin: 18px 0 0; }
.bl-ulist { list-style: none; margin: 0; padding: 0; }
.bl-ulist li { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline;
  gap: 4px 12px; padding: 9px 0; border-bottom: 1px solid #f1f4fa; font-size: 14.5px; }
.bl-uk { font-weight: 600; }
.bl-uv { color: #4a5368; white-space: nowrap; }

.bl-owned { margin: 18px 0 0; }
.bl-alist { list-style: none; margin: 0; padding: 0; }
.bl-alist li { display: flex; justify-content: space-between; align-items: center; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid #f1f4fa; font-size: 14.5px; }
.bl-ak { font-weight: 600; }

.bl-addons { display: grid; grid-template-columns: 1fr; gap: 14px; }
@media (min-width: 720px) { .bl-addons { grid-template-columns: repeat(2, 1fr); } }
.bl-addon { border: 1px solid #e3e8f2; border-radius: 12px; padding: 16px 15px; background: #fafbfe; }
.bl-adesc { color: #5a6479; font-size: 14px; margin: 0 0 10px; }
.bl-aprice { font-size: 21px; font-weight: 800; margin: 0; }
.bl-per { font-size: 13.5px; font-weight: 400; color: #7b8496; }

.bl-cta { display: flex; flex-wrap: wrap; gap: 10px; margin: 20px 0 0; }
.bl-btn { display: inline-block; box-sizing: border-box; font: inherit; font-size: 15.5px;
  font-weight: 700; padding: 12px 20px; border: 1px solid #d3daea; border-radius: 10px;
  background: #fff; color: #1b2333; text-decoration: none; cursor: pointer; min-height: 46px; }
.bl-btn:hover { border-color: #b9c3db; background: #f7f9fe; }
.bl-btn-primary { background: #e8492f; border-color: #e8492f; color: #fff; }
.bl-btn-primary:hover { background: #cf3a22; border-color: #cf3a22; color: #fff; }
.bl-btn:focus-visible { outline: 2px solid #2f6df6; outline-offset: 2px; }
/* Không phải một nút mờ: một dòng chữ trả lời đúng câu hỏi "vì sao tôi không làm được". */
.bl-denied { display: inline-block; font-size: 14px; color: #7b8496; background: #f5f7fc;
  border: 1px dashed #d3daea; border-radius: 10px; padding: 11px 14px; }

/* Bảng tiền cuộn trong hộp của nó, KHÔNG kéo giãn cả trang — đây là nguyên nhân tràn ngang
   phổ biến nhất trên 375px. */
.bl-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 0 0 4px; }
.bl-table { width: 100%; border-collapse: collapse; font-size: 14.5px; min-width: 520px; }
.bl-table th, .bl-table td { text-align: left; padding: 10px 12px; border-bottom: 1px solid #f1f4fa;
  white-space: nowrap; }
.bl-table th { color: #5a6479; font-size: 13px; text-transform: uppercase; letter-spacing: .4px; }
.bl-table td.bl-num, .bl-table th.bl-num { text-align: right; }
.bl-total { display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  margin: 14px 0 0; padding-top: 14px; border-top: 2px solid #e3e8f2; }
.bl-total .bl-tl { font-size: 15px; color: #4a5368; }
.bl-total .bl-tv { font-size: 24px; font-weight: 800; }
.bl-empty { color: #5a6479; font-size: 14.5px; margin: 0; }

/* ---------------------------------------------------------------------------------------------
   22A — BA LỚP CŨ ĐANG ĐƯỢC DÙNG NHƯNG CHƯA TỪNG CÓ LUẬT.

   `.note` (12 chỗ), `.pf-plan`, `.btn-primary` đo được **0 luật** trong cả `portal.css` lẫn
   `cc.css`, trong khi các trang billing và trang công khai vẫn đang dùng chúng. Định nghĩa ở đây
   thay vì đi sửa 14 chỗ gọi: thêm luật cho một lớp đang có 0 luật thì KHÔNG THỂ đè lên luật nào
   — nó chỉ có thể thêm kiểu dáng, không thể lấy đi.

   `.btn-primary` NEO VÀO `.btn`. Đây đúng là bài học `.pf-danger` của 08B: một lớp bổ nghĩa đứng
   một mình sẽ sơn lại mọi phần tử tình cờ mang tên đó ở nơi khác.
   --------------------------------------------------------------------------------------------- */
.note { color: #5a6479; font-size: 14.5px; line-height: 1.6; margin: 10px 0; }
.pf-plan { background: #fff; border: 1px solid #e3e8f2; border-radius: 14px;
  padding: 18px 18px 14px; margin: 0 0 18px; box-shadow: 0 6px 20px rgba(20,32,64,.05); }
.pf-plan h2 { margin: 0 0 8px; font-size: 19px; }
.btn.btn-primary { background: #e8492f; border-color: #e8492f; color: #fff; }
.btn.btn-primary:hover { background: #cf3a22; border-color: #cf3a22; color: #fff; }
/* Thẻ "gói hiện tại" là khối chính của trang — một vạch màu thương hiệu ở mép trên phân biệt nó
   với các thẻ phụ mà không cần thêm chữ nào. */
.bl-plan { border-top: 3px solid #e8492f; }

/* 22C — mỗi chu kỳ mang bốn con số: nhãn, tổng tiền, quy đổi/tháng, % tiết kiệm. */
.pr-cycles li { align-items: flex-start; }
.pr-cycv { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
.pr-permo { font-size: 12.5px; color: #7b8496; }
.pr-save { font-size: 11.5px; font-weight: 700; color: #15803d; background: #dcfce7;
  border-radius: 999px; padding: 1px 7px; margin-top: 2px; }

/* ───────────────────────────────────────────────────────────────────────────────────────────────────────
   Danh mục khóa entitlement — thu vào <details>.

   VÌ SAO CẦN KHỐI NÀY CHỨ KHÔNG PHẢI CHỈ BỌC THẺ: `.pf-card>h2` và `.pf-card>.pf-b` là bộ chọn CON TRỰC
   TIẾP. Bọc chúng vào `<details>` biến cả hai thành CHÁU, nên cả hai luật ngừng áp dụng và thẻ mất sạch
   viền, đệm, cỡ chữ — im lặng, không lỗi nào báo. Ba luật dưới đây khôi phục đúng các giá trị ấy cho
   trường hợp lồng, giữ nguyên bản gốc cho mọi thẻ khác.
   ─────────────────────────────────────────────────────────────────────────────────────────────────────── */
.pf-card>.pf-keyref-d>summary{cursor:pointer;padding:14px 18px;font-size:13px;font-weight:700;
  /* `list-style:revert` giữ lại tam giác mở/đóng của trình duyệt. Không dùng `display:flex` ở đây:
     Chrome bỏ marker khi summary là flex, và lúc đó không còn dấu hiệu nào cho biết khối mở được. */
  list-style:revert}
.pf-card>.pf-keyref-d[open]>summary{border-bottom:1px solid var(--pf-line-2)}
/* `h2` nằm TRONG summary: để block thì nó đẩy nhãn đếm xuống dòng và tách khỏi tam giác. */
.pf-card>.pf-keyref-d>summary>h2{display:inline;margin:0;padding:0;border:0;font-size:13px;font-weight:700}
.pf-card>.pf-keyref-d>summary>.muted{margin-left:10px;font-weight:400}
.pf-card>.pf-keyref-d>.pf-b{padding:18px}

/* TẠM TẮT 2FA — băng cảnh báo. Cố ý KHÓ bỏ qua: rủi ro thật của một cờ tạm không phải lúc bật nó, mà là
   ngày không ai còn nhớ nó đang bật. Ghim đáy màn hình để không che thanh điều hướng trên. */
.pf-mfa-off{position:fixed;left:0;right:0;bottom:0;z-index:9999;padding:10px 16px;
  background:#7f1d1d;color:#fff;font-size:13px;line-height:1.45;text-align:center;
  box-shadow:0 -2px 12px rgba(0,0,0,.25)}
.pf-mfa-off code{background:rgba(255,255,255,.18);padding:1px 6px;border-radius:5px}

/* Cột "Tác vụ" của bảng workspace. Các nút nằm NGANG, cách nhau đủ xa — hai trong ba dẫn tới thao tác
   không tầm thường, và chúng cách nhau vài pixel là cách một cú chạm trượt thành một workspace biến mất. */
.pf-acts{white-space:nowrap}
.pf-acts>a,.pf-acts>form{display:inline-block;margin-right:12px}
.pf-acts>a:last-child,.pf-acts>form:last-child{margin-right:0}
/* "Khôi phục" là một <button> trong <form> (POST), nhưng nó phải ĐỌC như hai liên kết bên cạnh — nếu không
   cùng một cột sẽ có hai ngôn ngữ thị giác cho ba việc cùng loại. */
.pf-act-link{background:none;border:0;padding:0;font:inherit;color:var(--pf-link);cursor:pointer;
  text-decoration:underline}
.pf-act-danger{color:#b91c1c}
.btn.danger{background:#b91c1c;border-color:#b91c1c;color:#fff}

/* ═══════════════════════════════════════════════════════════════════════════════════════════════════════
   FULL-V2 — BỘ THÀNH PHẦN CHUNG CỦA PORTAL.
   Đây là các bộ chọn MỚI, không đè luật nào — nên nối ở cuối tệp là an toàn, khác hẳn với việc chồng lại
   một thuộc tính đã khai ở trên (chỗ đó phải sửa tại chỗ).
   Trang con dùng lại CHÍNH các lớp này; đó là cách "cùng phong cách" được bảo đảm bằng cấu trúc chứ không
   bằng việc mỗi trang tự nhớ chép lại màu.
   ═══════════════════════════════════════════════════════════════════════════════════════════════════════ */

/* Đầu trang: tiêu đề + mô tả bên trái, thao tác bên phải. */
.pf-pagehead{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin:0 0 18px}
.pf-pagehead h1{margin:0 0 4px;font-size:22px;line-height:1.25;font-weight:700;color:var(--pf-ink)}
.pf-pagehead p{margin:0;font-size:13.5px;color:var(--pf-muted)}
.pf-pagehead-r{display:flex;align-items:center;gap:12px;flex:0 0 auto}

/* Bốn ô chỉ số lớn. `auto-fit` + `minmax` để nó tự xuống dòng ở màn hẹp mà không cần thêm mốc max-width —
   tệp này đã có quá nhiều mốc, và mỗi mốc mới là một chỗ cho "luật sau đè luật trước". */
.pf-hero{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:14px;margin:0 0 14px}
.pf-hero-c{display:flex;align-items:flex-start;gap:12px;padding:16px;background:var(--pf-card);
  border:1px solid var(--pf-line);border-radius:14px;box-shadow:var(--pf-sh)}
.pf-hero-i{flex:0 0 auto;width:38px;height:38px;border-radius:11px;display:flex;align-items:center;
  justify-content:center;font-size:17px}
.pf-hero-b{min-width:0}
.pf-hero-k{font-size:12.5px;color:var(--pf-muted);margin:0 0 2px}
.pf-hero-v{font-size:26px;line-height:1.1;font-weight:700;color:var(--pf-ink)}
.pf-hero-n{font-size:11.5px;color:var(--pf-muted-2);margin-top:3px}
/* Bốn sắc ô biểu tượng. Màu ở đây KHÔNG mang nghĩa trạng thái — nó chỉ để bốn ô phân biệt được với nhau.
   Màu mang nghĩa (ok/warn/no) nằm ở `.pf-pill`, và trộn hai hệ ấy là cách người dùng đọc "xanh" thành
   "tốt" ở một chỗ vốn chỉ muốn nói "ô thứ nhất". */
.pf-t-indigo{background:var(--pf-brand-050);color:var(--pf-brand)}
.pf-t-green{background:var(--pf-ok-bg);color:var(--pf-ok)}
.pf-t-blue{background:#e0f2fe;color:#0369a1}
.pf-t-amber{background:var(--pf-warn-bg);color:var(--pf-warn)}

/* Dải chỉ số phụ — gọn hơn hero, cùng một hàng. */
.pf-strip{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:0;margin:0 0 14px;
  background:var(--pf-card);border:1px solid var(--pf-line);border-radius:14px;box-shadow:var(--pf-sh);
  overflow:hidden}
.pf-strip-c{display:flex;align-items:center;gap:10px;padding:14px 16px;border-right:1px solid var(--pf-line-2)}
.pf-strip-c:last-child{border-right:0}
.pf-strip-i{flex:0 0 auto;width:28px;height:28px;border-radius:8px;display:flex;align-items:center;
  justify-content:center;font-size:13px;background:var(--pf-off-bg);color:var(--pf-off)}
.pf-strip-k{font-size:12.5px;color:var(--pf-muted)}
.pf-strip-v{font-size:17px;font-weight:700;color:var(--pf-ink);margin-left:auto}

/* Dải nhắc việc. KHÔNG phải `.pf-state-err`: đây là "có việc cần làm", không phải "hệ thống hỏng", và
   tô nó đỏ sẽ dạy người trực bỏ qua màu đỏ. */
.pf-note{display:flex;align-items:flex-start;gap:12px;padding:14px 16px;margin:0 0 14px;
  background:var(--pf-warn-bg);border:1px solid #fcd34d;border-radius:12px}
.pf-note-i{flex:0 0 auto;font-size:16px;line-height:1.2;color:var(--pf-warn)}
.pf-note-b{min-width:0;flex:1}
.pf-note-t{font-weight:650;font-size:13.5px;color:var(--pf-warn);margin:0 0 2px}
.pf-note-d{font-size:12.5px;color:#78350f;margin:0}
.pf-note a{flex:0 0 auto;font-size:13px;font-weight:600;color:var(--pf-warn);white-space:nowrap}

/* Hai thẻ cạnh nhau. */
.pf-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:14px}

/* Tình trạng mô-đun: hai cột, mỗi dòng một mô-đun. */
.pf-mods{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:0 28px}
.pf-mods .kv{border-bottom:1px solid var(--pf-line-2)}
.pf-headchips{display:flex;gap:8px;margin-left:auto;font-weight:400}

/* Tiêu đề NHÓM trong trình sửa gói. Trước đây là `muted small` — cùng một kiểu với mọi dòng chú thích
   xám khác trên trang, nên bốn nhóm tính năng không tách ra được khỏi nền chữ. Nay là tiêu đề thật. */
.pf-subhead{display:flex;align-items:baseline;gap:10px;margin:18px 0 8px;font-size:13.5px;font-weight:700;
  color:var(--pf-ink)}
.pf-subhead>span{font-weight:400;font-size:12px;color:var(--pf-muted)}
/* Khoá kỹ thuật dưới mỗi nhãn. VẪN HIỆN — người trực cần nó để đối chiếu với dữ liệu khi có sự cố, và
   "dễ đọc" không có nghĩa là "giấu đi thứ cần để sửa lỗi". Nhưng nó là hàng PHỤ, nên nó phải đọc như
   hàng phụ: nhỏ hơn, nhạt hơn, không tranh chấp với tên tính năng ở hàng trên. */
.pf-entkey{font-size:10.5px;color:var(--pf-muted-2);word-break:break-all}
