/* =====================================================================
   ui.css — Component CSS dùng chung cho user dashboard (Dashboard 360)
   Hợp đồng giao diện: docs/design/DESIGN.md
   Token: shared/views/fontTokens.ejs (--font-*, --fs-*) + shared/views/themeTokens.ejs
          (--brand-*, --ui-* : radius, chiều cao hàng, gap, màu ngữ nghĩa). File này KHÔNG tự đặt giá trị mới.
   Quy ước: mọi class tiền tố ui- ; trang chưa chuyển đổi không bị ảnh hưởng.
   Kiểm tra: node scripts/ui-lint.js [đường-dẫn-ejs]
   ===================================================================== */

/* ---------- Khung trang & grid 12 cột ---------- */
.ui-page { max-width: var(--ui-container-max); margin: 0 auto; padding: 20px; }
.ui-grid {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: var(--ui-gap);
    margin-bottom: var(--ui-gap);
}
.ui-span-2  { grid-column: span 2; }
.ui-span-3  { grid-column: span 3; }
.ui-span-4  { grid-column: span 4; }
.ui-span-5  { grid-column: span 5; }
.ui-span-6  { grid-column: span 6; }
.ui-span-7  { grid-column: span 7; }
.ui-span-8  { grid-column: span 8; }
.ui-span-9  { grid-column: span 9; }
.ui-span-12 { grid-column: span 12; }
/* chiều cao hàng cố định — ô trong cùng hàng luôn bằng nhau */
/* KPI/luồng: cao TỐI THIỂU theo token, nội dung dài thì nới — ô cùng hàng vẫn bằng nhau (grid stretch) */
.ui-h-kpi      { min-height: var(--ui-h-kpi); }
.ui-h-flow     { min-height: var(--ui-h-flow); }
.ui-h-chart    { height: var(--ui-h-chart); }
.ui-h-chart-sm { height: var(--ui-h-chart-sm); }
.ui-h-chart-lg { height: var(--ui-h-chart-lg); }
.ui-h-auto     { height: auto; }
/* cột xếp dọc nhiều card trong 1 ô */
.ui-col { display: flex; flex-direction: column; gap: var(--ui-gap); min-width: 0; }
.ui-col > .ui-card { flex: 1 1 0; min-height: 0; }

/* ---------- Card ---------- */
.ui-card {
    background: var(--ui-glass-bg);
    backdrop-filter: blur(15px);
    border-radius: var(--ui-r-card);
    padding: var(--ui-card-pad);
    box-shadow: var(--ui-shadow-card);
    border: 2px solid rgba(var(--brand-primary-rgb), 0.06);
    position: relative;
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow: hidden;
    box-sizing: border-box;
}
.ui-card-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
    flex: none;
}
.ui-card-title { font-size: var(--fs-lg); font-weight: 700; color: var(--brand-primary); margin: 0; line-height: 1.3; }
.ui-card-sub   { font-size: var(--fs-xs); color: var(--ui-muted); white-space: nowrap; }
.ui-card-body  { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }

/* ---------- Chart: canvas luôn nằm trong ô cao cố định ---------- */
.ui-chart { position: relative; flex: 1 1 auto; min-height: 0; }
.ui-chart canvas { width: 100% !important; height: 100% !important; }
.ui-chart-sm { flex: none; height: 240px; }
.ui-chart-md { flex: none; height: 280px; }
.ui-chart-lg { flex: none; height: 350px; }
/* khung cuộn ngang cho chart cột dày trên điện thoại — do UI.chart tự bọc (xem fitChart) */
.ui-chart-scroll { flex: 1 1 auto; min-height: 0; overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; }
.ui-chart-scroll > .ui-chart { flex: none; }

/* ---------- Bộ lọc ---------- */
.ui-filter { z-index: 50; overflow: visible; margin-bottom: var(--ui-gap); }
.ui-filter-title {
    color: var(--brand-primary);
    font-size: var(--fs-xl);
    font-weight: 700;
    margin: 0 0 18px;
    display: flex;
    align-items: center;
    gap: 10px;
}
.ui-filter-grid { display: grid; grid-template-columns: 2fr 2fr 1fr 1fr; gap: 15px; align-items: end; }
/* Ô lưới mặc định min-width:auto → .ui-dates / .ui-actions đặt thẳng trong lưới kéo cột rộng hơn card,
   phần dư bị body{overflow-x:hidden} cắt mất (nút "Nhận xét AI" /tiktok, ô giờ /fulfillment ở 390px). */
.ui-filter-grid > * { min-width: 0; }
.ui-field { display: flex; flex-direction: column; min-width: 0; }
.ui-field > label { margin-bottom: 8px; font-weight: 600; color: var(--brand-primary); font-size: var(--fs-base); }
.ui-dates { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; }
/* Bộ lọc có nhiều nút hành động (Báo cáo / Excel / AI): nút chiếm chỗ làm ô ngày bị ép cụt chữ ("18/0…")
   → khối ngày có bề rộng tối thiểu, ô chọn co lại. Dùng: <div class="ui-filter-grid dates-wide"> */
@media (min-width: 1025px) {
    .ui-filter-grid.dates-wide { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(320px, 1fr) auto; }
    /* Cột nút cuối (Báo cáo + Xuất Excel…) rộng THEO NỘI DUNG + nút không xuống dòng: trước đây cột 1fr quá hẹp
       → "Xuất Excel" rớt xuống hàng dưới, "Báo cáo ngay" nổi lên trên hàng ô lọc (/facebook, 2026-10-08). */
    .ui-filter-grid:not(.dates-wide):has(> .ui-actions:last-child) { grid-template-columns: 2fr 2fr 1fr auto; }
    .ui-filter-grid > .ui-actions:last-child { flex-wrap: nowrap; }
    /* 5 ô lọc + nhóm nút (không có khối ngày) — cùng nguyên tắc dates-wide: ô chia đều, nút rộng theo nội dung
       ở cuối hàng, ghi chú xuống hàng riêng. Dùng: <div class="ui-filter-grid five-actions"> (/customer-care). */
    .ui-filter-grid.five-actions { grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr) repeat(3, minmax(0, 1fr)) auto; }   /* ô 2 (Trạng thái) chữ dài nhất */
    .ui-filter-grid.five-actions > .ui-actions { flex-wrap: nowrap; }
    .ui-filter-grid.five-actions > .ui-note { grid-column: 1 / -1; }
}
.ui-filter-grid.dates-wide .ui-dates .ui-input { padding-left: 10px; padding-right: 8px; }
.ui-input {
    width: 100%;
    padding: 12px 16px;
    border: 2px solid var(--ui-line);
    border-radius: var(--ui-r-input);
    font-size: var(--fs-md);
    font-family: inherit;
    background: var(--ui-surface);
    color: var(--ui-text);
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
    box-sizing: border-box;
}
.ui-input:focus {
    outline: none;
    border-color: var(--brand-primary);
    box-shadow: 0 0 0 3px rgba(var(--brand-primary-rgb), 0.12);
}
button.ui-input { text-align: left; cursor: pointer; }
.ui-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.ui-actions > .ui-btn:first-child { flex: 1; }

/* ---------- Nút ---------- */
.ui-btn {
    padding: 13px 24px;
    border: none;
    border-radius: var(--ui-r-btn);
    font-size: var(--fs-md);
    font-family: inherit;
    font-weight: 600;
    cursor: pointer;
    transition: transform 0.2s ease, box-shadow 0.2s ease, opacity 0.2s ease;
    white-space: nowrap;
}
.ui-btn:hover:not(:disabled) { transform: translateY(-3px); }
.ui-btn:disabled { opacity: 0.6; cursor: not-allowed; }
/* Nút dạng <a>: thẻ neo mặc định là inline + gạch chân → vỡ hình nút.
   10 trang đang dùng <a class="ui-btn">. */
