:root{
  /* Brand palette:
     primary #F2F3EF (light surface) · secondary #0A0D17 (dark surface)
     CTA primary #C13A28 · CTA secondary #131A28 · CTA clicked #902416 */
  --vd:#0A0D17;            /* secondary — sidebar, dark gradient start */
  --vd2:#131A28;           /* CTA secondary — gradient end, secondary CTA button */
  --vg:#C13A28;            /* CTA red — focus rings, accents, active nav */
  --cta-clicked:#902416;   /* CTA red, pressed */
  /* Nút chính dùng đúng màu cam CTA của thương hiệu - cũng là màu mục đang chọn
     trên sidebar. Trước đây nó là xám #8B92A6 để không lẫn với --danger (#C4433A)
     của thao tác xoá, nhưng xám thì chìm hẳn: nút chính không còn nổi hơn nút phụ
     nền trắng là bao. Thao tác xoá trong admin này là nút icon hoặc nút viền đỏ nền
     trắng, chỉ đổi sang nền đỏ đặc khi rê chuột, nên hai màu không đứng cạnh nhau ở
     trạng thái thường. */
  --btn-primary:var(--accent);
  --btn-primary-hover:var(--cta-clicked);
  --accent:#C13A28;        /* was --gold; accents now follow the CTA colour */
  --ink:#161622; --muted:#6B7280; --hint:#9CA3AF;
  /* Neutral (not blue-tinted) borders so they sit correctly on the warm
     #F2F3EF surface — the original blue-grey lines read dingy against it. */
  --line:#E4E5E0; --line-strong:#D7D9D2;
  --surface:#F2F3EF;
  /* Đỏ sẫm hẳn so với cam CTA (#C13A28) của nút chính: hai màu này hay đứng cạnh
     nhau (Lưu / Xóa) nên phải nhìn ra ngay cái nào là thao tác phá huỷ. */
  --danger:#8E1F1A; --danger-soft:#F6E7E7;
  --tag-green:#1C9A6C; --tag-green-soft:#EAF7EF;
  --tag-purple:#131A28; --tag-purple-soft:#E7E9EE;
  --tag-amber:#B7791F; --tag-amber-soft:#FDF3E7;
  --tag-gray:#6B7280; --tag-gray-soft:#EBECE7;
  --sidebar-w:236px;
  --radius:8px; --radius-lg:10px;
  --shadow-card:0 1px 2px 0 rgba(20,20,40,.04),0 2px 8px 0 rgba(20,20,40,.04);
  --shadow-pop:0 20px 60px rgba(0,0,0,.25);
}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:'Inter',sans-serif;color:var(--ink);background:var(--surface);line-height:1.5715;font-size:14px;-webkit-font-smoothing:antialiased}
button{font-family:inherit;cursor:pointer}
input,select,textarea{font-family:inherit;font-size:14px}

.app{display:flex;min-height:100vh}

