    /* === DESIGN TOKENS (USER 2026-06-20, agent main) — nguồn chân lý màu/khoảng cách/độ rộng.
       Giá trị KHỚP hard-code đang dùng → thêm token KHÔNG đổi diện mạo; code mới xài token, code cũ
       migrate dần. CSS thuần (không Tailwind) theo quy ước dự án §2. === */
    :root { --bd:#d4d7dd; --pri:#1a73e8; --pri-d:#1558b8; --bg:#f7f8fa; --txt:#1f2330;
            --ok:#1a9d57; --info-bg:#eef4ff; --info-bd:#cfe0ff;
            /* Màu ngữ nghĩa (khớp giá trị có sẵn) */
            --pri-bg:#eef4ff; --ok-d:#157e46; --ok-bg:#dff5e1;
            --danger:#c0262e; --danger-d:#9e1f26; --danger-bg:#fde2e2; --danger-bd:#f0a3a3;
            --warn:#e0a800; --warn-bd:#e0c000; --warn-bg:#fff3cd; --warn-txt:#8a6d00;
            --ai:#6d28d9; --ai-bg:#f1ecfe;
            /* Bề mặt + chữ phụ + viền nhạt */
            --surface:#fff; --surface-2:#f5f8fc; --surface-3:#f6f8fc; --bd-2:#eef0f3;
            --txt-2:#5a6678; --txt-mut:#667085;
            /* Thang khoảng cách (4px base) */
            --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:24px; --sp-6:32px;
            /* Bo góc + đổ bóng */
            --r-sm:6px; --r:8px; --r-lg:10px; --r-xl:12px; --r-pill:999px;
            --sh-1:0 1px 3px rgba(20,40,80,.08); --sh-2:0 6px 20px rgba(20,40,80,.16);
            /* Độ rộng trang chuẩn — chống lệch max-width (báo cáo A2). Bảng nặng dùng --w-xwide,
               nội dung thường --w, dashboard/grid --w-wide, form hẹp --w-narrow. */
            --w:980px; --w-wide:min(1360px,95vw); --w-xwide:min(1680px,96vw); --w-narrow:680px;
            /* Lớp z thống nhất */
            --z-sticky:5; --z-nav:50; --z-fab:40; --z-toast:9999; }
    * { box-sizing: border-box; }
    body { font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
           color: var(--txt); margin: 0; background: var(--bg); line-height: 1.5; }
    header { padding: 8px 16px; background: #fff; border-bottom: 1px solid var(--bd); }
    header a { color: var(--pri); text-decoration: none; }
    /* Độ rộng trang chuẩn hoá (báo cáo A2): mặc định --w (980); trang chọn lớp qua
       {% block main_class %}. Lớp (specificity 0,1,1) thắng base main (0,0,1) → áp được mà
       KHÔNG cần inline <style>main{} ở từng trang. */
    main { max-width: var(--w); margin: 0 auto; padding: var(--sp-4); }
    main.is-narrow { max-width: var(--w-narrow); }
    main.is-wide   { max-width: var(--w-wide); }
    main.is-xwide  { max-width: var(--w-xwide); }
    h1 { font-size: 1.4rem; margin: 8px 0 12px; }
    a { color: var(--pri); }
    hr { border: none; border-top: 1px solid var(--bd); margin: 0; }
    input[type=text], input[type=search], input[type=url], input[type=number],
    input[type=password], input[type=email], textarea, select {
      padding: 9px 11px; border: 1px solid var(--bd); border-radius: 8px;
      font: inherit; width: 100%; max-width: 520px; background: #fff; color: var(--txt);
      transition: border-color .12s, box-shadow .12s; }
    /* Focus: viền xanh + quầng nhẹ — đồng nhất MỌI ô (gồm mật khẩu). */
    input:focus, textarea:focus, select:focus { outline: none; border-color: var(--pri);
      box-shadow: 0 0 0 3px rgba(26,115,232,.15); }
    textarea { resize: vertical; }
    /* === Ô NGÀY/GIỜ toàn site (USER 2026-09-23 "CSS bộ lọc ngày tháng rất xấu, kể cả các page khác") ===
       Vì sao: luật ô nhập ngay trên KHÔNG có input[type=date] ⇒ trình duyệt vẽ kiểu mặc định — đo
       Chrome headless /stats/: ô ngày cao 21px, chữ 13px, trong khi select 43px ⇒ nhãn đứng cạnh tụt lệch
       22px. Nay cùng padding/viền/bo góc/cỡ chữ/quầng focus với select + ô text; bề rộng TỰ NHIÊN
       (không kéo 100% như ô text). line-height 1.25 chứ không 1.5: Chrome đệm thêm 1px trên/dưới phần
       ngày bên trong ⇒ 1.5 ra 46px (đo), 1.25 ra 42px = đúng chiều cao nút. Kiểu hiện mm/dd/yyyy là theo
       NGÔN NGỮ MÁY người xem — CSS không đổi được, và không thêm thư viện chọn ngày (quy ước dự án §2). */
    input[type=date], input[type=datetime-local], input[type=month], input[type=week],
    input[type=time] {
      padding: 9px 11px; border: 1px solid var(--bd); border-radius: 8px; font: inherit;
      line-height: 1.25; background: #fff; color: var(--txt); min-width: 0; max-width: 100%;
      transition: border-color .12s, box-shadow .12s; }
    input[type=date]::-webkit-calendar-picker-indicator,
    input[type=datetime-local]::-webkit-calendar-picker-indicator,
    input[type=month]::-webkit-calendar-picker-indicator,
    input[type=week]::-webkit-calendar-picker-indicator {
      cursor: pointer; opacity: .6; margin-left: 4px; padding: 2px; border-radius: 4px; }
    input[type=date]::-webkit-calendar-picker-indicator:hover,
    input[type=datetime-local]::-webkit-calendar-picker-indicator:hover,
    input[type=month]::-webkit-calendar-picker-indicator:hover,
    input[type=week]::-webkit-calendar-picker-indicator:hover { opacity: 1; background-color: var(--info-bg); }
    /* Cặp TỪ → ĐẾN (dùng chung: <div class="date-range"> chứa 2 <input type="date">). Mũi tên giữa hai ô
       do CSS vẽ (::before + order) ⇒ trang KHÔNG cần thêm thẻ phân cách. Hai ô co đều được (min-width:0)
       ⇒ ở 360px vẫn nằm trên 1 hàng, không tràn ngang. */
    .date-range { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; min-width: 0;
      vertical-align: middle; }
    .date-range::before { content: "→"; order: 1; flex: none; color: var(--txt-mut); font-weight: 700; }
    .date-range > input:first-of-type { order: 0; }
    .date-range > input:last-of-type { order: 2; }
    .date-range > input { flex: 1 1 auto; width: auto; min-width: 0; }
    /* === HÀNG LỌC dùng chung (nhãn Ở TRÊN, các ô CĂN ĐÁY, cùng chiều cao 42px) ===
       Nhãn thẳng hàng chỉ khi mọi ô cùng cao: đo trước 23/09 select 43 · nút 42 · ô ngày 21 ⇒ nhãn lệch
       nhau tới 22px. Chốt cứng 42px (= nút) cho select/ô nhập/nút/link-nút trong hàng. */
    .filter-card { background: #fff; border: 1px solid var(--bd); border-radius: var(--r-xl);
      padding: 12px 14px; margin: 0 0 16px; box-shadow: var(--sh-1); }
    .filter-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 12px; }
    .filter-row .fld { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 0 1 auto; }
    .filter-row .fld > label { font-size: .8rem; font-weight: 600; color: var(--txt-2); line-height: 1.25;
      white-space: nowrap; }
    .filter-row select, .filter-row input:not([type=checkbox]):not([type=radio]), .filter-row button,
    .filter-row a.ghost, .filter-row a.btn { height: 42px; }
    .filter-row select { width: auto; min-width: 130px; max-width: 220px; }
    .filter-row .fld-actions { flex-direction: row; align-items: center; gap: 8px; }
    .filter-row a.ghost, .filter-row a.btn { display: inline-flex; align-items: center; }
    @media (max-width: 560px) {
      /* Điện thoại: 2 cột đều nhau; cặp ngày + nút chiếm trọn hàng. */
      .filter-row .fld { flex: 1 1 calc(50% - 6px); }
      .filter-row .fld.fld-date, .filter-row .fld.fld-actions { flex-basis: 100%; }
      .filter-row select { width: 100%; min-width: 0; max-width: none; }
      .filter-row .fld-date .date-range { width: 100%; }
      /* 2 ô ngày ~133px mỗi ô ở 360px: đệm ngang 11px làm cụt "mm/dd/yyy" (đo ảnh) ⇒ nới lòng ô. */
      .date-range { gap: 4px; }
      .date-range > input { padding-left: 7px; padding-right: 5px; }
    }
    button { font: inherit; padding: 8px 14px; border: 1px solid var(--pri); border-radius: 8px;
      background: var(--pri); color: #fff; cursor: pointer; }
    button:hover { background: var(--pri-d); }
    button.ghost { background: #fff; color: var(--pri); }
    /* Nút hành động chính (nổi bật): go = xanh lá (Gửi duyệt / Duyệt), danger = đỏ (Loại). */
    button.go { background: #1a9d57; border-color: #1a9d57; }
    button.go:hover { background: #157e46; }
    button.danger { background: #c0262e; border-color: #c0262e; }
    button.danger:hover { background: #9e1f26; }
    button.big { padding: 11px 20px; font-size: 1.02rem; font-weight: 600; }
    /* Nút BỊ KHOÁ: hiện rõ không bấm được (site-wide — USER 2026-06-06, trước chỉ mờ chữ). */
    button:disabled, button[disabled] { opacity: .5; cursor: not-allowed; }
    /* C7 (2026-07-09): LINK kiểu nút — <a class="ghost/go/btn"> thay <a><button> lồng nhau (markup
       hợp lệ). Style khớp button.* để giữ nguyên diện mạo nút Hủy / Tải CSV / Mở báo cáo. */
    a.ghost, a.go, a.btn { display: inline-block; font: inherit; padding: 8px 14px;
      border: 1px solid var(--pri); border-radius: 8px; background: var(--pri); color: #fff;
      cursor: pointer; text-decoration: none; }
    a.ghost:hover, a.go:hover, a.btn:hover { filter: brightness(.96); }
    a.ghost { background: #fff; color: var(--pri); }
    a.go { background: #1a9d57; border-color: #1a9d57; color: #fff; }
    /* Hàng CTA (nút chính 1 bước): caption XUỐNG DÒNG riêng, không tràn cạnh nút (hết loạn). */
    .cta-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-top: 12px;
      padding-top: 10px; border-top: 1px dashed var(--bd); }
    .cta-row .hint { flex-basis: 100%; margin: 4px 0 0; }
    /* Hàng toggle gom chung (Sóng/Auto…) — đồng nhất, cùng 1 hàng. */
    .toggle-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0; }
    /* === Hàng HÀNH ĐỘNG NGANG có ô nhập (vd Duyệt + Loại): FIX lệch dòng (USER 2026-06-04).
       Lỗi cũ: ô input thừa hưởng `width:100%` toàn cục → chiếm hết hàng → nút bị đẩy xuống
       dòng dưới + lệch nút bên cạnh. Cách chữa: trong các thanh này, ô nhập CO GIÃN theo chỗ
       trống (flex), KHÔNG ép full-width. Áp cho mọi hàng tương tự (review + thêm thẻ). === */
    .review-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
    .review-actions form { display: flex; align-items: center; gap: 8px; margin: 0; }
    .review-actions .reject-form { flex: 1 1 300px; min-width: 0; }
    .review-actions .reject-reason { flex: 1 1 auto; width: auto; min-width: 0; }
    fieldset { border: 1px solid var(--bd); border-radius: 10px; margin: 0 0 12px; padding: 10px 12px;
      background: #fff; }
    legend { font-weight: 600; padding: 0 6px; font-size: .95rem; }
    label { display: inline-block; }
    .field { margin-bottom: 12px; }
    .field > label { font-weight: 600; display: block; margin-bottom: 4px; }
    /* === Lưới chip bấm-chọn: native checkbox/radio + :has(), KHÔNG cần JS === */
    .chip-grid { display: flex; flex-wrap: wrap; gap: 6px; }
    .chip { display: inline-flex; align-items: center; gap: 4px; padding: 5px 12px;
      border: 1px solid var(--bd); border-radius: 999px; background: #fff; cursor: pointer;
      user-select: none; font-size: .92rem; transition: background .1s, border-color .1s; }
    .chip:hover { border-color: var(--pri); }
    .chip input { position: absolute; opacity: 0; width: 0; height: 0; }
    .chip:has(input:checked) { background: var(--pri); color: #fff; border-color: var(--pri); }
    .chip:has(input:checked)::before { content: "\2713\00a0"; font-weight: 700; }
    .chip.empty { color: #888; border-style: dashed; cursor: default; }
    /* ADR-0049: Sự việc CHÍNH đa-trị (Kiểu 2) — badge số thứ tự ưu tiên thay dấu ✓.
       JS (event_primary.js) điền số 1,2,3…; chưa tick badge "+" (ẩn). */
    .chip.ranked:has(input:checked)::before { content: ""; }
    .chip.ranked .rank { display: none; }
    .chip.ranked:has(input:checked) .rank { display: inline-flex; align-items: center;
      justify-content: center; min-width: 17px; height: 17px; border-radius: 999px;
      background: #fff; color: var(--pri-d); font-size: .72rem; font-weight: 800;
      margin-right: 2px; padding: 0 4px; }
    /* Nhạy cảm: chip chọn = ĐỎ (cờ rủi ro — SPEC §0). */
    .chip.sensitive:has(input:checked) { background: #c0262e; border-color: #c0262e; }
    .chip.sensitive:has(input:checked)::before { content: "\26A0\00a0"; }
    /* Ô bắt buộc: viền trái đỏ + dấu * đỏ. */
    fieldset.req { border-left: 3px solid #c0262e; }
    .req-star { color: #c0262e; font-weight: 700; }
    /* Cascade Sự việc: nhãn nhóm chủ đề. */
    .group-label { font-size: .82rem; color: #555; font-weight: 600; margin: 6px 0 2px; }
    /* Hàng "Hay dùng" (Đối tượng). */
    .frequent-row { background: #fffbe6; border: 1px dashed #e0c000; border-radius: 8px;
      padding: 6px 8px; margin-bottom: 6px; }
    .frequent-label { font-size: .82rem; font-weight: 600; color: #8a6d00; display: block; margin-bottom: 4px; }
    /* Indicator còn thiếu. */
    .missing-box { background: #fff3cd; border: 1px solid #e0c000; border-radius: 8px;
      padding: 6px 10px; margin-bottom: 10px; font-size: .9rem; }
    .missing-ok { background: #dff5e1; border: 1px solid #0a0; border-radius: 8px;
      padding: 6px 10px; margin-bottom: 10px; font-size: .9rem; color: #0a6b1e; }
    /* F2 — mục "còn thiếu" bấm nhảy tới ô (_missing.html dùng ở CẢ trang Add lẫn Detail;
       trước chỉ nằm trong <style> detail.html → trang Add mất style cảnh báo). */
    .missing-jump { color: #8a4b00; font-weight: 700; text-decoration: underline; cursor: pointer; }
    .missing-jump:hover { color: #c0262e; }
    /* Khối gập "thêm chi tiết". */
    details.more-block > summary { cursor: pointer; color: var(--pri); font-weight: 600;
      padding: 6px 0; user-select: none; }
    /* WAVE H (2026-07-20) — hint ⓘ bấm-mới-hiện cho từng option (dùng chung wizard + quick-clone).
       Nhãn gọn cạnh label; giải thích dài xổ khi bấm ⓘ. Zero-JS (native details), CSP-safe. */
    .cw-opt { display: flex; align-items: baseline; gap: 5px; margin: 2px 0; flex-wrap: wrap; }
    .cw-opt > label { cursor: pointer; }
    /* 9D (USER 2026-07-21) — ô số min–max trong bộ "Làm khác" bị CẮT chữ ("10"→"1(", "0.5"→"0.!"):
       app.css áp input[type=number]{padding:9px 11px} + spin-button Chrome ~18px ăn hết vùng chữ 52-58px.
       Rule DÙNG CHUNG 3 ngữ cảnh (wizard, clone-center, quick-clone). GIỮ width inline (specificity thắng). */
    .cw-opt input[type=number] { padding: 4px 6px; text-align: right; font-size: .9rem;
      appearance: textfield; -moz-appearance: textfield; }
    .cw-opt input[type=number]::-webkit-inner-spin-button,
    .cw-opt input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
    details.cw-hint { display: inline-block; }
    details.cw-hint > summary { cursor: pointer; color: var(--pri); font-size: .82rem;
      list-style: none; user-select: none; }
    details.cw-hint > summary::-webkit-details-marker { display: none; }
    details.cw-hint[open] > summary { color: #667; }
    details.cw-hint > .hint, details.cw-hint > p { display: block; margin: 3px 0 0 2px;
      flex-basis: 100%; }
    /* Badge phiên bản (điều kiện phải THẤY không cần bấm) — vd "≥2.9.61". */
    .cw-ver { display: inline-block; font-size: .7rem; font-weight: 700; color: var(--pri-d);
      background: #eef3ff; border: 1px solid var(--pri); border-radius: 999px; padding: 0 6px;
      vertical-align: middle; }
    .btn-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
    .hint { color: #666; font-size: .85rem; }
    /* "Giống clip trước" đưa LÊN ĐẦU (hành động bắt đầu): bar nhấn nhẹ, dễ thấy khi mở clip. */
    .quickstart { display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
      background: #eef4ff; border: 1px solid #cfe0ff; border-radius: 10px;
      padding: 8px 12px; margin-bottom: 12px; }
    /* === §7 Cụm chip: gom nhóm theo CỘT + ô gõ-để-lọc + chip 3 trạng thái === */
    /* O tim NOI BAT (USER 2026-06-10): to hon + vien + nen nhe + icon kinh lup -> de thay khi
       phai loc trong nhom lon ("Khac" ~713 chip). */
    /* `input.chip-filter` (0,1,1): hoà specificity với input[type=text] toàn cục ở trên, đứng SAU
       nên thắng — selector .chip-filter trần bị đè im lặng (icon kính lúp chưa từng render). */
    input.chip-filter { max-width: 360px; width: 100%; margin: 2px 0 10px; padding: 7px 11px 7px 30px;
      border: 1px solid #c7d0db; border-radius: 8px; font-size: .95rem; background:
      #f8fafc url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%237a8699' stroke-width='2'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M21 21l-4-4'/%3E%3C/svg%3E")
      no-repeat 8px center; }
    .chip-filter:focus { border-color: var(--pri); outline: none; background-color: #fff; }
    /* Nhom THU GON (<details.grp-collapsible>, vd "Khac"): summary la nhan bam duoc; mo ra hien chip. */
    .grp-collapsible > summary { cursor: pointer; list-style: revert; user-select: none; }
    .grp-collapsible > summary:hover { color: var(--pri); }
    .grp-count { color: #888; font-weight: 600; }
    .grp-hint { color: #9aa6b6; font-weight: 400; font-size: .76rem; }
    .grp-collapsible[open] > summary .grp-hint { display: none; }
    .grp-collapsible > .chip-col { margin-top: 6px; }
    /* USER 2026-06-01 (v2): nhóm xếp DỌC (nhãn trên), chip trong nhóm DÀN NGANG kín bề rộng
       (flex-wrap) → tận dụng tối đa chiều ngang, KHÔNG thừa khoảng trống, trang ngắn lại.
       (Trang nhập nới rộng max-width để dùng hết màn — xem detail.html.) */
    .chip-groups { display: flex; flex-direction: column; gap: 12px; }
    .chip-groups .grp { min-width: 0; }
    .chip-col { display: flex; flex-wrap: wrap; gap: 5px; }
    /* §3.2 Lưới chip 2 cột + §3.5 Cảm xúc/Chất lượng 1 hàng — _tag_form.html dùng ở CẢ trang Thêm
       lẫn Chi tiết (trước chỉ trong <style> detail.html → trang Thêm dồn 1 cột). Màn hẹp → 1 cột. */
    .chip-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; align-items: start; }
    .chip-cols .col-left, .chip-cols .col-right { min-width: 0; display: flex; flex-direction: column; gap: 12px; }
    .mq-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
    @media (max-width: 780px) { .chip-cols, .mq-row { grid-template-columns: 1fr; } }
    /* Chip "đang gợi ý" (§7.3/§7.4): CHƯA chọn nhưng liên quan → viền nét đứt + nền nhạt.
       Đã chọn (:has(:checked)) giữ style chọn (đậm) — gợi ý chỉ cho chip chưa chọn. */
    .chip.suggested:not(:has(input:checked)) { border-style: dashed; border-color: var(--pri);
      background: #eef4ff; }
    /* Nhóm đang gợi ý: nhãn nhóm kèm nguồn "liên quan Chủ đề". */
    .grp.suggested > .group-label::after { content: " · liên quan Chủ đề"; color: var(--pri);
      font-weight: 600; font-size: .76rem; }
    /* USER 2026-06-03 — LÀM MỜ THÔNG MINH: khi 1 mục có nhóm "liên quan Chủ đề"
       (.grp.suggested), các nhóm KHÔNG liên quan mờ đi (bớt rối, đỡ bấm nhầm) NHƯNG vẫn
       bấm được — giữ nguyên tắc §7.4 "không khoá". Rê chuột HOẶC nhóm đang có chip được chọn
       → sáng lại (không che lựa chọn lai). Mục chưa có nhóm gợi ý nào → KHÔNG mờ gì cả. */
    .chip-groups:has(.grp.suggested) .grp:not(.suggested) { opacity: .38; transition: opacity .15s; }
    .chip-groups:has(.grp.suggested) .grp:not(.suggested):hover,
    .chip-groups:has(.grp.suggested) .grp:not(.suggested):has(input:checked) { opacity: 1; }
    /* USER 2026-06-03: làm mờ CHIP-LEVEL (Cảm xúc — list phẳng) khi có chip "liên quan Chủ đề"
       (chip_suggest.js đánh dấu .suggested). Chip đang chọn / rê chuột → sáng lại. */
    .chip-grid.dim-target:has(.chip.suggested) .chip:not(.suggested):not(:has(input:checked)) {
      opacity: .38; transition: opacity .15s; }
    .chip-grid.dim-target:has(.chip.suggested) .chip:not(.suggested):hover { opacity: 1; }
    /* Thanh hành động dính đáy — nút quan trọng (Lưu/Lưu&tiếp/Gửi duyệt) LUÔN thấy
       khi cuộn danh sách chip dài (SPEC: tập trung nút hay bấm). */
    .action-bar { position: sticky; bottom: 0; z-index: 5; display: flex; flex-wrap: wrap;
      gap: 8px; align-items: center; padding: 10px 8px; margin-top: 8px;
      background: rgba(255,255,255,.97); border-top: 1px solid var(--bd);
      box-shadow: 0 -2px 8px rgba(20,40,80,.06); }
    .action-bar .spacer { flex: 1; }
    table { border-collapse: collapse; background: #fff; }
    .platform-badge { display: inline-block; padding: 2px 10px; border-radius: 999px;
      background: #e8f0fe; color: var(--pri-d); font-size: .85rem; font-weight: 600; }
    /* USER 30/09 — Nhật ký tải: MỖI NỀN TẢNG 1 MÀU, site báo/lạ = "Khác" xám. CHỈ class BỔ TRỢ `plat-*`
       (tag `nen_tang_badge`, slug ở `embed._NEN_TANG_HIEN_THI`); `.platform-badge` gốc ở trang khác giữ
       nguyên. Tương phản chữ/nền đã tính theo WCAG, cặp thấp nhất Reddit 4.52:1 (≥ 4.5). Nhãn luôn có CHỮ
       nên màu chỉ phụ trợ. Threads viền bằng `box-shadow inset` để viên không to hơn các viên khác 2px. */
    .platform-badge.plat-youtube { background: #fee2e2; color: #b91c1c; }
    .platform-badge.plat-reddit { background: #ffedd5; color: #c2410c; }
    .platform-badge.plat-twitter { background: #111827; color: #ffffff; }
    .platform-badge.plat-tiktok { background: #ccfbf1; color: #0f766e; }
    .platform-badge.plat-facebook { background: #dbeafe; color: #1d4ed8; }
    .platform-badge.plat-instagram { background: #f3e8ff; color: #7e22ce; }
    .platform-badge.plat-douyin { background: #fce7f3; color: #be185d; }
    .platform-badge.plat-bilibili { background: #fef9c3; color: #a16207; }
    .platform-badge.plat-xiaohongshu { background: #dcfce7; color: #15803d; }
    .platform-badge.plat-dailymotion { background: #f5e8da; color: #8a4b12; }
    .platform-badge.plat-threads { background: #ffffff; color: #111827; box-shadow: inset 0 0 0 1px #111827; }
    .platform-badge.plat-pinterest { background: #ecfccb; color: #4d7c0f; }
    .platform-badge.plat-telegram { background: #e0f2fe; color: #0369a1; }
    .platform-badge.plat-khac { background: #f1f5f9; color: #475569; }
    /* Badge trạng thái footage (dùng chung kho + detail). */
    .badge { font-size: .74rem; padding: 2px 9px; border-radius: 999px; font-weight: 600; white-space: nowrap; }
    .st-draft { background: #eceff3; color: #566; }
    .st-pending { background: #fff3cd; color: #8a6d00; }
    .st-approved { background: #dff5e1; color: #0a6b1e; }
    .st-rejected { background: #fde2e2; color: #c0262e; }
    .st-used { background: #e2ecfd; color: #1558b8; }
    .st-picked { background: #dff5e1; color: #0a6b1e; }  /* VideoPlan "Đã pick" (USER 2026-06-20) */
    .badge.q { background: #f0ebff; color: #5b3fbf; }
    .badge.flag { background: #fff0e6; color: #b35900; }
    /* ADR-0128: thẻ Bản quyền — đỏ đậm, nổi bật (clip của bên khác, CẤM Pick). */
    .badge.copyright { background: #c0262e; color: #fff; }
    /* === Badge AI nhất quán (USER 2026-06-03) — pill mềm, icon gọn. Provenance: bot tự thêm ·
       AI gắn nhãn · đã người kiểm · AI kiểm lại. Mỗi loại 1 màu nhạt riêng. Dùng `_ai_badges.html`. */
    .ai-badge { display: inline-flex; align-items: center; gap: 4px; font-size: .72rem;
      font-weight: 600; padding: 2px 9px; border-radius: 999px; border: 1px solid transparent;
      white-space: nowrap; line-height: 1.6; }
    .ai-badge.bot { background: #f1ecfe; color: #6d28d9; border-color: #e4d8fb; }      /* bot tự thêm */
    .ai-badge.tagged { background: #eef2ff; color: #4338ca; border-color: #e0e7ff; }   /* AI gắn nhãn */
    .ai-badge.verified { background: #ecfdf3; color: #047857; border-color: #c7f0d9; } /* NGƯỜI đã kiểm (xanh) */
    .ai-badge.aichecked { background: #f1f3f5; color: #64748b; border-color: #dde1e6; } /* MÁY/AI tự kiểm — xám, KHÁC người (USER 2026-06-15) */
    .ai-badge.recheck { background: #eff6ff; color: #1d4ed8; border-color: #d8e7fe; }  /* AI kiểm lại */
    .ai-badge.reddit { background: #fff0eb; color: #cc3700; border-color: #ffd3c2; }   /* tải từ Reddit */
    .ai-badge.xplat { background: #eceef0; color: #15202b; border-color: #cfd9de; }    /* tải từ X/Twitter */
    .ai-badge.ytplat { background: #fdeaea; color: #c00; border-color: #f6c4c4; }      /* nguồn YouTube */
    .ai-badge.ttplat { background: #e6fbfb; color: #0a7a78; border-color: #b8eef0; }   /* nguồn TikTok */
    .ai-badge.srcplat { background: #f1f3f5; color: #566; border-color: #dde1e6; }     /* nguồn khác */
    .ai-badge.nguon-mc { background: #f3ebff; color: #7c3aed; border-color: #e3d3fb; }   /* phân tích máy chủ AI (tím) */
    .ai-badge.nguon-nen { background: #e8f1fe; color: #1a56db; border-color: #c9defb; }      /* phân tích AI nền (xanh dương) */
    .ai-badge.edge { background: #fff7e6; color: #b45309; border-color: #f5d99a; }     /* phân tích Edge (cam) */
    .ai-badge.apipaid { background: #fdecef; color: #be123c; border-color: #f6c6d2; } /* phân tích API paid (đỏ) */
    /* Bình luận GỐC Reddit (USER 2026-06-09) — "mô tả 1→N" CÔNG KHAI mọi editor. Gọn: hiện 2, ẩn
       phần còn lại trong <details> để KHÔNG phình trang (10 comment). */
    .srccmt { margin: 10px 0 0; border: 1px solid #ffd3c2; border-left: 4px solid #ff4500;
      background: #fff6f2; border-radius: 8px; padding: 8px 11px; }
    .srccmt-list { margin: 0; padding-left: 0; list-style: none; display: flex;
      flex-direction: column; gap: 5px; }
    .srccmt-list li { font-size: .9rem; line-height: 1.5; color: #3a2c25; }
    .srccmt-n { display: inline-block; font-size: .72rem; font-weight: 700; color: #ff4500;
      background: #ffe7dd; border-radius: 5px; padding: 0 6px; margin-right: 5px; }
    /* USER 2026-06-24: badge lượt like (thay "@@username" rối mắt) — gọn, trực quan. */
    .srccmt-like { flex: none; display: inline-block; font-size: .72rem; font-weight: 700;
      color: #1565c0; background: #e3f0fd; border-radius: 5px; padding: 0 7px; margin-right: 4px;
      white-space: nowrap; align-self: flex-start; }
    .srccmt-more > summary { cursor: pointer; color: #cc3700; font-weight: 600;
      font-size: .85rem; margin-top: 6px; }
    .srccmt-more .srccmt-list { margin-top: 6px; }
    /* USER 2026-06-10 (task #4 Pha 1): nút ➕ thêm comment nguồn vào "mô tả riêng". */
    .srccmt-list li { display: flex; align-items: flex-start; gap: 6px; }
    .srccmt-t { flex: 1; }
    .srccmt-add { flex: none; padding: 1px 8px; font-size: .8rem; line-height: 1.5;
      border: 1px solid #ffd3c2; background: #fff; color: #cc3700; border-radius: 6px; cursor: pointer; }
    .srccmt-add:hover { background: #ffe7dd; }
    /* === B1/R0: phát file gốc LOCAL (File System Access) — player === */
    /* D6 (2026-07-09): bỏ CSS mồ côi .drive-connect/.drive-strip (+ dc-status/dc-hint/dc-icon) —
       không template/JS nào dùng (local_player.js đã refactor). GIỮ .local-video (player còn dùng). */
    .local-video { width: 100%; height: 100%; object-fit: contain; background: #000; display: block; }
    /* USER 2026-06-07: hover-scrub NGAY TRÊN video — nhãn gợi ý (USER 2026-06-08: BỎ vạch dọc xanh
       .scrub-line cho đỡ rối). pointer-events:none để KHÔNG chặn click video / điều khiển native. */
    .scrub-hint { position: absolute; top: 8px; left: 50%; transform: translateX(-50%); opacity: 0;
      background: rgba(0,0,0,.6); color: #dce6f5; font-size: .74rem; padding: 2px 10px;
      border-radius: 999px; pointer-events: none; z-index: 4; transition: opacity .15s; }
    .local-actions { margin-top: 6px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
    .local-note { color: #c0262e; font-size: .8rem; margin: 4px 0 0; }
    /* ADR-0017: nút "Nạp vào kho" + trạng thái tải (CaoVideo auto-poll). */
    .dl-box { margin-top: 8px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
    .dl-box button.go { padding: 6px 14px; }
    .dl-state { font-size: .85rem; font-weight: 600; padding: 4px 11px; border-radius: 999px; }
    .dl-state.ok { background: #dff5e1; color: #0a6b1e; }
    .dl-state.wait { background: #fff3cd; color: #8a6d00; }
    .dl-state.none { background: #eceff3; color: #566; font-weight: 500; }
    /* === ADR-0026 (USER 2026-06-04): badge CaoVideo Online/Offline trên thanh trên cùng —
       icon nhỏ, rõ, tự kiểm 60s/lần (caovideo_status.js). Chấm pulse khi offline để dễ thấy. === */
    .cv-badge { display: inline-flex; align-items: center; gap: 6px; font-size: .8rem; font-weight: 600;
      padding: 3px 11px; border-radius: 999px; border: 1px solid var(--bd); background: #fff;
      vertical-align: middle; line-height: 1.4; white-space: nowrap; cursor: default; }
    .cv-badge .cv-dot { width: 8px; height: 8px; border-radius: 50%; background: #9aa7b6; flex: none; }
    .cv-badge.is-online { background: #e9f9ef; border-color: #b6e3c4; color: #0a7a30; }
    .cv-badge.is-online .cv-dot { background: #1ca846; box-shadow: 0 0 0 3px rgba(28,168,70,.20); }
    .cv-badge.is-offline { background: #fdecec; border-color: #f3b9b9; color: #b3261e; cursor: help; }
    .cv-badge.is-offline .cv-dot { background: #e0352b; animation: cvBlink 1.2s ease-in-out infinite; }
    /* D6 (2026-07-09): bỏ .cv-badge.is-idle (mồ côi — caovideo_status.js không set 'is-idle'). */
    /* ADR-0076: 🔵 Đang bận — máy đang cầm lệnh DAM (restore/bundle) lease tươi, không phải Tắt. */
    .cv-badge.is-busy { background: #e8f1fd; border-color: #b3d0f3; color: #1c5fb8; cursor: help; }
    .cv-badge.is-busy .cv-dot { background: #2f7fe0; box-shadow: 0 0 0 3px rgba(47,127,224,.18); }
    .cv-badge.is-none { color: #7a8696; }
    @keyframes cvBlink { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
    /* Nút "Bật CaoVideo" (caovideo://) — mở app local từ web (USER 2026-06-05). Hiện khi offline. */
    .cv-launch { display: none; font-size: .78rem; font-weight: 600; text-decoration: none;
      padding: 3px 10px; border-radius: 999px; border: 1px solid var(--pri, #1a73e8);
      color: var(--pri, #1a73e8); background: #eef3ff; margin-left: 4px; vertical-align: middle; }
    .cv-launch:hover { background: var(--pri, #1a73e8); color: #fff; }
    .cv-launch.cv-show { display: inline-flex; align-items: center; }
    /* Trang Thêm footage GỘP (add-merge): bảng nhiều link điền tiêu đề/ghi chú.
       Viền + bo góc đặt ở WRAPPER (table border-collapse:collapse bỏ qua border-radius theo spec). */
    .add-table-wrap { overflow-x: auto; margin: 4px 0 12px; border: 1px solid var(--bd);
      border-radius: 10px; background: #fff; }
    .add-table { width: 100%; }
    .add-table th, .add-table td { padding: 6px 8px; border-bottom: 1px solid #eef0f3; text-align: left;
      font-size: .9rem; vertical-align: middle; }
    .add-table thead th { background: #f5f8fc; font-weight: 600; }
    .add-table tbody tr:last-child td { border-bottom: 0; }
    .add-table tr.dup { background: #fff6f6; }
    .add-table .urlcell { color: #345; max-width: 260px; display: inline-block; overflow: hidden;
      text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
    .add-table input { width: 100%; box-sizing: border-box; padding: 5px 8px; }
    .add-table .dup-tag { color: #c0262e; font-size: .72rem; font-weight: 700; }
    .add-table .rmrow { padding: 2px 8px; background: #fff; color: #c0262e; border-color: #e2c2c2; }
    .add-table .rmrow:hover { background: #fde2e2; }
    .single-prev { margin: 2px 0 8px; }
    /* P2 (ADR-0023) — card "Thêm video đã tải sẵn từ máy" (File System Access ghi Drive). */
    .add-local-box { border: 1px solid var(--bd); border-radius: 10px; background: #fff;
      padding: 2px 12px 12px; margin: 14px 0; }
    .add-local-box > summary { cursor: pointer; font-weight: 600; color: var(--pri-d);
      padding: 9px 0; user-select: none; }
    /* D6 (2026-07-09): bỏ .local-add-status(+.err/.ok) mồ côi (không template/JS dùng). */
    /* ADR-0038 #2 (USER 2026-06-09) — "Tải file lên từ máy" gắn vào clip đã có. Show/hide bằng
       <details> NATIVE (mặc định thu gọn), style giống thẻ "Công cụ CaoVideo" (.cv-get): viền xanh
       nhạt + mũi tên ▸ xoay khi mở. */
    .local-upload { border: 1px solid #cfe0ff; background: #f5f9ff; border-radius: 10px;
      padding: 8px 12px; margin-top: 8px; }
    .local-upload > summary { cursor: pointer; font-weight: 600; color: #1558b8; list-style: none;
      display: flex; align-items: center; gap: 8px; font-size: .88rem; }
    .local-upload > summary::-webkit-details-marker { display: none; }
    .local-upload > summary::before { content: "▸"; transition: transform .15s; }
    .local-upload[open] > summary::before { transform: rotate(90deg); }
    .local-upload-body { margin-top: 8px; display: flex; flex-wrap: wrap; gap: 8px;
      align-items: center; }
    .local-upload-body .lu-label { flex-basis: 100%; margin: 0; color: #345; font-size: .84rem; }
    .local-upload-body input[type=file] { flex: 1 1 200px; font-size: .82rem; min-width: 0; }
    .local-upload-body button.go { padding: 6px 14px; }
    .local-upload-status { flex-basis: 100%; margin: 0; font-size: .82rem; word-break: break-word;
      color: #666; }
    .local-upload-status.err { color: #c0262e; }
    .local-upload-status.ok { color: #0a6b1e; font-weight: 600; }
    /* === T2: nút + banner "Phân tích AI" (đồng bộ tím AI #6d28d9 — USER 2026-06-03) === */
    /* `button.ai-btn` (0,1,1): thắng button.ghost (0,1,1, đứng trước) — trước đây chữ bị xanh dương. */
    button.ai-btn { border-color: #6d28d9; color: #6d28d9; }
    .ai-btn:hover { background: #f1ecfe; }
    /* Nút Phân tích AI lúc ĐANG chạy (USER 2026-06-04): dim + đổi nhãn "Đang phân tích…" + con trỏ
       chờ. Bấm lại bị ai_guard.js chặn + cảnh báo. (.htmx-request = đang có request của chính nút.) */
    .ai-btn .ai-running { display: none; }
    .ai-btn.htmx-request { opacity: .7; cursor: progress; }
    .ai-btn.htmx-request .ai-label { display: none; }
    .ai-btn.htmx-request .ai-running { display: inline; }
    .ai-panel { border-radius: 10px; padding: 8px 12px; margin: 0 0 12px; font-size: .9rem; }
    .ai-panel.ok { background: #eef9f0; border: 1px solid #1a9d57; }
    .ai-panel.err { background: #fff3cd; border: 1px solid #e0c000; }
    .ai-panel .ai-head { font-weight: 600; margin-bottom: 4px; }
    .ai-panel p { margin: 4px 0 0; }
    .ai-panel .wow-chip, .ai-panel .newtag { display: inline-block; background: #fff;
      border: 1px solid var(--bd); border-radius: 999px; padding: 1px 9px; margin: 2px 3px 0 0;
      font-size: .82rem; }
    .ai-panel .newtag { border-style: dashed; border-color: var(--pri); color: var(--pri-d); }
    /* HM4: nút "➕ thêm" nhanh ngay trong chip nhãn AI đề xuất. */
    .ai-panel .newtag .ai-addchip { margin-left: 6px; padding: 1px 8px; font-size: .76rem;
      background: var(--pri); color: #fff; border: none; border-radius: 999px; cursor: pointer; }
    .ai-panel .newtag .ai-addchip:hover { background: var(--pri-d); }
    /* HM4 — nút "Thêm tất cả" nhãn AI (nổi bật hơn chip lẻ). */
    .ai-panel .ai-addall { margin-left: 8px; padding: 3px 12px; font-size: .82rem; font-weight: 600;
      background: #1a9d57; color: #fff; border: none; border-radius: 999px; cursor: pointer; }
    .ai-panel .ai-addall:hover { background: #157e46; }
    /* T7: khu "Nhạy cảm" cạnh Hook — viền trái đỏ nhạt để nổi bật là cờ RỦI RO. */
    .sensitive-box { border-left: 3px solid #c0262e; }

    /* ── ADR-0128 · USER 2026-09-18 — công tắc "© Bản quyền" ở ĐẦU form gắn thẻ ──────────────
       Vì sao KHÔNG tái dùng `.chip`: `chip_groups.js` chỉ nhận fieldset có `.chip input`, và với
       khối 1-ô-tick nó đẻ thêm badge đếm "✓ 1" + nút "… ✕" ⇒ 3 nút cho 1 trạng thái (ảnh USER
       gửi 18/09). Dùng class riêng ⇒ bộ máy chung bỏ qua, còn đúng 1 nút.
       Trạng thái đọc bằng CHỮ + BIỂU TƯỢNG + MÀU (không chỉ màu — người khó phân biệt màu vẫn
       đọc được "Không bản quyền" / "CÓ BẢN QUYỀN"). `:has()` đã dùng sẵn ở `.chip:has(...)` phía
       trên nên không thêm phụ thuộc trình duyệt mới nào. */
    .bq-box { border-left: 6px solid var(--ok); background: var(--ok-bg); }
    .bq-box:has(.bq-switch input:checked) { border-left-color: var(--danger); background: var(--danger-bg); }
    .bq-switch { display: flex; align-items: center; gap: 10px; cursor: pointer; user-select: none;
      padding: 9px 14px; border-radius: 999px; border: 2px solid var(--ok); background: #fff;
      color: var(--ok-d); font-size: .95rem; width: fit-content; max-width: 100%;
      transition: background .12s, border-color .12s, color .12s; }
    .bq-switch:hover { box-shadow: 0 0 0 3px rgba(0,0,0,.06); }
    .bq-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
    /* Đèn gạt: xám-xanh khi TẮT, trượt sang phải + đỏ khi BẬT. */
    .bq-den { flex: none; width: 42px; height: 23px; border-radius: 999px; background: var(--ok);
      position: relative; transition: background .12s; }
    .bq-den::after { content: ""; position: absolute; top: 3px; left: 3px; width: 17px; height: 17px;
      border-radius: 50%; background: #fff; transition: transform .12s; }
    .bq-chu b { font-weight: 700; }
    .bq-phu { font-weight: 400; opacity: .82; }
    .bq-chu .bq-bat { display: none; }
    .bq-switch:has(input:checked) { border-color: var(--danger); background: var(--danger);
      color: #fff; }
    .bq-switch:has(input:checked) .bq-den { background: rgba(255,255,255,.45); }
    .bq-switch:has(input:checked) .bq-den::after { transform: translateX(19px); }
    .bq-switch:has(input:checked) .bq-chu .bq-tat { display: none; }
    .bq-switch:has(input:checked) .bq-chu .bq-bat { display: inline; }
    /* Ô "Của bên nào" chỉ SÁNG khi đã bật cờ — tắt thì mờ đi để bớt nhiễu mắt, nhưng KHÔNG
       `disabled` (vẫn phải submit được giá trị cũ, và người dùng vẫn gõ trước-bật-sau được). */
    .bq-box .bq-owner { margin-top: 10px; opacity: .55; transition: opacity .12s; }
    .bq-box:has(.bq-switch input:checked) .bq-owner { opacity: 1; }
    .bq-box:has(.bq-switch input:checked) .bq-owner input { border-color: var(--danger-bd); }
    @media (prefers-reduced-motion: reduce) {
      .bq-switch, .bq-den, .bq-den::after, .bq-box .bq-owner { transition: none; }
    }
    /* ADR-0014: thêm nhanh chip vocab + chip đề xuất chờ duyệt. (D6 2026-07-09: bỏ .vocab-add-block mồ côi.) */
    /* Nút "➕ thêm thẻ mới" cuối MỖI mục (USER 2026-06-03) — nhỏ, mờ, không chiếm chú ý. */
    .vocab-add-inline { margin-top: 6px; }
    .vocab-add-inline > summary { cursor: pointer; color: #7b3fbf; font-size: .82rem;
      padding: 2px 0; user-select: none; list-style: none; }
    .vocab-add-inline > summary:hover { text-decoration: underline; }
    .vocab-add-inline .vocab-add { margin-top: 4px; }
    .vocab-add-inline input[type=text] { max-width: 220px; }
    .vocab-add { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 4px 0; }
    /* Ô gõ nhãn co giãn (nút "Kiểm tra" luôn cùng dòng, không rớt) — cùng fix lệch dòng. */
    .vocab-add input[type=text] { flex: 1 1 180px; width: auto; min-width: 0; }
    .vocab-rv { border-radius: 8px; padding: 6px 10px; margin-top: 6px; font-size: .9rem; }
    .vocab-rv.ok { background: #eef9f0; border: 1px solid #1a9d57; }
    .vocab-rv.warn { background: #fff3cd; border: 1px solid #e0c000; }
    .pending-box { border-left: 3px solid #7b3fbf; background: #faf7ff; }
    /* HM6 — Lời bình AI (dưới Mô tả VN): 4 nút phong cách + kết quả 1 câu. */
    .comment-box { border-left: 3px solid #6d28d9; background: #faf7ff; }
    .comment-styles { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
    .comment-btn.active { background: #6d28d9; color: #fff; border-color: #6d28d9; }
    .comment-result { margin: 8px 0 0; padding: 8px 10px; background: #fff; border: 1px solid var(--bd);
      border-radius: 8px; font-size: .95rem; line-height: 1.5; }
    .htmx-indicator { display: none; }
    .htmx-request .htmx-indicator, .htmx-request.htmx-indicator { display: inline; }
    /* === Toast thông báo (USER 2026-06-04): mọi hành động → toast GÓC DƯỚI PHẢI, tự rụng 5s.
       column-reverse = toast mới nhất ở dưới cùng (gần góc), cũ hơn xếp lên trên → hiện nhiều
       toast cùng lúc gọn gàng. Render qua toast.js (CSP-safe). === */
    /* bottom 84px: nổi TRÊN nút FAB góc dưới-phải (USER 2026-06-20) để không đè nhau. */
    #toast-root { position: fixed; bottom: 84px; right: 14px; z-index: var(--z-toast);
      display: flex; flex-direction: column-reverse; gap: 8px; max-width: min(380px, 92vw);
      pointer-events: none; }
    .toast { pointer-events: auto; display: flex; align-items: flex-start; gap: 8px;
      padding: 10px 12px; border-radius: 10px; border: 1px solid var(--bd);
      background: #fff; color: var(--txt); font-size: .9rem; line-height: 1.45;
      box-shadow: 0 6px 20px rgba(20,40,80,.16);
      opacity: 0; transform: translateX(16px); transition: opacity .18s, transform .18s; }
    .toast.toast-in { opacity: 1; transform: translateX(0); }
    .toast.toast-out { opacity: 0; transform: translateX(16px); }
    .toast .toast-msg { flex: 1; word-break: break-word; }
    .toast .toast-close { pointer-events: auto; background: transparent; border: none;
      color: inherit; font-size: 1.1rem; line-height: 1; padding: 0 2px; cursor: pointer;
      opacity: .6; }
    .toast .toast-close:hover { opacity: 1; background: transparent; }
    .toast.toast-success { border-left: 4px solid #1a9d57; background: #f1faf4; }
    .toast.toast-error   { border-left: 4px solid #c0262e; background: #fdf2f2; }
    .toast.toast-warning { border-left: 4px solid #e0a800; background: #fffaf0; }
    .toast.toast-info    { border-left: 4px solid var(--pri); background: #f3f8ff; }
    /* === Bảng dữ liệu (queue / QC / thống kê) — khung CUỘN NGANG mọi màn (mobile KHÔNG tràn trang) === */
    .tbl-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; border: 1px solid var(--bd);
      border-radius: 10px; margin: 8px 0; background: #fff; }
    .tbl { border-collapse: collapse; width: 100%; background: #fff; font-size: .9rem; }
    .tbl th, .tbl td { padding: 7px 10px; border-bottom: 1px solid #eef0f3; text-align: left; vertical-align: middle; }
    .tbl th { background: #f5f8fc; font-weight: 600; white-space: nowrap; }
    .tbl tbody tr:last-child td { border-bottom: 0; }
    .tbl td a { word-break: break-word; }
    /* === Mobile (USER 2026-06-06): chống TRÀN NGANG toàn site === */
    @media (max-width: 640px) {
      main { padding: 12px 10px; }
      h1 { font-size: 1.25rem; }
      header { font-size: .92rem; }
      /* Bảng KHÔNG bọc .tbl-wrap (admin/demo/cũ) → tự cuộn trong khung, không đẩy tràn cả trang. */
      table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
      /* Thanh hành động dính đáy gọn lại. */
      .action-bar { padding: 8px 6px; gap: 6px; }
    }
    /* Khổ máy tính bảng / cửa sổ hẹp (641–1023px, khớp breakpoint nav <1024px): bảng rộng CUỘN
       trong khung thay vì đẩy cả trang trôi ngang. Trước đây rule `table{display:block}` chỉ có ở
       ≤640px nên khoảng 641–1023px không ai đỡ — bảng ~859px (vd .pl-table) tràn ở 768px
       (báo cáo CSS 05/09: /pipeline/ @768 tràn 122px). */
    @media (max-width: 1023px) {
      table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
    }

/* Cảnh báo LINK TRÙNG khi add footage (USER 2026-06-06) — nổi bật, đỏ. */
.dup-warn { display: flex; gap: 8px; align-items: flex-start; margin-top: 8px;
  background: #fde2e2; border: 1px solid #f0a3a3; border-left: 4px solid #d9342b;
  border-radius: 8px; padding: 9px 12px; color: #9b1c17; font-size: .92rem; }
.dup-warn-ico { font-size: 1.1rem; line-height: 1.2; }
.dup-warn a { color: #9b1c17; font-weight: 700; text-decoration: underline; }
.dup-warn-block { margin: 10px 0 14px; }
.dup-warn-block code { background: #fff0f0; padding: 0 4px; border-radius: 4px; }

/* === HEADER nav gom 4 NHÓM (USER 2026-06-20) — 2 nút chính + dropdown <details> + hamburger. === */
.site-header { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px;
  padding: 8px 14px; border-bottom: 2px solid var(--pri); margin-bottom: var(--sp-3);
  background: var(--surface); position: relative; }
.site-header .brand { font-weight: 800; font-size: 1.05rem; color: var(--pri-d); text-decoration: none; }

/* 2 NÚT CHÍNH (dùng nhiều nhất) — solid, nổi bật, tách khỏi menu thường. */
.site-header .nav-primary { display: flex; gap: var(--sp-2); align-items: center; }
.np-btn { display: inline-flex; align-items: center; gap: 4px; padding: 6px 13px; border-radius: var(--r-pill);
  font-weight: 700; font-size: .9rem; text-decoration: none; color: #fff; white-space: nowrap;
  border: 1px solid transparent; box-shadow: var(--sh-1); transition: filter .12s, transform .06s; }
.np-btn:hover { filter: brightness(1.06); }
.np-btn:active { transform: translateY(1px); }
.np-add { background: var(--ok); }
.np-plan { background: var(--pri); }

/* Hamburger — ẩn ở desktop, hiện <1024px. */
.nav-burger { display: none; padding: 4px 11px; font-size: 1.15rem; line-height: 1; background: var(--surface);
  color: var(--txt); border: 1px solid var(--bd); border-radius: var(--r); cursor: pointer; }
.nav-burger:hover { background: var(--surface-2); }

/* Nav + nhóm. */
.site-header .main-nav { display: flex; flex-wrap: wrap; gap: 4px 6px; align-items: center; }
.nav-flat { padding: 6px 10px; border-radius: var(--r); text-decoration: none; color: #234;
  font-weight: 600; font-size: .92rem; }
.nav-flat:hover { background: var(--info-bg); }

/* Dropdown nhóm = <details> CSS thuần (nav_toggle.js chỉ thêm tiện ích đóng-ngoài). */
.nav-group { position: relative; }
.nav-group > summary { list-style: none; cursor: pointer; padding: 6px 10px; border-radius: var(--r);
  color: #234; font-weight: 600; font-size: .92rem; user-select: none; white-space: nowrap;
  display: inline-flex; align-items: center; gap: 4px; }
.nav-group > summary::-webkit-details-marker { display: none; }
.nav-group > summary::after { content: "▾"; font-size: .7rem; color: var(--txt-2); }
.nav-group > summary:hover, .nav-group[open] > summary { background: var(--info-bg); }
.nav-group .nav-menu { position: absolute; top: 100%; left: 0; z-index: var(--z-nav); margin-top: 4px;
  min-width: 190px; display: flex; flex-direction: column; gap: 2px; padding: 6px;
  background: var(--surface); border: 1px solid var(--bd); border-radius: var(--r-lg); box-shadow: var(--sh-2); }
.nav-group .nav-menu a { padding: 7px 10px; border-radius: var(--r-sm); text-decoration: none; color: #234;
  font-weight: 600; font-size: .9rem; white-space: nowrap; }
.nav-group .nav-menu a:hover { background: var(--info-bg); }
.nav-group .nav-menu .nav-admin { color: #8a5a00; }

.site-header .user-area { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-left: auto; }
.site-header .user-name { font-size: .85rem; color: var(--txt-2); }
.site-header .nav-icon { text-decoration: none; font-size: 1.05rem; }
.site-header .logout-form { display: inline; margin: 0; }
.site-header .logout-form button { padding: 3px 12px; font-size: .85rem; }

/* Responsive: <1024px → hamburger. Nav ẩn → mở thành panel dọc; dropdown thành tĩnh (mở sẵn). */
@media (max-width: 1023px) {
  .nav-burger { display: inline-block; order: 3; }
  .site-header .main-nav { display: none; order: 10; flex-basis: 100%; flex-direction: column;
    align-items: stretch; gap: 4px; padding: 8px 0 4px; }
  .site-header.nav-open .main-nav { display: flex; }
  .nav-group, .nav-flat { width: 100%; }
  .nav-group > summary::after { margin-left: auto; }
  .nav-group .nav-menu { position: static; box-shadow: none; border: none; min-width: 0;
    margin: 2px 0 4px 14px; padding: 0; }
}
@media (max-width: 560px) {
  .site-header { gap: 6px 8px; }
  .site-header .user-name { display: none; }
  .np-btn span { display: none; }   /* màn rất hẹp: chỉ còn icon ➕/🎬 */
  .np-btn { padding: 6px 10px; }
}

/* === FAB (nút nổi) góc dưới-phải — luôn thấy khi cuộn. <details> xoè 2 hành động (USER 2026-06-20).
   Ẩn ở trang có thanh hành động dính (.action-bar: detail/pick/result) để KHÔNG đè nút. === */
.fab { position: fixed; right: 18px; bottom: 18px; z-index: var(--z-fab); }
/* .cw-bar = thanh 🚀 wizard (N1.5); .cw-mixbar = thanh Trộn nguồn (C2 2026-07-20: z55 đè FAB z40 → ẩn FAB khi hiện). */
/* .res-savebar (thẻ Giọng), .pick-cta-sticky (chi tiết kế hoạch), .tc-actions (Cấu hình team) đều là
   thanh DÍNH đáy → FAB ➕ (z40) đè lên nút "Lưu"/"Pick" ở khổ điện thoại (báo cáo CSS 05/09:
   fixed_chong_lan=1 trên /pipeline/team-config/ và trang chi tiết kế hoạch). Ẩn FAB khi có các thanh này. */
body:has(.action-bar) .fab, body:has(.cw-bar) .fab,
body:has(.cw-mixbar:not([hidden])) .fab,
body:has(.res-savebar) .fab, body:has(.pick-cta-sticky) .fab,
body:has(.tc-actions) .fab { display: none; }
.fab > .fab-main { list-style: none; cursor: pointer; width: 52px; height: 52px; border-radius: 50%;
  background: var(--pri); color: #fff; font-size: 1.5rem; line-height: 1; display: flex;
  align-items: center; justify-content: center; box-shadow: var(--sh-2); user-select: none;
  transition: transform .15s, background .12s; }
.fab > .fab-main::-webkit-details-marker { display: none; }
.fab > .fab-main:hover { background: var(--pri-d); }
.fab[open] > .fab-main { transform: rotate(45deg); background: var(--danger); }  /* ➕ → ✕ */
.fab .fab-menu { position: absolute; right: 0; bottom: 62px; display: flex; flex-direction: column;
  gap: 8px; align-items: flex-end; }
.fab .fab-item { display: inline-flex; align-items: center; gap: 8px; padding: 9px 15px;
  background: var(--surface); color: var(--txt); font-weight: 700; font-size: .9rem; text-decoration: none;
  border: 1px solid var(--bd); border-radius: var(--r-pill); box-shadow: var(--sh-2); white-space: nowrap; }
.fab .fab-item:hover { background: var(--info-bg); border-color: var(--pri); }
.fab .fab-ico { font-size: 1.05rem; }
@media (max-width: 560px) { .fab { right: 12px; bottom: 12px; } }

/* Footer khẳng định chủ quyền team — mọi trang (USER 2026-06-07). Đơn giản mà đẹp. */
.site-footer { margin-top: 36px; padding: 18px 16px 22px; text-align: center;
  border-top: 1px solid var(--bd); color: #9aa0ab; font-size: .84rem; letter-spacing: .2px; }
.site-footer .sf-brand { font-weight: 800; letter-spacing: .6px;
  background: linear-gradient(90deg, var(--pri), #d6336c); -webkit-background-clip: text;
  background-clip: text; color: transparent; }
.site-footer .sf-sep { color: var(--bd); margin: 0 2px; }

/* Flow B (USER 2026-06-07) — trạng thái TẢI LIVE inline ở khu Add (pha + % bar). */
.dlb { border:1px solid var(--bd); border-radius:9px; padding:8px 11px; margin:8px 0;
  font-size:.88rem; background:#f7f9fc; }
.dlb-run { border-color:#cfe0ff; background:#f5f9ff; }
.dlb-warn { border-color:#fcd34d; background:#fffaf0; }
.dlb-done { border-color:#bfe6c8; background:#eef9f1; color:#0a6b1e; }
.dlb-err { border-color:#f0b3b3; background:#fde2e2; color:#9b1c17; }
.dlb-row { display:flex; align-items:center; gap:8px; margin-bottom:6px; }
.dlb-msg { flex:1; }
.dlb-pct { font-weight:700; color:var(--pri-d); font-variant-numeric:tabular-nums; }
.dlb-retry { padding:2px 10px; font-size:.82rem; margin-left:8px; }
.dl-pbar { height:8px; border-radius:999px; background:#e3e9f2; overflow:hidden; }
.dl-pfill { display:block; height:100%; border-radius:999px;
  background:linear-gradient(90deg,var(--pri),#34a853); transition:width .4s ease; }
/* Chưa có % thật (CaoVideo chưa gửi) → animation chạy qua lại cho biết "đang tải". */
.dl-pbar.indet .dl-pfill { width:38% !important; animation:dlindet 1.25s ease-in-out infinite; }
@keyframes dlindet { 0%{margin-left:-40%} 100%{margin-left:100%} }

/* Ô "Mô tả (tiếng Việt)" — dùng ở CẢ trang Add lẫn Detail (USER 2026-06-07). Trước CSS chỉ nằm
   trong detail.html → trang Add (_tag_form) thiếu → textarea bị global max-width:520 ép hẹp +
   rows=2 chật khi AI điền mô tả dài. Đưa vào app.css cho đồng nhất + min-height thoáng. */
.caption-box { border-left: 3px solid var(--pri); }
/* USER 2026-06-15: textarea AI Mô tả tự cao bằng nội dung (js-autogrow) → hiện hết text, không kéo. */
.caption-input { width: 100%; max-width: 100%; min-height: 84px; line-height: 1.55; padding: 9px 11px;
  font: inherit; font-size: .95rem; border: 1px solid #d8cef0; border-radius: 8px; resize: vertical;
  background: #fff; color: #1e2330; box-sizing: border-box; }
.caption-input:focus { outline: none; border-color: #7b5cd6; box-shadow: 0 0 0 3px rgba(123,92,214,.18); }

/* USER 2026-06-10 — "AI Mô tả" (vi_caption) sửa/lưu inline; USER 2026-06-15 — khung gọn đẹp. */
.ai-caption { margin: 10px 0; padding: 10px 12px; background: #faf8ff; border: 1px solid #e8e1f6;
  border-radius: 10px; }
.ai-cap-label { font-size: .9rem; font-weight: 700; margin-bottom: 6px; color: #4a3b6b; }
.ai-cap-bar { display: flex; align-items: center; gap: 8px; margin-top: 7px; }
.ai-cap-save { padding: 4px 14px; font-size: .84rem; }
.ai-cap-ok { color: #1a9d57; font-size: .82rem; font-weight: 600; }

/* Sửa nhanh TIÊU ĐỀ footage (nút bút chì + auto-lưu) — USER 2026-06-16. Dùng ở Kho + trang chi tiết. */
.ftitle-box { display: flex; align-items: center; gap: 4px; min-height: 1.3em; }
.ftitle-box--h { display: inline-flex; gap: 6px; }  /* trang chi tiết: bọc <h1> + bút chì thành 1 cụm */
.ttl-edit { flex: none; background: none; border: none; cursor: pointer; font-size: .78rem;
  line-height: 1; padding: 2px 4px; border-radius: 5px; opacity: .4;
  transition: opacity .12s, background .12s; }
.ttl-edit:hover { opacity: 1; background: #eef4ff; }
/* `input.ttl-input` (0,1,1): hoà specificity input[type=text] toàn cục, đứng sau nên thắng
   (trước bị đè: padding phình 9px, mất đậm/cỡ chữ). .ftitle-box--h (0,2,0) vẫn thắng ở heading. */
input.ttl-input { width: 100%; font-weight: 600; font-size: .9rem; padding: 2px 6px;
  border: 1px solid var(--pri); border-radius: 6px; outline: none; box-sizing: border-box; }
.ftitle-box--h .ttl-input { font-size: 1.1rem; min-width: 240px; }

/* === ADR-0077: Vẽ minh hoạ khoảnh khắc (illustrate) — cột trong bảng Giọng & lời bình === */
.illus-toolbar { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin: 6px 0 10px; }
/* Tím phân biệt với nút dịch/voice — cần `button.go.illus-batch` (0,2,1) thắng button.go (0,1,1),
   selector trần bị đè → nút từng hiện xanh lá. */
button.go.illus-batch { background: #6d3fb8; border-color: #6d3fb8; }
button.go.illus-batch:hover { background: #582f9e; border-color: #582f9e; }
.col-illus { width: 132px; vertical-align: top; }
.illus-tick-lbl { display: inline-flex; align-items: center; gap: 3px; font-size: .74rem;
  color: #6d3fb8; margin-bottom: 4px; cursor: pointer; }
.illus-thumb { display: block; }
.illus-thumb img { max-width: 120px; max-height: 90px; border-radius: 6px; border: 1px solid var(--bd);
  display: block; background: #faf7ff; }
.illus-inter { display: block; font-size: .72rem; color: #555; margin: 2px 0; font-style: italic; }
.illus-ctl { display: flex; flex-direction: column; gap: 4px; margin-top: 4px; }
.illus-emo-sel { font-size: .74rem; padding: 2px 4px; max-width: 128px; }
.illus-draw { font-size: .74rem; padding: 3px 6px; }
.illus-draw:disabled { opacity: .5; cursor: not-allowed; }
.illus-wait { font-size: .74rem; color: var(--pri-d); }
.illus-banner-ok { font-size: .8rem; color: #6d3fb8; font-weight: 600; }
.illus-msg { display: block; font-size: .72rem; margin: 2px 0; }
.illus-msg.blk, .illus-msg.err { color: var(--danger); }
.illus-msg.skp { color: #8a6d1e; }
.illus-style-field .illus-style-preset { margin-bottom: 5px; }
.illus-style-field textarea { width: 100%; max-width: 480px; box-sizing: border-box; font-size: .8rem;
  resize: vertical; }

/* ĐỢT 2 (USER 2026-07-18) — tooltip ⓘ tròn: chuyển từ plan_detail.html (page-scoped) lên app.css
   (GLOBAL) để form Nhân bản trong Trung tâm (_clone_channel_form) cũng ăn style (ADR-0086 dời form ra
   khỏi plan_detail → abbr.ihint mất nền/bo tròn). plan_detail dùng chung rule này qua base.html. */
abbr.ihint { display: inline-flex; align-items: center; justify-content: center; width: 18px;
  height: 18px; border-radius: 50%; background: #e6eefb; color: #1558b8; font-size: .72rem;
  font-weight: 700; cursor: help; border: 1px solid #cfe0ff; text-decoration: none; flex: none; }

/* === ADR-0084: ⚡ Nhân bản nhanh (quick clone) — trang riêng, khớp token site === */
.qk-form { display: flex; flex-direction: column; gap: 12px; align-items: flex-start; }
.qk-table { width: 100%; border-collapse: collapse; background: var(--surface, #fff);
  border: 1px solid var(--bd, #e2e8f0); border-radius: 8px; }
.qk-table th { text-align: left; padding: 8px 10px; background: #eef3fb; font-size: .82rem;
  border-bottom: 2px solid #c9d8ef; }
.qk-table td { padding: 7px 10px; border-bottom: 1px solid #eceff3; vertical-align: middle; }
.qk-table select, .qk-table input[type="text"] { width: 100%; max-width: 280px; font: inherit;
  padding: 5px 8px; }
.qk-lang { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; cursor: pointer;
  white-space: nowrap; }
.qk-opts { display: flex; flex-direction: column; gap: 6px; }
.qk-opts label { cursor: pointer; }
.qk-card { width: 100%; background: var(--surface, #fff); border: 1px solid var(--bd, #e2e8f0);
  border-radius: 8px; padding: 12px 14px; box-shadow: 0 1px 2px rgba(0,0,0,.05); }
.qk-card.qk-skip { opacity: .65; }
.qk-card-head { font-size: .95rem; margin-bottom: 8px; }
.qk-note { padding: 7px 10px; border-radius: 6px; background: #f6f8fc; border: 1px solid #e2e8f4;
  font-size: .88rem; }
.qk-note.qk-ok { background: #eaf7ee; border-color: #a9d8ba; color: #256b3a; }
.qk-note.qk-warn { background: #fff4e5; border-color: #f0c98a; color: #8a5a1a; }
.qk-warn-txt { color: #b45309; }
.qk-conflicts { margin-top: 8px; }
.qk-clip { display: flex; gap: 8px; align-items: center; }
.qk-clip img { width: 84px; max-height: 56px; object-fit: cover; border-radius: 6px;
  border: 1px solid var(--bd, #e2e8f0); }
.qk-clip .hint { display: block; }
button.go.big { font-size: 1rem; padding: 9px 20px; }

/* A1 (USER 2026-07-19) — ô tìm giọng GỘP tên + Voice ID (.vl), dùng chung sửa kênh + wizard */
.vl { position: relative; max-width: 420px; }
.vl-chip { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.vl-cur { font-size: .9rem; }
.vl-change { padding: 3px 10px; font-size: .82rem; }
.vl-search { margin-top: 5px; }
.vl-q { width: 100%; box-sizing: border-box; padding: 6px 10px; border: 1px solid var(--bd, #cbd5e1);
  border-radius: 7px; font-size: .9rem; }
.vl-q:focus { border-color: var(--accent, #3b6cff); outline: none; }
.vl-drop:not(:empty) { position: absolute; z-index: 30; left: 0; right: 0; margin-top: 3px;
  border: 1px solid var(--bd, #cbd5e1); border-radius: 8px; padding: 6px 10px;
  background: var(--surface, #fff); box-shadow: 0 6px 20px rgba(0,0,0,.14); max-height: 320px;
  overflow: auto; min-width: 260px; }
.vl-drop .voice-results { list-style: none; margin: 4px 0 0; padding: 0; }
.vl-drop .voice-results li { display: flex; gap: 7px; align-items: center; flex-wrap: wrap;
  padding: 4px 0; border-top: 1px solid #f0f2f6; }
.vl-drop .voice-results li:first-child { border-top: 0; }
/* V2.6 (2026-07-19) — badge provider giọng (dùng chung; theme sáng mặc định, .cw-page override tối). */
.vl-prov { font-size: .64rem; font-weight: 800; padding: 1px 5px; border-radius: 5px;
  background: #eef1f6; color: #556; border: 1px solid #dfe4ec; letter-spacing: .03em; }
.vl-prov.prov-el { background: #eef4ff; color: #2b57c8; border-color: #d3e0fb; }
/* ADR-0147 (2026-09-09) — badge 🧬 GIỌNG NHÂN BẢN trong ô chọn giọng.
   VÌ SAO phải là màu KHÁC HẲN `.prov-el`, không phải một sắc xanh khác: hai badge này đứng CẠNH
   NHAU trong cùng danh sách kết quả, mà mã của chúng thuộc HAI NAMESPACE không thể thay cho nhau
   (`21m00Tcm…` của ElevenLabs ↔ `user_3282_voice_…` của ai84/MiniMax). Chọn nhầm dòng = nhét mã
   nhân bản vào slot ElevenLabs ⇒ cả ba nguồn dự phòng đều tra trượt ⇒ **clip CÂM, không một dòng
   lỗi** (xem `models.Channel.ai84_clone_voice_id`). Tím = cùng hệ màu khối 🧬 `.ai84-plan-block`
   (#b9a3e8 / #f7f4ff) nên người dùng nối được "badge tím ↔ khối tím" mà không phải đọc chữ. */
.vl-prov.prov-clone { background: #f3edff; color: #6a3fb5; border-color: #ddcdf6; }

/* FB4 (USER 2026-07-19) — console Nhật ký (.pl-*) DÙNG CHUNG: trước chỉ có ở plan_detail (inline);
 * đưa ra app.css để Trung tâm Nhân bản hiện log tiến trình nhân bản y như tạo kế hoạch mới.
 * plan_detail vẫn có <style> .pl-* riêng (nạp sau → tự đè, cùng quy tắc — vô hại). */
.pl-log { border: 1px solid #E2E8F0; background: #fff; border-radius: 12px; padding: 14px 16px;
  margin: 12px 0 16px; width: auto; max-width: 100%; }
.pl-log.pl-empty { background: #fafbfc; border-color: #e7ebf1; }
.pl-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; font-size: .95rem; padding-bottom: 4px; }
.pl-ttl { font-weight: 800; color: #14315f; font-size: 1.02rem; }
.pl-badge { font-size: .78rem; font-weight: 700; padding: 3px 10px; border-radius: 6px; }
.pl-badge.run { background: #fff3d0; color: #8a6d00; }
.pl-badge.run::before { content: ""; display: inline-block; width: 7px; height: 7px; margin-right: 6px;
  border-radius: 50%; background: #f0a500; vertical-align: middle; animation: pl-blink 1s infinite; }
@keyframes pl-blink { 50% { opacity: .25; } }
.pl-badge.ok { background: #DCFCE7; color: #15803D; }
.pl-badge.err { background: #fde2e2; color: #c0262e; }
.pl-cnt { margin-left: auto; color: #3f5170; font-size: .9rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.pl-bar { height: 10px; background: #e9eef6; border-radius: 999px; overflow: hidden; margin: 10px 0 4px; }
.pl-bar > span { display: block; height: 100%; border-radius: 999px; background: #22C55E; transition: width .4s; }
.pl-lines { max-height: 280px; overflow: auto; margin-top: 10px; padding: 12px; line-height: 1.7;
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace; font-size: 12.5px;
  background: #0B1220; border-radius: 8px; color: #34D399; }
.pl-ln { white-space: pre-wrap; word-break: break-word; color: #34D399; }
.pl-ln b { color: #64748B; font-weight: 400; margin-right: 10px; font-variant-numeric: tabular-nums; }
.pl-ln.lv-ok { color: #34D399; }
.pl-ln.lv-warn { color: #FBBF24; }
.pl-ln.lv-error { color: #F87171; font-weight: 700; }
.pl-ln.lv-step { color: #93C5FD; font-weight: 700; border-top: 1px dashed #334865; margin-top: 8px; padding-top: 8px; }
.pl-clear { margin-left: 8px; background: none; border: 1px solid #d6dce8; color: #6b7890;
  border-radius: 6px; font-size: .76rem; padding: 2px 9px; cursor: pointer; }
.pl-idle { color: #7a8699; font-size: .9rem; }

/* USER 2026-09-03 — "gỡ thẻ khỏi nhóm chủ đề" (bảng chọn cascade). Đặt gập mặc định + chữ nhỏ để
   KHÔNG cạnh tranh thị giác với hàng chip đang dùng để gắn thẻ; chỉ ai đi tìm mới mở ra. */
.go-the-nhom { margin: 2px 0 8px; }
.go-the-nhom > summary { cursor: pointer; font-size: .78rem; color: var(--muted, #777); padding: 2px 0; }
.go-the-nhom > summary:hover { color: var(--pri, #b00); }
.go-the-nhom > .hint { font-size: .76rem; margin: 2px 0 4px; }
.go-the-x { font-size: .78rem; padding: 2px 8px; border-radius: 999px; }
.go-the-x:hover { border-color: var(--pri, #b00); color: var(--pri, #b00); }

/* UI-PIPELINE-GON (USER 2026-09-04 — "cột TÊN của dự án rất dài, gây khó dễ cho user"): cột Tên
   trang /pipeline/ dùng tên RÚT GỌN (#STT · loại · kênh · lang, xem `pipeline/nguon_tron.ten_ngan`)
   + kẹp bề rộng & ellipsis cho cả Tên lẫn Nguồn trộn — tên đầy đủ nằm ở tooltip (title=) và trang
   chi tiết. min-width:0 để flex cho phép co; vertical-align:bottom né tụt baseline khi inline-block. */
.pl-table td.pl-name { max-width: 340px; }
.pl-table .pl-name-view { max-width: 100%; min-width: 0; }
.pl-table a.pl-name-link { display: inline-block; max-width: 100%; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
/* USER 2026-09-10: *"cột Nguồn trộn không được ngắt dòng, nên sẽ bị… user không nhìn thấy"*.
   Trước: `white-space:nowrap` + `text-overflow:ellipsis` ⇒ đo Chrome headless @1280 với 14 hàng
   mẫu: 6/14 ô bị CẮT, ô dài nhất cần 860px mà chỉ được 260px — mất 70% chữ, mà chữ mất chính là
   tên nguồn phụ + tỉ lệ %, tức là toàn bộ thông tin của cột.
   Nay cho NGẮT DÒNG thật (`normal` + `break-word`) thay vì kẹp 2 dòng `-webkit-line-clamp`: cắt
   2 dòng vẫn giấu chữ, mà bảng KHÔNG hề thiếu chỗ — hàng ở khổ ≥1180 đã cao 67-88px sẵn (nút Mở +
   badge), 3 dòng chữ 1.35 chỉ ~54px nên nằm gọn trong chiều cao có sẵn, bảng không đẩy trang trôi
   ngang (đo lại 1180/1280/1440: page_scroll_w = đúng bề rộng cửa sổ, table không cuộn ngang).
   Nới trần 260→300px vì bảng còn chỗ trống ở khổ rộng (đo @1440: cột "Chế độ" tự phình tới 198px).
   ⚠ `min-width` là BẮT BUỘC, không phải trang trí: bỏ `nowrap` xong thì bố cục bảng tự động co cột
   này về min-content rồi đem chỗ dôi cho cột khác — đo lần 1 sau khi sửa: @1180 cột tụt 260→137px
   nên ô dài nhất cao 188px (4-5 dòng) trong khi cột "Chế độ" phình lên 120px không dùng tới. Ghim
   sàn 228px để kéo chỗ về đúng cột cần chữ (240px thì @1180 bảng dôi ra 1px so với khung).
   ⛔ ĐỪNG thêm lại `overflow:hidden` ở đây — ô này nay cao theo nội dung, hidden = cắt câm lần nữa. */
.pl-table td.pl-nguon { min-width: 228px; max-width: 300px; white-space: normal;
  overflow-wrap: break-word; line-height: 1.35; }
@media (max-width: 640px) {
  /* Màn hẹp: bảng đã là khung cuộn ngang (rule table display:block ở trên) — vẫn kẹp 2 cột dài
     để mỗi hàng KHÔNG kéo khung cuộn đi cả cây số. */
  .pl-table td.pl-name { max-width: 52vw; }
  /* Gỡ sàn 228px của khổ rộng — trên màn hẹp sàn đó ăn hết khung cuộn. Chữ vẫn KHÔNG bị cắt
     (đã `white-space:normal`), chỉ xuống dòng nhiều hơn. */
  .pl-table td.pl-nguon { min-width: 0; max-width: 40vw; }
}

/* V3 (USER 2026-09-10) — 2 cột CỜ "R2" + "QC" ở /pipeline/ (bảng lên 11 cột). Ô chỉ chứa MỘT ký
   tự (✅ / ⚠ / ·) nên ép hẹp + canh giữa: để cột tự dãn thì 11 cột cộng lại vượt khung và trang
   trôi ngang — đúng lớp lỗi báo cáo CSS 05/09 đã đo ở chính bảng này. Padding ngang bóp còn 3px
   vì `.pl-table td` mặc định 8px mỗi bên = 16px thừa cho một ký tự.
   ⚠ CỐ Ý KHÔNG bọc bảng trong khung `overflow-x:auto` ở khổ ≥1024px: menu ⋯ của mỗi hàng là
   `position:absolute` (plan_list.html) — tổ tiên có overflow là bị CẮT (chính vì thế ≤640px phải
   đổi menu sang `position:fixed`). Đo Chrome headless 10/09: 1180/1280/1440px đều KHÔNG tràn. */
.pl-table th.pl-col-flag, .pl-table td.pl-col-flag { width: 44px; text-align: center;
  padding-left: 3px; padding-right: 3px; }
.pl-table .pl-flag-no { color: #c3ccd9; }                 /* chưa làm — mờ, không phải "—" */
.pl-table .pl-flag-err { color: var(--danger, #c0262e); font-weight: 700; }
/* Badge DẪN XUẤT ở cột Trạng thái — màu KHÁC hẳn badge vòng đời (st-draft/st-picked) để mắt tách
   được hai chiều thông tin đứng cạnh nhau. Dùng chung bảng màu với nhãn 🧬/🔀 ở cột Tên. */
.pl-badge-clone { background: #eef2ff; color: #4338ca; }
.pl-badge-mix { background: #f3ebff; color: #7c3aed; }

/* ═══ KHUÔN A1 · B1 · C1 (USER chốt 22/09, mockup "Đặt tên kế hoạch") ═══════════════════════════
   Màu LẤY ĐÚNG mockup và trùng bảng màu badge ngay trên: chàm #4338ca = nhân bản · tím #7c3aed =
   trộn · xanh mòng két #0d9488 = mã team.
   ⚠ Mockup dùng JetBrains Mono nhưng CSP của prod là `default-src 'self'` (config/settings/prod.py
   — cố ý bỏ CDN bên thứ 3, chống supply-chain) nên KHÔNG nhúng font từ CDN ngoài được. Dùng mono HỆ
   THỐNG: vẫn đều chữ số, vẫn `tabular-nums`, 0 request ngoài. */
.pl-so { font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
         font-weight: 700; font-variant-numeric: tabular-nums; margin-right: 6px; color: #475569; }
.pl-so-clone { color: #4338ca; }
.pl-so-mix { color: #7c3aed; }
.pl-team { font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
           font-size: .78rem; font-weight: 700; letter-spacing: .04em; padding: 1px 7px;
           border-radius: 4px; background: #e6f6f4; color: #0d9488; border: 1px solid #b8e6e0;
           margin-right: 6px; }
.pl-ten { font-weight: 600; }

/* Cột Xuất xứ — 2 tầng */
.pl-xx-nguon { line-height: 1.45; }
.pl-nen { font-weight: 700; font-size: .72rem; letter-spacing: .05em; color: #7c3aed;
          background: #f3ebff; padding: 1px 6px; border-radius: 4px; margin-right: 4px; }
.pl-plus { color: #7c3aed; font-weight: 700; padding: 0 4px; }
.pl-xx-lbl { font-size: .72rem; font-weight: 700; text-transform: uppercase;
            letter-spacing: .05em; color: #77839a; }
.pl-pct { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-weight: 700;
          font-variant-numeric: tabular-nums; color: #64748B; }
.pl-pct-nen { color: #7c3aed; }
.pl-sysname { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
              font-size: .78rem; color: #77839a; margin-top: 2px; word-break: break-word; }

/* Thẻ rê chuột (C1) — thuần CSS, không JS (CSP `script-src 'self'`). */
/* Mốc định vị là chính ô <td class="pl-name"> (thẻ rê là ANH EM của thẻ <a>, không nằm trong nó). */
td.pl-name { position: relative; }
.pl-hov { position: absolute; left: 0; top: calc(100% + 6px); z-index: 60; width: 320px;
          max-width: min(320px, 92vw); background: #fff; border: 1px solid #d4d7dd;
          border-radius: 10px; box-shadow: 0 8px 26px rgba(15, 23, 42, .16);
          opacity: 0; visibility: hidden; transition: opacity .12s ease; pointer-events: none;
          text-align: left; font-weight: 400; }
/* Hiện khi rê chuột vào Ô TÊN, hoặc khi bàn phím focus vào link trong ô (a11y). */
.pl-name:hover .pl-hov, .pl-name:focus-within .pl-hov { opacity: 1; visibility: visible; }
/* Đang SỬA TÊN tại chỗ (ô tick ẩn `.pl-name-tog` bật) ⇒ ẩn thẻ, không che ô nhập. */
.pl-name-tog:checked ~ .pl-name-view .pl-hov { opacity: 0 !important; visibility: hidden !important; }
/* GỌN VỪA (USER 22/09: *"bỏ dòng thừa, chữ nhỏ hơn"*) — GIỮ ĐỦ 5 nhóm tin (Làm từ · Đi về · Quy mô ·
   Vướng gì · Tên hệ), chỉ nén lại còn ~2/3: 430→320px bề rộng, đầu thẻ 2 dòng → 1 DÒNG (trước đây
   `.pl-hov-nm` in `plan.title` y hệt dòng "Tên hệ" ở đáy thẻ — cùng một chuỗi in HAI lần trong cùng
   một thẻ; nay đầu thẻ mang TÊN HIỂN THỊ, đáy thẻ mang TÊN HỆ, hết trùng), đệm 10/12→7/9px, cỡ chữ
   .9→.8rem, cột nhãn 74→56px. */
.pl-hov-hd { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px;
             padding: 7px 11px; background: #f7f9fc; border-bottom: 1px solid #eef0f3;
             border-radius: 10px 10px 0 0; }
.pl-hov-ttl { display: inline; flex: none; }
.pl-hov-nm { display: inline; font-weight: 600; color: #1f2330; min-width: 0;
             overflow-wrap: anywhere; }
.pl-hov-bd { display: flex; flex-direction: column; gap: 6px; padding: 9px 11px; }
.pl-hov-row { display: grid; grid-template-columns: 56px 1fr; gap: 8px; align-items: baseline; }
.pl-hov-k { font-size: .66rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
            color: #77839a; }
.pl-hov-v { font-size: .8rem; color: #1f2330; line-height: 1.4; }
.pl-hov .pl-sysname { font-size: .72rem; margin-top: 0; }
.pl-hov-chips { display: flex; gap: 5px; flex-wrap: wrap; padding-top: 2px;
                border-top: 1px solid #eef0f3; margin-top: 1px; }
.pl-hov .pl-chip { font-size: .68rem; padding: 1px 7px; }
.pl-hov .pl-so { margin-right: 4px; }
.pl-hov .pl-team { font-size: .7rem; padding: 0 5px; margin-right: 2px; }
.pl-chip { font-size: .76rem; font-weight: 600; padding: 2px 9px; border-radius: 999px;
           background: #f5f8fc; border: 1px solid #e2e8f0; color: #4a5468; }
.pl-chip-ok { background: #e3f5e9; color: #157e46; border-color: #bce4cd; }
.pl-chip-warn { background: #fff3cd; color: #8a6d00; border-color: #eddc9a; }
/* VIỆC 7 (USER 22/09) — cột Tiến độ gộp: chip xếp dòng, ô trống khi chưa có gì để nói. */
.pl-chip-run { background: #fff3d0; color: #8a6d00; border-color: #e8d59a; }
.pl-tiendo { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; max-width: 190px; }
.pl-tiendo .pl-chip { font-size: .72rem; padding: 1px 7px; }

/* 🔴 LẬT THẺ — ĐO THẬT, KHÔNG ĐOÁN THEO VỊ TRÍ TRONG DOM (USER 22/09: *"vị trí dòng chỉ vào ở dưới
   cùng thì popup hiện lên trên, không để khuất tầm nhìn user"*).
   Luật CŨ là `.pl-table tbody tr:nth-last-child(-n+2) .pl-hov { bottom: ... }` — nó chỉ lật cho 2
   hàng CUỐI CỦA tbody. Trang phân 50 dòng/trang (views.plan_list `Paginator(qs, 50)`) nên 48/50
   hàng còn lại VẪN mở xuống, và hàng nào đang nằm gần mép dưới CỬA SỔ lúc rê chuột thì thẻ rơi ra
   ngoài tầm nhìn — đúng phàn nàn của USER. "Hàng cuối của bảng" và "hàng cuối trên màn hình" là hai
   chuyện khác nhau; chỉ đo `getBoundingClientRect` mới biết.
   Nay `plan_list.js` đo ô + thẻ rồi gắn `.pl-hov-up` (hết chỗ dưới) / `.pl-hov-left` (tràn mép phải).
   ⚠ Thẻ ẩn bằng `opacity/visibility` (KHÔNG `display:none`) nên đo lúc chưa rê vẫn ra kích thước
   thật — đừng đổi sang `display:none`, phép đo sẽ ra 0. */
.pl-hov-up { top: auto; bottom: calc(100% + 6px); }
.pl-hov-left { left: auto; right: 0; }
@media (prefers-reduced-motion: reduce) { .pl-hov { transition: none; } }
/* ≤1023px: `table{display:block;overflow-x:auto}` (app.css:487) biến bảng thành KHUNG CUỘN ⇒ thẻ
   `position:absolute` bị CẮT trong khung (đúng lý do menu ⋯ phải đổi sang `fixed` ở ≤640px).
   Trước đây chỗ này là `@media (max-width:760px){.pl-hov{display:none}}` — ẩn hẳn thẻ; cộng với
   việc bản vá này bỏ `title=` thô ở cột Tên thì màn hẹp sẽ MẤT HẲN tên đầy đủ (link bị ellipsis,
   app.css:788-789). Nên thay vì ẩn: đổi sang `fixed` + neo ĐÁY MÀN HÌNH, vị trí cố định nên
   KHÔNG cần JS tính, không bao giờ lọt ra ngoài tầm nhìn.
   Ghi rõ cả `.pl-hov-up`/`.pl-hov-left` để class do JS gắn (specificity 0,2,0) không thắng ngược. */
@media (max-width: 1023px) {
  .pl-hov, .pl-hov.pl-hov-up, .pl-hov.pl-hov-left {
    position: fixed; z-index: 70; top: auto; bottom: 10px; left: 4vw; right: 4vw;
    width: auto; max-width: none; }
}

/* GONBQ (USER 2026-09-06) — banner ĐỎ "kế hoạch chứa clip có thẻ Bản quyền" (ADR-0128,
   plan_detail.html): 266 kế hoạch dính banner, cao nhất 95 clip → danh sách không cắt đẩy hộp
   cảnh báo lên ~48 dòng màn hình. Hộp đỏ + số lượng + chữ "CẤM dùng" + 3 mã đầu LUÔN HIỆN;
   chỉ ĐUÔI danh sách gấp vào <details> native (zero-JS — prod đặt CSP script-src 'self').
   Mẫu bắt chước `.srccmt-more`. Hộp vẫn giữ style inline nên KHÔNG lệ thuộc file này. */
.pl-bq-more { display: inline; }
.pl-bq-more > summary { display: inline; list-style: none; cursor: pointer;
  color: #7a0010; text-decoration: underline dotted; }
.pl-bq-more > summary::-webkit-details-marker { display: none; }
.pl-bq-more > summary::after { content: " ▸"; }          /* ▸ đóng */
.pl-bq-more[open] > summary::after { content: " ▾"; }    /* ▾ mở */
.pl-bq-rest { display: block; margin-top: 6px; font-weight: 500; line-height: 1.7;
  max-height: 260px; overflow-y: auto; }
.pl-bq-fix { margin-top: 6px; font-weight: 500; }

/* ── ADR-0152 (USER 2026-09-18) — ô "© Cho phép clip bản quyền" TRONG form Pick ───────────────────
   Cùng ngôn ngữ hình với công tắc `.bq-switch` ở form gắn thẻ (xem mục "LƯỚI CHIP DÙNG CHUNG"):
   TẮT = xanh lá "an toàn", BẬT = đỏ + chữ hoa "ĐANG CHO PHÉP". Trạng thái đọc bằng CHỮ + BIỂU
   TƯỢNG + MÀU, không chỉ màu. Thân ô (cảnh báo + chip hãng) CHỈ hiện khi đã bật — CSS thuần
   `:has()`, không JS (JS chỉ lo nạp chip). */
.bqp-box { margin: 0 0 8px; padding: 9px 12px; border-radius: 8px;
  border: 1px solid var(--ok, #1a9d57); border-left: 6px solid var(--ok, #1a9d57);
  background: var(--ok-bg, #dff5e1); }
.bqp-box:has(.bqp-tog input:checked) { border-color: var(--danger, #c0262e);
  border-left-color: var(--danger, #c0262e); background: var(--danger-bg, #fde2e2); }
.bqp-tog { display: flex; align-items: center; gap: 10px; cursor: pointer; user-select: none;
  padding: 7px 13px; border-radius: 999px; border: 2px solid var(--ok, #1a9d57);
  background: #fff; color: var(--ok-d, #157e46); width: fit-content; max-width: 100%;
  transition: background .12s, border-color .12s, color .12s; }
.bqp-tog input { position: absolute; opacity: 0; width: 0; height: 0; }
.bqp-den { flex: none; width: 40px; height: 22px; border-radius: 999px;
  background: var(--ok, #1a9d57); position: relative; transition: background .12s; }
.bqp-den::after { content: ""; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px;
  border-radius: 50%; background: #fff; transition: transform .12s; }
.bqp-chu b { font-weight: 700; }
.bqp-phu { font-weight: 400; opacity: .82; }
.bqp-chu .bqp-bat { display: none; }
.bqp-tog:has(input:checked) { border-color: var(--danger, #c0262e);
  background: var(--danger, #c0262e); color: #fff; }
.bqp-tog:has(input:checked) .bqp-den { background: rgba(255, 255, 255, .45); }
.bqp-tog:has(input:checked) .bqp-den::after { transform: translateX(18px); }
.bqp-tog:has(input:checked) .bqp-chu .bqp-tat { display: none; }
.bqp-tog:has(input:checked) .bqp-chu .bqp-bat { display: inline; }
/* Thân ô: ẩn hẳn khi TẮT (không chỉ mờ) — chip hãng lúc đó vô nghĩa và chỉ làm rối form Pick. */
.bqp-than { display: none; }
.bqp-box:has(.bqp-tog input:checked) .bqp-than { display: block; margin-top: 9px; }
.bqp-canh { margin: 0 0 8px; font-size: .88rem; line-height: 1.6;
  color: var(--danger-d, #9e1f26); }
.bqp-hang-dau { font-weight: 600; font-size: .88rem; margin-bottom: 5px; }
.bqp-chips { display: flex; flex-wrap: wrap; gap: 6px; max-height: 190px; overflow-y: auto; }
@media (prefers-reduced-motion: reduce) {
  .bqp-tog, .bqp-den, .bqp-den::after { transition: none; }
}

/* CỔNG CHẶN "bấm lại cùng kênh ra 0 CLIP" (USER 2026-09-06) — dải cảnh báo đếm-TRƯỚC ở wizard
   nhân bản/trộn (clone_wizard.html mount `.cw-chan`, JS clone_wizard.js `renderChanTron`, số liệu
   src/pipeline/sua_lai.py). Đặt ở app.css vì `pipeline/clone_wizard.css` KHÔNG thuộc phạm vi sửa
   của đợt này; app.css nạp ở templates/base.html:14 (trước clone_wizard.css) và tên lớp `.cw-chan*`
   chưa tồn tại ở đâu ⇒ không đè lên rule sẵn có. 3 mức: do (⛔ chắc chắn 0 clip) · vang (⚠ vơi
   clip) · ok (không mất clip / nhân bản chỉ trùng). */
.cw-chan { border-radius: 10px; padding: 10px 14px; margin: 10px 0; font-size: .88rem;
  line-height: 1.55; border: 1px solid var(--warn-bd); background: var(--warn-bg);
  color: var(--warn-txt); }
.cw-chan.do { border-color: var(--danger-bd); background: var(--danger-bg); color: var(--danger-d); }
.cw-chan.vang { border-color: var(--warn-bd); background: var(--warn-bg); color: var(--warn-txt); }
.cw-chan.ok { border-color: #b9c6d4; background: #eef3f8; color: #34495e; }
.cw-chan-ls { margin: 4px 0 0; padding-left: 20px; }
.cw-chan-ls li { margin: 2px 0; }
.cw-chan-loi { margin-top: 8px; font-weight: 700; }

/* "♻ SỬA LẠI DỰ ÁN" (USER 2026-09-06) — dải cảnh báo ở ĐỈNH wizard khi vào bằng `?tu=<bản cũ>`
   (clone_wizard.html khối `.cw-sualai`, dữ liệu điền sẵn ở src/pipeline/sua_lai.py).
   Nội dung BẮT BUỘC: (1) đây là bản MỚI, bản cũ giữ nguyên — bộ clip bản dẫn xuất bị khoá nên
   KHÔNG sửa tại chỗ được; (2) TỐN PHÍ — dịch + lồng tiếng chạy lại toàn bộ, bấm nhầm 2 lần = 2 lượt
   tiền (wizard gửi `allow_dup=1` nên không có cổng chặn trùng 1 giờ).
   Đặt ở app.css vì `pipeline/clone_wizard.css` KHÔNG thuộc phạm vi sửa của đợt này; app.css nạp ở
   templates/base.html:14 (TRƯỚC clone_wizard.css) và tên lớp `.cw-sualai*` chưa tồn tại ở đâu ⇒
   không đè lên rule sẵn có. Màu VÀNG (không đỏ): đây là việc hợp lệ có phí, không phải lỗi. */
.cw-sualai { border: 1px solid var(--warn-bd); border-left: 6px solid var(--warn); border-radius: 10px;
  background: var(--warn-bg); color: var(--warn-txt); padding: 10px 14px; margin: 0 0 12px;
  font-size: .88rem; line-height: 1.55; }
.cw-sualai-ttl { font-weight: 700; font-size: .95rem; margin-bottom: 4px; }
.cw-sualai-ls { margin: 0; padding-left: 20px; }
.cw-sualai-ls li { margin: 3px 0; }

/* ══ ADR-0142 — ô "🚫 Không lấy" (widget dùng chung: plan_form + plan_detail) ══════════════ */
  /* ADR-0142 — ô "🚫 Không lấy". Màu ĐỎ có chủ ý: đây là cửa CẤM, phải phân biệt ngay với mọi ô
     lọc CHO-VÀO màu xanh ở quanh nó, kẻo người dùng tích nhầm rồi tưởng đang chọn. */
  .lt-box { border: 1px solid #f0cccc; background: #fffafa; border-radius: 10px; margin: 8px 0; }
  .lt-box.lt-on { border-color: #e08585; background: #fff4f4; }
  .lt-sum { cursor: pointer; padding: 7px 11px; font-weight: 600; color: #b3261e; user-select: none; }
  .lt-count { font-weight: 700; }
  .lt-help { margin: 0 11px 7px; }
  .lt-chips { padding: 0 11px 10px; max-height: 260px; overflow-y: auto; }
  .lt-row { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; margin-bottom: 6px; }
  .lt-truc { flex: 0 0 78px; font-size: .8rem; color: #7a4a4a; }
  .lt-chip { display: inline-flex; align-items: center; gap: 4px; font-size: .8rem; padding: 2px 9px;
    border: 1px solid #e3cccc; border-radius: 999px; background: #fff; color: #543; cursor: pointer; }
  .lt-chip:hover { border-color: #d09090; }
  .lt-chip.on { background: #fde2e2; border-color: #c0262e; color: #a01a22; font-weight: 600; }
  .lt-chip input { margin: 0; accent-color: #c0262e; }

  /* ── USER 2026-09-08: ô TÌM NHANH trong từng mục của khối 🏷 "Gắn nhãn luôn" (trang Thêm) ──
     *"Ở mỗi các phần requirement luôn có ô search để user tìm cho nhanh"*. Lọc chip tại chỗ,
     thuần client (xem `gan_nhan_nhanh.js`). Chip ĐANG TICK không bao giờ bị ẩn. */
  .gnn-loc { width: 100%; max-width: 320px; margin: 0 0 6px; padding: 5px 9px; font-size: .86rem;
    border: 1px solid var(--bd, #d7dce3); border-radius: 8px; background: #fff; color: inherit; }
  .gnn-loc:focus { outline: 2px solid #1a73e8; outline-offset: 1px; border-color: #1a73e8; }
  .gnn-rong { margin: 4px 0 0; font-style: italic; }

  /* ── USER 2026-09-08: thêm NHIỀU "✍ Mô tả riêng cho clip" trong một lượt dán link ──
     Mọi ô cùng name="note"; máy chủ đọc bằng getlist. Xem `mo_ta_nhieu.js`. */
  .note-hang { display: flex; gap: 6px; align-items: flex-start; margin-top: 6px; }
  .note-hang textarea { flex: 1; }
  .note-xoa { flex: 0 0 auto; align-self: stretch; padding: 0 10px; line-height: 1;
    border: 1px solid var(--bd, #d7dce3); border-radius: 8px; background: #fff; cursor: pointer;
    color: #a01a22; font-weight: 700; }
  .note-xoa:hover { background: #fde2e2; border-color: #c0262e; }
  [data-note-add] { margin-top: 6px; }
  [data-note-add][disabled] { opacity: .55; cursor: default; }

  /* ══ ADR-0147 (USER 2026-09-09) — PHỤ ĐỀ ai84 + GIỌNG NHÂN BẢN TẠI TRANG KẾ HOẠCH ═════════
     Khai MỘT LẦN ở đây vì dùng ở HAI nơi: Voice Studio (`voice_studio.html`, gói E) và thẻ
     "🎙 Giọng & lời bình" của kế hoạch (`_tab_voice.html`, gói F). Hai trang trước nay style rời
     nhau nên cùng một công tắc trông khác nhau — chính là thứ USER phàn nàn.

     YÊU CẦU USER, viết ra để đời sau đừng "dọn cho gọn": công tắc bật/tắt phụ đề phải RÕ RÀNG và
     NỔI BẬT HƠN ô thường — viền DÀY (2px), nền tương phản, chữ ĐẬM, cỡ chữ lớn hơn hint. KHÔNG
     được rút về `<input type=checkbox>` mặc định (mờ nhạt, người dùng lướt qua không thấy).
     CSS THUẦN (quy ước dự án §2 — không Tailwind). Không JS inline (CSP `script-src 'self'`). ══════ */

  /* ── Công tắc "Xuất kèm phụ đề" ─────────────────────────────────────────────────────────── */
  /* 🔴 PHẢI có selector thứ hai `.field > .srt-switch`. Đo thật bằng Chrome headless 09/09:
     công tắc là `<label>` con TRỰC TIẾP của `.field`, mà app.css:87 đã có
     `.field > label { display: block; font-weight: 600 }` — độ đặc hiệu (0,1,1) THẮNG `.srt-switch`
     (0,1,0) ⇒ công tắc bị ép `display:block`, núm gạt thành thẻ inline nên `width:46px;height:26px`
     BỊ BỎ QUA và cả hàng kéo dài 1216px. Nhìn ảnh chụp thì "vẫn có màu" nên rất dễ tưởng đã xong.
     `.field > .srt-switch` = (0,2,0) > (0,1,1) nên thắng lại; giữ luôn `.srt-switch` trần cho chỗ
     dùng ngoài `.field` (Voice Studio, gói E). */
  .srt-switch,
  .field > .srt-switch { display: inline-flex; align-items: center; gap: 10px; cursor: pointer;
    padding: 10px 14px; border: 2px solid #7d8798; border-radius: var(--r-lg, 10px);
    background: var(--surface, #fff); color: var(--txt, #1f2330);
    font-weight: 700; font-size: 1rem; line-height: 1.25; user-select: none; max-width: 100%;
    transition: background .12s, border-color .12s, box-shadow .12s; }
  .srt-switch:hover { border-color: var(--pri, #1a73e8); box-shadow: var(--sh-1, 0 1px 3px rgba(20,40,80,.08)); }
  /* Ô tick THẬT ẩn đi nhưng VẪN trong luồng focus (không `display:none`) — bàn phím Tab tới được,
     `:focus-visible` bên dưới vẽ quầng lên cả hàng. Cùng mẹo `.chip` phía trên file. */
  .srt-switch input[type="checkbox"] { position: absolute; opacity: 0; width: 0; height: 0; }
  .srt-switch:focus-within { outline: 3px solid rgba(26,115,232,.45); outline-offset: 2px; }
  /* Núm gạt — to hơn ô tick mặc định để nhìn thấy trạng thái từ xa. */
  .srt-switch__nut { flex: 0 0 auto; position: relative; width: 46px; height: 26px;
    border-radius: 999px; background: #828d9c; border: 1px solid #5f6a79;
    transition: background .15s, border-color .15s; }
  .srt-switch__nut::after { content: ""; position: absolute; top: 2px; left: 2px;
    width: 20px; height: 20px; border-radius: 50%; background: #fff;
    box-shadow: 0 1px 3px rgba(20,30,50,.35); transition: transform .15s; }
  .srt-switch__chu { flex: 1 1 auto; min-width: 0; }
  /* Chip giá: đo thật 09/09 là +15% credit cho MỌI cỡ text — phải nằm ngay trên công tắc để
     người bật biết mình đang đồng ý trả thêm. */
  .srt-switch__gia { flex: 0 0 auto; font-size: .78rem; font-weight: 800; letter-spacing: .2px;
    padding: 3px 9px; border-radius: 999px; border: 1px solid #dfb400;
    background: var(--warn-bg, #fff3cd); color: #7a5c00; white-space: nowrap; }
  /* TRẠNG THÁI BẬT — khai HAI đường cùng nội dung: `.srt-switch--on` (JS bật, chạy ở mọi trình
     duyệt) và `:has()` (chạy cả khi JS tắt). Không gộp bằng dấu phẩy trong một khối được vì trình
     duyệt cũ không hiểu `:has()` sẽ bỏ NGUYÊN khối ⇒ mất luôn nhánh `--on`. */
  .srt-switch--on { border-color: #0f8a4d; background: #e8f8ef; color: #0b5c34; }
  .srt-switch--on .srt-switch__nut { background: var(--ok, #1a9d57); border-color: #0f8a4d; }
  .srt-switch--on .srt-switch__nut::after { transform: translateX(20px); }
  .srt-switch:has(input[type="checkbox"]:checked) { border-color: #0f8a4d; background: #e8f8ef; color: #0b5c34; }
  .srt-switch:has(input[type="checkbox"]:checked) .srt-switch__nut { background: var(--ok, #1a9d57); border-color: #0f8a4d; }
  .srt-switch:has(input[type="checkbox"]:checked) .srt-switch__nut::after { transform: translateX(20px); }

  /* 🔴 TRANG KẾ HOẠCH: ép ô phụ đề chiếm TRỌN MỘT HÀNG của `.cfg-grid`.
     Ô `#plan-srt-field` là con của `.cfg-grid` (`_tab_voice.html`: `display:flex; flex-wrap:wrap`
     + `.res-cfg .cfg-grid .field { flex: 1 1 240px }`) nên bị xếp CHUNG HÀNG với 3-4 ô cấu hình
     khác. Đo thật bằng Chrome headless 2026-09-09 (khổ 360/768/1280, iframe cố định bề rộng):

       khổ 1280 → cột chữ của công tắc chỉ còn **86,7px ⇒ nhãn vỡ 4 DÒNG**, cả ô cao **104px**
                  trong khi <select> ngay cạnh chỉ cao 35px — ra một cục chữ vụn
       khổ  768 → cột chữ 136,6px ⇒ 3 dòng, cao 84px
       khổ  360 → cột chữ 102,6px ⇒ 3 dòng, cao 84px

     Nghịch lý: màn CÀNG RỘNG càng vỡ (1280 tệ hơn 768) vì grid nhồi thêm ô vào cùng hàng ⇒ đúng
     màn hình máy bàn — nơi USER nhìn nhiều nhất — là nơi công tắc xấu nhất. Trong khi cùng bộ CSS
     đó ở Voice Studio (không nằm trong grid) ra 490×50px, chữ 1 dòng, rất rõ.
     Chiếm trọn hàng ⇒ công tắc tự co theo nội dung (~490px), nhãn về 1 dòng.
     Chọn selector id vì độ đặc hiệu (1,0,0) THẮNG `.res-cfg .cfg-grid .field` (0,3,0) ⇒ không cần
     `!important` và KHÔNG phải sửa template (`_tab_voice.html` thuộc gói khác). */
  #plan-srt-field { flex: 1 1 100%; }

  /* ── Nhãn NGUỒN phụ đề (USER: "phải báo rõ phụ đề của bên nào") ─────────────────────────── */
  .srt-nguon { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap;
    font-size: .78rem; font-weight: 700; padding: 3px 10px; border-radius: 999px;
    border: 1px solid #9dc0ee; background: #e7f0ff; color: #10457f; }
  .srt-nguon--dam { border-color: #ccd2d9; background: #eef0f2; color: #3d4551; }
  /* TRỘN hai nguồn (ADR-0147, 09/09): phải KHÁC HẲN màu 'ai84' — cùng nền xanh là người dùng
     tưởng cả file đều là bản nghe-lại-thật của ai84. Hổ phách = "có, nhưng không trọn vẹn". */
  .srt-nguon--hon_hop { border-color: #e0a02a; background: #fff4e0; color: #7a4b00; }

  /* ── Biển báo "kế hoạch của nhóm khác" (mất hàng rào quota — xem _plan_khac_team.html) ──── */
  .plan-khac-team { display: flex; gap: 10px; align-items: flex-start;
    border: 2px solid #b56408; border-left: 8px solid #b56408; border-radius: var(--r-lg, 10px);
    background: #fff6e6; color: #6b3d05; padding: 12px 14px; margin: 0 0 12px;
    font-size: .92rem; font-weight: 600; line-height: 1.55; }
  .plan-khac-team__icon { flex: 0 0 auto; font-size: 1.35rem; line-height: 1.1; }
  .plan-khac-team__chu { min-width: 0; }
  .plan-khac-team__ttl { display: block; font-weight: 800; font-size: 1.02rem;
    color: #8a3f00; margin-bottom: 3px; }

  /* ── Khối 🧬 giọng nhân bản trên trang kế hoạch ─────────────────────────────────────────── */
  /* `[hidden]` phải THẮNG: các khối này bị JS ẩn/hiện theo nhà cung cấp giọng, mà quy tắc lớp của
     tác giả (dù chỉ `display:block`) vẫn đè `display:none` của trình duyệt. Ghim `!important` cho
     chắc — quên dòng này là ô phụ đề hiện với MỌI provider, kể cả provider không có phụ đề ai84. */
  #plan-ai84-block[hidden], #plan-srt-field[hidden] { display: none !important; }
  .ai84-plan-block { border: 2px dashed #b9a3e8; border-radius: var(--r-lg, 10px);
    background: #f7f4ff; padding: 10px 12px; }
  .ai84-plan-lbl { display: block; font-weight: 700; margin-bottom: 4px; color: #4c2a95; }
  .ai84-plan-select { max-width: 460px; }
  .ai84-plan-clone { margin-top: 10px; padding-top: 10px; border-top: 1px dashed #c9bde8; }
  .ai84-plan-clone__ttl { display: block; font-weight: 700; margin-bottom: 2px; color: #4c2a95; }
  .ai84-plan-clone input[type="file"] { display: block; margin-bottom: 8px; max-width: 100%; }
  .ai84-plan-clone input[type="text"] { display: inline-block; width: 240px; margin-right: 8px; }
  .ai84-plan-ok { border: 1px solid #b6e3c7; background: #f0fff4; color: #157e46;
    border-radius: var(--r, 8px); padding: 8px 11px; margin-top: 8px; font-size: .88rem; }
  .ai84-plan-loi { border: 1px solid var(--danger-bd, #f0a3a3); background: var(--danger-bg, #fde2e2);
    color: #8f1d24; border-radius: var(--r, 8px); padding: 8px 11px; margin-top: 8px;
    font-size: .88rem; font-weight: 600; }
  .ai84-plan-cho { border: 1px solid #c9d8ef; background: #eef3fb; color: #1558b8;
    border-radius: var(--r, 8px); padding: 8px 11px; margin-top: 8px; font-size: .88rem; }

  /* ══ LƯỚI CHIP DÙNG CHUNG — dời từ <style> của detail.html sang đây (fixnew 2026-09-11) ══════
     Vì sao dời: các lớp dưới đây tô cho phần tử do JS dựng (`chip_groups.js` · `chip_filter.js`).
     Trước 11/09 chúng nằm trong thẻ <style> RIÊNG của `detail.html`, nên khi đem cùng bộ JS sang
     trang Thêm footage thì phần tử ra đúng nhưng TRẦN TRỤI — không một dòng style. Đây đúng kiểu
     "vá một bên quên bên kia" mà quy ước dự án §0.0 cảnh báo: JS dùng chung mà CSS thì không.
     Đo 11/09: sel-bar/sel-pill/grp-unset/chip-filter-create đếm được 0 lần trong app.css,
     1-2 lần trong detail.html. ══════════════════════════════════════════════════════════════ */

  /* 🔴 `[hidden]` trên chip phải THẮNG. `.chip { display: inline-flex }` (app.css:90) và
     `.field > label { display: block }` là quy tắc của TÁC GIẢ nên LUÔN đè `[hidden]{display:none}`
     của trình duyệt (khác NGUỒN cascade, không phải khác specificity) ⇒ `el.hidden = true` không
     ẩn được gì. Đo Chrome headless 11/09: chip đặt hidden vẫn `display:flex`, rộng 46-70px — đó
     chính là lỗi "ô tìm kiếm không hoạt động" USER báo. Cùng một cái bẫy đã phải vá cho
     `#plan-ai84-block[hidden]` phía trên file. */
  .chip[hidden], .chip-col[hidden], .grp[hidden], .frequent-row[hidden] { display: none !important; }

  /* E4 — bộ đếm trên legend + cảnh báo nhóm bắt buộc chưa chọn. Scope `legend >` để KHÔNG đè lây
     sang count "(N)" trong summary nhóm thu gọn (.grp-count — chữ xám thường). */
  legend > .grp-count { font-size: .72rem; font-weight: 700; margin-left: 7px; padding: 1px 8px;
    border-radius: 999px; background: #e6f7ee; color: #0b8a44; vertical-align: middle; }
  legend > .grp-count.warn { background: #fff3cd; color: #8a6d00; }
  fieldset.grp-unset { border-left-color: #e8a33d !important; }
  fieldset.grp-unset > legend { color: #a9710f; }

  /* E3 — thanh thẻ đã chọn (nền xanh) + ✕ bỏ nhanh. */
  .sel-bar { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 8px; }
  .sel-pill { display: inline-flex; align-items: center; gap: 4px; font-size: .8rem; font-weight: 600;
    background: #e6f7ee; color: #0b6e4f; border: 1px solid #bfe3d2; border-radius: 999px;
    padding: 2px 10px; cursor: pointer; }
  .sel-pill:hover { background: #d6f0e2; border-color: #0b8a44; }

  /* E2 — gợi ý tạo thẻ khi ô tìm không thấy kết quả. */
  .chip-filter-create { display: none; margin: 0 0 10px; font-size: .83rem; font-weight: 600;
    background: #fff; color: var(--pri); border: 1px dashed var(--pri); border-radius: 8px;
    padding: 5px 11px; cursor: pointer; }
  .chip-filter-create:hover { background: var(--info-bg); }

  /* E8 — nhóm khổng lồ ("Khác" ~700+ thẻ): khu xem-tất-cả có chiều cao TỐI ĐA + cuộn riêng. */
  .grp-collapsible .chip-col { max-height: 320px; overflow-y: auto; }

  /* F2 — mục "còn thiếu" bấm nhảy tới ô; chừa lề trên cho thanh dính khỏi che. */
  [data-chip-root] fieldset[id] { scroll-margin-top: 64px; }

  /* USER 2026-09-11 — nhãn "thẻ này đang hiện ở N nhóm" (`chip_groups.js`). Trước 11/09 nó in ký
     tự ⧉ (U+29C9) bằng style INLINE; USER đọc ra thành lỗi font ("các số nhỏ trong thẻ chip đang
     bị lỗi") vì ⧉ trông y hệt ô vuông tofu. Nay là nhãn CHỮ, style ở đây. */
  .dup-mark { display: inline-block; margin-left: 5px; padding: 0 6px; border-radius: 999px;
    font-size: .68rem; font-weight: 700; line-height: 1.55; vertical-align: middle;
    background: rgba(0, 0, 0, .07); color: inherit; opacity: .8; cursor: help; }
  .chip:has(input:checked) .dup-mark { background: rgba(255, 255, 255, .28); }

  /* ── USER 2026-09-11 — khối "Xem tất cả N thẻ" của khuôn chip dùng chung ──────────────────
     ★ Hay dùng (10 thẻ) luôn hiện; phần còn lại nằm trong <details> này. Summary phải trông
     BẤM ĐƯỢC (USER đã một lần tưởng khối Gắn nhãn "thiếu ô" vì nó gập mà không ai thấy). */
  .lc-tatca { border: 1px dashed var(--bd, #d7dce3); border-radius: var(--r, 8px);
    margin: 6px 0 2px; background: #fbfcfe; }
  .lc-sum { cursor: pointer; padding: 6px 10px; font-size: .86rem; font-weight: 600;
    color: var(--pri, #1a73e8); user-select: none; list-style-position: inside; }
  .lc-sum:hover { background: var(--info-bg, #eef4ff); border-radius: var(--r, 8px); }
  .lc-tatca[open] > .lc-sum { border-bottom: 1px dashed var(--bd, #d7dce3); border-radius: 0; }
  .lc-tatca > .chip-filter { margin: 8px 10px 6px; width: calc(100% - 20px); max-width: 360px; }
  .lc-tatca > .chip-groups { padding: 0 10px 10px; }
  /* `.frequent-row` / `.frequent-label` ĐÃ có ở app.css:115-117 (hộp vàng nhạt) — KHÔNG khai lại
     ở đây, khai lại là đè mất viền vàng mà không ai biết vì sao. */

  /* ── USER 2026-09-11 — khối 🏷 "Gắn nhãn luôn" (trang Thêm footage) ────────────────────────
     Trước 11/09 các lớp này KHÔNG có một dòng CSS nào (đo thật) nên khối hiện ra trần trụi,
     không ai nhận ra đó là bảng nhập bắt buộc. */
  .gnn-box { border: 2px solid var(--pri, #1a73e8); border-radius: var(--r-lg, 10px);
    background: var(--surface, #fff); padding: 2px 12px 12px; margin: 14px 0; }
  .gnn-box.gnn-du { border-color: #0f8a4d; }
  .gnn-sum { cursor: pointer; padding: 10px 2px; font-weight: 800; font-size: 1.02rem;
    user-select: none; }
  .gnn-thieu { display: inline-block; margin-left: 8px; padding: 2px 10px; border-radius: 999px;
    font-size: .78rem; font-weight: 700; background: var(--warn-bg, #fff3cd); color: #7a5c00; }
  .gnn-thieu.ok { background: #e8f8ef; color: #0b5c34; }

  /* USER 2026-09-11 — nút "Tạo nháp" ĐƯA LÊN ngay dưới ô Link nguồn.
     *"Nút Tạo Nháp chuyển lên trên cùng, vị trí dễ click để user có thể add nhanh"*.
     Đo trước khi sửa: nút nằm sau 898 chip, phải cuộn 1.826px (màn 1440) mới bấm được. */
  .add-go-top { display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
    margin: 2px 0 14px; padding: 10px 12px; border-radius: var(--r-lg, 10px);
    border: 1px solid var(--bd, #d7dce3); background: var(--info-bg, #eef4ff); }
  .add-go-top .hint { flex: 1 1 240px; min-width: 0; margin: 0; }

  /* ── Bước 3 PA1 (USER 24/09) — thẻ 3 "Nhận bản dựng": 2 nút LẤY VỀ + 2 nút GỬI LÊN ─────────────
     Class RIÊNG `.b3-*` — KHÔNG sửa `.go` / `.big` dùng chung (đổi là đổi màu hàng loạt nút trang khác).
     Màu chốt theo bảng đổi tên của kế hoạch: xanh lá đậm #15803D + cam #C2410C + xanh dương #2563EB
     (cả ba cho chữ trắng tương phản ~5:1). Nút LẤY VỀ (hàng 1) khác màu nút GỬI LÊN (hàng 2) để
     member không nhầm hướng. Hẹp quá thì 2 nút tự xếp dọc, nút ĐÃ EDIT ở TRÊN (thứ tự DOM). */
  .b3-hang { display: flex; flex-wrap: wrap; gap: 10px; align-items: stretch; margin: 8px 0 0; }
  .b3-o { flex: 1 1 130px; min-width: 0; margin: 0; display: flex; }
  button.b3-nut { width: 100%; min-height: 64px; display: flex; flex-direction: column;
    align-items: flex-start; justify-content: center; gap: 3px; text-align: left;
    padding: 10px 14px; border-radius: 10px; font-weight: 700; color: #fff;
    white-space: normal; overflow-wrap: anywhere; }
  .b3-ten { font-size: 1.02rem; line-height: 1.25; }
  .b3-phu { font-size: .82rem; font-weight: 500; line-height: 1.3; }
  button.b3-da { background: #15803D; border-color: #15803D; }
  button.b3-da:hover { background: #166534; border-color: #166534; }
  button.b3-chua { background: #C2410C; border-color: #C2410C; }
  button.b3-chua:hover { background: #9A3412; border-color: #9A3412; }
  /* Nút MỜ = <button disabled>: nền xám + chữ #64748B (đọc được lý do), KHÔNG dùng opacity .5 mặc định
     của `button:disabled` — mờ kiểu đó làm dòng lý do bên trong nút gần như không đọc nổi. */
  button.b3-mo, button.b3-mo:hover { background: #E2E8F0; border-color: #CBD5E1; color: #64748B;
    opacity: 1; cursor: not-allowed; }
  /* Đang nhận (khung tiến độ có poller sống) ⇒ 2 nút to MỜ + không bấm được; poller xong thì khung
     đổi sang nhánh tĩnh ⇒ nút tự sáng lại, KHÔNG phải tải lại trang. Gói thô của dự án gốc là form
     tải lại trang (không có poller) ⇒ chỉ làm mờ, vẫn bấm được — server có cổng chống đua nói rõ lý do. */
  .b3:has(.restore-live) .b3-nhan button.b3-nut,
  .b3:has(.b3-dang) .b3-nhan button.b3-nut { opacity: .45; }
  .b3:has(.restore-live) .b3-nhan button.b3-nut { pointer-events: none; }
  .b3-giong { margin: 6px 0 2px; padding: 6px 10px; border-radius: 6px; font-weight: 600; }
  .b3-giong.ok { background: #eaf7ee; border: 1px solid #a9d8ba; color: #256b3a; }
  .b3-giong.thieu { background: #fff4e5; border: 1px solid #f0c98a; color: #8a5a1a; }
  .b3-dan { margin: 14px 0 0; font-weight: 700; color: #0F172A; }
  .b3-sau { margin-top: 6px; }
  .b3-sau > form { margin: 0; }
  button.b3-qc { background: #fff; border: 1px solid #2563EB; color: #2563EB; font-weight: 700; }
  button.b3-qc:hover { background: #EFF6FF; }
  button.b3-luu { background: #2563EB; border-color: #2563EB; color: #fff; font-weight: 700; }
  button.b3-luu:hover { background: #1D4ED8; border-color: #1D4ED8; }
  a.b3-nb { display: inline-block; margin: 10px 0 0; padding: 8px 14px; border-radius: 8px;
    background: #fff; color: #15803D; border: 1px solid #15803D; font-weight: 600;
    text-decoration: none; }
  a.b3-nb:hover { background: #F0FDF4; }
  button.b3-phu-nut, a.b3-phu-nut { display: inline-block; padding: 6px 12px; border-radius: 8px;
    background: #fff; border: 1px solid #CBD5E1; color: #334155; font-weight: 600;
    text-decoration: none; }
  button.b3-phu-nut:hover, a.b3-phu-nut:hover { background: #F1F5F9; }
  /* 🎙 Lấy lại giọng lần lưu trước — giữ màu cam nhạt cũ (bảng đổi tên §4): phép hoán đổi, không phá. */
  button.b3-giong-cu { background: #fff4e5; border-color: #f0b37e; color: #5c3b00; }
  button.b3-giong-cu:hover { background: #ffe9cc; }
  button.b3-nhan-chon { background: #15803D; border-color: #15803D; color: #fff; font-weight: 700; }
  button.b3-nhan-chon:hover { background: #166534; border-color: #166534; }
  .b3-goi { margin: 8px 0 0; padding: 8px 10px; border-radius: 6px; background: #eef4ff;
    border: 1px solid #b9cdf0; color: #2a4a82; }
  .b3-goi.loi { background: #fff4e5; border-color: #f0c98a; color: #8a5a1a; }
  .b3-goi form { display: inline-block; margin: 6px 0 0; }
  details.b3-them { margin: 12px 0 0; border: 1px solid #CBD5E1; border-radius: 8px;
    background: #fff; padding: 6px 12px; }
  details.b3-them > summary { cursor: pointer; font-weight: 600; color: #334155; list-style: none; }
  details.b3-them > summary::-webkit-details-marker { display: none; }
  details.b3-them > summary::before { content: "▸ "; }
  details.b3-them[open] > summary::before { content: "▾ "; }
  .b3-them-hang { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 8px 0 0; }
  .b3-them-hang > form { margin: 0; }
  .b3-them-hang input[type="text"] { flex: 1 1 200px; min-width: 0; padding: 6px 8px; }

/* === XUẤT XỨ KÊNH (dem27 27/09) — trang /pipeline/channel/<uuid>/xuat-xu/ ======================
   Thanh "công thức" mỗi video, màu = KÊNH của dự án nguồn (template `channel_xuat_xu.html`).
   Mobile-first: điện thoại ~390px một cột, thanh rộng hết thẻ, KHÔNG cuộn ngang (mọi con flex có
   min-width:0 + chữ dài tự xuống dòng); vùng bấm ≥40px (link/summary/tab/phân trang).
   Màu kênh là biến RIÊNG của khối (`--xx-k*`) vì bảng token chung không có dải màu phân loại; phần
   còn lại chỉ dùng token sẵn có. Chữ trắng trên 6 màu đủ tương phản; xám "khác" dùng chữ đậm. */
.xx { --xx-k1:#1a73e8; --xx-k2:#d9650b; --xx-k3:#0f8f99; --xx-k4:#7b4fc9; --xx-k5:#c2185b;
      --xx-k6:#6b5a00; --xx-k0:#aab2bf;
      display: flex; flex-direction: column; gap: var(--sp-3); min-width: 0; }
.xx h1 { margin: 0; overflow-wrap: anywhere; }
.xx-dieu-huong { margin: 0; display: flex; flex-wrap: wrap; justify-content: space-between;
  gap: var(--sp-2); font-size: .9rem; }
.xx-dieu-huong a { display: inline-flex; align-items: center; min-height: 40px; }
.xx-tong { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-2); }
.xx-chip { font-size: .8rem; padding: 3px 9px; border-radius: var(--r-pill); background: var(--surface);
  border: 1px solid var(--bd); color: var(--txt-2); white-space: nowrap; font-variant-numeric: tabular-nums; }
.xx-chu-giai { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-3); font-size: .8rem; color: var(--txt-2); }
.xx-chu-giai li { display: inline-flex; align-items: center; gap: 5px; min-width: 0; overflow-wrap: anywhere; }
.xx-sw { width: 12px; height: 12px; border-radius: 3px; display: inline-block; flex: none; }
.xx-tabs { display: flex; gap: var(--sp-1); border-bottom: 1px solid var(--bd); }
.xx-tab { display: inline-flex; align-items: center; min-height: 44px; padding: 0 var(--sp-3);
  color: var(--txt-2); text-decoration: none; border-bottom: 2px solid transparent; font-size: .92rem; }
.xx-tab.is-on { color: var(--pri); border-bottom-color: var(--pri); font-weight: 600; }
.xx-ds { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.xx-vid, .xx-src { background: var(--surface); border: 1px solid var(--bd); border-radius: var(--r);
  padding: var(--sp-1) var(--sp-3) var(--sp-2); display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.xx-vtop { display: flex; gap: var(--sp-2); align-items: center; justify-content: space-between; min-width: 0; }
.xx-vten { flex: 1 1 auto; min-width: 0; display: block; padding: 10px 0; line-height: 20px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--txt); text-decoration: none; }
a.xx-vten:hover { color: var(--pri); }
.xx-src .xx-vten { white-space: normal; overflow-wrap: anywhere; }
.xx-so { color: var(--pri); font-variant-numeric: tabular-nums; }
.xx-n { flex: none; font-size: .8rem; color: var(--txt-mut); font-variant-numeric: tabular-nums; }
.xx-meta { display: flex; flex-wrap: wrap; gap: 4px 6px; align-items: center; font-size: .8rem;
  color: var(--txt-2); min-width: 0; overflow-wrap: anywhere; }
/* Link nhỏ trong dòng meta: nới VÙNG BẤM lên ~40px bằng padding + margin âm — không đổi chiều cao dòng.
   Chip "⚠ trùng" là link có nền màu ⇒ padding sẽ phình cả khối màu; nới bằng ::after trong suốt. */
.xx-meta a:not(.xx-b) { padding: 10px 2px; margin: -10px 0; }
.xx-meta a.xx-b { position: relative; }
.xx-meta a.xx-b::after { content: ""; position: absolute; inset: -10px -2px; }
.xx-b { font-size: .72rem; font-weight: 700; padding: 1px 7px; border-radius: 5px; white-space: nowrap;
  text-decoration: none; }
.xx-b-mix { background: var(--pri-bg); color: var(--pri); }
.xx-b-clone { background: var(--ok-bg); color: var(--ok-d); }
.xx-b-xao { background: var(--ai-bg); color: var(--ai); }
.xx-b-goc { background: var(--bd-2); color: var(--txt-2); }
.xx-b-warn { background: var(--warn-bg); color: var(--warn-txt); }
.xx-bar { display: flex; width: 100%; height: 24px; border-radius: 5px; overflow: hidden; gap: 2px;
  background: var(--bd-2); }
.xx-seg { display: flex; align-items: center; justify-content: center; min-width: 3px; overflow: hidden;
  white-space: nowrap; font-size: .72rem; font-weight: 700; color: #fff; font-variant-numeric: tabular-nums; }
.xx-bar-rong { display: flex; align-items: center; padding: 0 var(--sp-2); font-size: .72rem; color: var(--txt-mut); }
.xx-k1 { background: var(--xx-k1); } .xx-k2 { background: var(--xx-k2); } .xx-k3 { background: var(--xx-k3); }
.xx-k4 { background: var(--xx-k4); } .xx-k5 { background: var(--xx-k5); } .xx-k6 { background: var(--xx-k6); }
.xx-k0 { background: var(--xx-k0); color: var(--txt); }
.xx-goc { background: repeating-linear-gradient(45deg, var(--bd-2) 0 6px, var(--surface-2) 6px 12px);
  color: var(--txt-2); }
.xx-seg.xx-goc { border: 1px dashed var(--bd); }
.xx-drill > summary { cursor: pointer; min-height: 40px; display: flex; align-items: center; list-style: none;
  color: var(--pri); font-size: .85rem; font-weight: 600; }
.xx-drill > summary::-webkit-details-marker { display: none; }
.xx-drill > summary::before { content: "▸"; margin-right: 6px; }
.xx-drill[open] > summary::before { content: "▾"; }
.xx-rows { list-style: none; margin: 0; padding: var(--sp-1) 0 0; border-top: 1px dashed var(--bd);
  display: flex; flex-direction: column; }
.xx-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--sp-2); align-items: center;
  min-height: 40px; font-size: .84rem; }
.xx-t { min-width: 0; overflow-wrap: anywhere; }
.xx-t a { padding: 8px 0; }  /* inline: nhãn NỀN đứng cùng dòng với tên; padding chỉ nới vùng bấm */
.xx-kenh { display: block; font-size: .72rem; color: var(--txt-mut); overflow-wrap: anywhere; }
.xx-vtop > .xx-kenh { flex: none; max-width: 40%; text-align: right; }
.xx-num { white-space: nowrap; text-align: right; font-size: .8rem; color: var(--txt-2); font-variant-numeric: tabular-nums; }
.xx-nen { font-size: .66rem; font-weight: 800; background: var(--txt); color: var(--surface); padding: 0 5px;
  border-radius: 4px; margin-right: 4px; }
.xx-xoa { color: var(--danger); font-style: normal; }
.xx-note { margin: 0; font-size: .8rem; color: var(--txt-mut); }
.xx-canh { margin: 0; padding: var(--sp-2) var(--sp-3); border-radius: var(--r); background: var(--warn-bg);
  color: var(--warn-txt); font-size: .85rem; }
.xx-rong { margin: 0; color: var(--txt-mut); }
.xx-dots { display: flex; flex-wrap: wrap; gap: 4px; }
.xx-dots span { font-size: .72rem; padding: 1px 6px; border-radius: 4px; background: var(--pri-bg); color: var(--pri);
  font-variant-numeric: tabular-nums; }
.xx-dots span.is-nen { background: var(--txt); color: var(--surface); }
.xx-cap { display: flex; height: 10px; border-radius: 5px; overflow: hidden; background: var(--bd-2); }
.xx-cap i { display: block; height: 100%; }
.xx-cap-da { background: var(--txt-mut); }
.xx-cap-con { background: var(--ok); }
.xx-con { color: var(--ok-d); }
.xx-trang { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: center; justify-content: center; }
.xx-trang a { display: inline-flex; align-items: center; min-height: 44px; padding: 0 var(--sp-3); }
/* === HẾT XUẤT XỨ KÊNH (dem27 27/09) === */
/* Nút "Dùng các nguồn này để nhân bản/trộn tiếp" (USER 27/09 nut_dung) — vùng bấm >=40px trên điện thoại. */
.xx-dung { margin: var(--sp-2) 0 0; }
.xx-dung-btn { display: inline-flex; align-items: center; min-height: 40px; padding: 0 var(--sp-3);
  border: 1px solid var(--pri); border-radius: var(--r); color: var(--pri); background: var(--pri-bg);
  font-weight: 600; text-decoration: none; max-width: 100%; }
.xx-dung-btn:hover { filter: brightness(.96); }

/* === KHỐI LỖI TO ĐẦU TRANG (USER 28/09 "báo lỗi TO, rõ ràng") ================================
   Lời TỪ CHỐI kiểu "CHƯA tạo gì" (templates/_loi_to.html, vẽ bởi thẻ `loi_to_dau_trang` ở đầu
   <main> của base.html). Toast góc màn hình quá nhỏ cho loại lời này: người dùng tưởng đã tạo xong.
   Đọc bằng CHỮ + BIỂU TƯỢNG ⛔ + MÀU, không chỉ màu. Chỉ dùng token màu có sẵn. */
.loi-to { margin: 0 0 var(--sp-4); padding: var(--sp-3) var(--sp-4); border: 2px solid var(--danger);
  border-left-width: 8px; border-radius: var(--r-lg); background: var(--danger-bg); color: var(--danger-d);
  box-shadow: var(--sh-1); line-height: 1.6; overflow-wrap: anywhere; }
.loi-to-tieu-de { margin: 0 0 var(--sp-2); font-size: 1.3rem; font-weight: 800; color: var(--danger-d); }
.loi-to-mo-dau { margin: 0 0 var(--sp-2); font-weight: 600; }
.loi-to-ds, .loi-to-cach { margin: 0 0 var(--sp-2); padding-left: 22px; }
.loi-to-ds li, .loi-to-cach li { margin: 4px 0; }
.loi-to-cach-ttl { margin: var(--sp-2) 0 2px; font-weight: 700; }
.loi-to-nut { display: inline-flex; align-items: center; min-height: 36px; margin: 2px 0; padding: 0 var(--sp-3);
  border: 1px solid var(--danger); border-radius: var(--r); background: var(--surface); color: var(--danger-d);
  font-weight: 700; text-decoration: none; max-width: 100%; }
.loi-to-nut:hover { background: var(--danger); color: #fff; }
/* === HẾT KHỐI LỖI TO === */

/* === V13 nb30 (ADR-0178) — nhãn TRẠNG THÁI EDIT (bảng Kế hoạch · wizard bước 1 · trang Lô) === */
.nhan-edit { display: inline-block; padding: 0 6px; border-radius: 999px; font-size: .78rem; line-height: 1.5;
  white-space: nowrap; border: 1px solid var(--line, #d8dee9); background: var(--surface, #fff); color: #4a5568;
  vertical-align: middle; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.nhan-edit--da_edit { border-color: var(--ok); background: var(--ok-bg); color: var(--ok-d); }
.nhan-edit--duoi_tho { border-color: var(--warn-bd); background: var(--warn-bg); color: var(--warn-txt); }
.nhan-edit--chua_edit { border-color: var(--danger, #c0392b); background: #fdecea; color: var(--danger-d, #922b21); }
.nhan-edit--chua_luu, .nhan-edit--chua_do { color: #6b7280; }
/* === HẾT KHỐI NHÃN TRẠNG THÁI EDIT === */
