/* 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-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;
  --pf-nav:#0f172a; --pf-nav-2:#1e293b; --pf-nav-ink:#cbd5e1; --pf-nav-ink-2:#64748b;
  --pf-font:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --pf-r:10px; --pf-r-sm:6px; --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;
  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-nav-2);color:#fff;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:#fff}
.pf-side a.on{background:var(--pf-brand);color:#fff;font-weight:600}
.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-nav-2);font-size:11px;color:var(--pf-nav-ink-2);
  white-space:nowrap;overflow:hidden}
.pf-who b{display:block;color:#fff;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%}
.pf-title{margin:0 0 4px;font-size:21px;font-weight:700;letter-spacing:-.01em}
.pf-lede{margin:0 0 20px;color:var(--pf-muted);font-size:13px;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:13px;
  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-nav-2)}
.pf-logout button{width:100%;background:0;border:1px solid var(--pf-nav-2);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:#fff}

/* ================================================================= ĐĂ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)}

/* 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}

@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; }