/* Sidebar */
.sidebar{width:var(--sidebar-w);flex-shrink:0;background:var(--vd);color:#fff;display:flex;flex-direction:column;position:sticky;top:0;height:100vh}
.sb-brand{display:flex;align-items:center;gap:10px;padding:16px 16px 14px;border-bottom:1px solid rgba(255,255,255,.12);text-decoration:none}
.sb-logo{width:100%;height:auto;display:block}
.sb-badge{width:32px;height:32px;border-radius:50%;border:2px solid var(--accent);display:flex;align-items:center;justify-content:center;color:var(--accent);font-size:10px;font-weight:600;flex-shrink:0}
.sb-brand-txt div:first-child{font-size:14px;font-weight:600}
.sb-brand-txt div:last-child{font-size:11px;color:rgba(255,255,255,.55)}
.sb-nav{flex:1;overflow-y:auto;padding:8px}
/* Nhóm menu gập/mở được. Tiêu đề nhóm là nút bấm nên phải tự dựng lại nền, viền,
   font - button không thừa hưởng từ .sidebar. */
.sb-group-head{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;background:none;border:none;font-family:inherit;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:rgba(255,255,255,.35);padding:14px 12px 6px;font-weight:500;cursor:pointer;text-align:left}
.sb-group-head:hover{color:rgba(255,255,255,.7)}
.sb-group-head i{font-size:14px;transition:transform .15s}
.sb-group.collapsed .sb-group-head i{transform:rotate(-90deg)}
.sb-group.collapsed .sb-group-items{display:none}
.sb-group-items{display:flex;flex-direction:column;gap:2px}
.sb-item{display:flex;align-items:center;gap:10px;padding:0 12px;height:40px;border-radius:var(--radius);color:rgba(255,255,255,.75);font-size:14px;cursor:pointer;text-decoration:none;justify-content:space-between;transition:background .15s,color .15s}
.sb-item .lft{display:flex;align-items:center;gap:10px}
.sb-item i{font-size:16px;width:16px;text-align:center;flex-shrink:0}
.sb-item:hover{background:rgba(255,255,255,.08);color:#fff}
.sb-item.active{background:var(--accent);color:#fff;font-weight:600}
.sb-item.active i{color:#fff}
.sb-count{font-size:11px;background:rgba(255,255,255,.15);padding:0 7px;height:18px;line-height:18px;border-radius:9px;min-width:18px;text-align:center}
.sb-item.active .sb-count{background:rgba(0,0,0,.22);color:#fff}

/* Main */
.main{flex:1;min-width:0;display:flex;flex-direction:column}
.topbar{background:#fff;border-bottom:1px solid var(--line);padding:16px 28px;display:flex;align-items:center;gap:14px;flex-wrap:wrap;position:sticky;top:0;z-index:5}
.topbar h1{font-size:20px;font-weight:600;color:var(--ink)}
.topbar .sub{font-size:13px;color:var(--hint);margin-top:2px}
.topbar-actions{margin-left:auto;display:flex;gap:8px;flex-wrap:wrap}
.topbar-user{position:relative;flex-shrink:0}
.avatar-btn{width:38px;height:38px;border-radius:50%;background:var(--vd,#1a2332);color:#fff;border:none;cursor:pointer;font-size:14px;font-weight:600;display:flex;align-items:center;justify-content:center}
.avatar-menu{position:absolute;top:calc(100% + 8px);right:0;background:#fff;border:1px solid var(--line);border-radius:10px;box-shadow:0 8px 24px rgba(0,0,0,.12);min-width:200px;padding:6px;display:none;z-index:20}
.avatar-menu.on{display:block}
.avatar-menu-name{padding:8px 10px;font-size:13px;font-weight:600;color:var(--ink);border-bottom:1px solid var(--line);margin-bottom:4px;word-break:break-all}
.avatar-menu a{display:flex;align-items:center;gap:8px;padding:8px 10px;font-size:13px;color:var(--ink);text-decoration:none;border-radius:6px}
.avatar-menu a:hover{background:#f2f4f7}
/* Đổi ngôn ngữ: nút riêng cạnh avatar, dùng chung cách đổ bóng và khoảng đệm
   với menu tài khoản để hai ô ở góc phải trông như một bộ. */
.topbar-lang{position:relative;flex-shrink:0}
.lang-btn{height:38px;padding:0 11px;border-radius:19px;background:#fff;color:var(--ink);border:1px solid var(--line-strong);cursor:pointer;display:flex;align-items:center;gap:6px;font-size:16px;line-height:1}
.lang-btn:hover,.lang-btn[aria-expanded="true"]{background:#f2f4f7}
.lang-btn-code{font-size:12px;font-weight:600;letter-spacing:.04em}
.lang-menu{position:absolute;top:calc(100% + 8px);right:0;background:#fff;border:1px solid var(--line);border-radius:10px;box-shadow:0 8px 24px rgba(0,0,0,.12);min-width:170px;padding:6px;display:none;z-index:20}
.lang-menu.on{display:block}
.lang-menu a{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 10px;font-size:13px;color:var(--ink);text-decoration:none;border-radius:6px;white-space:nowrap}
.lang-menu a:hover{background:#f2f4f7}
.lang-menu a.on{font-weight:600}
.lang-menu a.on i{color:var(--vd)}

/* Buttons */
.btn{border:1px solid transparent;border-radius:var(--radius);height:32px;padding:0 15px;font-size:14px;font-weight:400;display:inline-flex;align-items:center;gap:6px;transition:color .15s,border-color .15s,background .15s}
.btn-primary{background:var(--btn-primary);border-color:var(--btn-primary);color:#fff}
.btn-primary:hover,.btn-primary:active{background:var(--btn-primary-hover);border-color:var(--btn-primary-hover)}
/* Secondary CTA (was .btn-gold) — the dark #131A28 of the brand palette. */
.btn-gold{background:var(--vd2);border-color:var(--vd2);color:#fff}
.btn-gold:hover{background:var(--vd);border-color:var(--vd)}
.btn-ghost{background:#fff;color:var(--ink);border:1px solid var(--line-strong)}
.btn-ghost:hover{border-color:#C3C5BD}
/* Ô nhập tiền: đơn vị bám sát bên phải ngay trong ô, không phải một dòng chữ rời bên
   dưới. Số tiền không có đơn vị đứng cạnh là số dễ đọc nhầm một chữ số. */
.fld-money{position:relative}
/* Ba lớp chọn (.fld .fld-money + [type=text]) là CỐ Ý, không phải viết thừa.

   Luật chung của ô nhập là `.fld input[type=text]{padding:8px 11px}` - độ đặc hiệu
   (0,2,1). Bản cũ ở đây viết `.fld-money input` chỉ (0,1,1) nên nó THUA, padding-right
   rơi về 11px trong khi chữ VNĐ ngồi ở right:11px: placeholder căn phải chạy thẳng vào
   dưới chữ VNĐ, đọc ra một đống chồng nhau. Đo trên trình duyệt bên giaidau:
   padding-right thực tế là 11px chứ không phải 52px như luật này tưởng.

   Không sửa bằng cách chuyển luật xuống dưới: hai luật cùng độ đặc hiệu thì thứ tự
   quyết định, và lần sắp xếp lại file sau là lỗi quay về. Ba lớp chọn thắng ở mọi
   thứ tự. */
.fld .fld-money input[type=text]{padding-right:52px;text-align:right}
.fld-money .money-unit{position:absolute;right:11px;top:50%;transform:translateY(-50%);
  font-size:13px;color:var(--muted);pointer-events:none}

/* Nút đã KHOÁ. Không có luật này thì .btn-ghost khoá trông y hệt .btn-ghost bấm được -
   cùng nền trắng, cùng viền, cùng màu chữ - còn .btn-primary khoá thì vẫn đỏ rực như
   đang mời bấm. Người dùng chỉ biết nó khoá sau khi bấm mà không thấy gì xảy ra.
   Đặt ở .btn nên áp cho mọi biến thể; :disabled (0,2,0) thắng .btn-primary (0,1,0),
   và bản :hover (0,3,0) thắng .btn-primary:hover (0,2,0) nên hover cũng không đổi màu. */
.btn:disabled,.btn[disabled]{background:var(--surface);border-color:var(--line);color:var(--hint);cursor:not-allowed}
.btn:disabled:hover,.btn[disabled]:hover{background:var(--surface);border-color:var(--line);color:var(--hint)}
.btn-danger-outline{background:#fff;color:var(--danger);border:1px solid var(--line-strong)}
.btn-danger-outline:hover{color:#fff;background:var(--danger);border-color:var(--danger)}
.btn-icon{background:none;border:1px solid transparent;color:var(--hint);width:28px;height:28px;border-radius:var(--radius);font-size:14px;display:inline-flex;align-items:center;justify-content:center}
.btn-icon:hover{background:rgba(0,0,0,.04);color:var(--ink)}
/* Action icon buttons. Plain .btn-icon is --hint grey with no border, which
   reads as decoration next to a status chip; these carry a real state change
   so they get a border, a solid colour and a slightly larger glyph. */
.btn-icon-action{width:30px;height:30px;font-size:16px;border-color:var(--line-strong);background:#fff;color:var(--ink)}
.btn-icon-action:hover{background:#F6F7F3;border-color:#C3C5BD;color:var(--ink)}
.btn-icon-action:focus-visible{outline:2px solid var(--vg);outline-offset:1px}
.btn-icon-success{border-color:var(--tag-green);background:var(--tag-green);color:#fff}
.btn-icon-success:hover{background:#17805A;border-color:#17805A;color:#fff}

/* Tooltip — hover/focus hint for icon-only controls. Rendered above the
   control so it stays inside .tbl-wrap's overflow:hidden when used in a table row. */
.tip{position:relative}
.tip::after,.tip::before{opacity:0;visibility:hidden;transition:opacity .12s;pointer-events:none;z-index:30}
.tip::after{content:attr(data-tip);position:absolute;bottom:calc(100% + 6px);left:50%;transform:translateX(-50%);background:var(--vd);color:#fff;font-size:12px;font-weight:400;line-height:1.4;padding:4px 8px;border-radius:6px;white-space:nowrap;box-shadow:var(--shadow-card)}
.tip::before{content:"";position:absolute;bottom:calc(100% + 1px);left:50%;transform:translateX(-50%);border:5px solid transparent;border-top-color:var(--vd)}
.tip:hover::after,.tip:hover::before,.tip:focus-visible::after,.tip:focus-visible::before{opacity:1;visibility:visible}
/* Tooltip cho câu mô tả dài. .tip mặc định là nowrap - đúng cho nhãn nút vài chữ,
   nhưng một đoạn mô tả sẽ thành một dòng dài hơn cả màn hình và tràn ra ngoài. */
.tip-wide::after{white-space:normal;width:300px;text-align:left;font-size:12.5px}

/* Ở màn hẹp, tooltip ĐANG ẨN cũng phải ra khỏi bố cục.

   visibility:hidden vẫn giữ nguyên hộp 300px của .tip-wide, và một hộp tuyệt đối thì
   cộng vào bề rộng CUỘN của trang. Đo bên giaidau ở 375px: một dấu chấm gợi ý gần mép
   phải kéo trang rộng ra 612px - tức là cả trang cuộn ngang được, đúng thứ .tbl-wrap
   và mọi chỗ khác đã cẩn thận tránh.

   Lúc ĐANG hiện thì neo theo màn hình: bong bóng rộng căn giữa một dấu chấm nằm lệch
   phải thì luôn thò ra ngoài, mà CSS thuần không biết dấu chấm đang ở đâu.
   position:fixed cắt luôn bài toán - hộp cố định không cộng vào bề rộng cuộn, và neo
   hai mép thì nó vừa màn ở mọi vị trí. Máy bàn không đổi gì. */
@media (max-width:760px){
  .tip::after,.tip::before{display:none}
  .tip:hover::after,.tip:focus-visible::after{display:block}
  /* Mũi tên nhỏ chỉ về dấu chấm KHÔNG hiện trên màn hẹp: bong bóng nay neo theo màn
     hình chứ không theo dấu chấm, nên mũi tên sẽ chỉ vào một chỗ trống. */
  .tip:hover::before,.tip:focus-visible::before{display:none}
  .tip::after{position:fixed;left:12px;right:12px;top:auto;bottom:auto;width:auto;
    transform:none;white-space:normal;max-width:none}
}
/* Dấu chấm hỏi đứng cạnh tiêu đề, thay cho đoạn mô tả in thẳng dưới tiêu đề.
   <button> chứ không phải <span>: có tooltip thì phải tới được bằng bàn phím. */
.hint-dot{display:inline-flex;align-items:center;justify-content:center;width:17px;height:17px;
  margin-left:6px;padding:0;vertical-align:middle;border:1px solid var(--line-strong);border-radius:50%;
  background:var(--surface);color:var(--hint);font-size:11px;line-height:1;cursor:help;flex:0 0 auto}
.hint-dot:hover{color:var(--ink);border-color:var(--muted)}
.hint-dot i{font-size:12px}
/* Tooltip của .hint-dot mở SANG PHẢI từ chính dấu chấm, không canh giữa.
   Dấu chấm luôn đứng ngay sau một tiêu đề hay nhãn, tức nằm sát mép trái của thẻ;
   canh giữa thì một tooltip rộng 300px thò 150px ra ngoài mép trái màn hình. */
.hint-dot::after{left:0;right:auto;transform:none}
.hint-dot::before{left:4px;transform:none}

/* Nội dung DÙNG HẾT bề ngang màn hình. Trước đây khối này bị kẹp ở 800px và các màn
   có bảng nhiều cột phải tự khai .content.is-wide để nới lên 1280px. Thực tế màn
   backoffice nào cũng là bảng nhiều cột hoặc form nhiều ô, nên cái kẹp đó chỉ tạo ra
   hai dải trắng hai bên và ép bảng phải cuộn ngang trong khi màn hình còn thừa chỗ.

   Bề rộng dễ đọc của TỪNG khối vẫn giữ ở chính khối đó - .lede-hint kẹp 62ch, đoạn
   mô tả trong .dash-hero kẹp 520px - nên bỏ kẹp ở đây không làm dòng chữ dài ra.
   .content.is-wide đã bỏ; khai nó cũng không còn tác dụng gì. */
.content{padding:24px 28px 60px;width:100%}
/* Hai cột cho các thẻ xếp chồng. Cột hẹp lại nên nhìn hết một màn không phải cuộn,
   và minmax(0,1fr) là bắt buộc: 1fr thôi thì một bảng rộng trong cột sẽ đẩy cả lưới
   rộng ra thay vì tự cuộn trong ô của nó. */
.col-2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px;align-items:start}
/* Thẻ cần cả bề ngang: bảng nhiều cột, sơ đồ nhánh. */
.col-2 > .col-span{grid-column:1 / -1}
@media(max-width:1100px){.col-2{grid-template-columns:minmax(0,1fr)}}
.toolbar{display:flex;gap:10px;align-items:center;margin-bottom:16px;flex-wrap:wrap}
.search{display:flex;align-items:center;gap:7px;background:#fff;border:1px solid var(--line-strong);border-radius:var(--radius);padding:0 11px;height:32px;min-width:220px;flex:1;max-width:320px;transition:border-color .15s,box-shadow .15s}
.search:focus-within{border-color:var(--vg);box-shadow:0 0 0 2px rgba(193,58,40,.14)}
.search input{border:none;outline:none;font-size:14px;width:100%;background:transparent}
.search i{color:var(--hint)}
.count-pill{font-size:13px;color:var(--hint)}

/* Table */
.tbl-wrap{background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);overflow:hidden;overflow-x:auto}
table{width:100%;border-collapse:collapse}
th{font-size:12.5px;color:var(--muted);text-align:left;padding:12px 20px;border-bottom:1px solid var(--line);background:#fff;font-weight:600}
td{padding:14px 20px;border-bottom:1px solid var(--line);font-size:13.5px;vertical-align:middle}
tr:last-child td{border-bottom:none}
tbody tr{transition:background .15s}
tbody tr:hover{background:#FAFAF7}
td.actions{text-align:right;white-space:nowrap}

/* Tags */
.badge{font-size:12px;font-weight:500;padding:3px 10px;border-radius:100px;background:var(--tag-purple-soft);color:var(--tag-purple);white-space:nowrap;display:inline-block}
.status{font-size:11px;font-weight:600;padding:3px 9px;border-radius:100px;white-space:nowrap;display:inline-block}
.status.green{background:var(--tag-green-soft);color:var(--tag-green)}
.status.gold{background:var(--tag-amber-soft);color:var(--tag-amber)}
.status.gray{background:var(--tag-gray-soft);color:var(--tag-gray)}
.status.blue{background:var(--tag-purple-soft);color:var(--tag-purple)}
.status.red{background:var(--danger-soft);color:var(--danger)}
.featured-flag{color:var(--accent)}
.cell-muted{color:var(--hint)}
.empty{padding:56px 20px;text-align:center;color:var(--hint)}
.empty i{font-size:32px;color:rgba(0,0,0,.15);display:block;margin-bottom:10px}
.empty b{color:var(--muted);display:block;margin-bottom:4px;font-size:14px;font-weight:500}

/* Cards (dashboard) */
.dash-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:16px;margin-bottom:24px}
.dash-card{background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);padding:18px;cursor:pointer;transition:box-shadow .15s,border-color .15s}
.dash-card:hover{box-shadow:var(--shadow-card);border-color:var(--line-strong)}
.dash-card .n{font-size:26px;font-weight:600;color:var(--ink);line-height:1.3}
.dash-card .l{font-size:13px;color:var(--hint);margin-top:4px;display:flex;align-items:center;gap:6px}
.dash-card i{color:var(--accent)}
.dash-hero{background:linear-gradient(135deg,var(--vd),var(--vd2));color:#fff;border-radius:var(--radius-lg);padding:24px 26px;margin-bottom:24px;display:flex;align-items:center;gap:18px;flex-wrap:wrap}
.dash-hero h2{font-size:20px;font-weight:600}
.dash-hero p{font-size:13px;color:rgba(255,255,255,.75);margin-top:6px;max-width:520px}

/* Form */
.form-card{background:#fff;border:1px solid var(--line-strong);border-radius:var(--radius-lg);padding:24px}
.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px 20px}
.form-grid.full{grid-template-columns:1fr}
.fld{margin-bottom:2px}
.fld.span2{grid-column:1/3}
.fld label{font-size:12.5px;color:var(--ink);margin-bottom:6px;display:block;font-weight:600}
.fld input[type=text],.fld input[type=number],.fld input[type=date],.fld input[type=password],.fld input[type=email],.fld input[type=datetime-local],.fld input[type=time],.fld input[type=file],.fld select,.fld textarea{
  width:100%;border:1px solid var(--line-strong);border-radius:7px;padding:8px 11px;font-size:13.5px;color:var(--ink);background:#fff;outline:none;transition:border-color .15s,box-shadow .15s;
}
.fld select{appearance:none;-webkit-appearance:none;padding-right:32px;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%236B7280' stroke-width='1.5' fill='none'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 12px center;
}
.fld input:focus,.fld select:focus,.fld textarea:focus{border-color:var(--vg);box-shadow:0 0 0 2px rgba(193,58,40,.14)}
.fld textarea{resize:vertical;min-height:80px}
.fld input:disabled,.fld select:disabled,.fld textarea:disabled{background:var(--surface);color:var(--hint);cursor:not-allowed}
.fld .fld-hint{font-size:11.5px;color:var(--hint);margin-top:5px}
/* Lỗi của từng ô: chữ đỏ ngay dưới ô, nhãn đỏ theo và ô sai đổi viền/nền.
   public/js/field-errors.js gắn vào từ danh sách lỗi server trả về. */
.fld-error{display:flex;gap:6px;align-items:flex-start;font-size:11.5px;font-weight:500;color:var(--danger);margin-top:5px}
.fld-error i{font-size:13px;line-height:1.3;flex:none}
.fld.has-error > label{color:var(--danger)}
.fld.has-error .checkbox-row label{color:var(--danger)}
/* Viết theo từng thẻ chứ không dùng !important: cùng độ ưu tiên với luật .fld
   input[type=text] ở trên, mà nằm sau nên thắng. */
.is-invalid,.fld input.is-invalid,.fld select.is-invalid,.fld textarea.is-invalid{
  border-color:var(--danger);background-color:var(--danger-soft);
}
.fld input.is-invalid:focus,.fld select.is-invalid:focus,.fld textarea.is-invalid:focus{
  border-color:var(--danger);box-shadow:0 0 0 2px rgba(142,31,26,.16);
}
.fld .view-value{font-size:13.5px;color:var(--ink);padding:9px 0;min-height:20px}
tr.row-hidden{opacity:.5}
.gd-prev{font-family:'Be Vietnam Pro',sans-serif;border:1px solid var(--line);border-radius:10px;overflow:hidden;margin:-24px;width:calc(100% + 48px)}
.gd-prev .gd-note{background:#FBEEEC;color:#902416;font-size:11.5px;padding:7px 22px;border-bottom:1px solid #EFC7BF}
.gd-prev .gd-band{background:#C8102E;padding:20px 22px}
.gd-prev .gd-crumb{font-size:11px;color:#F5D6D8}
.gd-prev .gd-org{display:flex;align-items:center;gap:10px;margin-top:12px}
.gd-prev .gd-org-ic{width:30px;height:30px;border-radius:8px;background:#fff;display:flex;align-items:center;justify-content:center;flex-shrink:0;color:#7A1F17}
.gd-prev .gd-org-lbl{color:#F5D6D8;font-size:11.5px}
.gd-prev .gd-org-name{color:#fff;font-size:12.5px;font-weight:500;margin-top:1px}
.gd-status{font-size:10.5px;font-weight:500;padding:2px 8px;border-radius:4px;background:#fff;color:#7A1F17;display:inline-block;margin-top:12px}
.gd-prev .gd-title{color:#fff;font-size:19px;font-weight:600;margin-top:9px}
.gd-prev .gd-meta{color:#F5D6D8;font-size:12px;margin-top:5px}
.gd-prev .gd-tabs{padding:0 22px;border-bottom:1px solid var(--line);display:flex;gap:20px}
.gd-tab{font-size:12.5px;color:var(--hint);padding:11px 0;border-bottom:2px solid transparent;cursor:pointer}
.gd-tab.on{color:#7A1F17;font-weight:600;border-bottom-color:#C8102E}
.gd-prev .gd-body{padding:20px 22px}
.gd-h{font-size:14px;font-weight:600;color:#7A1F17;margin:0 0 10px}
.gd-cta-row{display:flex;flex-wrap:wrap;align-items:center;gap:12px;border:1px solid var(--line);border-radius:10px;padding:12px 14px;margin-bottom:18px;background:var(--surface)}
.gd-cta-info{flex:1;min-width:180px;font-size:12px;color:var(--hint);line-height:1.8}
.gd-cta-info b{color:#7A1F17}
.gd-btn{display:inline-block;background:#fff;border:1px solid #7A1F17;color:#7A1F17;font-size:12.5px;font-weight:500;padding:8px 16px;border-radius:6px;white-space:nowrap}
.gd-tbl{width:100%;border-collapse:collapse;margin-bottom:20px}
.gd-tbl th{font-size:10px;text-transform:uppercase;color:var(--hint);text-align:left;padding:8px 10px;border-bottom:1px solid var(--line)}
.gd-tbl td{padding:8px 10px;border-bottom:1px solid var(--line);font-size:12.5px;color:var(--ink)}
.gd-rules{border:1px solid var(--line);border-radius:8px;padding:14px 16px}
.gd-li{font-size:12.5px;color:#444;line-height:1.6;padding-left:16px;position:relative;margin-top:6px}
.gd-li:before{content:'';position:absolute;left:2px;top:7px;width:5px;height:5px;border-radius:50%;background:#C8102E}
.gd-prev .gd-tabpanel{display:none}
.gd-prev .gd-tabpanel.on{display:block}
.gd-row{display:flex;align-items:center;gap:10px;border:1px solid var(--line);border-radius:8px;padding:10px 12px;margin-top:8px}
.gd-row:first-child{margin-top:0}
.gd-row.live{border-color:#C8102E;background:#FFF5F5}
.gd-row.pending{opacity:.6}
.gd-mbadge{font-size:10.5px;font-weight:600;padding:3px 8px;border-radius:20px;min-width:44px;text-align:center;flex-shrink:0}
.gd-mbadge.kt{background:#F1F1EE;color:#8A968F}
.gd-mbadge.live{background:#FDECEC;color:#9E2A2B}
.gd-mbadge.soon{background:#F4F1E8;color:#902416}
.gd-match{flex:1;display:flex;justify-content:space-between;align-items:center;gap:10px;flex-wrap:wrap}
.gd-match b{font-size:13px;color:#7A1F17}
.gd-match .score{font-size:14px;font-weight:700;color:#7A1F17}
.gd-match .opp{font-size:13px;color:var(--muted)}
.gd-pods{display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;margin-bottom:18px}
.gd-pod{flex:1;min-width:110px;background:#fff;border:1px solid var(--line);border-radius:10px;padding:14px 8px;text-align:center}
.gd-pod .av{width:46px;height:46px;border-radius:50%;background:var(--surface);display:flex;align-items:center;justify-content:center;margin:8px auto;color:var(--hint)}
.gd-pod .nm{font-size:12.5px;font-weight:500;color:var(--ink);margin-top:2px}
/* Tournament bracket engine (SE/DE/RR/Swiss) */
.tbk-ctl{display:flex;gap:10px;align-items:center;flex-wrap:wrap;background:#fff;border:1px solid var(--line);border-radius:var(--radius-lg);padding:11px 14px;margin-bottom:14px}
.tbk-badge{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.4px;padding:4px 10px;border-radius:99px}
.tbk-badge.sim{color:var(--accent);border:1px solid #EFC7BF;background:#FBEEEC}
.tbk-badge.op{color:var(--tag-green);border:1px solid #BFE6D2;background:var(--tag-green-soft)}
.tbk-wrap{position:relative;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-lg);overflow:hidden;height:560px}
.tbk-view{position:absolute;inset:0;overflow:hidden;cursor:grab}
.tbk-view.drag{cursor:grabbing}
.tbk-stage{position:absolute;top:0;left:0;transform-origin:0 0}
.tbk-conn{position:absolute;top:0;left:0;pointer-events:none;overflow:visible}
.tbk-rlabel{position:absolute;font-size:11px;font-weight:700;color:var(--hint);text-transform:uppercase;letter-spacing:.5px;white-space:nowrap}
.tbk-m{position:absolute;width:188px;background:#fff;border:1px solid var(--line-strong);border-radius:9px;overflow:hidden;cursor:pointer;box-shadow:var(--shadow-card);transition:border-color .12s}
.tbk-m:hover{border-color:var(--vd)}
.tbk-m.ready{border-color:var(--vd)}
.tbk-m .br{display:flex;align-items:center;gap:7px;padding:6px 9px;height:30px}
.tbk-m .br+.br{border-top:1px solid var(--line)}
.tbk-m .sd{font-size:9.5px;color:var(--hint);font-weight:700;width:16px;flex:none}
.tbk-m .pn{font-size:12.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;color:var(--ink)}
.tbk-m .sc{font-variant-numeric:tabular-nums;font-weight:800;font-size:13px;color:var(--hint);width:18px;text-align:center;flex:none}
.tbk-m .br.w .pn{color:var(--accent)}.tbk-m .br.w .sc{color:var(--accent)}
.tbk-m .br.bye .pn{color:var(--hint);font-style:italic}
.tbk-m.gf{border-color:var(--accent)}
.tbk-zoom{position:absolute;right:12px;bottom:12px;display:flex;gap:6px;z-index:5}
.tbk-zoom button{padding:8px 11px;background:#ffffffe6;border:1px solid var(--line-strong);color:var(--ink);font-size:14px;backdrop-filter:blur(4px);border-radius:8px}
.tbk-label{position:absolute;left:12px;top:12px;font-size:11.5px;color:var(--muted);background:#ffffffcc;border:1px solid var(--line);padding:5px 10px;border-radius:8px;z-index:5}
.tbk-champ{color:var(--accent);font-weight:700}
.tbk-modline{display:flex;align-items:center;gap:10px;padding:9px 0}
.tbk-modline .pn{flex:1;font-weight:600;font-size:14.5px}
.tbk-modline input{width:64px;text-align:center}
.tbk-fix{display:flex;align-items:center;gap:9px;padding:9px 12px;border-radius:9px;background:var(--surface);margin:6px 0;flex-wrap:wrap;border:1px solid var(--line)}
.tbk-fix .pn{flex:1;min-width:90px;font-weight:600;font-size:13.5px;color:var(--ink)}
.tbk-fix .pn.r{text-align:right}
.tbk-fix .pn.w{color:var(--vd)}.tbk-fix .pn.l{color:var(--hint)}
.tbk-fix input{width:48px;text-align:center;padding:7px 4px;border:1px solid var(--line-strong);border-radius:6px}
.tbk-fix .vs{color:var(--hint);font-weight:700;font-size:12px}
.tbk-rrtab{display:flex;gap:6px;flex-wrap:wrap;padding:12px 16px;border-bottom:1px solid var(--line)}
.tbk-rrtab button{background:var(--surface);color:var(--muted);border:1px solid var(--line);font-size:12.5px;padding:6px 11px;border-radius:99px}
.tbk-rrtab button.on{background:var(--vd);color:#fff;border-color:transparent}
.tbk-row{display:grid;grid-template-columns:26px 1fr 90px 56px auto;align-items:center;gap:7px;padding:8px 10px;border-radius:10px;margin:3px 0;background:var(--surface)}
.tbk-row.dead{opacity:.45;filter:grayscale(.4)}
.tbk-row .rk{font-weight:700;color:var(--hint);font-size:13px;text-align:center}
.tbk-row .who{display:flex;align-items:center;gap:8px;min-width:0}
.tbk-row .nm{font-weight:600;font-size:13.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--ink)}
.tbk-grp{font-size:10.5px;font-weight:700;padding:2px 7px;border-radius:99px;white-space:nowrap;text-align:center}
.tbk-wl{font-variant-numeric:tabular-nums;font-weight:700;font-size:13px;color:var(--muted);text-align:center}
.tbk-wl b{color:var(--ink)}
.tbk-lives{display:flex;gap:3px;justify-content:flex-end;flex-wrap:wrap}
.tbk-ball{width:12px;height:12px;border-radius:50%;background:radial-gradient(circle at 32% 30%,#e08574,var(--accent) 60%,#7a1e12)}
.tbk-ball.gone{background:var(--line-strong);opacity:.7}
.tbk-deadtag{font-size:10px;font-weight:700;color:var(--danger);text-align:right}
.tbk-res{font-variant-numeric:tabular-nums;font-weight:800;font-size:15px;background:var(--surface);border:1px solid var(--line);padding:4px 10px;border-radius:8px}
.tbk-winner{color:var(--vd)}.tbk-loser{color:var(--hint)}
.tbk-champbar{background:linear-gradient(90deg,#FBEEEC,#E7E9EE);border:1px solid var(--accent);border-radius:10px;padding:11px 13px;margin:10px 0;display:flex;align-items:center;gap:10px;font-weight:700;color:var(--ink)}
.tbk-byebadge{font-size:11px;font-weight:700;color:var(--tag-green);border:1px solid #BFE6D2;background:var(--tag-green-soft);padding:3px 9px;border-radius:99px}
.tbk-logtools{display:flex;gap:10px;align-items:center;flex-wrap:wrap;padding:12px 16px;border-bottom:1px solid var(--line)}
.tbk-logtools input{flex:1;min-width:150px}
.tbk-logtable{max-height:280px;overflow:auto}
.tbk-lg{display:grid;grid-template-columns:70px 46px 1fr;gap:10px;align-items:center;padding:8px 16px;border-bottom:1px solid var(--line);font-size:13px}
.tbk-lg .t{color:var(--hint);font-size:11px}
.tbk-lg .rr{font-size:11px;font-weight:700;color:var(--muted);background:var(--surface);border:1px solid var(--line);padding:2px 7px;border-radius:7px;text-align:center}
.tbk-grid2{display:grid;grid-template-columns:1fr 340px;gap:14px;align-items:start}
@media(max-width:980px){.tbk-grid2{grid-template-columns:1fr}}
.news-editor{max-width:100%}
.ne-title-wrap{border-bottom:1px solid var(--line);padding-bottom:10px}
.news-editor-title{width:100%;border:none;outline:none;background:none;font-size:24px;font-weight:600;color:var(--ink);font-family:inherit;padding:4px 0}
.news-editor-title::placeholder{color:var(--hint);font-weight:500}
.rte-lg .rte-body{min-height:420px;max-height:600px}
/* Ô nội dung bài viết dùng Quill (xem resources/views/admin/news/form.blade.php),
   nên phần soạn thảo là .ql-editor chứ không phải .rte-body của khung soạn cũ. */
/* `.rte.rte-lg` chứ không phải `.rte-lg`: luật `.rte .ql-editor{min-height:140px}`
   phía dưới cùng hạng ưu tiên mà đứng sau, nên nó thắng và ô soạn dài chưa bao giờ
   cao 420px như ý ở đây. Đo được 140px trên trình duyệt trước khi sửa. */
.rte.rte-lg .ql-editor{min-height:420px;max-height:600px}
.ne-banner{width:100%;height:220px;border-radius:10px;overflow:hidden;background:var(--surface);border:1px dashed var(--line-strong);display:flex;align-items:center;justify-content:center;cursor:pointer}
.ne-banner img{width:100%;height:100%;object-fit:cover;display:block}
.ne-banner-empty{display:flex;flex-direction:column;align-items:center;gap:6px;color:var(--hint);font-size:13px}
.ne-banner-empty i{font-size:26px}
.checkbox-row{display:flex;align-items:center;gap:10px;margin-top:6px}
.checkbox-row label{font-size:13.5px;color:var(--ink)}
/* Nhãn của .fld là block, đậm và có margin-bottom - trong hàng ô tick thì
   những thứ đó đẩy chữ lệch khỏi ô vuông. */
.fld .checkbox-row label{margin-bottom:0;font-weight:500;line-height:1.3}
.req{color:var(--danger)}

/* Chip (multi-select toggle) */
.chiplist{display:flex;flex-wrap:wrap;gap:8px}
.chip{font-size:12.5px;font-weight:500;padding:7px 14px;border-radius:100px;border:1px solid var(--line-strong);background:#fff;cursor:pointer;color:var(--muted);white-space:nowrap;transition:background .15s,color .15s,border-color .15s;user-select:none}
.chip:hover{border-color:#C3C5BD}
.chip.on{background:var(--vg);border-color:var(--vg);color:#fff}

/* Switch (toggle) */
.switch{width:36px;height:20px;border-radius:100px;background:#D7D9D2;position:relative;cursor:pointer;display:inline-block;flex-shrink:0;transition:background .15s}
.switch.on{background:var(--vg)}
.switch::after{content:'';position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#fff;transition:left .15s}
.switch.on::after{left:18px}
/* Công tắc của một dòng không bật được (ví dụ ghim trang chủ khi bài chưa đăng):
   vẫn thấy trạng thái nhưng không mời bấm. */
.switch.is-locked{opacity:.45;cursor:not-allowed}

/* Card */
.card{background:#fff;border:1px solid var(--line-strong);border-radius:var(--radius-lg)}
.card-head{display:flex;align-items:flex-start;justify-content:space-between;padding:18px 20px;border-bottom:1px solid var(--line)}
.card-head h2{font-size:15px;font-weight:600;margin:0 0 3px;color:var(--ink)}
.card-head .desc{font-size:12.5px;color:var(--muted)}
.card-body.padded{padding:20px}

/* Section builder (list + detail) */
.sec-builder{display:flex;gap:20px;align-items:flex-start}
.sec-list-card{width:300px;flex-shrink:0;position:sticky;top:88px}
.sec-detail-card{flex:1;min-width:0}
.sec-list{padding:8px}
.sec-row{display:flex;align-items:center;gap:10px;padding:10px 10px;border-radius:8px;cursor:pointer;transition:background .15s}
.sec-row:hover{background:#FAFAF7}
.sec-row.selected{background:var(--tag-purple-soft)}
.sec-row-order{display:flex;flex-direction:column;gap:0}
.sec-row-order .btn-icon{width:22px;height:16px;font-size:11px}
.sec-row-label{flex:1;font-size:13.5px;font-weight:500;color:var(--ink);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sec-row.selected .sec-row-label{color:var(--vg);font-weight:600}
.sec-detail-group{padding:20px;border-bottom:1px solid var(--line)}
.sec-detail-group:last-of-type{border-bottom:none}
.sec-detail-group-label{font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--hint);margin-bottom:14px}
.sec-detail-actions{padding:16px 20px;border-top:1px solid var(--line);display:flex;justify-content:flex-end;gap:8px}
.sec-status-tag{font-size:11px;font-weight:600;padding:2px 9px;border-radius:100px}
.sec-status-tag.on{background:var(--tag-green-soft);color:var(--tag-green)}
.sec-status-tag.off{background:var(--tag-gray-soft);color:var(--tag-gray)}
.sec-type-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.sec-type-card{display:flex;align-items:flex-start;gap:11px;border:1.5px solid var(--line-strong);border-radius:var(--radius-lg);padding:13px;cursor:pointer;transition:border-color .15s,background .15s}
.sec-type-card:hover{border-color:var(--vg)}
.sec-type-card.on{border-color:var(--vg);background:var(--tag-purple-soft)}
.sec-type-card i{font-size:19px;color:var(--vg);flex-shrink:0;margin-top:1px}
.sec-type-title{font-size:13.5px;font-weight:600;color:var(--ink)}
.sec-type-desc{font-size:11.5px;color:var(--muted);margin-top:2px;line-height:1.4}
@media(max-width:520px){ .sec-type-grid{grid-template-columns:1fr} }
@media(max-width:960px){
  .sec-builder{flex-direction:column}
  .sec-list-card{width:100%;position:static}
}

/* Modal */
.modal-overlay{position:fixed;inset:0;background:rgba(20,20,35,.45);display:none;align-items:center;justify-content:center;z-index:100;padding:20px}
.modal-overlay.on{display:flex}
.modal{background:#fff;border-radius:12px;max-width:560px;width:100%;max-height:88vh;display:flex;flex-direction:column;overflow:hidden;box-shadow:var(--shadow-pop)}
.modal.wide{max-width:760px}
.rte{border:1px solid var(--line-strong);border-radius:var(--radius);overflow:hidden;transition:border-color .15s,box-shadow .15s}
.rte:focus-within{border-color:var(--vg);box-shadow:0 0 0 2px rgba(193,58,40,.14)}
.rte-toolbar{display:flex;gap:2px;padding:5px;border-bottom:1px solid var(--line);background:#fafafa;flex-wrap:wrap}
.rte-toolbar button{width:28px;height:28px;border:none;background:transparent;border-radius:4px;color:var(--muted);display:inline-flex;align-items:center;justify-content:center;font-size:14px}
.rte-toolbar button:hover{background:#fff;color:var(--vg)}
.rte-toolbar .sep{width:1px;background:var(--line-strong);margin:3px 2px}
.rte-body{min-height:140px;max-height:340px;overflow-y:auto;padding:10px 12px;font-size:14px;line-height:1.6;outline:none}
.rte-body:empty:before{content:attr(data-placeholder);color:var(--hint)}
.rte-body ul,.rte-body ol{padding-left:20px;margin:6px 0}
.rte-body p{margin:0 0 8px}
.modal-hd{padding:16px 24px;border-bottom:1px solid var(--line);display:flex;align-items:center;justify-content:space-between}
.modal-hd h3{font-size:16px;font-weight:600;color:var(--ink)}
.modal-close{background:none;border:none;font-size:16px;color:var(--hint);cursor:pointer;padding:4px;border-radius:4px}
.modal-close:hover{color:var(--ink);background:rgba(0,0,0,.04)}
/* Phần lớn modal bọc ba khối con trong một <form>, nên con trực tiếp DUY NHẤT của
   .modal là cái form đó - mọi thuộc tính flex đặt lên .modal-body đều vô tác dụng vì
   nó là CHÁU chứ không phải con. Thiếu dòng này thì form cứ dài theo nội dung, chân
   modal trôi ra ngoài khung và overflow:hidden của .modal cắt mất nút bấm: danh sách
   dài là mất luôn nút xác nhận. Đo thật trên Chromium 1280x620: thân modal cao 676px
   trong một modal cao 546px, nút nằm ở y=771.

   min-height:0 cũng bắt buộc, không phải trang trí: một flex item mặc định
   min-height:auto nên nó KHÔNG co xuống dưới chiều cao nội dung. */
.modal > form{display:flex;flex-direction:column;min-height:0;flex:1 1 auto}
.modal-hd{flex-shrink:0}
.modal-body{padding:24px;overflow-y:auto;flex:1 1 auto;min-height:0}
.modal-ft{padding:12px 24px;border-top:1px solid var(--line);display:flex;justify-content:space-between;gap:8px;flex-shrink:0}

/* Bộ chọn nhiều dòng trong hộp thoại (thêm cơ thủ vào giải): danh sách cuộn
   trong khung cố định để hộp thoại không dài ra theo số kết quả. */
.pick-toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:14px 0 8px}
.pick-toolbar .checkbox-row span{font-size:13px;color:var(--ink)}
.pick-list{border:1px solid var(--line-strong);border-radius:var(--radius);max-height:320px;overflow-y:auto;background:#fff}
.pick-row{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:10px;padding:9px 12px;border-bottom:1px solid var(--line);cursor:pointer;font-size:13.5px}
.pick-row:last-child{border-bottom:none}
.pick-row:hover{background:#FAFAF7}
.pick-name{color:var(--ink)}
.pick-empty{padding:16px;text-align:center;font-size:13px;color:var(--hint)}

/* Danh sách đã chọn của bộ chọn "chọn rồi bấm Thêm" trong form (trọng tài, địa
   điểm, hạng đấu). */
.pick-chosen{display:flex;flex-direction:column;gap:6px;margin-top:8px}
.pick-chosen-row{display:flex;align-items:center;gap:8px;padding:5px 6px 5px 11px;border:1px solid var(--line-strong);border-radius:var(--radius);background:#fff;font-size:13.5px}
.pick-chosen-row span{flex:1;word-break:break-word}

/* Khung soạn thảo có định dạng (Quill) cho thể lệ & mô tả giải thưởng. */
.rte{background:#fff}
.rte .ql-editor{min-height:140px;font-size:13.5px;color:var(--ink)}
.ql-toolbar.ql-snow,.ql-container.ql-snow{border-color:var(--line-strong)}
.ql-toolbar.ql-snow{border-radius:var(--radius) var(--radius) 0 0}
.ql-container.ql-snow{border-radius:0 0 var(--radius) var(--radius)}

/* Bảng gọn dùng trong hộp thoại: th/td chung của trang có padding 12-20px, quá
   rộng cho một bảng 3 cột nằm trong modal. */
.tbl-mini{width:100%;border-collapse:collapse;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
.tbl-mini th,.tbl-mini td{padding:8px 10px;font-size:13px;text-align:left;border-bottom:1px solid var(--line)}
.tbl-mini thead th{background:var(--surface);color:var(--muted);font-size:12px;font-weight:600}
.tbl-mini tbody tr:last-child td{border-bottom:none}
.tbl-mini .num{text-align:right;white-space:nowrap;font-variant-numeric:tabular-nums}
.tbl-mini .delta-up{color:var(--tag-green);font-weight:600}
.tbl-mini .delta-down{color:var(--danger);font-weight:600}

/* Menu thả xuống cho nút hành động trên thanh công cụ. */
.dropdown{position:relative}
.dropdown-menu{position:absolute;top:calc(100% + 6px);left:0;background:#fff;border:1px solid var(--line);border-radius:10px;box-shadow:0 8px 24px rgba(0,0,0,.12);min-width:210px;padding:6px;display:none;z-index:30}
.dropdown-menu.on{display:block}
.dropdown-menu button{display:flex;align-items:center;gap:8px;width:100%;padding:8px 10px;font-size:13px;color:var(--ink);background:none;border:none;border-radius:6px;text-align:left}
.dropdown-menu button:hover{background:#f2f4f7}
.dropdown-menu button i{color:var(--hint);font-size:15px}

/* Thanh tab của một đối tượng (giải đấu): các màn con của nó đọc như một màn
   hình nhiều tab, dù mỗi tab vẫn là một route riêng. */
/* Sơ đồ nhánh cuộn NGANG, không nuốt con lăn dọc.

   overflow-x:auto một mình đã đủ gây lỗi: theo quy tắc CSS, đặt một trục khác
   'visible' thì trục còn lại tự thành 'auto'. Thế là khối sơ đồ trở thành một vùng
   cuộn dọc nằm giữa trang, con trỏ đặt lên nó là bánh xe cuộn sơ đồ chứ không cuộn
   trang - người dùng thấy trang đứng hình. overflow-y:hidden không cắt mất gì: khối
   này không đặt chiều cao nào, nó cao đúng bằng sơ đồ bên trong. */
.bracket-scroll{overflow-x:auto;overflow-y:hidden}

/* .topbar là position:sticky, nên MỌI thứ được cuộn tới đều nằm khuất một phần sau
   nó. Đặt sẵn khoảng chừa cho các mốc cuộn, thay vì đi sửa từng chỗ gọi
   scrollIntoView - chỗ nào quên thì lỗi quay lại đúng như cũ. */
h1,h2,h3,.sec-head,.card-head,[id]{scroll-margin-top:96px}

/* Thanh tab cuộn ngang khi hẹp. Ở 375px nó dài hơn khung mà KHÔNG có dấu hiệu nào cho
   biết còn tab nữa - người dùng đọc tới tab cuối nhìn thấy được rồi dừng.

   Bóng ở mép làm bằng background-attachment: hai lớp 'local' trôi theo nội dung che
   đi, hai lớp 'scroll' đứng yên lộ ra - nên bóng chỉ hiện ở đúng phía còn nội dung
   chưa cuộn tới. Thuần CSS, không cần JavaScript đo bề rộng ở mỗi lần đổi kích thước. */
.tabs{display:flex;gap:24px;border-bottom:1px solid var(--line);margin-bottom:20px;overflow-x:auto;
  background:
    linear-gradient(to right,var(--surface) 40%,rgba(255,255,255,0)) left center/22px 100% no-repeat local,
    linear-gradient(to left,var(--surface) 40%,rgba(255,255,255,0)) right center/22px 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%,rgba(16,24,40,.22),rgba(16,24,40,0)) left center/16px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%,rgba(16,24,40,.22),rgba(16,24,40,0)) right center/16px 100% no-repeat scroll}

/* Ngón tay không bấm trúng một vòng tròn 17px. Nới VÙNG BẤM chứ không nới hình: dấu
   chấm gợi ý to bằng ngón tay sẽ tranh chỗ với chính cái nhãn nó đi kèm. Chỉ áp cho
   thiết bị trỏ thô (cảm ứng); chuột thì 17px là đủ chính xác. */
@media (pointer:coarse){
  .hint-dot{position:relative}
  .hint-dot::before{content:'';position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
    width:44px;height:44px}
}
.tab{padding:9px 2px 11px;font-size:14px;color:var(--muted);text-decoration:none;border-bottom:2px solid transparent;white-space:nowrap;transition:color .15s,border-color .15s}
.tab:hover{color:var(--ink);text-decoration:none}
.tab.on{color:var(--ink);font-weight:600;border-bottom-color:var(--vg)}

/* Toast */
/* Toasts. Flash messages and validation errors used to render inline at the top
   of .content, so every message pushed the page down and shifted the layout the
   user was looking at. They now stack in this fixed overlay instead. */
.toast-stack{position:fixed;top:16px;left:50%;transform:translateX(-50%);z-index:400;display:flex;flex-direction:column;align-items:center;gap:10px;width:min(460px,calc(100vw - 32px));pointer-events:none}
.toast{pointer-events:auto;max-width:100%;display:flex;align-items:flex-start;gap:10px;background:#fff;color:var(--ink);padding:11px 12px;border-radius:var(--radius);border-left:3px solid var(--tag-gray);font-size:13.5px;line-height:1.45;box-shadow:var(--shadow-pop);opacity:0;transform:translateY(-10px);transition:opacity .18s ease,transform .18s ease}
.toast.show{opacity:1;transform:translateY(0)}
.toast.leaving{opacity:0;transform:translateY(-10px)}
.toast>i{font-size:16px;flex-shrink:0;margin-top:1px}
.toast-msg{flex:1;word-break:break-word}
.toast-close{background:none;border:none;color:var(--hint);font-size:13px;line-height:1;padding:3px;flex-shrink:0;border-radius:4px}
.toast-close:hover{color:var(--ink);background:rgba(0,0,0,.05)}
.toast-success{border-left-color:var(--tag-green)}
.toast-success>i{color:var(--tag-green)}
.toast-error{border-left-color:var(--danger)}
.toast-error>i{color:var(--danger)}
.toast-warning{border-left-color:var(--tag-amber)}
.toast-warning>i{color:var(--tag-amber)}
.toast-info{border-left-color:var(--tag-purple)}
.toast-info>i{color:var(--tag-purple)}
.toast-stack-main{left:calc(50% + var(--sidebar-w) / 2)}  /* centred on the content, not the viewport */
@media (max-width:860px){.toast-stack-main{left:50%}}  /* sidebar is off-canvas here */
@media (max-width:600px){.toast-stack{top:12px;width:calc(100vw - 24px)}}

/* Login */
.login-screen{position:fixed;inset:0;background:linear-gradient(135deg,var(--vd),var(--vd2));display:flex;align-items:center;justify-content:center;padding:20px;z-index:500}
.login-card{background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-pop);padding:36px 32px;width:100%;max-width:360px}
.login-badge{width:48px;height:48px;border-radius:50%;border:2px solid var(--accent);display:flex;align-items:center;justify-content:center;color:var(--vg);font-size:13px;font-weight:600;margin:0 auto 16px}
/* Logo_Icon.png carries its own dark ground, so it reads as a rounded
   brand tile on the white login card. */
.login-logo{width:56px;height:56px;border-radius:12px;display:block;margin:0 auto 16px}
.login-card h2{font-size:18px;font-weight:600;color:var(--ink);text-align:center}
.login-card p.sub-txt{font-size:13px;color:var(--muted);text-align:center;margin-top:4px;margin-bottom:24px}
.login-card .fld{margin-bottom:16px}
.login-error{font-size:12.5px;color:var(--danger);background:var(--danger-soft);border-radius:7px;padding:8px 11px;margin-bottom:16px;display:none}
.login-card .btn-primary{width:100%;justify-content:center;height:38px}
.login-card .btn-primary i{transform:rotate(180deg)}

.navtgl{display:none}
@media(max-width:860px){
  .sidebar{position:fixed;left:0;top:0;bottom:0;z-index:50;transform:translateX(-100%);transition:transform .2s}
  .sidebar.open{transform:translateX(0)}
  .navtgl{display:inline-flex;align-items:center;justify-content:center;background:#fff;color:var(--ink);border:1px solid var(--line-strong);width:32px;height:32px;border-radius:var(--radius);font-size:16px}
  .form-grid{grid-template-columns:1fr}
  .fld.span2{grid-column:1/2}
  .content{padding:16px}
  .topbar{padding:12px 16px}
}

/* ---------- Pagination (app addition, matches design system) ---------- */
.pager{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.pager-size{display:flex;align-items:center;gap:8px;margin-right:8px}
.pager-size label{font-size:13px;color:var(--muted);white-space:nowrap}
.pager-size select{height:32px;border:1px solid var(--line-strong);border-radius:var(--radius);background:#fff;color:var(--ink);font-size:13.5px;padding:0 26px 0 10px;cursor:pointer;
  appearance:none;-webkit-appearance:none;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236B7280' stroke-width='2.5'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 8px center}
.pager-btn{min-width:32px;height:32px;padding:0 9px;border:1px solid var(--line-strong);border-radius:var(--radius);background:#fff;color:var(--ink);font-size:13.5px;display:inline-flex;align-items:center;justify-content:center;text-decoration:none;transition:border-color .15s,background .15s,color .15s}
.pager-btn:hover{border-color:#C3C5BD;text-decoration:none}
/* Trang đang xem tô nền tối, không dùng cam CTA: cam đang là màu nút chính, để
   cả hai cùng nổi thì mắt không biết nhìn đâu trước. */
.pager-btn.active{background:var(--vd2);border-color:var(--vd2);color:#fff;font-weight:600}
.pager-btn.disabled{color:var(--line-strong);background:#fff;cursor:default}
.pager-dots{color:var(--hint);padding:0 2px;font-size:13.5px;letter-spacing:1px}
.pager-info{margin-left:auto;font-size:13px;color:var(--hint)}
.btn{text-decoration:none}
.btn:hover{text-decoration:none}
a.dash-card{color:inherit}

/* Ô "Bàn" sửa tại chỗ trong danh sách cặp đấu. Trông như chữ thường cho tới khi rê
   chuột hay đặt con trỏ vào, để một bảng dày ô nhập không thành một biển khung viền. */
.table-cell{width:100%;max-width:74px;height:30px;padding:0 8px;font:inherit;font-size:13px;color:var(--ink);
  background:#fff;border:1px solid var(--line-strong);border-radius:6px;transition:border-color .12s,box-shadow .12s}
.table-cell:hover{border-color:var(--primary)}
.table-cell:focus{outline:none;border-color:var(--primary);box-shadow:0 0 0 3px rgba(0,0,0,.05)}
.table-cell::placeholder{color:var(--hint)}
.table-cell.is-saving{opacity:.55}
.table-cell.is-saved{border-color:var(--ok,#4E9E6A);background:#F2FAF4}
.table-cell.is-error{border-color:var(--danger);background:#FFF4F2}

/* ============================================================================
   Tab Tổng quan — trang đọc như một trang, không như một bản ghi CSDL.
   Câu trạng thái dẫn đầu, số liệu đi thành một dòng, phần thiết lập là danh sách
   định nghĩa gọn thay vì lưới hai cột thưa thếch.
   ========================================================================== */
.lede{display:flex;align-items:flex-start;gap:24px;flex-wrap:wrap;
  padding:26px 28px;background:#fff;border-radius:16px;margin-bottom:18px;
  box-shadow:0 1px 2px rgba(16,24,40,.04),0 6px 16px -6px rgba(16,24,40,.08)}
.lede-main{flex:1;min-width:260px}
.lede-line{font-size:22px;font-weight:600;letter-spacing:-.01em;line-height:1.3;color:var(--ink)}
.lede-hint{font-size:14.5px;color:var(--muted);margin-top:7px;line-height:1.55;max-width:62ch}
.lede-cta{height:40px;padding:0 20px;font-size:14.5px;font-weight:600;flex-shrink:0}

.factbar{display:flex;flex-wrap:wrap;gap:14px 34px;padding:0 4px 22px}
.fact{display:flex;align-items:baseline;gap:9px}
.fact-value{font-size:24px;font-weight:700;letter-spacing:-.02em;color:var(--ink);line-height:1}
.fact-label{font-size:14px;color:var(--muted)}
.fact-warn{color:var(--danger);font-weight:500}

.setup{background:#fff;border-radius:16px;padding:22px 28px 26px;
  box-shadow:0 1px 2px rgba(16,24,40,.04),0 6px 16px -6px rgba(16,24,40,.08)}
.setup-title{font-size:15px;font-weight:600;color:var(--ink);margin:0 0 4px}
.setup-list{display:grid;grid-template-columns:repeat(auto-fit,minmax(420px,1fr));gap:0 48px;margin:0}
.setup-list>div{display:flex;gap:16px;align-items:baseline;padding:12px 0;border-bottom:1px solid var(--line)}
.setup-list dt{flex:0 0 118px;font-size:13px;color:var(--hint);font-weight:500}
.setup-list dd{margin:0;font-size:14px;color:var(--ink)}
@media(max-width:640px){
  .lede{padding:20px}
  .lede-line{font-size:19px}
  .setup{padding:18px 20px 22px}
  .setup-list dt{flex-basis:92px}
}

/* Màn Xếp hạng đọc như bảng kết quả chung cuộc: một dòng trạng thái, rồi bục vinh
   danh ba hạng đầu, rồi mới tới bảng đầy đủ. */
.standings-status{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:16px;padding:10px 14px;background:#F8FAFC;border:1px solid var(--border-subtle,var(--line));border-radius:10px;font-size:13px}
.standings-status.is-final{background:#F2FAF4;border-color:#CDE8D5}
.standings-status .status i{margin-right:4px}

/* Bục vinh danh dạng BẬC THANG: nhì trái, nhất giữa và cao nhất, ba phải. Thứ hạng
   nằm ở CHIỀU CAO chứ không ở một con số, nên đọc được ngay từ cái liếc đầu tiên.
   Một bậc là một THỨ HẠNG chứ không phải một người: thua bán kết là đồng hạng 3 nên
   bậc ba thường có hai người đứng chung. */
.podium{display:flex;align-items:flex-end;justify-content:center;gap:14px;margin-bottom:18px}
@media(max-width:760px){.podium{flex-wrap:wrap;align-items:stretch}}
.podium-card{flex:1 1 0;max-width:280px;min-width:170px;display:flex;flex-direction:column;
  background:#fff;border:1px solid var(--line-strong);border-bottom:none;border-radius:14px 14px 0 0;overflow:hidden;text-align:center}
/* Thân ba bậc cao bằng nhau để CHIỀU CAO TỔNG chỉ do bậc quyết định - không có nó thì
   bậc hạng 3 hai người lại là ô cao nhất, đúng thứ hình bậc thang phải nói ngược lại. */
.podium-body{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;padding:16px 14px;min-height:260px}
.podium-card.podium-1{border-color:#E3C266;background:linear-gradient(180deg,#FFFBF0 0%,#fff 60%)}
.podium-card.podium-2{border-color:#B9C2CF}
.podium-card.podium-3{border-color:#D2A176}
.podium-rank{display:flex;align-items:center;gap:6px;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--hint)}
.podium-1 .podium-rank{color:#A67C11}
.podium-2 .podium-rank{color:#6B7684}
.podium-3 .podium-rank{color:#9A6636}
.podium-face{width:56px;height:56px;border-radius:50%;object-fit:cover;background:#EDEFF3;border:2px solid var(--line)}
.podium-1 .podium-face{width:68px;height:68px;border-color:#E3C266}
.podium-face-text{display:flex;align-items:center;justify-content:center;font-size:22px;font-weight:600;color:#5A6472;text-transform:uppercase}
.podium-name{font-size:15px;font-weight:700;color:var(--ink);line-height:1.3}
.podium-name + .podium-face{margin-top:8px;padding-top:0}
.podium-record{font-size:12.5px;color:var(--hint)}
/* Bậc: chiều cao khác nhau chính là thứ hạng. */
.podium-base{display:flex;align-items:flex-start;justify-content:center;padding-top:6px;font-size:19px;font-weight:800;color:#2B3440}
.podium-1 .podium-base{height:64px;background:#E3C266}
.podium-2 .podium-base{height:44px;background:#C3CBD8}
.podium-3 .podium-base{height:30px;background:#D9A273}

/* Dải trạng thái nhận đăng ký trên màn Người chơi. */
.reg-status{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:16px;padding:11px 14px;background:#F8FAFC;border:1px solid var(--border-subtle,var(--line));border-radius:10px;font-size:13px;color:var(--ink)}
.reg-status.is-full{background:#FFF8E6;border-color:#F0DFB0}
.reg-status .status i{margin-right:4px}

/* Hàng lọc hạng / khoảng điểm trong hộp thoại thêm cơ thủ. */
.pick-filter{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.pick-filter select{flex:1 1 190px;min-width:150px}
.pick-filter input[type=number]{width:110px}
.pick-filter-dash{color:var(--hint)}


/* ---- Vận hành giải: hai giai đoạn ------------------------------------------
   Giải Swiss có cắt top chạy hai giai đoạn khác hẳn nhau về luật - vòng loại tính
   điểm, vòng đối kháng thua là về - nên màn vận hành nói rõ đang ở giai đoạn nào
   thay vì đổ mọi thẻ vào một dòng chảy duy nhất. */
.phase-nav{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin-bottom:22px}
@media(max-width:760px){.phase-nav{grid-template-columns:minmax(0,1fr)}}
.phase-step{display:flex;gap:12px;align-items:flex-start;padding:13px 15px;background:#fff;
  border:1px solid var(--line-strong);border-radius:var(--radius-lg);text-decoration:none;color:inherit}
.phase-step.on{border-color:var(--primary);box-shadow:0 0 0 1px var(--primary) inset}
.phase-step.is-todo{background:var(--surface);color:var(--muted)}
.phase-num{display:flex;align-items:center;justify-content:center;width:26px;height:26px;flex:0 0 auto;
  border-radius:50%;background:var(--surface);border:1px solid var(--line-strong);
  font-size:12.5px;font-weight:700;color:var(--muted)}
.phase-step.on .phase-num{background:var(--primary);border-color:var(--primary);color:#fff}
.phase-step.is-done .phase-num{background:var(--tag-green);border-color:var(--tag-green);color:#fff}
.phase-label{font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--hint)}
.phase-title{font-size:14.5px;font-weight:600;color:var(--ink);margin-top:2px;display:flex;align-items:center}
.phase-meta{font-size:12.5px;color:var(--muted);margin-top:3px}

/* Sơ đồ nhánh và danh sách cặp đấu nằm CẠNH nhau trong cùng một khối: hai thứ mô tả
   đúng một tập trận, và xếp chồng thì phải cuộn qua cả sơ đồ mới thấy bảng để bấm
   ghi kết quả. Cột sơ đồ co giãn và tự cuộn ngang; cột danh sách giữ bề rộng đọc
   được. minmax(0,...) ở cả hai vế vì nếu không, sơ đồ rộng sẽ nong cả lưới. */
.ops-2col{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,420px);align-items:stretch}
.ops-2col > * + *{border-left:1px solid var(--line)}
.ops-col{min-width:0;padding:18px 20px}
.ops-col-list{padding:0;background:var(--surface);max-height:620px;overflow-y:auto}
@media(max-width:1180px){
  .ops-2col{grid-template-columns:minmax(0,1fr)}
  .ops-2col > * + *{border-left:none;border-top:1px solid var(--line)}
  .ops-col-list{max-height:none}
}

/* ---- Cắt top: bảng chọn cơ thủ vào nhánh ---------------------------------- */
.pick-list{border:1px solid var(--line-strong);border-radius:var(--radius);max-height:320px;overflow-y:auto;background:#fff}
.pick-empty{padding:16px;text-align:center;font-size:13px;color:var(--hint)}
.cut-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:14px;align-items:end;margin-bottom:14px}
.cut-bar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin:14px 0 8px}
.cut-count{font-size:13px;color:var(--muted)}
.cut-count b{color:var(--ink);font-variant-numeric:tabular-nums}
.cut-count.is-ok b{color:var(--tag-green)}
.cut-count.is-over b{color:var(--danger)}
.cut-row{display:grid;grid-template-columns:auto 34px 1fr repeat(3,58px);align-items:center;gap:10px;
  padding:8px 12px;border-bottom:1px solid var(--line);cursor:pointer;font-size:13.5px}
.cut-row:last-child{border-bottom:none}
.cut-row:hover{background:#FAFAF7}
.cut-row.is-off{color:var(--hint)}
.cut-row.is-off .cut-name{color:var(--hint)}
.cut-head{position:sticky;top:0;z-index:1;background:var(--surface);color:var(--muted);
  font-size:11.5px;font-weight:600;cursor:default;text-transform:uppercase;letter-spacing:.03em}
.cut-head:hover{background:var(--surface)}
.cut-seed{color:var(--muted);font-variant-numeric:tabular-nums;text-align:right}
.cut-name{color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cut-num{text-align:right;font-variant-numeric:tabular-nums}


/* ---- Danh sách người chơi: ô tên, ô đóng phí, menu "..." -------------------- */

/* Số điện thoại làm dòng phụ dưới tên thay vì một cột riêng: nó là cách nhận ra
   người này, không phải một con số để so sánh giữa các dòng. */
.player-sub{font-size:12px;color:var(--hint);margin-top:2px}
.player-name{display:flex;align-items:center;gap:6px}
.player-from{color:var(--hint);font-size:14px;line-height:1;cursor:help}
.player-from:hover{color:var(--muted)}

/* Đóng phí là một cờ bật/tắt, nên vẽ như một ô tick chứ không phải hai nhãn chữ
   khác nhau ("Chính thức" / "Chờ xác nhận") - hai nhãn đó bắt phải ĐỌC mới biết,
   còn cột này người trực giải quét mắt qua hàng chục dòng. */
.fee-toggle{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;
  padding:0;border:none;background:none;border-radius:8px;cursor:pointer;
  color:var(--hint);font-size:21px;line-height:1;transition:background .12s,color .12s}
.fee-toggle:hover{background:#F1F5F9}
.fee-toggle.is-paid{color:var(--tag-green)}
.fee-toggle.is-paid:hover{color:var(--tag-green);background:#ECFDF3}

/* Bill chuyển khoản cơ thủ tự nộp, đứng ngay cạnh ô tick: người trực giải xem chứng
   từ rồi mới xác nhận. Ảnh nhỏ chỉ để nhận ra tờ chuyển khoản, bấm vào mở ảnh gốc. */
.fee-bill{display:inline-flex;vertical-align:middle;width:30px;height:30px;margin-left:6px;
  border:1px solid var(--line-strong);border-radius:6px;overflow:hidden;background:#F8FAFC}
.fee-bill img{display:block;width:100%;height:100%;object-fit:cover}
.fee-bill:hover{border-color:var(--hint)}
/* Chưa nộp thì là một dòng chữ mờ, không phải ô trống: nhìn cả cột là thấy ai còn thiếu. */
.fee-bill-reject{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;
  margin-left:4px;vertical-align:middle;border:0;background:none;padding:0;cursor:pointer;
  color:var(--hint);border-radius:4px;font-size:14px}
.fee-bill-reject:hover{color:#B42318;background:#FEF3F2}
.fee-bill-none{display:inline-block;vertical-align:middle;margin-left:6px;
  font-size:11px;line-height:1.2;color:var(--hint);cursor:help}

/* Menu "..." của một dòng. position:fixed do public/js/row-menu.js đặt lúc mở -
   .tbl-wrap có overflow:hidden nên menu absolute trong ô sẽ bị cắt. */
.row-menu{position:fixed;display:none;min-width:200px;padding:6px;background:#fff;
  border:1px solid var(--line-strong);border-radius:10px;box-shadow:var(--shadow-pop);z-index:60}
.row-menu.on{display:block}
.row-menu a,.row-menu button{display:flex;align-items:center;gap:9px;width:100%;padding:8px 10px;
  font:inherit;font-size:13px;color:var(--ink);text-align:left;text-decoration:none;
  background:none;border:none;border-radius:6px;cursor:pointer}
.row-menu a:hover,.row-menu button:hover{background:#F3F4F6}
.row-menu i{color:var(--hint);font-size:16px}
.row-menu .is-danger{color:var(--danger)}
.row-menu .is-danger i{color:var(--danger)}
.row-menu .is-danger:hover{background:#FEE2E2}
.row-menu-sep{height:1px;margin:5px 6px;background:var(--line)}


/* ---- Khối gập được -----------------------------------------------------------
   Dùng <details>/<summary> chứ không phải một nút + JS: gập/mở là hành vi sẵn có
   của trình duyệt, đi được bằng bàn phím, và mở đúng khi người dùng bấm Ctrl+F tìm
   chữ nằm bên trong. Vòng đã chốt hay giai đoạn đã xong thì mặc định gập - trang
   vận hành chỉ nên bày ra thứ đang cần thao tác. */
details.card > summary,
.stage-fold > summary{list-style:none;cursor:pointer}
details.card > summary::-webkit-details-marker,
.stage-fold > summary::-webkit-details-marker{display:none}
details.card > summary{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;
  padding:18px 20px;border-bottom:1px solid transparent}
details.card[open] > summary{border-bottom-color:var(--line)}
details.card > summary:hover{background:#FAFAF7}
details.card > summary h2{font-size:15px;font-weight:600;margin:0;color:var(--ink);display:flex;align-items:center}
.fold-caret{color:var(--hint);font-size:16px;line-height:1;transition:transform .15s;flex:0 0 auto;margin-top:2px}
details[open] > summary .fold-caret{transform:rotate(90deg)}
.fold-head{display:flex;align-items:flex-start;gap:9px;min-width:0}

/* Cả một giai đoạn gập lại: tiêu đề giai đoạn kiêm luôn nút gập. */
.stage-fold{margin-bottom:20px}
.stage-fold > summary{display:flex;align-items:center;gap:9px;padding:10px 2px;
  font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--hint)}
.stage-fold > summary:hover{color:var(--muted)}
.stage-fold > summary .status{text-transform:none;letter-spacing:0}

/* ── Xem thử nội dung trên nền của front office ────────────────────────────────
   Ô soạn thảo là nền trắng chữ đen; front office dựng bài trên nền navy chữ trắng
   phấn, trong một vỏ rộng 430px. Chữ nhạt hay đoạn dán kèm màu đọc tốt lúc soạn
   rồi mới lộ ra khi bài đã lên trang - nút "Nền tối" (public/js/rte-theme.js) bật
   lớp này để thấy ngay tại chỗ.

   Giá trị lấy đúng từ front office, không ước lượng:
     nền   --biadi-navy  #0A0D17      chữ  --biadi-chalk #F2F3EF
     liên kết --biadi-red #C13A28     chữ mờ --biadi-muted #5C6378
     viền  --biadi-line  #1F2637      vỏ 430px, đệm ngang 20px
   Cỡ chữ và khoảng cách chép từ .article-content trong app-ui.css.

   KHÔNG đụng vào danh sách: trong ô soạn thảo, dấu đầu dòng do Quill tự vẽ bằng
   ::before chứ không phải list-style, nên đặt list-style ở đây là ra hai dấu. */
/* [data-rte] đứng trước để thắng `.ql-snow.ql-toolbar button` của quill.snow.css -
   luật đó ép mọi nút trong thanh công cụ về 28x24 và float:left, nên không nâng hạng
   thì nút này bị bóp còn một ô vuông và rơi xuống dòng dưới. Đo được trước khi sửa.
   float:right để nó đứng tách khỏi cụm nút định dạng: đây là nút XEM, không phải một
   công cụ soạn thảo. */
[data-rte] .ql-toolbar button.rte-nen-toi,
.rte-nen-toi{display:inline-flex;align-items:center;gap:5px;width:auto;height:28px;
  padding:0 9px;float:right;white-space:nowrap;
  border:1px solid var(--line-strong);background:#fff;border-radius:4px;
  font-size:11px;font-weight:600;color:var(--muted);cursor:pointer}
[data-rte] .ql-toolbar button.rte-nen-toi:hover,
.rte-nen-toi:hover{color:var(--vg);border-color:var(--vg)}
[data-rte] .ql-toolbar button.rte-nen-toi[aria-pressed="true"],
.rte-nen-toi[aria-pressed="true"]{background:var(--vd);border-color:var(--vd);color:#F2F3EF}
/* Màn chỉ-xem không có thanh công cụ: nút đứng riêng nên cần khoảng thở phía dưới.
   Lớp này do JS gắn lúc đặt nút ra ngoài thanh, không đoán bằng selector lồng. */
.rte-nen-toi.rieng{float:none;margin-bottom:6px}

/* [data-rte] đứng trước KHÔNG thừa: quill.snow.css nạp sau file này và có luật
   `.ql-snow .ql-editor h2{font-size:1.5em}` cùng hạng ưu tiên, nên không nâng thêm
   một bậc là cỡ tiêu đề trong bản xem thử vẫn là cỡ của Quill. Đã đo: 21px thay vì
   17px của front office. */
/* Ngoài cột 430px dùng --biadi-bg (#070910) - đúng màu nền NGOÀI vỏ app của front
   office - còn mép phải cột kẻ một vạch --biadi-line, đúng cái viền vỏ. Nhờ vậy
   nhìn ra ngay mép màn hình điện thoại nằm ở đâu, tức là thấy được chữ nào sắp
   tràn dòng. Để cả vùng cùng một màu tối thì cột 430px tan vào nền và mất hẳn
   thông tin đó. */
[data-rte].rte-xem-toi .ql-container{background:#070910}
[data-rte].rte-xem-toi .ql-editor{
  /* Rộng 430px đúng bằng vỏ app, nhưng KHÔNG căn giữa. Bề ngang mới là thứ quyết
     định chỗ chữ xuống dòng; còn căn giữa chỉ tái hiện FO trên desktop, mà người
     đọc thật thì ở trên điện thoại - nơi vỏ chiếm hết màn hình. Đổi lại, bật/tắt
     nút thì chữ gần như đứng yên nên so trước/sau mới nhìn ra: đo được lệch 5px,
     đúng bằng chênh lệch giữa lề 20px của FO và lề mặc định 15px của Quill. Bản
     căn giữa trước đó lệch 284px - mắt phải đi tìm lại chữ sau mỗi lần bấm. */
  max-width:430px;padding:16px 20px;
  background:#0A0D17;color:#F2F3EF;border-right:1px solid #1F2637;
  font:400 14px/1.65 "Be Vietnam Pro",system-ui,-apple-system,"Segoe UI","Helvetica Neue",sans-serif}
[data-rte].rte-xem-toi .ql-editor.ql-blank::before{color:#5C6378;left:20px;right:20px}
/* Tách từng thuộc tính chứ không dùng shorthand `font`: shorthand BẮT BUỘC có
   font-family, mà ở đây muốn thừa kế đúng bộ chữ đã đặt cho .ql-editor. */
[data-rte].rte-xem-toi .ql-editor h2{font-weight:700;font-size:17px;line-height:1.35;margin:20px 0 8px}
[data-rte].rte-xem-toi .ql-editor h3{font-weight:700;font-size:15px;line-height:1.35;margin:16px 0 6px}
[data-rte].rte-xem-toi .ql-editor p{margin:0 0 12px}
[data-rte].rte-xem-toi .ql-editor ul,
[data-rte].rte-xem-toi .ql-editor ol{margin:0 0 12px}
[data-rte].rte-xem-toi .ql-editor a{color:#C13A28;text-decoration:underline}
[data-rte].rte-xem-toi .ql-editor img{max-width:100%;height:auto;border-radius:8px;margin:8px 0}
[data-rte].rte-xem-toi .ql-editor blockquote{border-left:3px solid #1F2637;padding-left:12px;
  margin:0 0 12px;color:#5C6378}

/* ---------------------------------------------------------------------------
   Sơ đồ nhánh kép (màn Vận hành giải loại kép)

   Vẽ bằng grid thuần, không qua jquery-bracket: nhánh kép có người THUA cũng đi
   tiếp, nên "ai vào ô nào" không phải phép chia hai mà là liên kết đã lưu trong
   league_de_nodes - thư viện kia tự tính ở trình duyệt nên không dùng được.

   Cuộn ngang nằm TRONG .de-board. Để tràn ra trang thì ở 390px mọi thứ khác trên
   trang cũng lệch theo, mà một sơ đồ 7 bậc thì không có bề rộng điện thoại nào
   chứa nổi.
   --------------------------------------------------------------------------- */
/* ---- Sơ đồ nhánh kép: mặt phẳng kéo/phóng, ba khung nhánh ----------------
   Viewport cố định chiều cao và CẮT nội dung; mặt phẳng bên trong mang transform.
   Không dùng cuộn: cuộn hai chiều trong một khung lồng vào trang đã có cuộn dọc là
   chỗ con lăn chuột không biết nghe ai. Xem public/js/de-bracket-pan.js. */
.de-board{position:relative;border:1px solid var(--line);border-radius:10px;background:var(--surface);overflow:hidden}
/* user-select:none vì cả mặt phẳng này là một thứ để KÉO, không phải để đọc chọn.
   Không có nó thì mỗi cú kéo lại bôi đen tên cơ thủ, trình duyệt chuyển sang chế độ
   kéo-thả đoạn văn bản đang chọn, và cú kéo tiếp theo không di chuyển sơ đồ nữa. Tên
   cơ thủ vẫn chọn chép được ở bảng cặp đấu ngay dưới sơ đồ. */
.de-vp{position:relative;height:clamp(380px,62vh,680px);overflow:hidden;touch-action:none;cursor:grab;user-select:none;-webkit-user-select:none}
.de-vp.is-keo{cursor:grabbing}
.de-canvas{position:absolute;left:0;top:0;transform-origin:0 0}

/* Khung nhóm nhánh. Nền rất nhạt + viền đứt: nó là một vùng, không phải một hộp - để
   nó đặc thì mười ba thẻ bên trong mất hẳn tương phản. */
.de-band{position:absolute;border-radius:12px;border:1px dashed}
.de-band.is-win{background:rgba(28,154,108,.05);border-color:rgba(28,154,108,.35)}
.de-band.is-lose{background:rgba(142,31,26,.045);border-color:rgba(142,31,26,.3)}
.de-band.is-ko{background:rgba(176,137,24,.05);border-color:rgba(176,137,24,.38)}
.de-band-hd{position:absolute;left:14px;top:9px;font-size:11.5px;font-weight:800;
  letter-spacing:.06em;text-transform:uppercase;white-space:nowrap}
.de-band.is-win .de-band-hd{color:var(--tag-green)}
.de-band.is-lose .de-band-hd{color:var(--danger)}
.de-band.is-ko .de-band-hd{color:#8a6a12}
/* Câu phụ nói LUẬT của khung ("thua thêm là bị loại"), nên nó thường chứ không hoa. */
.de-band-hd span{margin-left:10px;font-weight:600;letter-spacing:0;text-transform:none;color:var(--muted)}

.de-colhd{position:absolute;font-size:11px;font-weight:700;color:var(--muted);
  text-transform:uppercase;letter-spacing:.04em;white-space:nowrap}

.de-node{position:absolute;width:188px;border:1px solid var(--line);border-radius:8px;
  background:#fff;padding:6px 8px 7px;z-index:1}
/* Ô trống vẫn phải CHE được đường nối đi qua phía sau, nếu không thì một đường cắt
   ngang chữ "Thua T3" đọc thành gạch xoá. Trắng mờ: vẫn nhẹ hơn ô có người, vẫn đủ
   đục để làm nền cho chữ. */
.de-node.is-empty{border-style:dashed;background:rgba(255,255,255,.78)}
.de-node.is-bye{opacity:.75}
.de-code{font-size:11px;font-weight:700;color:var(--hint);letter-spacing:.03em}
.de-seat{display:flex;align-items:baseline;gap:8px;min-height:22px;
  border-top:1px solid var(--line-soft);padding-top:2px}
.de-seat:first-of-type{border-top:0;margin-top:1px}
.de-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.de-score{font-variant-numeric:tabular-nums;font-weight:600}
.de-seat.is-won .de-name{font-weight:700}
.de-seat.is-won .de-score{color:var(--tag-green)}
/* Ghế trống ghi nguồn: nhạt và nghiêng, để không đọc nhầm thành một cơ thủ. */
.de-src{color:var(--hint);font-style:italic}

/* Lớp đường nối nằm DƯỚI các hộp ở bản canvas: ba khung đã tách nhau nên đường không
   còn phải xuyên qua hộp của cột giữa như bố cục một hàng cột trước đây. */
.de-edges{position:absolute;left:0;top:0;pointer-events:none;z-index:0;overflow:visible}
.de-edge{stroke-width:1.5;opacity:.5}
.de-edge.is-win{stroke:var(--tag-green)}
/* Nét đứt cho nhánh thua: hai đường cắt nhau thì màu thôi chưa đủ để tách, nhất là
   khi in đen trắng. */
.de-edge.is-lose{stroke:var(--danger);stroke-dasharray:5 3}

.de-tools{display:flex;align-items:center;gap:6px;padding:8px 10px;border-top:1px solid var(--line);background:#fff}
.de-tools .de-hint{flex:1;font-size:11.5px;color:var(--hint)}
.de-tools .btn-icon{min-width:30px;height:28px;font-size:14px;line-height:1}

/* Hàng nút thao tác sơ đồ: nút bị chặn đi kèm câu nói vì sao, nên mỗi "nút" là
   một khối chứ không phải một thẻ button đơn - gói theo chiều dọc ở màn hẹp. */
.de-actions{display:flex;flex-wrap:wrap;gap:12px;align-items:flex-start;margin-top:14px}
.de-actions form{margin:0}
.de-action-blocked{display:flex;flex-direction:column;gap:4px;max-width:320px}
.de-action-blocked .fld-hint{margin:0}

@media (max-width:760px){
  /* Màn hẹp: khung sơ đồ thấp hơn một chút để còn thấy mấy khối bên dưới, và mở sẵn
     ở mức thu nhỏ - de-bracket-pan.js tự tính "vừa khung" khi tải. */
  .de-vp{height:clamp(320px,52vh,520px)}
  .de-action-blocked{max-width:100%}
}

/* Khối chỉ định suất miễn Vòng 1. Danh sách có thể dài bằng số người đăng ký, nên
   nó tự cuộn trong khung của mình thay vì đẩy mọi thứ khác xuống dưới màn hình. */
.de-bye-modes{display:flex;flex-wrap:wrap;gap:18px;margin:10px 0 12px}
.de-bye-tools{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-bottom:10px}
.de-bye-list{max-height:280px;overflow-y:auto;border:1px solid var(--line);border-radius:8px;
  padding:6px 10px;display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:2px 16px}
.de-bye-row{display:flex;align-items:center;gap:8px;min-height:30px}
.de-bye-seed{display:inline-block;min-width:22px;font-variant-numeric:tabular-nums;
  font-size:11px;font-weight:700;color:var(--hint)}

@media (max-width:760px){
  .de-bye-list{grid-template-columns:1fr;max-height:320px}
}

/* Thanh xác nhận đóng phí hàng loạt. Dính trên đầu vùng cuộn vì bảng dài hơn màn
   hình: chọn tới dòng thứ 30 rồi phải cuộn ngược lên tìm nút là bỏ đi phần lớn cái
   lợi của việc gộp. */
.fee-bulkbar{position:sticky;top:0;z-index:3;display:flex;align-items:center;gap:10px;
  margin-bottom:10px;padding:10px 14px;border:1px solid var(--line-strong);border-radius:var(--radius);
  background:#fff;box-shadow:0 1px 3px rgba(16,24,40,.06)}
.fee-bulkbar [data-fee-bulkcount]{font-size:13px;font-weight:600;color:var(--ink);margin-right:auto}

/* CHẠM TỪNG VÒNG của giải Đấu loại kép.
   Một giải 64 người có 9 ô; xếp dọc thì khối cấu hình dài gấp đôi phần còn lại và
   người điền phải cuộn để so hai vòng cạnh nhau. Lưới tự co theo bề ngang, mỗi ô đủ
   rộng cho nhãn dài nhất ("Vòng 2 — nhánh thắng"). */
.de-race-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(170px,1fr));gap:10px}
.de-race-item{display:flex;flex-direction:column;gap:4px;min-width:0}
.de-race-item label{font-size:12px;color:var(--muted);font-weight:600;margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.de-race-item input{width:100%}