a.ui-btn { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; }
.ui-btn-block { width: 100%; }
/* Liên kết chữ màu thương hiệu (trong câu, không phải nút) */
.ui-link { color: var(--brand-primary); text-decoration: none; font-weight: 600; cursor: pointer; }
.ui-link:hover { text-decoration: underline; }
.ui-btn-primary { background: var(--brand-gradient); color: var(--ui-on-brand); box-shadow: 0 8px 25px rgba(var(--brand-primary-rgb), 0.25); }
.ui-btn-primary:hover:not(:disabled) { box-shadow: 0 15px 35px rgba(var(--brand-primary-rgb), 0.3); }
.ui-btn-ok { background: linear-gradient(135deg, #12b76a, #12b76a); color: #fff; box-shadow: 0 8px 25px rgba(18, 183, 106, 0.25); }
html[data-palette="project"] .ui-btn-ok { background: var(--ui-ok); box-shadow: 0 8px 25px var(--ui-ok-bg); }
/* Trang kênh: một màu chủ đạo — nút phụ (Xuất Excel) là nút viền màu kênh, không xanh lá */
html[data-palette="project"][data-chart-channel] .ui-btn-ok { background: var(--ui-surface); color: var(--brand-primary); border: 2px solid rgba(var(--brand-primary-rgb), 0.45); box-shadow: none; }
html[data-palette="project"][data-chart-channel] .ui-btn-ok:hover:not(:disabled) { background: rgba(var(--brand-primary-rgb), 0.06); }
.ui-btn-ghost { background: var(--ui-surface); color: var(--ui-text); border: 2px solid var(--ui-line); }

/* ---------- Thẻ KPI (hero / nhỏ / mini / bước luồng) ----------
   Hợp đồng xuất Excel (dashboardExport.js, cardPrefix 'ui-kpi'):
   .ui-kpi-card > .ui-kpi-title + .ui-kpi-value (+ .ui-kpi-description) */
.ui-kpi-card {
    background: var(--ui-glass-bg);
    backdrop-filter: blur(15px);
    border-radius: var(--ui-r-card);
    padding: 20px 22px;
    box-shadow: var(--ui-shadow-card);
    border: 2px solid rgba(var(--brand-primary-rgb), 0.06);
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    /* Canh TRÊN: tiêu đề → số → badge luôn cùng vị trí giữa các thẻ cạnh nhau (space-between làm
       số trôi xuống giữa thẻ khi thẻ thiếu badge/mô tả). Mô tả neo đáy bằng margin-top:auto. */
    justify-content: flex-start;
    gap: 8px;
    min-width: 0;
    box-sizing: border-box;
    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.3s ease;
}
.ui-kpi-card::before {
    content: '';
    position: absolute; top: 0; left: 0; right: 0; height: 4px;
    background: var(--brand-gradient);
    transform: scaleX(0);
    transition: transform 0.3s ease;
}
.ui-kpi-card:hover { transform: translateY(-6px); box-shadow: var(--ui-shadow-hover); }
.ui-kpi-card:hover::before { transform: scaleX(1); }
.ui-kpi-title { font-size: var(--fs-md); font-weight: 700; color: var(--brand-primary); line-height: 1.25; }
.ui-kpi-value {
    font-size: var(--fs-2xl);
    font-weight: 800;
    color: var(--ui-text);
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
    word-break: break-word;
}
.ui-kpi-description { font-size: var(--fs-sm); color: var(--ui-muted); line-height: 1.4; margin-top: auto; }
/* hero: số lớn màu brand + sparkline bên phải */
.ui-kpi-hero { flex-direction: row; align-items: stretch; gap: 16px; }
.ui-kpi-hero-main { display: flex; flex-direction: column; justify-content: space-between; min-width: 0; flex: 1 1 auto; }
.ui-kpi-hero .ui-kpi-title { font-size: var(--fs-xl); }
.ui-kpi-hero .ui-kpi-value { font-size: 2.4rem; color: var(--brand-primary); }
.ui-kpi-spark { width: 240px; flex: none; display: flex; flex-direction: column; justify-content: flex-end; gap: 4px; }
.ui-kpi-spark svg { width: 100%; height: 96px; display: block; overflow: visible; }
.ui-kpi-spark-axis { display: flex; justify-content: space-between; font-size: var(--fs-2xs); color: var(--ui-muted-2); font-family: var(--font-mono); }

/* ---------- Hàng so sánh kỳ (Kỳ này / Kỳ trước / Cùng kỳ năm trước) ----------
   KPI chỉ có số tuyệt đối thì người xem không biết tốt hay xấu. Hàng này đặt ngay
   dưới số lớn, mỗi cột một mốc thời gian. Thiếu dữ liệu thì để dấu — (UI.fmt trả '--'),
   KHÔNG bịa số 0. */
.ui-kpi-compare {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(90px, 1fr));
    gap: 10px 16px;
    padding: 12px 0;
    margin-top: 4px;
    border-top: 1px solid var(--ui-line-soft);
    border-bottom: 1px solid var(--ui-line-soft);
}
.ui-kpi-compare + * { margin-top: 14px; }
.ui-cmp { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ui-cmp-label { font-size: var(--fs-2xs); color: var(--ui-muted-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ui-cmp-value {
    font-size: var(--fs-md); font-weight: 700; font-variant-numeric: tabular-nums;
    color: var(--ui-text); display: flex; align-items: center; gap: 4px; white-space: nowrap;
}
/* Sắc thái gán theo Ý NGHĨA (tốt/xấu), không theo mốc thời gian — tăng doanh thu là
   tốt nhưng tăng tỷ lệ hoàn là xấu, nên trang phải tự quyết định lớp nào. */
.ui-cmp-value.is-up   { color: var(--ui-ok); }
.ui-cmp-value.is-down { color: var(--ui-bad); }
.ui-cmp-value.is-flat { color: var(--ui-muted); }
.ui-cmp-value.is-na   { color: var(--ui-muted-2); font-weight: 600; }
.ui-cmp-arrow { font-size: var(--fs-xs); line-height: 1; }

/* ---------- Lưu đồ: thác nước (UI.waterfall) ----------
   Diễn đạt "doanh thu trừ dần các khoản" — dễ nhận ra mạch hơn bảng số thuần. */
.ui-wf { position: relative; display: flex; flex-direction: column; height: 100%; min-height: 0; }
.ui-wf-svg { flex: 1 1 auto; width: 100%; min-height: 0; overflow: visible; }
.ui-wf-val { font-size: 2.6px; font-weight: 700; fill: var(--ui-text); font-family: var(--font-mono); }
.ui-wf-names { position: relative; height: 30px; flex: none; margin-top: 2px; }
.ui-wf-name {
    position: absolute; top: 0; transform: translateX(-50%);
    font-size: var(--fs-2xs); color: var(--ui-muted); text-align: center;
    max-width: 68px; line-height: 1.25;
    overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}

/* ---------- Lưu đồ: luồng trạng thái (UI.flow) ---------- */
.ui-flowmap { display: flex; align-items: flex-start; gap: 0; flex-wrap: wrap; padding: 6px 0; }
.ui-flowmap-step { display: flex; flex-direction: column; align-items: center; gap: 5px; flex: 1 1 0; min-width: 62px; }
.ui-flowmap-dot {
    width: 15px; height: 15px; border-radius: 50%; background: var(--c);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--c) 22%, transparent);
    flex: none;
}
.ui-flowmap-label { font-size: var(--fs-2xs); color: var(--ui-muted); text-align: center; line-height: 1.25; }
.ui-flowmap-value { font-size: var(--fs-md); font-weight: 800; font-variant-numeric: tabular-nums; }
.ui-flowmap-link { flex: 0 0 auto; width: 18px; height: 2px; background: var(--ui-line); margin-top: 7px; border-radius: 2px; }
/* Phễu dòng chảy (UI.funnelFlow): dải chính màu thương hiệu, nhánh rời đi màu "xấu", bước cuối màu "tốt" */
.ui-ff-scroll { overflow-x: auto; }
.ui-ff { display: block; overflow: visible; }
.ui-ff-name { font-size: var(--fs-xs); fill: var(--ui-muted); }
.ui-ff-val { font-size: var(--fs-lg); font-weight: 700; fill: var(--ui-text); font-variant-numeric: tabular-nums; }
.ui-ff-rate { font-size: var(--fs-2xs); fill: var(--ui-muted); }
.ui-ff-rate.bad, .ui-ff-drop.bad { fill: var(--ui-bad); }
.ui-ff-band { fill: var(--brand-primary); opacity: .16; transition: opacity .2s; }
.ui-ff-band:hover { opacity: .32; }
.ui-ff-drip { fill: var(--ui-bad); opacity: .2; transition: opacity .2s; }
.ui-ff-drip.worst { opacity: .42; }
.ui-ff-drip:hover { opacity: .62; }
.ui-ff-dot { fill: var(--ui-bad); }
.ui-ff-node { fill: var(--brand-primary); }
.ui-ff-node.last { fill: var(--ui-ok); }
.ui-ff-drop { font-size: var(--fs-sm); font-weight: 700; fill: var(--ui-text); font-variant-numeric: tabular-nums; }
.ui-ff-why { font-size: var(--fs-2xs); fill: var(--ui-muted); }
.ui-ff-insight { display: flex; align-items: center; gap: 16px; margin-top: 14px; background: var(--ui-bad-bg); color: var(--ui-bad); border-radius: var(--ui-r-inner); padding: 14px 16px; }
.ui-ff-insight b { display: block; font-size: var(--fs-md); }
.ui-ff-insight p { margin: 2px 0 0; font-size: var(--fs-sm); color: var(--ui-text); }
.ui-ff-insight-num { font-size: var(--fs-2xl); font-weight: 800; line-height: 1; min-width: 80px; font-variant-numeric: tabular-nums; }
/* Phễu dọc cho khung hẹp */
.ui-ffv { display: flex; flex-direction: column; gap: 6px; }
.ui-ffv-head { display: flex; justify-content: space-between; gap: 10px; font-size: var(--fs-sm); color: var(--ui-muted); }
.ui-ffv-head b { color: var(--ui-text); font-size: var(--fs-md); font-variant-numeric: tabular-nums; }
.ui-ffv-bar { height: 10px; border-radius: 5px; background: var(--ui-surface-2); overflow: hidden; margin-top: 3px; }
.ui-ffv-bar span { display: block; height: 100%; border-radius: 5px; background: var(--brand-primary); }
.ui-ffv-bar span.last { background: var(--ui-ok); }
.ui-ffv-drop { font-size: var(--fs-xs); color: var(--ui-muted); padding: 2px 0 2px 12px; border-left: 2px solid var(--ui-bad-bg); line-height: 1.45; }
.ui-ffv-drop b { color: var(--ui-text); font-variant-numeric: tabular-nums; }
.ui-ffv-drop.bad, .ui-ffv-drop.bad b { color: var(--ui-bad); }
.ui-ffv-drop.bad { border-left-color: var(--ui-bad); }
/* Đầu phễu: tỉ lệ chuyển đổi lớn (trái) + thanh nguồn (phải) */
.ui-ff-hero { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 24px; align-items: end; margin-bottom: 16px; }
.ui-ff-big { display: flex; align-items: flex-end; gap: 14px; }
.ui-ff-big strong { font-size: var(--fs-3xl); font-weight: 800; line-height: .9; letter-spacing: -.03em; font-variant-numeric: tabular-nums; color: var(--ui-text); }
.ui-ff-big span { font-size: var(--fs-sm); color: var(--ui-muted); max-width: 220px; }
@media (max-width: 720px) { .ui-ff-hero { grid-template-columns: 1fr; gap: 14px; } .ui-ff-insight { flex-direction: column; align-items: flex-start; gap: 6px; } }

/* ---------- Dải băng hành trình (UI.ribbon) ----------
   Mỗi hàng = MỘT hành trình; dải băng chạy qua các trạm nó đi qua, dày theo số
   người. Trạm thẳng cột nhờ các ô .ui-rb-slot chia đều. */
.ui-rb { display: flex; flex-direction: column; gap: 8px; }
.ui-rb-row { display: flex; align-items: center; gap: 12px; }
.ui-rb-track {
    position: relative; flex: 1 1 auto; min-width: 0;
    display: flex; align-items: center; height: 30px;
}
.ui-rb-slot { flex: 1 1 0; display: flex; align-items: center; justify-content: center; min-width: 0; position: relative; z-index: 1; }
.ui-rb-band {
    position: absolute; top: 50%; transform: translateY(-50%);
    border-radius: 999px; opacity: 0.26; z-index: 0;
}
.ui-rb-dot {
    width: 22px; height: 22px; border-radius: 50%; background: var(--c);
    display: flex; align-items: center; justify-content: center; flex: none;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--c) 22%, transparent);
}
.ui-rb-step { font-size: var(--fs-2xs); font-weight: 800; color: var(--ui-on-brand); line-height: 1; }
.ui-rb-meta { flex: 0 0 150px; display: flex; align-items: baseline; justify-content: flex-end; gap: 8px; }
.ui-rb-people { font-size: var(--fs-md); font-weight: 800; font-variant-numeric: tabular-nums; color: var(--ui-text); }
.ui-rb-rate { font-size: var(--fs-2xs); font-weight: 700; white-space: nowrap; }
.ui-rb-rate.is-ok { color: var(--ui-ok); }
.ui-rb-rate.is-warn { color: var(--ui-warn); }
.ui-rb-rate.is-bad { color: var(--ui-muted-2); }
.ui-rb-heads .ui-rb-track { height: auto; align-items: flex-end; }
.ui-rb-head {
    font-size: var(--fs-2xs); color: var(--ui-muted); text-align: center; line-height: 1.2;
    overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.ui-rb-foot { font-size: var(--fs-2xs); color: var(--ui-muted-2); padding-top: 6px; border-top: 1px solid var(--ui-line-soft); }
@media (max-width: 768px) {
    .ui-rb-meta { flex: 0 0 96px; }
    .ui-rb-dot { width: 18px; height: 18px; }
    .ui-rb-head { font-size: 0.66rem; }
}

/* ---------- Lưu đồ dòng chảy (UI.sankey) ----------
   Dòng người chảy qua các bước hành trình. Nhãn cột đầu đặt NGOÀI svg để không
   bị kéo méo bởi preserveAspectRatio="none". */
.ui-sk { position: relative; display: flex; height: 100%; min-height: 0; gap: 8px; }
.ui-sk-names { position: relative; flex: 0 0 132px; }
.ui-sk-name {
    position: absolute; right: 0; transform: translateY(-50%);
    font-size: var(--fs-2xs); color: var(--ui-muted); text-align: right;
    max-width: 132px; line-height: 1.2; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis;
}
.ui-sk-svg { flex: 1 1 auto; min-width: 0; height: 100%; overflow: visible; }
/* Sankey ghi nhãn mọi nút (UI.sankey opts.labels='all') — nhãn HTML phủ lên SVG, hẹp thì cuộn ngang */
.ui-sk-wrap { height: 100%; overflow-x: auto; overflow-y: hidden; }
.ui-sk-full { position: relative; height: 100%; display: flex; flex-direction: column; }
.ui-sk-cols { position: relative; height: 22px; flex: none; }
.ui-sk-col { position: absolute; top: 0; font-size: var(--fs-2xs); font-weight: 700; color: var(--ui-muted); text-transform: uppercase; letter-spacing: 0.3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ui-sk-stage { position: relative; flex: 1 1 auto; min-height: 0; }
.ui-sk-stage .ui-sk-svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.ui-sk-label { position: absolute; transform: translateY(-50%); padding: 0 6px; font-size: var(--fs-2xs); font-weight: 600; line-height: 1.2; color: var(--ui-on-brand); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; pointer-events: none; }
.ui-sk-label b { display: block; font-family: var(--font-mono); font-size: var(--fs-xs); }
.ui-sk-val { font-size: 2.4px; font-weight: 700; fill: var(--ui-on-brand); font-family: var(--font-mono); }
@media (max-width: 480px) {
    .ui-sk-names { flex: 0 0 84px; }
    .ui-sk-name { max-width: 84px; font-size: 0.66rem; }
}
@media (max-width: 768px) {
    .ui-flowmap-link { display: none; }
    .ui-flowmap-step { flex: 0 0 33.333%; margin-bottom: 12px; }
    .ui-wf-name { font-size: 0.66rem; max-width: 52px; }
}
/* mini: ô con trong 1 card (lưới 2×2) */
.ui-kpi-mini {
    padding: 12px 14px;
    border-radius: var(--ui-r-inner);
    background: var(--ui-surface-2);
    border: 1px solid var(--ui-line-soft);
    box-shadow: none;
    backdrop-filter: none;
    gap: 4px;
}
.ui-kpi-mini::before { display: none; }
.ui-kpi-mini:hover { transform: none; box-shadow: none; }
.ui-kpi-mini .ui-kpi-title { font-size: var(--fs-sm); color: var(--ui-muted); }
.ui-kpi-mini .ui-kpi-value { font-size: var(--fs-xl); white-space: nowrap; word-break: normal; }
.ui-kpi-mini .ui-kpi-description { font-size: var(--fs-xs); }
.ui-mini-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; flex: 1 1 auto; min-height: 0; }
.ui-mini-grid.one { grid-template-columns: 1fr; }
.ui-mini-grid.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ui-mini-grid.five { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.ui-mini-grid.auto { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
.ui-mini-grid.four { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.ui-mini-grid.three .ui-kpi-value, .ui-mini-grid.five .ui-kpi-value { font-size: var(--fs-lg); }
/* Ô hẹp (3–5 cột): số tiền "42.736.052 ₫" (~6em) không xuống dòng → co chữ theo bề rộng ô thay vì bị cắt (2026-10-08).
   100cqi = bề rộng nội dung ô; /7 chừa cho chuỗi tới 13 ký tự. Ô đủ rộng vẫn giữ --fs-lg như cũ. */
.ui-mini-grid.three > .ui-kpi-card, .ui-mini-grid.five > .ui-kpi-card { container-type: inline-size; }
@supports (font-size: 1cqi) {
    .ui-mini-grid.three .ui-kpi-value, .ui-mini-grid.five .ui-kpi-value { font-size: clamp(0.8rem, calc(100cqi / 7), var(--fs-lg)); }
}
.ui-kpi-card.ui-span-2 .ui-kpi-value { font-size: var(--fs-xl); white-space: nowrap; word-break: normal; }

/* ---------- Bảng chi tiết gập/mở dưới chart ---------- */
.ui-detail { margin-top: 14px; border-top: 1px solid rgba(var(--brand-primary-rgb), 0.12); padding-top: 10px; flex: none; }
.ui-detail-toggle {
    display: inline-flex; align-items: center; gap: 7px;
    background: rgba(var(--brand-primary-rgb), 0.07);
    border: 1px solid rgba(var(--brand-primary-rgb), 0.18);
    color: var(--brand-primary);
    font-size: var(--fs-sm); font-weight: 600; font-family: inherit;
    padding: 7px 14px; border-radius: 8px; cursor: pointer;
    transition: background 0.15s ease;
}
.ui-detail-toggle:hover { background: rgba(var(--brand-primary-rgb), 0.14); }
.ui-detail-caret { display: inline-block; transition: transform 0.15s ease; }
.ui-detail-toggle[aria-expanded="true"] .ui-detail-caret { transform: rotate(90deg); }
.ui-detail-note { font-size: var(--fs-xs); color: var(--ui-muted); margin: 10px 0 8px; line-height: 1.5; }
.ui-detail-note code { background: rgba(var(--brand-primary-rgb), 0.08); padding: 1px 5px; border-radius: 4px; }
.ui-detail-body { padding: 10px 0 2px; }
/* thanh tỉ trọng vẽ trong ô bảng (lặp ở customer-journey, customer-segments, compare-channels) */
.ui-cell-bar { display: block; height: 6px; border-radius: 3px; background: var(--brand-primary); }
.ui-empty.is-loading { color: var(--ui-muted); border-style: solid; }
.ui-mini-grid > .ui-kpi-card { min-height: 0; }
/* dòng KPI xếp dọc trong 1 card (khối Sản phẩm) */
.ui-kpi-rows { display: flex; flex-direction: column; justify-content: space-between; flex: 1 1 auto; min-height: 0; }
.ui-kpi-card.ui-kpi-row {
    padding: 8px 0;
    background: none;
    border: none;
    border-bottom: 1px solid var(--ui-line-soft);
    border-radius: 0;
    box-shadow: none;
    backdrop-filter: none;
    display: flex; flex-direction: column; gap: 2px;
}
.ui-kpi-card.ui-kpi-row::before { display: none; }
.ui-kpi-card.ui-kpi-row:hover { transform: none; box-shadow: none; }
.ui-kpi-card.ui-kpi-row:last-child { border-bottom: none; }
.ui-kpi-row .ui-kpi-title { font-size: var(--fs-sm); color: var(--ui-muted); }
.ui-kpi-row .ui-kpi-value { font-size: var(--fs-xl); }
.ui-kpi-row .ui-kpi-description { font-size: var(--fs-xs); }
.ui-kpi-row .card-delta { margin: 0; }
.ui-kpi-row-line { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
/* thanh mức (tỷ lệ %) */
.ui-meter { height: 6px; border-radius: 3px; background: var(--ui-line-soft); overflow: hidden; }
.ui-meter > span { display: block; height: 100%; width: 0; background: var(--ui-warn); transition: width 0.4s ease; }

/* ---------- Luồng đơn hàng ---------- */
.ui-flow { display: flex; align-items: stretch; gap: 10px; flex: 1 1 auto; min-height: 0; }
.ui-flow-step {
    /* basis auto + KHÔNG co: ô luôn cao đủ nội dung.
       Trước đây `flex: 1 1 0` khiến các ô chia đều chiều cao container — khi xếp
       DỌC trên điện thoại (min-height về 0) thì mỗi ô co về gần 0 và chữ tràn ra
       ngoài viền. Trên máy tính cũng sát ngưỡng (63px so với 64px nội dung cần). */
    /* Máy tính: chia ĐỀU (basis 0) nhưng không ô nào hẹp hơn con số của nó (min-content — value nowrap).
       Trước đây basis auto ⇒ ô có MÔ TẢ dài chiếm chỗ, ô TIỀN mô tả ngắn bị bóp, số tiền bị cắt (2026-10-08).
       Điện thoại (≤768px) vẫn ghi đè flex: 0 0 auto khi xếp dọc. */
    flex: 1 1 0;
    min-width: min-content;
    padding: 12px 14px;
    border-radius: var(--ui-r-inner);
    background: var(--ui-surface-2);
    border: 1px solid var(--ui-line-soft);
    box-shadow: none;
    backdrop-filter: none;
    gap: 4px;
}
.ui-flow-step::before { display: none; }
.ui-flow-step:hover { transform: none; box-shadow: none; }
.ui-flow-step .ui-kpi-title { font-size: var(--fs-sm); color: var(--ui-muted); }
.ui-flow-step .ui-kpi-value { font-size: var(--fs-lg); white-space: nowrap; word-break: normal; }
.ui-flow-step .ui-kpi-description { font-size: var(--fs-2xs); }
.ui-flow-step.is-bad  { border-color: rgba(254, 44, 85, 0.35); }
.ui-flow-step.is-bad  .ui-kpi-value { color: var(--ui-bad); }
.ui-flow-step.is-warn { border-color: rgba(245, 184, 0, 0.4); }
.ui-flow-step.is-warn .ui-kpi-value { color: var(--ui-warn); }
.ui-flow-step.is-ok   { background: var(--ui-ok-bg); border-color: rgba(18, 183, 106, 0.35); }
.ui-flow-step.is-ok   .ui-kpi-value { color: var(--ui-ok); }
.ui-flow-step.is-brand { background: rgba(var(--brand-primary-rgb), 0.08); border-color: rgba(var(--brand-primary-rgb), 0.3); }
.ui-flow-step.is-brand .ui-kpi-value { color: var(--brand-primary); }
.ui-flow-arrow { display: flex; align-items: center; color: var(--ui-muted-2); flex: none; font-size: var(--fs-lg); }

/* ---------- Thanh xếp chồng + legend (thay chart tròn) ---------- */
.ui-stack { display: flex; height: 12px; border-radius: 6px; overflow: hidden; gap: 2px; flex: none; margin-bottom: 12px; }
.ui-stack > span { display: block; height: 100%; min-width: 2px; }
.ui-legend { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 14px; font-size: var(--fs-xs); overflow: auto; min-height: 0; flex: 1 1 auto; align-content: start; }
.ui-legend > .ui-empty { grid-column: 1 / -1; }
.ui-legend-item { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ui-legend-dot { width: 8px; height: 8px; border-radius: 2px; flex: none; }
.ui-legend-name { flex: 1 1 auto; color: var(--ui-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ui-legend-val { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--ui-text); }

/* ---------- Dãy thanh ngang (top N, tỷ lệ) ---------- */
.ui-bars { display: flex; flex-direction: column; gap: 10px; flex: 1 1 auto; min-height: 0; overflow: auto; }
.ui-bar-row { display: flex; align-items: center; gap: 10px; font-size: var(--fs-sm); }
.ui-bar-label { width: 96px; flex: none; color: var(--ui-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ui-bar-track { flex: 1 1 auto; height: 14px; border-radius: 4px; background: var(--ui-line-soft); overflow: hidden; }
.ui-bar-fill { display: block; height: 100%; border-radius: 4px; background: var(--brand-primary); }
.ui-bar-val { width: 64px; flex: none; text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; }

/* ---------- Bảng ---------- */
.ui-table-scroll { overflow: auto; max-height: 460px; border: 1px solid var(--ui-line-soft); border-radius: var(--ui-r-inner); }
/* bảng là nội dung chính của trang (danh sách dài) — cao hơn, hoặc .free = không giới hạn */
.ui-table-scroll.tall { max-height: 70vh; }
.ui-table-scroll.free { max-height: none; }
.ui-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); white-space: nowrap; }
.ui-table thead th {
    position: sticky; top: 0; z-index: 1;
    background: var(--ui-surface-2);
    text-align: left;
    font-weight: 700;
    color: var(--ui-text);
    padding: 9px 10px;
    border-bottom: 2px solid var(--ui-line);
}
.ui-table td { padding: 8px 10px; border-top: 1px solid var(--ui-line-soft); }
.ui-table tbody tr:hover { background: rgba(var(--brand-primary-rgb), 0.04); }
.ui-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.ui-table .idx { width: 40px; text-align: right; color: var(--ui-muted-2); }
.ui-table .name { white-space: normal; min-width: 220px; max-width: 380px; }
.ui-table tfoot td { background: var(--ui-surface-2); border-top: 2px solid var(--ui-line); font-weight: 700; padding: 10px; }
.ui-table th[data-sort] { cursor: pointer; user-select: none; }
.ui-pos  { color: var(--ui-ok); font-weight: 600; }
.ui-neg  { color: var(--ui-bad); font-weight: 600; }
.ui-warn { color: var(--ui-warn); font-weight: 600; }
.ui-muted { color: var(--ui-muted-2); }

.ui-table a { color: var(--brand-primary); font-weight: 600; text-decoration: none; }
.ui-kpi-value.ui-pos, .ui-kpi-value.ui-neg { font-weight: 800; }

/* ---------- Dùng chung rút từ các trang đã chuyển (2026-09-21) ---------- */
/* Thẻ KPI có sắc thái ngữ nghĩa (giao thành công / chờ / thất bại) */
.ui-kpi-card.is-ok   { background: var(--ui-ok-bg);  border-color: rgba(18, 183, 106, 0.35); }
.ui-kpi-card.is-ok   .ui-kpi-value { color: var(--ui-ok); }
.ui-kpi-card.is-warn { background: var(--ui-warn-bg); border-color: rgba(245, 184, 0, 0.4); }
.ui-kpi-card.is-warn .ui-kpi-value { color: var(--ui-warn); }
.ui-kpi-card.is-bad  { background: var(--ui-bad-bg); border-color: rgba(254, 44, 85, 0.35); }
.ui-kpi-card.is-bad  .ui-kpi-value { color: var(--ui-bad); }
/* Nhãn dài xuống dòng được (lý do hủy/hoàn) — khác .ui-badge là pill 1 dòng */
.ui-tag {
    display: inline-block; padding: 4px 11px; margin: 2px;
    background: rgba(var(--brand-primary-rgb), 0.08);
    border: 1px solid rgba(var(--brand-primary-rgb), 0.25);
    border-radius: 8px; font-size: var(--fs-xs); color: var(--brand-primary);
    font-weight: 500; white-space: normal;
}
/* Mã SKU / mã đơn trong bảng */
.ui-code, .ui-table code {
    background: rgba(var(--brand-primary-rgb), 0.08); padding: 2px 7px; border-radius: 6px;
    font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--brand-primary);
}
/* Làm nổi dòng đáng chú ý trong bảng (top N, vượt ngưỡng) */
.ui-table tbody tr.highlight-row > td { background: var(--ui-bad-bg); }
/* Dải phân mục cho trang dài chia phần */
.ui-section { margin: 6px 0 var(--ui-gap); padding: 0 4px; }
.ui-section h2 { font-size: var(--fs-2xl); color: var(--brand-primary); margin: 0 0 4px; }
.ui-section p  { font-size: var(--fs-md); color: var(--ui-muted); margin: 0; }
/* Bọc nút mở .ui-pop (bộ lọc nhiều lựa chọn) */
.ui-pop-wrap { position: relative; }
/* Danh sách bản ghi dạng thẻ (modal đơn của khách — trang không dùng bảng) */
.ui-record-list { max-height: 460px; overflow-y: auto; }
.ui-record {
    border: 1px solid var(--ui-line); border-radius: var(--ui-r-inner);
    padding: 16px; margin-bottom: 12px; background: var(--ui-surface);
}
.ui-record-head {
    display: flex; justify-content: space-between; align-items: center; gap: 10px;
    padding-bottom: 12px; margin-bottom: 12px; border-bottom: 1px solid var(--ui-line-soft);
}
.ui-record-id     { font-size: var(--fs-lg); font-weight: 700; color: var(--brand-primary); }
.ui-record-date   { font-size: var(--fs-sm); color: var(--ui-muted); }
.ui-record-amount { font-size: var(--fs-xl); font-weight: 700; color: var(--ui-ok); white-space: nowrap; }
/* Hộp modal rộng, thân cuộn bên trong (bảng dài trong modal) */
.ui-modal-box.wide-scroll { width: min(1200px, 95vw); max-width: none; max-height: 90vh; text-align: left; display: flex; flex-direction: column; overflow: hidden; }

/* ---------- Sắc thái số trong bảng (rút từ 5 trang analytics, 2026-09-22) ---------- */
.val-ok   { color: var(--ui-ok);       font-weight: 600; }
.val-warn { color: var(--ui-warn);     font-weight: 600; }
.val-bad  { color: var(--ui-bad);      font-weight: 600; }
.val-flat { color: var(--ui-muted-2);  font-weight: 600; }
.val-na   { color: var(--ui-muted-2); }
/* ô bảng cho chữ dài xuống dòng (tên SP, danh sách phụ kiện) */
.ui-table td.wrap-cell, .ui-table th.wrap-cell { text-align: left; white-space: normal; }
/* dòng phụ nhỏ trong ô bảng (SKU dưới tên, kênh dưới mã đơn) */
.cell-sub { color: var(--ui-muted); font-size: var(--fs-xs); font-weight: 400; }
/* thẻ KPI bấm được để xem chi tiết */
.ui-kpi-card.clickable { cursor: pointer; }
.ui-kpi-card.clickable:hover { border-color: var(--brand-primary); box-shadow: var(--ui-shadow-hover); }
/* chữ trên nền màu thương hiệu / nền màu do dữ liệu quyết định */
:root { --ui-on-brand: #ffffff; }

/* ---------- Trạng thái rỗng / nhãn ---------- */
.ui-empty {
    padding: 16px;
    text-align: center;
    color: var(--ui-muted);
    font-size: var(--fs-sm);
    border: 1px dashed var(--ui-line);
    border-radius: var(--ui-r-inner);
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
}
.ui-empty a { color: var(--brand-primary); font-weight: 600; text-decoration: none; }
.ui-badge { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: var(--fs-xs); font-weight: 600; background: var(--ui-surface-2); color: var(--ui-text); }
.ui-badge.ok { background: var(--ui-ok-bg); color: #0a663b; }
.ui-badge.warn { background: var(--ui-warn-bg); color: #946F00; }
.ui-badge.bad { background: var(--ui-bad-bg); color: #fe2c55; }
.ui-chip { padding: 5px 11px; border-radius: 999px; border: 1px solid var(--ui-line); background: var(--ui-surface); font-size: var(--fs-xs); cursor: pointer; color: var(--ui-muted); }
.ui-chip.on { background: var(--brand-primary); color: var(--ui-on-brand); border-color: var(--brand-primary); }

/* ---------- Dropdown nổi (multi-select trong bộ lọc) ---------- */
.ui-pop {
    display: none;
    position: absolute; z-index: 1000; top: 100%; left: 0; margin-top: 4px;
    background: var(--ui-surface); border: 1px solid var(--ui-line); border-radius: 8px; padding: 8px;
    max-height: 300px; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain;
    min-width: 240px; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
}
.ui-pop-all { display: flex; align-items: center; gap: 6px; font-weight: 600; border-bottom: 1px solid var(--ui-line-soft); padding-bottom: 6px; margin-bottom: 6px; cursor: pointer; color: var(--ui-text); }
.ui-pop-list { display: flex; flex-direction: column; gap: 4px; }
.ui-pop-list label { display: flex; align-items: center; gap: 6px; cursor: pointer; font-size: var(--fs-base); color: var(--ui-text); }
.ui-pop-note { color: var(--ui-muted-2); font-size: var(--fs-sm); }

/* ---------- Progress / loading / toast (mọi trang báo cáo) ---------- */
.ui-progress { position: fixed; top: 0; left: 0; height: 3px; width: 0; background: var(--brand-gradient); z-index: 2000; transition: width 0.4s; }
.ui-modal {
    display: none; position: fixed; inset: 0; background: rgba(0, 0, 0, 0.45);
    z-index: 1500; align-items: center; justify-content: center;
}
.ui-modal.show { display: flex; }
.ui-modal-box {
    background: var(--ui-surface); border-radius: var(--ui-r-card); padding: 36px 44px; text-align: center;
    box-shadow: 0 25px 60px rgba(0, 0, 0, 0.25); max-width: 90vw;
}
.ui-modal-box h3 { color: var(--ui-text); margin: 0 0 6px; font-size: var(--fs-lg); }
.ui-modal-box p { color: var(--ui-muted); font-size: var(--fs-base); margin: 0; }
.ui-spinner {
    width: 44px; height: 44px; margin: 0 auto 16px;
    border: 4px solid var(--ui-line); border-top-color: var(--brand-primary);
    border-radius: 50%; animation: ui-spin 0.9s linear infinite;
}
@keyframes ui-spin { to { transform: rotate(360deg); } }
.ui-toast {
    position: fixed; top: 20px; right: 20px; padding: 14px 22px; border-radius: var(--ui-r-inner);
    background: #333; color: #fff; font-weight: 600; z-index: 2500; font-size: var(--fs-base);
    opacity: 0; transform: translateX(30px); transition: all 0.3s; pointer-events: none; max-width: 380px;
}
.ui-toast.show { opacity: 1; transform: translateX(0); }
.ui-toast.success { background: linear-gradient(135deg, #12b76a, #12b76a); }
.ui-toast.error   { background: linear-gradient(135deg, #fe2c55, #fe2c55); }
.ui-toast.warning { background: #F5B800; }
.ui-toast.info    { background: var(--brand-gradient); }

/* ---------- Responsive ---------- */
@media (max-width: 1024px) {
    .ui-mini-grid.four, .ui-mini-grid.five { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .ui-span-2, .ui-span-3, .ui-span-4, .ui-span-5, .ui-span-7, .ui-span-8, .ui-span-9 { grid-column: span 6; }
    .ui-filter-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 768px) {
    .ui-page { padding: 15px; }
    .ui-grid { gap: 15px; margin-bottom: 15px; }
    .ui-span-2, .ui-span-3, .ui-span-4, .ui-span-5, .ui-span-6, .ui-span-7, .ui-span-8, .ui-span-9 { grid-column: span 12; }
    .ui-h-kpi, .ui-h-flow { min-height: 0; }
    .ui-h-chart, .ui-h-chart-sm, .ui-h-chart-lg { height: 320px; }
    .ui-mini-grid.three, .ui-mini-grid.four, .ui-mini-grid.five { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .ui-section h2 { font-size: var(--fs-xl); }
    .ui-kpi-hero { flex-direction: column; }
    .ui-kpi-spark { width: 100%; }
    /* iOS in ngày dạng "ngày 30 thg 9, 2026" — nửa hàng 390px gãy 2 dòng nếu giữ đệm 16px/chữ md */
    .ui-dates .ui-input { padding-left: 10px; padding-right: 8px; font-size: var(--fs-sm); }
    .ui-flow { flex-direction: column; align-items: stretch; }
    /* xếp dọc: mỗi ô cao theo nội dung, tuyệt đối không co */
    .ui-flow-step { flex: 0 0 auto; }
    .ui-flow-arrow { justify-content: center; transform: rotate(90deg); }
    .ui-filter-grid { grid-template-columns: minmax(0, 1fr); }
    .ui-actions > .ui-btn { flex: 1 1 auto; }
    /* Tiêu đề + mô tả xếp ngang trên một dòng hẹp → tiêu đề bị ép, chữ chen nhau.
       Cho xuống dòng và canh trái. */
    .ui-card-head { flex-wrap: wrap; align-items: flex-start; }
    .ui-card-sub { white-space: normal; }
    .ui-toast { max-width: calc(100vw - 24px); right: 12px; font-size: var(--fs-sm); }
}

/* =====================================================================
   NGUYÊN LIỆU CHO MẪU TRANG B/C/D (bổ sung 2026-09-21) — docs/design/DESIGN.md mục 5, 6
   ===================================================================== */

/* ---------- Tab lớn (đổi vùng nội dung) & segment (đổi cách xem trong 1 card) ---------- */
.ui-tabs { display: flex; gap: 4px; box-shadow: inset 0 -2px 0 var(--ui-line-soft); margin-bottom: var(--ui-gap); overflow-x: auto; overflow-y: hidden; flex: none; }   /* đường kẻ bằng box-shadow: tab không tràn dọc nên không hiện thanh cuộn */
.ui-tab {
    padding: 10px 16px;
    border: none; border-bottom: 2px solid transparent; background: none;
    font-family: inherit; font-size: var(--fs-md); font-weight: 600; color: var(--ui-muted);
    cursor: pointer; white-space: nowrap; transition: color 0.15s ease, border-color 0.15s ease;
}
.ui-tab:hover { color: var(--brand-primary); }
.ui-tab.on, .ui-tab[aria-selected="true"] { color: var(--brand-primary); border-bottom-color: var(--brand-primary); }
.ui-tab .ui-badge { margin-left: 6px; }
.ui-tab-panel[hidden] { display: none; }
.ui-segment { display: inline-flex; gap: 4px; padding: 3px; border-radius: 8px; background: var(--ui-surface-2); border: 1px solid var(--ui-line-soft); }
.ui-segment > button {
    height: 28px; padding: 0 10px; border: none; border-radius: 6px; background: transparent;
    font-family: inherit; font-size: var(--fs-xs); font-weight: 600; color: var(--ui-muted); cursor: pointer;
}
.ui-segment > button.on, .ui-segment > button[aria-pressed="true"] { background: var(--ui-surface); color: var(--brand-primary); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); }

/* ---------- Bảng nâng cao: sort, tìm kiếm, phân trang, cột dính, dòng mở rộng, cột hành động ---------- */
.ui-table th[data-sort] { cursor: pointer; user-select: none; padding-right: 18px; }
/* \FE0E = dạng CHỮ: iOS vẽ ↕ ↑ ↓ thành emoji (ô xanh to) đè lên chữ tiêu đề cột */
.ui-table th[data-sort]::after { content: '\2195\FE0E'; position: absolute; right: 6px; opacity: 0.35; font-size: var(--fs-2xs); }
.ui-table th[data-sort][aria-sort="ascending"]::after { content: '\2191\FE0E'; opacity: 1; color: var(--brand-primary); }
.ui-table th[data-sort][aria-sort="descending"]::after { content: '\2193\FE0E'; opacity: 1; color: var(--brand-primary); }
.ui-table .sticky-col { position: sticky; left: 0; background: var(--ui-surface); z-index: 1; box-shadow: 2px 0 0 var(--ui-line-soft); }
.ui-table thead .sticky-col { z-index: 2; background: var(--ui-surface-2); }
.ui-table tr.is-open > td { background: rgba(var(--brand-primary-rgb), 0.05); }
.ui-table tr.ui-row-detail > td { background: var(--ui-surface-2); padding: 12px 16px; white-space: normal; }
.ui-table td.actions, .ui-table th.actions { text-align: right; white-space: nowrap; width: 1%; }
.ui-table td.actions .ui-btn { padding: 5px 10px; font-size: var(--fs-xs); }
.ui-table-toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; flex: none; }
.ui-table-toolbar .ui-search { flex: 1 1 260px; max-width: 360px; }
.ui-table-toolbar select.ui-input, .ui-table-toolbar input[type="number"].ui-input { width: auto; min-width: 0; }
.ui-table-toolbar select.ui-input { min-width: 170px; }
.ui-search { position: relative; }
.ui-search .ui-input { padding-left: 34px; }
.ui-search::before { content: '⌕'; position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--ui-muted-2); font-size: var(--fs-lg); pointer-events: none; }
.ui-pager { display: flex; align-items: center; justify-content: flex-end; gap: 6px; margin-top: 10px; font-size: var(--fs-xs); color: var(--ui-muted); flex: none; flex-wrap: wrap; }
.ui-pager button {
    min-width: 30px; height: 30px; padding: 0 8px; border: 1px solid var(--ui-line); border-radius: 6px;
    background: var(--ui-surface); font-family: inherit; font-size: var(--fs-xs); color: var(--ui-text); cursor: pointer;
}
.ui-pager button:hover:not(:disabled) { border-color: var(--brand-primary); color: var(--brand-primary); }
.ui-pager button.on { background: var(--brand-primary); border-color: var(--brand-primary); color: var(--ui-on-brand); }
.ui-pager button:disabled { opacity: 0.45; cursor: default; }
.ui-pager .ui-pager-info { margin-right: auto; }

/* ---------- Form ---------- */
.ui-form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 15px; margin-bottom: 15px; }
.ui-form-group { display: flex; flex-direction: column; gap: 6px; min-width: 0; margin-bottom: 15px; }
.ui-form-row > .ui-form-group { margin-bottom: 0; }
.ui-form-group > label, .ui-label { font-size: var(--fs-sm); font-weight: 600; color: var(--ui-text); }
.ui-label .req { color: var(--ui-bad); margin-left: 2px; }
.ui-help { font-size: var(--fs-xs); color: var(--ui-muted); line-height: 1.45; }
.ui-error { font-size: var(--fs-xs); color: var(--ui-bad); }
.ui-input.is-invalid { border-color: var(--ui-bad); box-shadow: 0 0 0 3px var(--ui-bad-bg); }
.ui-input:disabled, .ui-input[readonly] { background: var(--ui-surface-2); color: var(--ui-muted); cursor: not-allowed; }
textarea.ui-input { min-height: 96px; resize: vertical; }
.ui-input-sm { padding: 8px 12px; font-size: var(--fs-sm); border-radius: 8px; }
.ui-input-group { display: flex; align-items: stretch; }
.ui-input-group .ui-input { border-radius: var(--ui-r-input) 0 0 var(--ui-r-input); }
.ui-input-group .ui-addon {
    display: flex; align-items: center; padding: 0 12px; border: 2px solid var(--ui-line); border-left: none;
    border-radius: 0 var(--ui-r-input) var(--ui-r-input) 0; background: var(--ui-surface-2); color: var(--ui-muted); font-size: var(--fs-sm); white-space: nowrap;
}
.ui-check { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-base); color: var(--ui-text); cursor: pointer; }
.ui-check input { width: 16px; height: 16px; accent-color: var(--brand-primary); margin: 0; }
.ui-check-list { display: flex; flex-direction: column; gap: 6px; }
.ui-switch { position: relative; display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: var(--fs-base); }
.ui-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.ui-switch .ui-switch-track { width: 40px; height: 22px; border-radius: 11px; background: var(--ui-line); position: relative; transition: background 0.2s; flex: none; }
.ui-switch .ui-switch-track::after { content: ''; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: var(--ui-surface); transition: transform 0.2s; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); }
.ui-switch input:checked + .ui-switch-track { background: var(--brand-primary); }
.ui-switch input:checked + .ui-switch-track::after { transform: translateX(18px); }
.ui-switch input:focus-visible + .ui-switch-track { box-shadow: 0 0 0 3px rgba(var(--brand-primary-rgb), 0.25); }
.ui-form-actions { display: flex; gap: 10px; justify-content: flex-end; align-items: center; padding-top: 12px; border-top: 1px solid var(--ui-line-soft); margin-top: 6px; }
.ui-form-actions .left { margin-right: auto; }

/* ---------- Nút bổ sung (cỡ nhỏ, viền, nguy hiểm, icon) ---------- */
.ui-btn-sm { padding: 7px 14px; font-size: var(--fs-sm); border-radius: 8px; }
.ui-btn-outline { background: var(--ui-surface); color: var(--brand-primary); border: 2px solid rgba(var(--brand-primary-rgb), 0.35); }
.ui-btn-outline:hover:not(:disabled) { background: rgba(var(--brand-primary-rgb), 0.06); }
.ui-btn-danger { background: var(--ui-bad); color: #fff; box-shadow: 0 8px 25px var(--ui-bad-bg); }
.ui-btn-danger-outline { background: var(--ui-surface); color: var(--ui-bad); border: 2px solid rgba(254, 44, 85, 0.35); }
.ui-btn-warn { background: var(--ui-warn); color: #fff; }
html[data-palette="project"] .ui-btn-warn { color: #161823; }   /* nền vàng → chữ đen mới đủ tương phản */
.ui-btn-icon { padding: 8px; width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center; border-radius: 8px; }
.ui-btn-group { display: inline-flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/* ---------- Drawer (panel trượt bên phải: chi tiết / sửa 1 dòng) ---------- */
.ui-drawer-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.35); z-index: 1400; opacity: 0; visibility: hidden; transition: opacity 0.2s; }
.ui-drawer {
    position: fixed; top: 0; right: 0; bottom: 0; z-index: 1450;
    width: min(560px, 100vw); background: var(--ui-surface); box-shadow: -10px 0 40px rgba(0, 0, 0, 0.15);
    display: flex; flex-direction: column; transform: translateX(100%); transition: transform 0.25s ease;
}
.ui-drawer.wide { width: min(880px, 100vw); }
.ui-drawer.show, .ui-drawer-overlay.show { transform: none; opacity: 1; visibility: visible; }
.ui-drawer-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 16px 20px; border-bottom: 1px solid var(--ui-line-soft); flex: none; }
.ui-drawer-head h3 { margin: 0; font-size: var(--fs-lg); color: var(--brand-primary); }
.ui-drawer-close { width: 34px; height: 34px; border: none; border-radius: 8px; background: var(--ui-surface-2); font-size: var(--fs-lg); cursor: pointer; color: var(--ui-muted); }
.ui-drawer-body { flex: 1 1 auto; overflow: auto; padding: 16px 20px; }
.ui-drawer-foot { flex: none; padding: 12px 20px; border-top: 1px solid var(--ui-line-soft); display: flex; gap: 10px; justify-content: flex-end; background: var(--ui-surface); }
.ui-drawer-section { margin-bottom: 18px; }
.ui-drawer-section h4 { margin: 0 0 8px; font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.4px; color: var(--ui-muted); }
.ui-kv { display: grid; grid-template-columns: minmax(120px, 40%) 1fr; gap: 6px 12px; font-size: var(--fs-sm); }
.ui-kv .k { color: var(--ui-muted); }
.ui-kv .v { color: var(--ui-text); font-weight: 600; word-break: break-word; }

/* ---------- Modal form (tạo/sửa trong trang không dùng drawer) ---------- */
.ui-modal-box.form { text-align: left; padding: 24px 28px; width: min(600px, 92vw); max-width: none; max-height: 90vh; overflow-y: auto; }
.ui-modal-box.form.wide { width: min(900px, 92vw); }
.ui-modal-box.form h3 { margin-bottom: 14px; color: var(--brand-primary); }

/* ---------- Modal xác nhận (dùng chung khung .ui-modal) ---------- */
.ui-modal-box.confirm { text-align: left; padding: 24px 28px; max-width: 460px; width: 92vw; }
.ui-modal-box.confirm h3 { margin-bottom: 10px; }
.ui-modal-box.confirm p { margin-bottom: 18px; }
.ui-modal-box.confirm .ui-form-actions { border-top: none; padding-top: 0; }

/* ---------- Tiến trình tác vụ (sync / gửi / tải) ---------- */
.ui-task { padding: 12px 14px; border-radius: var(--ui-r-inner); background: var(--ui-surface-2); border: 1px solid var(--ui-line-soft); display: flex; flex-direction: column; gap: 8px; }
.ui-task-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: var(--fs-sm); }
.ui-task-head .ui-task-status { font-weight: 700; }
.ui-task-bar { height: 8px; border-radius: 4px; background: var(--ui-line-soft); overflow: hidden; }
.ui-task-bar > span { display: block; height: 100%; width: 0; background: var(--brand-gradient); transition: width 0.3s ease; }
.ui-task.is-done .ui-task-bar > span { background: var(--ui-ok); }
.ui-task.is-error .ui-task-bar > span { background: var(--ui-bad); }
.ui-task-log { max-height: 160px; overflow: auto; font-family: var(--font-mono); font-size: var(--fs-2xs); color: var(--ui-muted); background: var(--ui-surface); border: 1px solid var(--ui-line-soft); border-radius: 6px; padding: 8px 10px; white-space: pre-wrap; }

/* ---------- Tiện ích ---------- */
.ui-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ui-row.between { justify-content: space-between; }
.ui-stack-v { display: flex; flex-direction: column; gap: 10px; }
.ui-hr { height: 1px; background: var(--ui-line-soft); margin: 12px 0; border: none; }
.ui-note { font-size: var(--fs-xs); color: var(--ui-muted); line-height: 1.5; }
.ui-callout { padding: 10px 14px; border-radius: var(--ui-r-inner); background: rgba(var(--brand-primary-rgb), 0.06); border-left: 3px solid var(--brand-primary); font-size: var(--fs-sm); color: var(--ui-text); }
.ui-callout.warn { background: var(--ui-warn-bg); border-left-color: var(--ui-warn); }
.ui-callout.bad { background: var(--ui-bad-bg); border-left-color: var(--ui-bad); }
.ui-callout.ok { background: var(--ui-ok-bg); border-left-color: var(--ui-ok); }
.ui-skeleton { background: linear-gradient(90deg, var(--ui-line-soft) 25%, var(--ui-surface-2) 50%, var(--ui-line-soft) 75%); background-size: 200% 100%; animation: ui-shimmer 1.2s infinite; border-radius: 6px; min-height: 14px; }
@keyframes ui-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
.ui-hide { display: none !important; }
/* thuộc tính hidden thắng display:flex/grid của component */
.ui-card[hidden], .ui-grid[hidden], .ui-row[hidden], .ui-kpi-card[hidden], .ui-filter[hidden], .ui-chart[hidden], .ui-empty[hidden] { display: none; }
/* ô trống trong bảng: td giữ table-cell để colspan còn tác dụng */
td.ui-empty { display: table-cell; text-align: center; }

@media (max-width: 768px) {
    .ui-tabs { gap: 0; }
    .ui-tab { padding: 10px 12px; font-size: var(--fs-sm); }
    .ui-form-row { grid-template-columns: 1fr; }
    .ui-drawer, .ui-drawer.wide { width: 100vw; }
    .ui-form-actions { flex-wrap: wrap; }
    .ui-table-toolbar .ui-search { max-width: none; }
    /* bộ chọn phân đoạn 4 mục ("Mọi thiết bị / Điện thoại / …") bẹp mỗi ô ~65px, chữ gãy 2 dòng → cuộn ngang */
    .ui-segment { max-width: 100%; overflow-x: auto; }
    .ui-segment > button { white-space: nowrap; flex: none; }
}

/* ---------- Điện thoại hẹp (≤480px) ----------
   Lưới 2 cột ở khổ này chỉ còn ~170px/ô — số tiền 9-10 chữ số bị xuống dòng hoặc
   tràn. Về 1 cột. (Ảnh lỗi người dùng gửi là màn 390px.) */
@media (max-width: 480px) {
    .ui-flowmap-step { flex: 0 0 50%; }
    /* Dãy thanh ngang: ô giá trị cố định 64px nên chuỗi dài ("0,9% · 196/22.922 phiên") gãy 3 dòng.
       Về bố cục 2 tầng: nhãn trái + giá trị phải, thanh chiếm trọn hàng dưới. */
    .ui-bar-row { flex-wrap: wrap; row-gap: 4px; }
    .ui-bar-label { width: auto; flex: 1 1 auto; }
    .ui-bar-val { width: auto; white-space: nowrap; }
    .ui-bar-track { flex: 1 1 100%; order: 3; }
    .ui-card, .ui-kpi-card { padding: 16px; }
    .ui-card-head { flex-wrap: wrap; }
    .ui-card-sub { white-space: normal; }
}

/* ===================================================================
   CHẾ ĐỘ TỐI — phần không thể làm bằng token
   Token ngữ nghĩa (--ui-text/line/surface-2/glass-bg...) đã đổi ở
   themeTokens.ejs nên mọi class ui-* tự theo. Phần dưới xử lý 2 thứ
   token không với tới được:
     1. nền <body>: 52 trang tự khai cùng MỘT gradient sáng cứng
        (rgba(255,255,255,1)) trong <style> riêng → đè tại đây, đỡ phải
        sửa 52 file.
     2. vài chỗ #fff cứng còn sót trong ui.css.
   =================================================================== */
html[data-theme="dark"] body {
    background: linear-gradient(135deg, rgba(var(--brand-primary-rgb), 0.10), var(--ui-page-bg)) fixed;
    color: var(--ui-text);
}

/* Card kính: nền tối + viền sáng nhẹ cho tách khỏi nền */
html[data-theme="dark"] .ui-card,
html[data-theme="dark"] .ui-kpi-card,
html[data-theme="dark"] .ui-filter,
html[data-theme="dark"] .ui-modal-box,
html[data-theme="dark"] .ui-drawer-panel {
    border-color: var(--ui-line);
}

html[data-theme="dark"] .ui-input::placeholder { color: var(--ui-muted-2); }

/* Nhãn trạng thái: chữ xanh/hổ phách/đỏ SẪM trên nền mờ → không đọc được ở nền tối */
html[data-theme="dark"] .ui-badge.ok   { color: var(--ui-ok); }
html[data-theme="dark"] .ui-badge.warn { color: var(--ui-warn); }
html[data-theme="dark"] .ui-badge.bad  { color: var(--ui-bad); }

/* Toast nền #333 gần trùng nền trang tối → nâng sáng cho tách khỏi nền */
html[data-theme="dark"] .ui-toast { background: #3d4354; }

/* Lịch/giờ của trình duyệt mặc định vẽ icon đen → đảo sang sáng */
html[data-theme="dark"] input[type="date"]::-webkit-calendar-picker-indicator,
html[data-theme="dark"] input[type="month"]::-webkit-calendar-picker-indicator {
    filter: invert(1) opacity(0.7);
}

/* Bảng: hàng sọc + hover dựa trên đen mờ → chuyển sang trắng mờ */
html[data-theme="dark"] .ui-table tbody tr:hover { background: rgba(255, 255, 255, 0.05); }
html[data-theme="dark"] .ui-table-scroll { background: transparent; }


/* =====================================================================
   BỐ CỤC ĐIỆN THOẠI (≤768px) — THIẾT KẾ LẠI, KHÔNG CHỈ DỒN CỘT
   Đo bằng Chromium thật ở 390px (scripts/ui-shot.js): cấu trúc PC bị dồn
   thành một cột dài — /offline có ~20 thẻ KPI mỗi thẻ chiếm trọn hàng, phải
   cuộn ~3.000px mới tới biểu đồ đầu tiên. Nguyên tắc ở đây:
     - KPI: 2 thẻ/hàng, gọn (bỏ khoảng trống, mô tả tối đa 2 dòng)
     - bảng nhiều cột: cột đầu dính khi cuộn ngang để không mất ngữ cảnh
     - thông báo nổi xuống đáy màn hình, không che thanh đầu trang
   ===================================================================== */
@media (max-width: 768px) {
    /* KPI đứng thẳng trong lưới (ui-span-2/3/4) → nửa hàng thay vì cả hàng */
    .ui-grid > .ui-kpi-card:not(.ui-kpi-hero) { grid-column: span 6; }
    /* thẻ KPI LẺ cuối nhóm chiếm trọn hàng thay vì để trống nửa hàng */
    .ui-grid > .ui-kpi-card:not(.ui-kpi-hero):nth-last-child(1 of .ui-kpi-card:not(.ui-kpi-hero)):nth-child(odd of .ui-kpi-card:not(.ui-kpi-hero)) { grid-column: span 12; }
    .ui-grid { gap: 10px; }
    .ui-mini-grid,
    .ui-mini-grid.three, .ui-mini-grid.four, .ui-mini-grid.five,
    .ui-mini-grid.auto { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
    .ui-mini-grid.one { grid-template-columns: 1fr; }
    /* Lưới KPI trang tự khai (gads-kpi, spa-summary, aff-summary, einv-kpi…) dùng
       repeat(auto-fit, minmax(170px,…)) → ở 390px chỉ vừa 1 cột. Mọi lưới chứa từ 2
       thẻ KPI trở lên (trừ lưới trang và luồng) về 2 cột. */
    :not(.ui-grid):not(.ui-flow):not(.ui-mini-grid.one):has(> .ui-kpi-card + .ui-kpi-card) {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .ui-kpi-card:not(.ui-kpi-hero) { padding: 12px 12px; gap: 4px; min-height: 0; }
    .ui-kpi-card:not(.ui-kpi-hero) .ui-kpi-title { font-size: var(--fs-xs); line-height: 1.25; }
    /* cỡ theo bề ngang màn: số tiền 13-15 ký tự vừa nửa hàng 390px */
    .ui-kpi-card:not(.ui-kpi-hero) .ui-kpi-value { font-size: clamp(0.95rem, 4.4vw, 1.2rem); }
    .ui-kpi-card:not(.ui-kpi-hero) .ui-kpi-description {
        font-size: var(--fs-2xs); line-height: 1.35;
        display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
    }
    .ui-kpi-hero .ui-kpi-value { font-size: 1.9rem; }
    .ui-kpi-card:hover { transform: none; }

    /* bảng cuộn ngang: GIỮ cột đầu (tên/mã) đứng yên để biết đang đọc dòng nào */
    .ui-table-scroll .ui-table tr > :first-child {
        position: sticky; left: 0; z-index: 1;
        background: var(--ui-surface);
        box-shadow: 1px 0 0 var(--ui-line-soft);
    }
    .ui-table-scroll .ui-table thead tr > :first-child { z-index: 3; background: var(--ui-surface-2); }

    /* thông báo nổi: xuống đáy, rộng theo màn — trước đây nằm góc trên che logo */
    .ui-toast { top: auto; bottom: 16px; left: 12px; right: 12px; max-width: none; transform: translateY(20px); }
    .ui-toast.show { transform: none; }

    .ui-card { padding: 14px; }
    .ui-card-title { font-size: var(--fs-md); }
}

/* ===== BỘ MÀU DỰ ÁN (chốt 2026-09-25) — ĐANG ÁP THỬ theo trang (<html data-palette="project">) =====
   Các thành phần trên còn màu tự đặt (viền, chữ badge, toast) → quy về token của bộ màu. Áp toàn dự án thì
   gộp khối này vào quy tắc gốc ở trên và xoá khối. */
html[data-palette="project"] .ui-flow-step.is-bad,
html[data-palette="project"] .ui-kpi-card.is-bad  { border-color: color-mix(in srgb, var(--ui-bad) 35%, transparent); }
html[data-palette="project"] .ui-flow-step.is-warn,
html[data-palette="project"] .ui-kpi-card.is-warn { border-color: color-mix(in srgb, var(--ui-warn) 45%, transparent); }
html[data-palette="project"] .ui-flow-step.is-ok,
html[data-palette="project"] .ui-kpi-card.is-ok   { border-color: color-mix(in srgb, var(--ui-ok) 35%, transparent); }
html[data-palette="project"] .ui-badge.ok   { color: color-mix(in srgb, var(--ui-ok) 70%, var(--ui-text)); }
html[data-palette="project"] .ui-badge.warn { color: color-mix(in srgb, var(--ui-warn) 55%, var(--ui-text)); }
html[data-palette="project"] .ui-badge.bad  { color: color-mix(in srgb, var(--ui-bad) 75%, var(--ui-text)); }
html[data-palette="project"] .ui-toast.success { background: var(--ui-ok); }
html[data-palette="project"] .ui-toast.error   { background: var(--ui-bad); }
html[data-palette="project"] .ui-toast.warning { background: var(--ui-warn); color: #161823; }
html[data-palette="project"] .ui-btn-danger-outline { border-color: color-mix(in srgb, var(--ui-bad) 35%, transparent); }
html[data-palette="project"] .ui-ff-band,
html[data-palette="project"] .ui-ff-node { fill: var(--ui-info); }   /* phễu là biểu đồ → xanh; bước cuối vẫn xanh lá (.last) */
html[data-palette="project"] .ui-ff-node.last { fill: var(--ui-ok); }
html[data-palette="project"] .ui-ffv-bar span { background: var(--ui-info); }
html[data-palette="project"] .ui-ffv-bar span.last { background: var(--ui-ok); }
html[data-palette="project"] .ui-ff-drip { fill: #F74A55; opacity: 1; }          /* rơi = đỏ ĐẶC (tông sáng của đỏ), không pha trong suốt → không thành hồng */
html[data-palette="project"] .ui-ff-drip.worst { fill: var(--ui-bad); }
html[data-palette="project"] .ui-ff-drip:hover { opacity: .85; }
html[data-palette="project"] .ui-ff-insight { border-left: 3px solid var(--ui-bad); }
html[data-palette="project"] .ui-ffv-drop { border-left-color: var(--ui-bad); }
/* Sankey dáng chuẩn (UI.sankey opts.thin): nút là thanh mảnh, nhãn nằm CẠNH thanh → chữ màu thường, không trên nền màu */
.ui-sk-label.thin { color: var(--ui-text); padding: 0 2px; font-weight: 600; }
.ui-sk-label.thin b { display: inline; font-family: var(--font-mono); font-size: var(--fs-2xs); color: var(--ui-muted); margin-left: 4px; }
.ui-sk-label.thin.end, .ui-sk-col.end { text-align: right; }

/* Offline: KPI phụ trung tính, không gợi ý hành động khi chỉ hiển thị số liệu. */
html[data-chart-channel="offline"] .ui-kpi-card:not(.ui-kpi-hero) .ui-kpi-title { color: var(--ui-muted); }
html[data-chart-channel="offline"] .ui-kpi-card:not(.clickable):hover { transform: none; box-shadow: var(--ui-shadow-card); }
html[data-chart-channel="offline"] .ui-kpi-card:not(.clickable):hover::before { transform: scaleX(0); }
html[data-chart-channel="offline"] #offline-store-panel { width: min(340px, calc(100vw - 62px)); }
html[data-chart-channel="offline"] .ui-btn:focus-visible,
html[data-chart-channel="offline"] .ui-drawer-close:focus-visible { outline: 2px solid var(--brand-primary); outline-offset: 3px; }

/* ===== Ảnh đại diện SP cạnh tên SP (user/public/js/productThumb.js — escThumb + ProductThumb.hydrate; rê chuột → phóng to) ===== */
.ui-thumb { display: block; width: 40px; height: 40px; border-radius: 6px; overflow: hidden; background: var(--ui-surface-2); flex: none; }
.ui-thumb[data-zoom] { cursor: zoom-in; }
.ui-thumb img { width: 40px; height: 40px; object-fit: cover; display: block; }
.ui-table td.thumb, .ui-table th.thumb { width: 48px; padding-right: 0; }
.ui-thumb-zoom { position: fixed; z-index: 3000; width: 280px; height: 280px; padding: 6px; border-radius: 12px; background: var(--ui-surface);
    box-shadow: 0 12px 40px rgba(0, 0, 0, .25); pointer-events: none; display: none; }
.ui-thumb-zoom.show { display: block; }
.ui-thumb-zoom img { width: 100%; height: 100%; object-fit: contain; display: block; border-radius: 8px; }
