/* Ảnh nền rất sáng ở giữa nên chữ đặt thẳng lên sẽ khó đọc.
   Cách xử lý: ảnh phủ toàn trang nhưng luôn có một lớp mờ trắng đè lên, còn khu vực
   đọc (khung chat, thẻ nội dung) thì dùng nền gần đục để tương phản chữ luôn đủ. */

:root {
  --green-900: #14532d;
  --green-700: #15803d;
  --green-600: #16a34a;
  --green-50:  #f0fdf4;
  --ink:       #14261c;
  --ink-soft:  #4b5f54;
  --line:      rgba(20, 83, 45, .14);
  --card:      rgba(255, 255, 255, .96);
  --radius:    14px;
  --shadow:    0 6px 24px rgba(20, 83, 45, .10);
}

* { box-sizing: border-box; }

/* Bất kỳ quy tắc nào của trang đặt `display` (ví dụ `.gate { display:flex }`) đều
   THẮNG quy tắc mặc định `[hidden]{display:none}` của trình duyệt, vì CSS của trang
   xếp trên UA stylesheet. Hậu quả: gắn thuộc tính `hidden` bằng JS mà phần tử vẫn
   hiện - đúng lỗi khung đăng nhập không chịu biến mất sau khi đăng nhập xong.
   Khai báo một lần ở đây cho toàn trang thay vì vá từng lớp một. */
[hidden] { display: none !important; }

body {
  margin: 0;
  /* KHOÁ chiều cao trang đúng bằng màn hình và cấm cả trang cuộn. Chỉ vùng tin nhắn
     (.messages) được phép cuộn, nên header, tab và thanh bên luôn đứng yên - giống
     cách ChatGPT/Claude làm. Dùng `min-height` như trước thì trang dài ra theo nội
     dung và cả giao diện bị cuộn mất. 100dvh cho di động (trừ thanh địa chỉ). */
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  font: 15px/1.6 "Segoe UI", system-ui, -apple-system, sans-serif;
  color: var(--ink);
  /* Dùng bản _web (2400px, 344KB) chứ không phải file gốc 4928px/3,7MB: trang đi qua
     Cloudflare Tunnel nên 3,7MB là vài giây màn hình trắng ở lần vào đầu tiên, trong
     khi màn hình rộng nhất cũng không hiển thị nổi quá 2400px. File gốc vẫn giữ
     nguyên trong assets/ để sau này cần cắt lại. */
  background: url("/assets/thay_the_background_v2_web.jpg") center / cover fixed no-repeat;
  display: flex;
  flex-direction: column;
}
body::before {                     /* lớp phủ làm dịu ảnh nền */
  content: "";
  position: fixed;
  inset: 0;
  /* Ảnh v2 sáng ngược lại với hai ảnh trước: bầu trời nửa trên gần như trắng. Phủ
     TRẮNG lên đó (như bản cũ làm) thì càng chói và header nền trắng .82 gần như tan
     vào nền. Nên phủ một lớp xanh đậm rất nhạt, đậm hơn ở trên - vừa hạ chói vùng
     trời, vừa làm các khối trắng nổi lên, mà không làm ảnh bị bạc màu.
     Chữ vẫn đọc tốt vì mọi khối có nội dung - header, thanh bên, bong bóng chat,
     ô nhập - đều có nền trắng riêng gần như đục, không đặt chữ thẳng lên ảnh. */
  background: linear-gradient(180deg, rgba(20,83,45,.14), rgba(20,83,45,.05));
  z-index: -1;
}

/* ---------------- trang đăng nhập ---------------- */
.gate {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  padding: 20px; overflow-y: auto;
}
.gate-card {
  width: 100%; max-width: 400px;
  background: rgba(255, 255, 255, .96);
  border: 1px solid var(--line); border-radius: 18px;
  padding: 30px 28px 24px; box-shadow: 0 12px 40px rgba(20, 83, 45, .16);
}
.gate-logo {
  width: 62px; height: 62px; object-fit: contain;
  display: block; margin: 0 auto 14px;
}
.gate-title { margin: 0; font-size: 20px; text-align: center; color: var(--green-900); }
.gate-sub   { margin: 5px 0 22px; text-align: center; color: var(--ink-soft); font-size: 14px; }

.field { display: block; margin-bottom: 14px; }
.field span { display: block; font-size: 13px; color: var(--ink-soft); margin-bottom: 5px; }
.field input {
  width: 100%; padding: 10px 12px; font: inherit;
  border: 1px solid var(--line); border-radius: 10px; background: #fff; color: var(--ink);
}
.field input:focus { outline: 2px solid var(--green-600); outline-offset: -1px; }

.gate-btn {
  width: 100%; padding: 11px; margin-top: 4px;
  border: 0; border-radius: 10px; cursor: pointer;
  background: var(--green-700); color: #fff; font: inherit; font-weight: 600;
}
.gate-btn:hover:not(:disabled) { background: var(--green-900); }
/* Nút tắt phải trông ĐÃ TẮT, không chỉ mờ đi: mờ 60% một nút xanh đậm thì vẫn còn
   xanh rõ, người dùng tưởng bấm được rồi thắc mắc sao bấm không ăn. Chuyển hẳn sang
   xám mới đọc ra ngay là chưa dùng được. */
.gate-btn:disabled {
  background: #e3e6e3; color: #9aa39a; cursor: not-allowed;
}
.ghost-btn:disabled {
  opacity: 1; background: #f2f4f2; color: #9aa39a;
  border-color: #e0e4e0; cursor: not-allowed;
}

.gate-error {
  background: #fef2f2; border: 1px solid #fecaca; color: #b91c1c;
  border-radius: 9px; padding: 9px 12px; font-size: 13.5px; margin-bottom: 12px;
}
.gate-switch { text-align: center; margin: 16px 0 0; font-size: 13.5px; color: var(--ink-soft); }
.gate-note   { text-align: center; margin: 10px 0 0; font-size: 12px; color: var(--ink-soft); }

/* ---------------- tài khoản trên header ---------------- */
.account { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.account-email { color: var(--ink-soft); }

/* ---------------- thanh bên lịch sử ---------------- */
.sidebar {
  width: 252px; flex: none;
  display: flex; flex-direction: column; gap: 8px;
  padding: 14px 10px; min-height: 0;
  background: rgba(255, 255, 255, .78);
  border-right: 1px solid var(--line);
}
.new-chat-btn {
  border: 1px solid var(--line); background: #fff; cursor: pointer;
  border-radius: 10px; padding: 9px 12px; font: inherit; font-size: 14px;
  color: var(--green-900); text-align: left; flex: none;
}
.new-chat-btn:hover { border-color: var(--green-600); }

.conv-list { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.conv-item {
  display: flex; align-items: center; gap: 4px;
  border-radius: 9px; padding: 8px 6px 8px 10px; cursor: pointer;
}
.conv-item:hover { background: rgba(22, 163, 74, .09); }
.conv-item.is-active { background: rgba(22, 163, 74, .16); }
.conv-title {
  flex: 1; font-size: 13.5px; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.conv-del {
  border: 0; background: transparent; cursor: pointer; flex: none;
  color: var(--ink-soft); font-size: 15px; line-height: 1;
  padding: 2px 5px; border-radius: 6px; opacity: 0;
}
.conv-item:hover .conv-del { opacity: 1; }
.conv-del:hover { background: #fee2e2; color: #b91c1c; }
.conv-empty { font-size: 13px; color: var(--ink-soft); padding: 10px; }

/* ---------------- thanh trên ---------------- */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 12px 22px;
  background: rgba(255, 255, 255, .82);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: 12px; }
/* Logo nền trắng, đặt trong khung trắng bo tròn để không bị "dán" thô lên nền mờ. */
.logo {
  width: 38px; height: 38px; flex: none;
  object-fit: contain; border-radius: 9px;
  background: #fff; padding: 3px;
  box-shadow: 0 1px 4px rgba(20, 83, 45, .12);
}
.brand-name { font-weight: 650; letter-spacing: -.01em; }
.brand-sub-row { display: flex; align-items: baseline; gap: 8px; }
.brand-sub  { font-size: 12px; color: var(--ink-soft); }
#syncBtn { font-size: 11.5px; }

.tabs { display: flex; gap: 4px; }
.tab {
  border: 0; background: transparent; cursor: pointer;
  padding: 8px 15px; border-radius: 999px;
  font: inherit; font-size: 14px; color: var(--ink-soft);
}
.tab:hover { background: rgba(22, 163, 74, .09); }
/* Các mục điều hướng nay là <a> (để mở được tab mới) - giữ nguyên dáng nút cũ. */
a.tab, a.wb-tab, a.conv-item { text-decoration: none; }
a.tab { display: inline-block; }
a.wb-tab { display: inline-block; }
.tab.is-active { background: var(--green-700); color: #fff; }

/* ---------------- khung chung ---------------- */
/* #app bọc toàn bộ ứng dụng (để ẩn đi khi hiện trang đăng nhập). Nó phải là flex
   column giãn hết chiều cao, nếu không chuỗi flex từ body xuống main bị đứt và
   khu vực chat chỉ cao bằng nội dung, để trống nửa dưới màn hình. */
#app { flex: 1; display: flex; flex-direction: column; min-height: 0; }

main { flex: 1; display: flex; min-height: 0; }
.view { display: none; flex: 1; min-height: 0; }
.view.is-active { display: flex; }

.chat-wrap {
  flex: 1;
  display: flex;
  flex-direction: column;
  max-width: 860px;
  width: 100%;
  margin: 0 auto;
  padding: 18px 18px 12px;
  min-height: 0;
}

/* ---------------- tin nhắn ---------------- */
/* `min-height: 0` là bắt buộc: mặc định flex item có `min-height: auto`, nghĩa là
   không co lại nhỏ hơn nội dung - overflow-y:auto sẽ không bao giờ kích hoạt và
   khung chat cứ dài ra đẩy cả trang. */
.messages { flex: 1; min-height: 0; overflow-y: auto; padding-right: 4px; }

/* Chữ ở màn hình chào nằm TRỰC TIẾP trên ảnh nền (không có thẻ nền như bong bóng
   chat), nên cần một lớp sáng mờ phía sau để tương phản không phụ thuộc vùng ảnh
   đang sáng hay tối. */
.welcome {
  text-align: center; margin: 8vh auto 0; max-width: 620px;
  background: rgba(255, 255, 255, .74);
  border-radius: 18px; padding: 22px 26px;
  backdrop-filter: blur(3px);
}
.welcome h1 { font-size: 26px; margin: 0 0 8px; color: var(--green-900); letter-spacing: -.02em; }
.welcome p  { margin: 0 0 22px; color: var(--ink-soft); }
.examples { display: flex; flex-direction: column; gap: 8px; }
.examples button {
  border: 1px solid var(--line); background: var(--card);
  border-radius: 11px; padding: 11px 14px; cursor: pointer;
  font: inherit; font-size: 14px; text-align: left; color: var(--ink);
}
.examples button:hover { border-color: var(--green-600); background: #fff; }

.msg { margin: 14px 0; display: flex; }
.msg.user { justify-content: flex-end; }
.bubble {
  max-width: 82%;
  padding: 11px 15px;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.msg.user .bubble { background: var(--green-700); color: #fff; border-bottom-right-radius: 4px; }
.msg.bot  .bubble { background: var(--card); border: 1px solid var(--line); border-bottom-left-radius: 4px; }
.bubble strong { font-weight: 650; }

/* dòng trạng thái trong lúc chờ */
.status {
  display: flex; align-items: center; gap: 9px;
  color: var(--ink-soft); font-size: 13.5px; margin: 4px 2px 0;
}
.dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--green-600);
  animation: pulse 1.1s ease-in-out infinite;
}
@keyframes pulse { 0%,100% { opacity: .25; transform: scale(.8); } 50% { opacity: 1; transform: scale(1.15); } }

.caret {
  display: inline-block; width: 7px; height: 15px; vertical-align: -2px;
  background: var(--green-600); animation: blink .9s steps(2) infinite; margin-left: 1px;
}
@keyframes blink { 0%,50% { opacity: 1; } 51%,100% { opacity: 0; } }

/* ---------------- markdown trong câu trả lời ---------------- */
/* .bubble đặt white-space: pre-wrap để giữ xuống dòng của văn xuôi. Bảng phải gỡ ra,
   nếu không mỗi ô giữ nguyên khoảng trắng canh lề của model và cột phình vô lý. */
.md-para { white-space: pre-wrap; }
.md-para + .md-para { margin-top: 8px; }
.md-table-wrap { margin: 10px 0; overflow-x: auto; }
.md-table {
  white-space: normal;
  border-collapse: collapse;
  font-size: 13px;
  min-width: 100%;
}
.md-table th, .md-table td {
  border: 1px solid var(--line);
  padding: 5px 9px;
  text-align: left;
  vertical-align: top;
}
.md-table th { background: var(--green-50); font-weight: 650; color: var(--green-900); }
.md-table td.num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.md-table tbody tr:nth-child(even) { background: rgba(0, 0, 0, .02); }
.md-code {
  margin: 10px 0; padding: 9px 11px; overflow-x: auto;
  background: #f4f4f0; border: 1px solid var(--line); border-radius: 8px;
  font-size: 12px; line-height: 1.45; white-space: pre;
}
.bubble code {
  background: #f4f4f0; border: 1px solid var(--line); border-radius: 4px;
  padding: 0 4px; font-size: 12.5px;
}

/* nguồn trích dẫn - gập lại mặc định */
.sources { margin-top: 9px; padding-top: 9px; border-top: 1px dashed var(--line); }
.sources-title {
  font-size: 12px; color: var(--ink-soft);
  cursor: pointer; user-select: none; list-style: none;
  display: flex; align-items: center; gap: 5px;
}
.sources-title::-webkit-details-marker { display: none; }   /* Safari vẽ tam giác riêng */
.sources-title:hover { color: var(--green-900); }
.sources-caret { display: inline-block; transition: transform .15s ease; font-size: 10px; }
.sources[open] .sources-caret { transform: rotate(90deg); }
.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.chip {
  font-size: 12px; padding: 4px 9px; border-radius: 999px;
  background: var(--green-50); border: 1px solid var(--line); color: var(--green-900);
}
.badge-table {
  display: inline-block; font-size: 11px; padding: 2px 8px; border-radius: 999px;
  background: #fef3c7; border: 1px solid #fcd34d; color: #78350f; margin-bottom: 7px;
}
.error-text { color: #b91c1c; }

/* ---------------- ô nhập ---------------- */
.composer {
  display: flex; align-items: flex-end; gap: 8px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 8px; box-shadow: var(--shadow);
  margin-top: 10px;
}
.composer textarea {
  flex: 1; border: 0; outline: 0; resize: none; background: transparent;
  font: inherit; color: var(--ink); max-height: 180px; padding: 6px 4px;
}
.icon-btn, .send-btn {
  border: 0; cursor: pointer; border-radius: 10px; flex: none;
  width: 36px; height: 36px; font-size: 17px; line-height: 1;
}
.icon-btn { background: rgba(22,163,74,.10); color: var(--green-900); }
.icon-btn:hover { background: rgba(22,163,74,.18); }
.send-btn { background: var(--green-700); color: #fff; }
.send-btn:hover { background: var(--green-900); }
.send-btn:disabled, .icon-btn:disabled { opacity: .45; cursor: not-allowed; }

/* ---------------- Dữ liệu công suất ngày ---------------- */
/* Tiêu đề đã nằm ở <summary> của thẻ dashboard, nên hàng này chỉ còn các nút điều
   khiển - dồn về bên phải cho thẳng hàng với mép thẻ. */
.card-head {
  display: flex; align-items: center; justify-content: flex-end;
  gap: 12px; flex-wrap: wrap; margin-bottom: 10px;
}
.card-head h3 { margin: 0; }
.card-tools { display: flex; align-items: center; gap: 10px; }
.card-tools input[type="date"] {
  padding: 5px 8px; border: 1px solid var(--line); border-radius: 8px;
  font: inherit; font-size: 13px; color: var(--ink);
}
.stat-row {
  display: flex; flex-wrap: wrap; gap: 10px 26px; margin-bottom: 12px;
}
.stat-label { font-size: 12px; color: var(--ink-soft); }
.stat-value { font-size: 20px; font-weight: 700; color: var(--green-900); }

.entry {
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line);
}
.entry-head {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-bottom: 10px; font-size: 13px;
}
.entry-head select {
  padding: 5px 8px; border: 1px solid var(--line); border-radius: 8px;
  font: inherit; margin-left: 6px;
}
/* Cột chồng và biểu đồ tròn nằm cạnh nhau trên màn rộng, xuống dòng trên màn hẹp.
   CHỈ áp cho dashboard: `.viz-group` trong khung chat phải giữ nguyên xếp dọc, vì
   bong bóng chat hẹp, hai biểu đồ cạnh nhau sẽ bị bóp nát. */
#powerChart {
  display: flex; flex-wrap: wrap; align-items: flex-start; gap: 14px;
}
/* Cột chồng chiếm gần hết bề ngang: nó có 48 mốc phải đọc được, còn biểu đồ tròn
   chỉ có 3 lát nên to thêm cũng không rõ hơn - phần lớn thông tin của nó nằm ở
   dòng chú giải có sẵn số và phần trăm. */
#powerChart > .viz { flex: 6 1 520px; }
/* max-width CHỈ cho biểu đồ tròn. Đặt ở quy tắc chung thì nó bóp luôn biểu đồ cột,
   vì quy tắc :first-child bên trên chỉ đặt `flex` chứ không ghi đè `max-width`. */
#powerChart > .viz:not(:first-child) { flex: 1 1 200px; max-width: 280px; }
.viz-pie { width: 100%; max-width: 132px; height: auto; display: block; margin: 0 auto; }
.viz-legend-col { flex-direction: column; gap: 5px; margin-top: 10px; }
/* Nhiều cột trên màn rộng: 22 nhà máy xếp một cột dọc thì phải cuộn rất dài,
   trong khi người nhập cần nhìn thấy hết cùng lúc để biết còn sót ô nào. */
.entry-grid {
  display: grid; gap: 6px 18px;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
/* auto ở cột cuối để hàng không chừa chỗ trống khi đã lọc theo loại hình
   (lúc đó không còn nhãn loại hình nữa). */
.entry-row {
  display: grid; grid-template-columns: 1fr 88px auto; align-items: center;
  gap: 8px; font-size: 13px;
}
.entry-row input {
  padding: 5px 8px; border: 1px solid var(--line); border-radius: 8px;
  font: inherit; text-align: right; width: 100%;
}
.entry-row input:focus { outline: 2px solid var(--green-600); outline-offset: -1px; }
.entry-name { color: var(--ink); }
.entry-kind { font-size: 11.5px; color: var(--ink-soft); }
.entry-foot {
  display: flex; align-items: center; gap: 14px; margin-top: 14px;
  font-size: 13px; color: var(--ink-soft);
}
.entry-foot .gate-btn { width: auto; padding: 8px 22px; }

/* ---------------- Lịch trực phòng ROC ---------------- */
.icon-btn.sm { width: 26px; height: 26px; font-size: 15px; line-height: 1; }
.roc-legend { display: flex; flex-wrap: wrap; gap: 8px 14px; margin-bottom: 10px; }
.roc-chip {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--ink-soft);
}
.roc-sw {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 4px; flex: none;
  color: #fff; font-size: 11px; font-weight: 700;
}
/* Lưới 31 cột không thể bóp vừa màn hẹp - cho cuộn ngang trong khung riêng, không
   để nó đẩy giãn cả trang. */
.roc-grid-wrap { overflow-x: auto; }
.roc-grid { border-collapse: collapse; font-size: 12px; }
/* Viền đậm hơn hẳn --line (alpha .14): trên nền trắng nó gần như vô hình nên lưới
   trông như một mảng trắng không có ô. Bảng lịch cần thấy rõ từng ô để dò đúng cột. */
.roc-grid th, .roc-grid td {
  border: 1px solid #cfd6cf; padding: 0; text-align: center;
}
/* Bảng chiếm trọn bề ngang khung: 31 cột ngày + cột tên + cột tổng vừa khít nên
   không còn thanh trượt ngang. Vẫn giữ .roc-grid-wrap cuộn được cho màn hẹp. */
.roc-grid { width: 100%; table-layout: fixed; background: #fff; }
.roc-name-col {
  position: sticky; left: 0; z-index: 2; background: #fff;
  text-align: left !important; padding: 4px 8px !important;
  white-space: nowrap; font-weight: 600;
  width: 170px; min-width: 170px; max-width: 170px;
  overflow: hidden; text-overflow: ellipsis;
}
.roc-pos { color: var(--ink-soft); font-weight: 400; font-size: 11px; }
.roc-day { font-weight: 600; color: var(--ink-soft); padding: 2px 0 !important; }
/* Cuối tuần tô xám trung tính, không dùng sắc xanh của thương hiệu: xám nói
   'ngày nghỉ' rõ hơn, và không lẫn với màu xanh lá của ký hiệu Công tác.
   Dùng !important vì ô cuối tuần vẫn có thể mang các lớp khác (hôm nay, đang sửa)
   đặt nền riêng - ngày nghỉ phải luôn thấy được là ngày nghỉ. */
.roc-day.is-weekend, .roc-cell.is-weekend { background: #d7dbd7 !important; }
.roc-day.is-weekend { color: #5c635c; }
.roc-cell.is-weekend:hover { background: #c9cfc9 !important; }
.roc-day.is-today { background: var(--green-600); color: #fff; }
.roc-cell { height: 26px; cursor: pointer; }
/* Nút phụ: cùng cỡ nút Lưu nhưng viền rỗng, để hai nút cạnh nhau không tranh nhau
   sự chú ý - Lưu là hành động chính, Huỷ bỏ là lối thoát. */
.ghost-btn {
  border: 1px solid var(--line); background: #fff; color: var(--ink);
  border-radius: 10px; cursor: pointer; font: inherit; font-weight: 600;
}
.ghost-btn:hover:not(:disabled) { border-color: var(--green-600); color: var(--green-900); }
.ghost-btn.sm { padding: 6px 18px; font-size: 13px; }

/* Hộp chọn ký hiệu, đặt nổi trên trang theo toạ độ của ô được bấm. */
.roc-picker {
  position: fixed; z-index: 60; min-width: 168px;
  background: #fff; border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 10px 30px rgba(20, 83, 45, .18);
  padding: 5px; display: flex; flex-direction: column; gap: 2px;
}
.roc-picker-item {
  display: flex; align-items: center; gap: 8px;
  border: 0; background: transparent; cursor: pointer;
  padding: 7px 9px; border-radius: 7px; font: inherit; font-size: 13.5px;
  color: var(--ink); text-align: left; width: 100%;
}
.roc-picker-item:hover { background: rgba(22, 163, 74, .10); }
.roc-picker-item.is-current { background: var(--green-50); font-weight: 600; }
.roc-picker-item.is-clear { border-top: 1px solid var(--line); margin-top: 3px; padding-top: 9px; }
.roc-sw.is-empty { background: #e6e6e2; color: #6b6b66; }
.roc-cell.is-picking { outline: 2px solid var(--green-700); outline-offset: -2px; }

.roc-cell.is-editable { cursor: pointer; }
.roc-cell.is-editable:hover { outline: 2px solid var(--green-600); outline-offset: -2px; }
/* Ô vừa sửa nhưng CHƯA lưu: viền cam để phân biệt với ô đã nằm trong database. */
.roc-cell.is-dirty { box-shadow: inset 0 0 0 2px #d97706; }
.roc-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 4px;
  color: #fff; font-weight: 700; font-size: 11px;
}
.roc-total-col { min-width: 30px; font-weight: 700; color: var(--green-900); }

/* Các phần bên trong "Lịch làm việc": ngăn cách bằng đường kẻ thay vì bằng thẻ
   sổ ra riêng, để chỉ cần lăn chuột là đọc hết. */
.roc-section { margin-top: 22px; padding-top: 16px; border-top: 1px solid var(--line); }
.roc-section-head {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 12px;
}
.roc-section-head h3 { margin: 0; font-size: 14.5px; color: var(--green-900); }
.roc-section-head .muted { margin: 0; }
.roc-section-head input[type="date"] {
  padding: 5px 8px; border: 1px solid var(--line); border-radius: 8px;
  font: inherit; font-size: 13px; color: var(--ink);
}

.roc-block { margin-bottom: 18px; }
.roc-block h4 { margin: 0 0 8px; font-size: 13.5px; color: var(--green-900); }
.roc-duty { display: flex; flex-wrap: wrap; gap: 10px 18px; }
.roc-task {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 5px 0; font-size: 13.5px; cursor: pointer;
}
.roc-task input { margin-top: 3px; flex: none; }
.roc-hint { color: var(--ink-soft); font-size: 12.5px; }
.roc-by { margin-left: auto; color: var(--ink-soft); font-size: 11.5px; flex: none; }
/* Hàng tiêu đề của mỗi khối, chứa nút Lưu và trạng thái lưu. */
.roc-block-head {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 8px;
}
.roc-block-head h4 { margin: 0; }
.gate-btn.sm { width: auto; padding: 6px 18px; font-size: 13px; }
.roc-save-state { font-size: 12.5px; color: var(--ink-soft); }
.roc-save-state.is-dirty { color: #b45309; font-weight: 600; }
.roc-save-state.is-ok { color: var(--green-700); }

.roc-event-list { display: flex; flex-direction: column; gap: 10px; }
/* Ô giờ hẹp, hai ô mô tả rộng đều nhau: mô tả sự kiện và hành động xử lý thường
   dài hơn một dòng nên dùng textarea chứ không phải input. */
.roc-event-row {
  display: grid; grid-template-columns: 74px 1fr 1fr auto;
  gap: 10px; align-items: start;
  padding: 10px 0; border-top: 1px solid var(--line);
}
.roc-event-row input, .roc-event-row textarea {
  padding: 7px 9px; border: 1px solid var(--line); border-radius: 8px;
  font: inherit; font-size: 13.5px; width: 100%;
}
.roc-event-row textarea { resize: vertical; min-height: 46px; }
.roc-ev-time { text-align: center; letter-spacing: .5px; }
.roc-event-row input:focus, .roc-event-row textarea:focus {
  outline: 2px solid var(--green-600); outline-offset: -1px;
}
@media (max-width: 760px) {
  .roc-event-row { grid-template-columns: 74px 1fr auto; }
  .roc-ev-act { grid-column: 2 / 4; }
}

.roc-contacts { border-collapse: collapse; font-size: 13px; width: 100%; }
.roc-contacts th, .roc-contacts td {
  border-bottom: 1px solid var(--line); padding: 6px 10px; text-align: left;
  vertical-align: top;
}
.roc-contacts th { color: var(--ink-soft); font-size: 12px; white-space: nowrap; }
.roc-contacts tr.is-header td { background: var(--green-50); font-weight: 700; }
.roc-no { color: var(--ink-soft); white-space: nowrap; }

/* ---------------- biểu đồ trong câu trả lời ---------------- */
.viz-group { margin-top: 12px; display: flex; flex-direction: column; gap: 14px; }
.viz {
  border: 1px solid var(--line); border-radius: 10px;
  background: #fff; padding: 10px 12px 8px;
}
.viz-title {
  font-size: 12.5px; font-weight: 600; color: var(--ink); margin-bottom: 6px;
}
.viz-svg { width: 100%; height: auto; display: block; }
/* Cỡ chữ trong SVG phải đặt bằng CSS chứ không dùng thuộc tính font-size, vì SVG
   được co giãn theo viewBox - đặt cứng thì chữ to nhỏ theo bề rộng khung chat. */
.viz-tick { font-size: 10px; font-family: inherit; }
/* Nhãn xoay của biểu đồ dày cột: nhỏ hơn một bậc để 48 mốc không chạm nhau. */
.viz-tick-sm { font-size: 8.5px; font-family: inherit; }
/* Số trong từng lớp cột chồng. Cỡ chữ đặt bằng thuộc tính SVG theo đơn vị khung vẽ
   (xem LABEL_FS trong viz.js) nên ở đây chỉ khai báo font và độ đậm. */
.viz-seg { font-family: inherit; font-weight: 600; }
.viz-value { font-size: 10px; font-weight: 600; font-family: inherit; }
.viz-legend {
  display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 6px;
  font-size: 12px; color: var(--ink-soft);
}
.viz-legend-item { display: inline-flex; align-items: center; gap: 5px; }
.viz-swatch { width: 10px; height: 10px; border-radius: 2px; flex: none; }

/* Tệp đính kèm của cuộc trò chuyện, nằm ngay trên ô nhập để luôn thấy được phạm vi
   tài liệu mà chatbot đang dùng thêm ngoài kho chung. */
.attachments {
  display: flex; flex-wrap: wrap; gap: 6px; padding: 0 4px 7px;
}
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px; border-radius: 999px; font-size: 12.5px;
  background: var(--green-50); border: 1px solid var(--line); color: var(--green-900);
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chip-icon { flex: none; }

.composer-hint {
  display: flex; justify-content: space-between; align-items: center;
  font-size: 12.5px; color: var(--ink-soft); padding: 7px 4px 0; min-height: 22px;
}
.link-btn {
  border: 0; background: transparent; cursor: pointer;
  font: inherit; font-size: 12.5px; color: var(--green-700); text-decoration: underline;
}

/* ---------------- báo cáo / dashboard ---------------- */
/* Thiếu #view-schedule ở đây là tab Schedule không cuộn được: body khoá chiều cao
   đúng bằng màn hình, phần nội dung vượt ra ngoài bị cắt và không có cách nào tới. */
#view-reports, #view-dashboard, #view-schedule, #view-contacts { overflow-y: auto; }
.panel { max-width: 980px; margin: 0 auto; padding: 26px 20px 40px; width: 100%; }
/* Dashboard rộng hơn hẳn phần còn lại: 980px là bề ngang tốt để ĐỌC chữ, nhưng
   dashboard là thứ để QUÉT MẮT - biểu đồ càng rộng càng đọc được nhiều mốc thời
   gian, mà màn hình công ty thường 1920px nên để 980px là bỏ phí nửa màn hình. */
#view-dashboard .panel, #view-schedule .panel, #view-contacts .panel {
  max-width: 1680px; padding-left: 28px; padding-right: 28px;
}

/* ---------------- danh sách dashboard xổ ra được ---------------- */
.dash {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 6px 16px; margin-bottom: 12px;
}
.dash > summary {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 0; cursor: pointer; list-style: none;
  font-size: 15px; font-weight: 600; color: var(--ink);
}
.dash > summary::-webkit-details-marker { display: none; }
/* Mũi tên tự vẽ, xoay khi mở. Marker mặc định của trình duyệt mỗi nơi một kiểu. */
.dash > summary::before {
  content: "›"; font-size: 20px; line-height: 1; color: var(--green-700);
  transform: rotate(0deg); transition: transform .15s ease; flex: none;
}
.dash[open] > summary::before { transform: rotate(90deg); }
.dash > summary:hover { color: var(--green-900); }
.dash-title { flex: 1; }
.dash-hint { font-size: 12.5px; font-weight: 400; color: var(--ink-soft); }
.dash > summary + * { margin-top: 4px; }
.dash > *:last-child { margin-bottom: 12px; }
.panel h2 { margin: 0 0 6px; color: var(--green-900); letter-spacing: -.02em; }
.muted { color: var(--ink-soft); margin: 0 0 16px; }
.placeholder-grid {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
}
.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px; box-shadow: var(--shadow);
}
.card h3 { margin: 0 0 6px; font-size: 15px; }
.card p  { margin: 0; font-size: 13.5px; }
.note {
  margin-top: 18px; padding: 11px 14px; border-radius: 10px;
  background: rgba(255,255,255,.7); border: 1px dashed var(--line);
  font-size: 13.5px; color: var(--ink-soft);
}

@media (max-width: 860px) {
  /* Màn hình hẹp: giấu thanh bên để chỗ đọc chat không bị bóp lại. */
  .sidebar { display: none; }
}

@media (max-width: 640px) {
  .topbar { padding: 10px 14px; }
  .bubble { max-width: 92%; }
  .welcome { margin-top: 4vh; }
  .account-email { display: none; }
}

/* ============ Báo cáo > Daily Report ============
   Bố cục hai cột: cây điều hướng cố định bên trái, nội dung báo cáo bên phải.
   .panel khoá max-width 980px cho các trang chữ, nhưng bảng báo cáo cần rộng hơn -
   nên khu vực này tự nới ra bằng lớp bọc riêng thay vì sửa .panel (sửa .panel là
   mọi tab khác cùng giãn theo). */
/* Dashboard cần bề ngang tối đa: bảng số liệu và hai biểu đồ đều dày đặc, bó vào
   980px như các tab chữ là chữ chen nhau còn hai bên bỏ trống. Không đặt max-width
   cố định vì màn hình nhà máy mỗi nơi một cỡ - cứ dùng hết chỗ có. */
#view-reports .panel { max-width: none; padding-left: 16px; padding-right: 16px; }

.rp-wrap { display: grid; grid-template-columns: 236px 1fr; gap: 18px; align-items: start; }

.rp-nav {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 10px; position: sticky; top: 0;
}
.rp-report, .rp-kind {
  width: 100%; text-align: left; background: none; border: 0; cursor: pointer;
  font: inherit; color: var(--green-900); font-weight: 600;
  padding: 8px 10px; border-radius: 9px; display: flex; align-items: center; gap: 7px;
}
.rp-report { font-size: 15px; }
.rp-kind   { font-size: 14px; font-weight: 500; color: var(--ink); }
.rp-report:hover, .rp-kind:hover { background: rgba(22, 163, 74, .09); }

/* Mũi tên xoay bằng transform thay vì đổi ký tự: đổi ký tự thì bề rộng nhảy và cả
   dòng chữ dịch sang phải mỗi lần mở/đóng. */
.rp-caret { display: inline-block; transition: transform .15s; font-size: 11px; }
.is-open > .rp-caret { transform: rotate(90deg); }

.rp-count {
  margin-left: auto; font-size: 11px; color: var(--ink-soft);
  background: var(--green-50); border: 1px solid var(--line);
  border-radius: 999px; padding: 1px 7px;
}


.rp-main {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow); padding: 18px 20px 22px;
  min-width: 0;                  /* cho phép bảng bên trong co lại và tự cuộn */
}
.rp-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.rp-head h3 { margin: 0 0 3px; color: var(--green-900); font-size: 17px; }
.rp-sub { margin: 0; font-size: 12.5px; color: var(--ink-soft); }
.rp-datepick { font-size: 12.5px; color: var(--ink-soft); display: flex; align-items: center; gap: 7px; }
.rp-datepick input {
  font: inherit; font-size: 13px; padding: 5px 8px;
  border: 1px solid var(--line); border-radius: 8px; background: #fff; color: var(--ink);
}

.rp-kpis {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
  gap: 10px; margin: 16px 0 6px;
}
.rp-kpi { background: var(--green-50); border: 1px solid var(--line); border-radius: 11px; padding: 10px 12px; }
.rp-kpi-label { font-size: 11.5px; color: var(--ink-soft); margin-bottom: 3px; }
.rp-kpi-value { font-size: 19px; font-weight: 600; color: var(--green-900); letter-spacing: -.02em; }
.rp-kpi-unit  { font-size: 12px; font-weight: 400; color: var(--ink-soft); }

.rp-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); gap: 14px; margin-top: 14px; }
.rp-block { border: 1px solid var(--line); border-radius: 11px; padding: 12px 14px; background: #fff; min-width: 0; }
.rp-block h4 { margin: 0 0 8px; font-size: 13.5px; color: var(--green-700); }
.rp-wide { margin-top: 14px; }

.rp-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.rp-table th, .rp-table td { padding: 5px 6px; border-bottom: 1px solid var(--line); text-align: left; }
.rp-table th { font-weight: 500; color: var(--ink-soft); }
.rp-table td { text-align: right; font-variant-numeric: tabular-nums; }
.rp-table td.rp-unit { text-align: left; color: var(--ink-soft); font-size: 11.5px; width: 44px; }
.rp-table tr:last-child th, .rp-table tr:last-child td { border-bottom: 0; }

.rp-loss thead th, .rp-loss tfoot th { color: var(--green-900); font-weight: 600; }
.rp-loss thead th:not(:first-child) { text-align: right; }
/* Cột đầu ("Month") căn TRÁI cho khớp với ô dữ liệu bên dưới. Trước 08/09/2026 nó
   thừa hưởng căn giữa từ `.dash-tbl` nên tiêu đề lệch 9px so với tên tháng - ít, nhưng
   là cột duy nhất còn lệch sau khi đã chỉnh cả bốn nhà máy. */
.rp-loss thead th:first-child { text-align: left; }
.rp-loss tfoot td, .rp-loss tfoot th { border-top: 2px solid var(--line); font-weight: 600; }
.rp-loss tr.is-current { background: var(--green-50); }

.rp-grid-wrap { overflow-x: auto; }
.rp-incidents { font-size: 12.5px; }
.rp-incidents thead th { color: var(--green-900); font-weight: 600; white-space: nowrap; }
.rp-incidents td { text-align: left; }
.rp-incidents td.rp-r { text-align: right; }

.rp-none  { font-size: 13px; color: var(--ink-soft); margin: 4px 0 0; }

/* Ngày chưa nhập số liệu: lời nhắc việc cần làm, KHÔNG phải khối lỗi đỏ. */
/* Thanh chọn khoảng của báo cáo giai đoạn. Nằm TRÊN kết quả chứ không nằm cạnh:
   ba ô báo cáo ngày ở trên đã chiếm hết bề ngang, nhét thêm vào hàng đó là mỗi ô
   hẹp lại và văn bản bị ngắt dòng lung tung. */
.wb-period { margin-top: 22px; }
.wb-period-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
                 padding: 10px 14px; margin-bottom: 12px; border-radius: 8px;
                 background: #eef4ef; border: 1px solid var(--line); }
.wb-period-bar h4 { margin: 0; font-size: 15px; font-weight: 700; }
.wb-period-bar label { font-size: 13px; color: var(--ink-soft);
                       display: inline-flex; align-items: center; gap: 6px; }
.wb-period-bar input[type="date"] { padding: 5px 8px; font-size: 13px;
                                    border: 1px solid var(--line); border-radius: 6px; }

.wb-empty { background: #fffbe6; border: 1px solid #ecd9a0; border-left: 4px solid #e0a800;
            border-radius: 8px; padding: 14px 16px; font-size: 14px;
            line-height: 1.6; color: var(--ink); }
.wb-empty p { margin: 0 0 6px; }
.wb-empty p:last-child { margin-bottom: 0; }
.rp-error { font-size: 13.5px; color: #b3261e; margin: 0; }
.rp-source { margin: 14px 0 0; font-size: 11.5px; color: var(--ink-soft); }

@media (max-width: 820px) {
  .rp-wrap { grid-template-columns: 1fr; }
  .rp-nav { position: static; }
}

/* ---- workbook: dải tab và nội dung từng tab ---- */
.wb-tabs {
  display: flex; flex-wrap: wrap; gap: 4px; margin: 14px 0 0;
  border-bottom: 2px solid var(--line); padding-bottom: 0;
}
.wb-tab {
  font: inherit; font-size: 13px; cursor: pointer; border: 1px solid var(--line);
  border-bottom: 0; background: var(--green-50); color: var(--ink);
  padding: 7px 12px; border-radius: 8px 8px 0 0; position: relative; top: 2px;
}
.wb-tab:hover { background: rgba(22, 163, 74, .14); }
.wb-tab.is-active {
  background: var(--green-700); color: #fff; border-color: var(--green-700);
  font-weight: 600;
}
.wb-body { padding-top: 14px; min-width: 0; }
.wb-hint { font-size: 12.5px; color: var(--ink-soft); margin: 0 0 10px; }
.wb-hint code { background: var(--green-50); padding: 1px 4px; border-radius: 4px; }
.wb-block { border: 1px solid var(--line); border-radius: 11px; padding: 12px 14px;
            background: #fff; margin-bottom: 14px; min-width: 0; }
.wb-block h4 { margin: 0 0 8px; font-size: 13.5px; color: var(--green-700); }
.wb-wide { margin-top: 14px; }

/* Bảng dữ liệu thô rất rộng (tới 40 cột) nên phải cuộn ngang TRONG khung, không để
   cả trang giãn ra theo. Đầu bảng dính lại khi cuộn dọc. */
.wb-grid { font-size: 12px; white-space: nowrap; }
.wb-grid thead th {
  position: sticky; top: 0; background: #fff; z-index: 1;
  color: var(--green-900); font-weight: 600;
}
.wb-grid td { text-align: right; font-variant-numeric: tabular-nums; }
.wb-grid td:first-child, .wb-grid th:first-child { text-align: left; }

/* Thanh lọc của tab Tổng hợp sự cố. Xếp theo lưới TỰ CO chứ không phải flex một
   hàng: sáu ô lọc trên màn hình laptop mà ép một hàng thì mỗi ô còn chưa tới 150px,
   không đọc nổi giá trị đang chọn. */
.wb-fltbar { display: grid; gap: 10px 14px; align-items: end;
             grid-template-columns: repeat(auto-fit, minmax(165px, 1fr));
             padding: 12px 14px; margin-bottom: 10px; border-radius: 8px;
             background: #eef4ef; border: 1px solid var(--line); }
.wb-flt { position: relative; display: flex; flex-direction: column; gap: 4px;
          font-size: 12px; color: var(--ink-soft); }
.wb-flt-lb { line-height: 1.2; }
.wb-cb { position: relative; display: flex; }
/* Chừa chỗ bên phải cho hai nút chồng lên ô nhập, để chữ dài không chui xuống dưới
   nút mà vẫn đọc được. */
.wb-flt-in { flex: 1; min-width: 0; padding: 6px 46px 6px 8px; font-size: 13px;
             color: var(--ink); border: 1px solid var(--line); border-radius: 6px;
             background: #fff; }
.wb-flt-in:focus { outline: 2px solid var(--green-700); outline-offset: -1px; }

/* Thanh lọc chỉ có MỘT ô (tra cứu mã lỗi): không giãn ô ra hết bề ngang, một ô nhập
   dài 1000px vừa khó ngắm vừa gợi ý sai rằng phải gõ vào đó rất nhiều chữ. */
.wb-fltbar-1 { grid-template-columns: minmax(240px, 420px); }
.wb-none { color: var(--ink-soft); font-style: italic; }

/* Bảng tra cứu mã lỗi là bảng CHỮ, không phải bảng số: căn trái và cho xuống dòng.
   Quy tắc chung của `.wb-grid` là căn phải + không ngắt dòng, đúng cho các bảng số
   liệu vận hành (so độ lớn theo cột, cuộn ngang khi rộng), nhưng áp vào đây thì câu
   "Tự động khôi phục sau khi..." dạt sang phải rồi bị cắt ở mép khung - đúng phần
   người trực cần đọc lại là phần khuất. */
#fcTable .wb-grid th, #fcTable .wb-grid td { text-align: left; white-space: normal; }
#fcTable .wb-grid td:first-child { white-space: nowrap;
                                   font-variant-numeric: tabular-nums; }
#fcTable .wb-grid th:nth-child(1) { width: 90px; }
#fcTable .wb-grid th:nth-child(2) { width: 34%; }
#fcTable .rp-grid-wrap { max-height: 460px; }

/* ---- Tab Data: chỉnh sửa danh mục (06/10/2026, chỉ quản trị viên) ----
   Nút Sửa/Xoá nằm ở CUỐI DÒNG và chỉ HIỆN KHI DI CHUỘT tới dòng đó (user chốt): bảng
   800 mã lỗi mà dòng nào cũng thường trực hai nút thì rối mắt. Ẩn (opacity) chứ
   không `display` để cột không co giãn mỗi lần rê chuột. Màn hình cảm ứng không có
   "di chuột" nên luôn hiện; dòng đang sửa (`is-on`) cũng luôn hiện nút Lưu/Huỷ. */
.dm-act { white-space: nowrap; text-align: right !important; width: 1%; }
/* Bảng mã lỗi cho chữ xuống dòng (`#fcTable ... td`, đặc hiệu cao hơn) - không chặn lại
   thì Sửa/Xoá xếp chồng hai dòng và MỌI dòng cao gấp đôi, kể cả lúc nút đang ẩn. */
#fcTable .wb-grid td.dm-act { white-space: nowrap; }
/* Ẩn bằng opacity chứ KHÔNG bằng visibility: phần tử visibility:hidden không nhận được
   tiêu điểm, người dùng bàn phím Tab qua bảng không bao giờ tới được nút Sửa/Xoá. */
.dm-act .wb-link { opacity: 0; pointer-events: none; transition: opacity .12s; }
tr:hover > .dm-act .wb-link, tr:focus-within > .dm-act .wb-link,
.dm-act .wb-link:focus-visible, .dm-act.is-on .wb-link { opacity: 1; pointer-events: auto; }
@media (hover: none) { .dm-act .wb-link { opacity: 1; pointer-events: auto; } }
.wb-link.dm-xoa { color: #b3261e; }
.wb-link.dm-xoa:hover { color: #d33a2f; }
.dm-act .dm-btn { margin-right: 4px; }

.dm-head { display: flex; align-items: center; justify-content: space-between;
           gap: 10px; margin-bottom: 8px; }
.dm-head h4 { margin: 0; }
.wb-btn.dm-btn { padding: 4px 11px; font-size: 12.5px; }
.wb-btn.dm-btn-2 { background: #fff; color: var(--green-700);
                   border: 1px solid var(--green-700); }
.wb-btn.dm-btn-2:hover { background: var(--green-50); }
.dm-bar { display: flex; align-items: center; justify-content: space-between;
          gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.dm-nam { font-size: 12.5px; color: var(--ink-soft); display: flex; align-items: center;
          gap: 7px; }
.dm-nut { display: flex; gap: 8px; }
.wb-in.dm-in-nam { width: 96px; background: #fff; text-align: left; }

/* Ô nhập trong bảng: hẹp hơn ô chỉ số công tơ, căn phải như số trong bảng. */
.wb-in.dm-in { max-width: 160px; text-align: right; }
.wb-in.dm-txt { max-width: none; text-align: left; resize: vertical; }
tr.dm-dang-sua > td { background: #fffdf0; vertical-align: top; }
.dm-dv { text-align: left !important; color: var(--ink-soft); font-size: 11.5px;
         white-space: nowrap; width: 1%; }
.dm-note { margin: 8px 0 0; }
.dm-ghichu { display: flex; flex-direction: column; gap: 4px; margin-top: 10px;
             font-size: 12.5px; color: var(--ink-soft); }
.dm-ghichu .wb-in { max-width: none; text-align: left; background: #fff; }
.dm-hieuluc { margin: 8px 0 0; padding: 6px 10px; border-radius: 6px;
              background: #fff8e1; border-left: 3px solid #f0b400; color: #6b4a00; }

/* Bảng chữ (người báo cáo, nhật ký): căn trái như bảng mã lỗi. */
.dm-nbc th, .dm-nbc td, .dm-nk-t th, .dm-nk-t td { text-align: left; }
.dm-nbc td:first-child { width: 28px; color: var(--ink-soft); }
.dm-nk-t td { white-space: normal; }
.dm-nk-t td:first-child, .dm-nk-t td:nth-child(2) { white-space: nowrap; }
.dm-kh tfoot th, .dm-kh tfoot td { border-top: 2px solid var(--line); font-weight: 600; }
#dmPc .rp-grid-wrap { max-height: 460px; }

.dm-ls, .dm-nk { margin-top: 10px; font-size: 12.5px; }
.dm-ls summary, .dm-nk summary { cursor: pointer; color: var(--green-700); font-weight: 500; }
.dm-ls ul { margin: 6px 0 0; padding-left: 18px; }
.dm-ls li { margin: 3px 0; }
.dm-ai { color: var(--ink-soft); }

.wb-cb-x, .wb-cb-ar { position: absolute; top: 1px; bottom: 1px; width: 22px;
                      display: flex; align-items: center; justify-content: center;
                      border: 0; background: none; cursor: pointer; padding: 0;
                      color: var(--ink-soft); line-height: 1; }
.wb-cb-x  { right: 23px; font-size: 17px; }
.wb-cb-ar { right: 2px;  font-size: 11px; }
.wb-cb-x:hover, .wb-cb-ar:hover { color: var(--green-800, #17512b); }
/* Ô Mã lỗi không có mũi tên nên nút xoá lùi sát mép, và ô nhập cũng chỉ cần chừa
   chỗ cho một nút thay vì hai. */
.wb-cb:not(:has(.wb-cb-ar)) .wb-cb-x { right: 2px; }
.wb-cb:not(:has(.wb-cb-ar)) .wb-flt-in { padding-right: 26px; }

.wb-cb-list { position: absolute; top: 100%; left: 0; right: 0; z-index: 20;
              margin: 3px 0 0; padding: 4px; list-style: none; max-height: 260px;
              overflow: auto; background: #fff; border: 1px solid var(--line);
              border-radius: 8px; box-shadow: 0 8px 20px rgba(0,0,0,.14); }
.wb-cb-list li { display: flex; justify-content: space-between; gap: 10px;
                 align-items: baseline; padding: 5px 8px; border-radius: 5px;
                 font-size: 13px; color: var(--ink); cursor: pointer; }
.wb-cb-list li:hover, .wb-cb-list li.is-on { background: #e6f0e8; }
.wb-cb-list li[aria-selected="true"] { font-weight: 600; }
.wb-cb-n { font-size: 11.5px; color: var(--ink-soft);
           font-variant-numeric: tabular-nums; }
/* Không để nút giãn hết ô lưới: ô rộng 187px mà nút chỉ có hai chữ thì nhìn như
   một khối màu, lại to ngang các ô nhập nên tranh chỗ chú ý với chúng. */
.wb-fltbar .wb-btn { align-self: end; justify-self: start; }

/* TIÊU ĐỀ CỘT PHẢI CĂN CÙNG PHÍA VỚI CON SỐ NẰM DƯỚI NÓ.
   `.rp-table th` căn trái còn `.wb-grid td` căn phải, nên trong một cột rộng thì
   tiêu đề dạt hẳn mép trái còn con số dạt mép phải - hai thứ thuộc cùng một cột mà
   nằm ở hai đầu. Bảng Downtime 13 cột giãn hết bề ngang màn hình rộng, mỗi cột
   khoảng 150px, nên "Th4" trông như đứng trên con số của cột bên cạnh.
   Đo thật 07/09/2026: lệch ở 6 trên 7 tab có bảng - downtime, tổng hợp sự cố, thống
   kê, sản lượng doanh thu, tự dùng, data.
   Cột ĐẦU giữ căn trái nhờ `th:first-child` ở trên (đặc trưng cao hơn quy tắc này).
   Tab Raw data KHÔNG bị ảnh hưởng: `.wb-raw thead th` khai sau nên vẫn căn giữa
   kiểu dải tiêu đề Excel, và cột ở đó hẹp nên vốn không lệch. */
.wb-grid thead th { text-align: right; }
/* Tab Nhập liệu ép ô dữ liệu về căn trái, nên tiêu đề phải đi theo. */
#wbBody[data-tab="entry"] .wb-grid th { text-align: left; }
/* Tab Raw data cũng ép ô dữ liệu về căn trái, nhưng CHỈ các bảng phái sinh - bảng
   lớn `.wb-raw` giữ dải tiêu đề căn giữa kiểu Excel. Không loại trừ `.wb-raw` ở đây
   thì dải màu xanh mất luôn kiểu.
   Đo ngày 08/09/2026 khi chưa có quy tắc này: tiêu đề căn PHẢI còn số căn TRÁI, lệch
   tới 143px ở VPL (cột rộng vì chỉ 7 trụ), 82px ở TPD2 và Ia Bang, 21px ở TPD1. Bốn
   bảng "Tốc độ gió đã làm tròn / Công suất / Nhiệt độ / ..." của cả bốn nhà máy đều
   dính. */
#wbBody[data-tab="raw"] .wb-grid:not(.wb-raw) th { text-align: left; }
.rp-grid-wrap { overflow: auto; max-height: 62vh; }

/* ---- Tab Nhập liệu và Raw data: ô dữ liệu CĂN TRÁI ----
   Hai tab này là bảng NHẬP và bảng tra theo hàng, cột lại rộng hơn nội dung nhiều
   (chỉ số công tơ 14 ký tự nằm trong cột 200px, tốc độ gió 3 ký tự trong cột 90px).
   Căn phải thì con số dạt về mép phải còn tiêu đề cột nằm bên trái, mắt phải bắc cầu
   qua cả khoảng trống mới ghép được số với tên cột. Căn trái thì số nằm ngay dưới
   tiêu đề của nó.
   Vẫn giữ `tabular-nums` nên các chữ số vẫn thẳng hàng theo chiều dọc.
   CHỈ hai tab này - các tab tra cứu khác giữ căn phải để so sánh độ lớn. */
#wbBody[data-tab="entry"] .wb-entry td,
#wbBody[data-tab="entry"] .wb-grid td,
#wbBody[data-tab="raw"]   .wb-grid td { text-align: left; }
#wbBody[data-tab="entry"] .wb-in { text-align: left; }
/* Trừ hàng ĐƠN VỊ của sheet Raw data: đó là dải nhãn kiểu Excel, không phải dữ liệu. */
#wbBody[data-tab="raw"] .wb-raw .wb-units td { text-align: center; }

/* Bảng nhập chỉ số công tơ */
.wb-entry td { text-align: right; }
.wb-entry .wb-ro   { color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.wb-entry .wb-calc { font-weight: 600; font-variant-numeric: tabular-nums; }
.wb-in {
  font: inherit; font-size: 13px; width: 100%; max-width: 190px; text-align: right;
  padding: 5px 8px; border: 1px solid var(--line); border-radius: 7px;
  /* Ô nhập tô vàng đúng quy ước của file Excel gốc: chỗ nào vàng là chỗ phải điền. */
  background: #fffbe6;
}
.wb-in:focus { outline: 2px solid var(--green-600); outline-offset: -1px; }

.wb-save { display: flex; align-items: center; gap: 12px; margin-top: 12px;
           flex-wrap: wrap; font-size: 13px; }
.wb-save input {
  font: inherit; font-size: 13px; padding: 5px 8px; width: 110px;
  border: 1px solid var(--line); border-radius: 7px;
}
.wb-btn {
  font: inherit; font-size: 13px; cursor: pointer; border: 0; border-radius: 8px;
  background: var(--green-700); color: #fff; padding: 7px 14px; font-weight: 500;
}
.wb-btn:hover { background: var(--green-600); }
.wb-msg { font-size: 12.5px; color: var(--ink-soft); }
.wb-msg.is-ok  { color: var(--green-700); font-weight: 500; }
.wb-msg.is-bad { color: #b3261e; font-weight: 500; }
.wb-hint.is-bad { color: #b3261e; font-weight: 500; }
.wb-goiy:not(:empty) { color: #8a5a00; background: #fff8e1; border-left: 3px solid #f0b400;
                       padding: 6px 10px; border-radius: 4px; }

.wb-quick-grid { display: grid; gap: 14px;
                 grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.wb-quick-head { display: flex; justify-content: space-between; align-items: center;
                 gap: 10px; }
.wb-quick-head h4 { margin: 0; }
.wb-text {
  margin: 8px 0 0; font: 12.5px/1.55 ui-monospace, "Cascadia Code", Consolas, monospace;
  background: var(--green-50); border: 1px solid var(--line); border-radius: 8px;
  padding: 10px 12px; white-space: pre-wrap; word-break: break-word; max-height: 46vh;
  overflow: auto;
}

/* ---- form nhập sự cố ---- */
.wb-rowact { white-space: nowrap; text-align: right; }
.wb-link {
  font: inherit; font-size: 12.5px; background: none; border: 0; cursor: pointer;
  color: var(--green-700); text-decoration: underline; padding: 2px 4px;
}
.wb-link:hover { color: var(--green-600); }
.wb-incform {
  margin-top: 12px; border: 1px dashed var(--green-600); border-radius: 10px;
  padding: 12px 14px; background: var(--green-50);
}
.wb-incform h5 { margin: 0 0 10px; font-size: 13.5px; color: var(--green-900); }
.wb-fgrid { display: grid; gap: 10px;
            grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.wb-f { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px;
        color: var(--ink-soft); margin-bottom: 8px; }
.wb-f .wb-in { max-width: none; text-align: left; }
.wb-f select.wb-in { background: #fffbe6; }
.wb-f .wb-in:disabled { background: var(--green-50); color: var(--ink-soft);
                        font-style: italic; }
.wb-fgroup { margin: 14px 0 8px; font-size: 12px; letter-spacing: .03em;
             color: var(--green-800, var(--green-900)); border-bottom: 1px solid
             var(--green-100, #dcefe1); padding-bottom: 3px; }
.wb-req { color: #c0392b; }
.wb-gio { font-variant-numeric: tabular-nums; letter-spacing: .02em; }
.wb-in.is-bad { border-color: #c0392b; background: #fdecea; }
.wb-kq-note { font-weight: 400; letter-spacing: 0; color: var(--ink-soft); }
.wb-kq { display: grid; gap: 8px; margin-bottom: 8px;
         grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); }
.wb-kq-o { display: flex; flex-direction: column; gap: 4px; padding: 7px 10px;
           background: #fff; border: 1px solid #d9e6dc; border-radius: 8px;
           font-size: 12px; color: var(--ink-soft); }
.wb-kq-o[hidden] { display: none; }
.wb-kq-o b { font-size: 15px; color: var(--ink, #1d2b22);
             font-variant-numeric: tabular-nums; }
.wb-kq-o.is-main { border-color: var(--green-600); background: #f3faf5; }
.wb-kq-o.is-main b { color: var(--green-900); }

/* ---- khu vực tải raw data ---- */
.wb-upload {
  border: 1px dashed var(--green-600); border-radius: 10px; padding: 10px 14px;
  background: var(--green-50); margin-bottom: 14px;
}
.wb-upload summary { cursor: pointer; font-weight: 600; color: var(--green-900);
                     font-size: 13.5px; }
.wb-upload[open] summary { margin-bottom: 8px; }
.wb-upload input[type="file"] { font: inherit; font-size: 12.5px; display: block;
                                margin-bottom: 8px; }
.wb-upload textarea {
  width: 100%; font: 12px/1.5 ui-monospace, Consolas, monospace; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 8px; background: #fff; resize: vertical;
}
.wb-warn { margin: 8px 0 0; padding-left: 20px; font-size: 12.5px; color: #8a5a00; }
.wb-warn li { margin-bottom: 3px; }

.rp-headtools { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.wb-dl { text-decoration: none; display: inline-block; line-height: 1.3; }

/* ---- các bảng tính toán của Raw data ---- */
.wb-secth { margin: 18px 0 8px; font-size: 14px; color: var(--green-900);
            border-bottom: 2px solid var(--line); padding-bottom: 5px; }
.wb-gridblock {
  border: 1px solid var(--line); border-radius: 9px; margin-bottom: 8px;
  background: #fff; padding: 8px 12px;
}
.wb-gridblock summary { cursor: pointer; font-size: 13px; font-weight: 500;
                        color: var(--ink); }
.wb-gridblock[open] summary { margin-bottom: 8px; }
/* Nhãn ô Excel gốc: người quen file cũ đối chiếu được ngay cột nào ứng với cột nào. */
.wb-xl { font: 11px ui-monospace, Consolas, monospace; color: var(--ink-soft);
         background: var(--green-50); border: 1px solid var(--line);
         border-radius: 4px; padding: 1px 5px; margin-left: 6px; }
.wb-unit { font-size: 11.5px; color: var(--ink-soft); margin-left: 6px; }

.wb-comment { margin-top: 12px; }
/* SL tại WTG gõ tay (Ia Bang, VPL) - ô vàng như ô phải điền của file Excel. */
.wb-wtg { margin-top: 12px; }
.wb-wtg input {
  font: inherit; font-size: 13px; width: 100%; max-width: 190px; text-align: right;
  padding: 5px 8px; border: 1px solid var(--line); border-radius: 7px;
  background: #fffbe6;
}
.wb-comment textarea {
  width: 100%; font: inherit; font-size: 13px; padding: 7px 9px;
  border: 1px solid var(--line); border-radius: 8px; background: #fffbe6;
  resize: vertical;
}
.rp-comment { margin-top: 14px; }
.rp-comment p { margin: 0; font-size: 13.5px; white-space: pre-wrap; }

/* ---- bảng Raw data: màu lấy theo sheet Excel để người quen file cũ nhìn là biết ----
   Thứ tự quan trọng: hàng tiêu đề và hàng đơn vị phủ XANH LÁ toàn bộ, ba hàng
   Max/Average/Min phủ XANH DƯƠNG toàn bộ, và màu riêng của ba cột nhà máy CHỈ áp cho
   các hàng dữ liệu. Trước đây bốn nhóm này cùng độ ưu tiên CSS nên quy tắc cột đứng
   sau đè lên, làm ô "MW"/"oC" ở hàng đơn vị và ô Power/Temp ở hàng thống kê bị nhuộm
   nhầm màu cột. Dùng :not(.wb-stat) để tách hẳn, không dựa vào thứ tự khai báo. */
.wb-raw thead th,
.wb-raw thead th.c-time,
.wb-raw thead th.c-wind,
.wb-raw thead th.c-power,
.wb-raw thead th.c-temp {
  background: #a9d08e; color: #1c3a1c; border: 1px solid #7fae66;
  font-weight: 600; text-align: center; white-space: nowrap;
}
.wb-raw thead th.c-time { text-align: left; }

.wb-raw .wb-units td,
.wb-raw .wb-units td.c-time,
.wb-raw .wb-units td.c-wind,
.wb-raw .wb-units td.c-power,
.wb-raw .wb-units td.c-temp {
  background: #a9d08e; color: #1c3a1c; border: 1px solid #7fae66;
  text-align: center; font-size: 11.5px; font-weight: 500;
}

/* Ba hàng Max / Average / Min: xanh dương suốt cả hàng, kể cả các cột trụ. */
.wb-raw .wb-stat td,
.wb-raw .wb-stat th,
.wb-raw .wb-stat td.c-time,
.wb-raw .wb-stat td.c-wind,
.wb-raw .wb-stat td.c-power,
.wb-raw .wb-stat td.c-temp {
  background: #b4c6e7; font-weight: 600; border: 1px solid #9bb3dc;
}
.wb-raw .wb-stat th { text-align: left; color: var(--ink); }

/* Màu riêng ba cột mức nhà máy, CHỈ ở hàng dữ liệu. Cột trụ để trắng. */
.wb-raw tbody tr:not(.wb-stat) td.c-time  { background: #b4c6e7; font-weight: 500; }
.wb-raw tbody tr:not(.wb-stat) td.c-wind  { background: #b4c6e7; }
.wb-raw tbody tr:not(.wb-stat) td.c-power { background: #fce4d6; }
.wb-raw tbody tr:not(.wb-stat) td.c-temp  { background: #fff2cc; }
.wb-raw tbody td { border: 1px solid #e2e8e4; }

/* Đầu bảng dính khi cuộn: hai hàng, nên hàng đơn vị phải lùi xuống đúng chiều cao
   hàng tiêu đề, không thì nó chồng lên. */
.wb-raw thead th { position: sticky; top: 0; z-index: 2; }
.wb-raw .wb-units td { position: sticky; top: 28px; z-index: 2; }

/* ---- khối Thông số vận hành trong tab Nhập liệu ---- */
.wb-auto {
  font-size: 11.5px; color: var(--green-700); background: var(--green-50);
  border: 1px solid var(--line); border-radius: 999px; padding: 2px 9px;
}
.wb-ops {
  display: grid; gap: 8px; margin-top: 4px;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
/* Ô CHỈ ĐỌC nên phải khác hẳn ô nhập. Trước đây dùng cam nhạt #fdf3e3, gần như trùng
   với vàng #fffbe6 của ô nhập ở mục 2 - nhìn lướt tưởng gõ được vào đây. Vàng đã là
   quy ước "ô phải điền" từ file Excel, nên phần tính toán tuyệt đối không dùng vàng. */
.wb-op {
  background: #f1f6f3; border: 1px solid var(--line); border-radius: 9px;
  padding: 7px 10px;
}
.wb-sub {
  font-weight: 400; font-size: 12px; color: var(--ink-soft); margin-left: 8px;
}
.wb-op-label { font-size: 11px; color: var(--ink-soft); margin-bottom: 2px; }
.wb-op-value { font-size: 15px; font-weight: 600; color: var(--green-900);
               font-variant-numeric: tabular-nums; }
.wb-op-unit  { font-size: 11px; font-weight: 400; color: var(--ink-soft); }

.wb-checks { margin-top: 12px; font-size: 12.5px; }
.wb-checks thead th { color: var(--green-900); font-weight: 600; white-space: nowrap; }
.wb-checks td { text-align: right; font-variant-numeric: tabular-nums; }
.wb-checks th { text-align: left; font-weight: 500; }
.wb-checks td.wb-chk { text-align: left; color: var(--green-700); font-weight: 600; }
/* Dòng hỏng tô đỏ nhạt VÀ có dấu ⚠ - màu không bao giờ là thứ duy nhất mang thông tin. */
.wb-checks tr.is-bad td, .wb-checks tr.is-bad th { background: #fdecea; }
.wb-checks tr.is-bad td.wb-chk { color: #b3261e; }

/* Bảng công tơ gộp: ba cột đầu là phần nhập, bốn cột sau do hệ thống tính. */
.wb-entry thead th { color: var(--green-900); font-weight: 600; white-space: nowrap;
                     font-size: 12px; }
.wb-entry th { text-align: left; }
.wb-entry td { text-align: right; font-variant-numeric: tabular-nums; }
.wb-entry td.wb-chk { text-align: left; color: var(--green-700); font-weight: 600;
                      white-space: nowrap; }
.wb-entry tr.is-bad td, .wb-entry tr.is-bad th { background: #fdecea; }
.wb-entry tr.is-bad td.wb-chk { color: #b3261e; }

/* Ghi chú kỹ thuật của người vận hành - giải thích vì sao số ngày đó khác công thức.
   Tô nổi vì đây là cảnh báo về NGUỒN GỐC con số, không phải bình luận thường. */
.wb-note {
  margin: 10px 0 0; font-size: 12.5px; color: #8a5a00; background: #fff8e6;
  border: 1px solid #f0dca8; border-radius: 8px; padding: 7px 10px;
}

/* ================= Dashboard báo cáo ngày =================
   Excel tách bạch từng trường bằng ĐƯỜNG KẺ liền nhau, không phải bằng khoảng trắng.
   Nên ở đây các ô cũng dính nhau và ngăn bằng viền chung, giống bảng tính - thay vì
   kiểu thẻ rời có bóng đổ. Người quen file cũ nhìn ra ngay đâu là một trường. */
/* `container-type: inline-size` biến chính khối dashboard thành THƯỚC ĐO cho các
   quy tắc co giãn bên dưới. Bắt buộc phải đo ở đây chứ không đo cửa sổ trình duyệt:
   khối này còn bị cây điều hướng bên trái ăn mất hơn 250px, nên cửa sổ 1400px mà
   dashboard chỉ còn hơn 1100px. Đo nhầm chỗ là ra đúng cảnh laptop: vẫn ba cột chật
   cứng trong khi lẽ ra phải xuống hai cột. */
/* KHÔNG có viền ngoài cùng: dashboard đã nằm trong khung trắng của tab rồi, thêm
   một khung nữa là hai lớp viền lồng nhau.
   `--dash-rule` là màu của MỌI vạch ngăn bên trong - để một chỗ, đổi một dòng là
   đổi cả trang; rải `var(--green-700)` khắp nơi như trước thì sửa sót là chuyện sớm
   muộn. */
.dash { background: #fff; border: 0; border-radius: 4px;
        overflow: hidden; container-type: inline-size; container-name: dash;
        --dash-rule: #000; }
.dash-head { display: flex; justify-content: space-between; align-items: center;
             gap: 16px; flex-wrap: wrap; padding: 8px 12px;
             border-bottom: 2px solid var(--dash-rule); }
.dash-head h3 { margin: 0 0 2px; color: #000; font-size: 20px; }

/* Hàng chỉ tiêu dùng CHÍNH lưới ba cột của phần dưới, rồi mỗi cột tự chia tiếp
   2 | 3 | 2 ô. Nhờ vậy vạch ngăn của hàng KPI trùng thẳng với vạch ngăn ba cột bên
   dưới, đúng như Excel. Để hàng KPI tự chia 7 cột đều nhau thì hai lưới lệch nhau,
   nhìn rời rạc. */
/* MỘT khai báo chia ba cột cho CẢ hàng KPI, phần thân và ảnh xuất ra. Trước 06/10/2026
   mỗi chỗ chép tay một bản: nới cột 3 của phần thân (.8fr -> .9fr) mà quên hàng KPI là
   vạch ngăn trên web lệch hẳn so với vạch bên dưới, trong khi ảnh tải về vẫn thẳng. */
:root { --dash-cot: minmax(210px, 1fr) minmax(290px, 1.5fr) minmax(175px, .9fr); }
.dash-kpis { display: grid; border-bottom: 2px solid var(--dash-rule);
             grid-template-columns: var(--dash-cot); }
.dash-kpi-grp { display: grid; grid-template-columns: repeat(var(--n), 1fr);
                border-right: 2px solid var(--dash-rule); min-width: 0; }
.dash-kpi-grp:last-child { border-right: 0; }
/* KHÔNG có vạch ngăn giữa cột 1 và cột 2 - xem chú thích ở `.dash-card` bên dưới. */
.dash-kpi-grp:first-child { border-right: 0; }
.dash-kpi { padding: 9px 12px; border-right: 1px solid var(--line);
            background: #fff; min-width: 0;
            display: flex; align-items: center; gap: 8px; }
.dash-kpi-txt { min-width: 0; }
/* Biểu tượng trong huy hiệu tròn nền xanh nhạt - file Excel dùng ảnh clipart nhiều
   màu, nhưng trên web mà mỗi ô một màu riêng thì bảy ô thành bảy hướng nhìn. Một màu
   chung để biểu tượng làm đúng việc của nó: nhận ra ô nào là ô nào, không tranh chỗ
   với con số. */
.dash-kpi-ico { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%;
                display: grid; place-items: center;
                background: var(--green-50); color: var(--green-700); }
.dash-kpi-ico svg { width: 19px; height: 19px; display: block; }
/* Biểu tượng bị ẩn khi dashboard hẹp - xem ba bậc co giãn ở cuối tệp. */
.dash-kpi-grp .dash-kpi:last-child { border-right: 0; }
/* Nhãn KPI là thứ người xem đọc TRƯỚC để biết con số bên dưới là gì, nên phải đọc
   được từ xa. Để mờ và nhỏ như chú thích phụ thì mắt lướt qua mất. */
/* Nhãn XUỐNG DÒNG chứ không cắt bằng dấu ba chấm. Sau khi thêm biểu tượng, ô hẹp
   đi 40px nên "Average Wind Speed" và "Capacity Factor" bị cắt cụt - mà nhãn bị cắt
   thì người xem không biết con số bên dưới là gì, tệ hơn hẳn việc thẻ cao thêm một
   dòng. */
.dash-kpi-label { font-size: 14px; font-weight: 600; color: #000;
                  margin-bottom: 4px; letter-spacing: .01em; line-height: 1.25;
                  overflow-wrap: break-word; }
/* Tên thẻ, con số và đơn vị đều ĐEN (user chốt 28/08/2026). Thứ bậc giữa chúng do
   cỡ chữ và độ đậm gánh, không cần dùng thêm màu - trang này đã có đủ màu ở cột,
   đường và vành khuyên rồi. */
.dash-kpi-value { font-size: 25px; font-weight: 600; color: #000;
                  letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.dash-kpi-unit { font-size: 13px; font-weight: 400; color: #000; }

/* Ba cột như Excel. Bề rộng tối thiểu phải cộng lại VỪA KHUNG CHỨA, không phải vừa
   màn hình: khung này còn bị cây điều hướng 236px ăn mất bên trái. Cột 3 = .9fr (trước
   06/10/2026 là .8fr: ở laptop 1366px bảng Energy loss tràn 21px, khuất nửa cột cuối). */
.dash-grid { display: grid; align-items: stretch; grid-template-columns: var(--dash-cot); }
.dash-card { padding: 11px 13px; background: #fff; min-width: 0;
             border-right: 2px solid var(--dash-rule);
             border-bottom: 1px solid var(--line); }
.dash-card:nth-child(3n) { border-right: 0; }
/* Bỏ vạch ngăn giữa CỘT 1 và CỘT 2 (user chốt 28/08/2026). Hai cột này nay nói cùng
   một chuyện: vành khuyên tháng/năm đứng cạnh biểu đồ 10 ngày và biểu đồ 12 tháng,
   Comments đứng cạnh chính biểu đồ mà nó nhận xét. Vạch kẻ giữa chúng làm mắt đọc
   thành hai khối rời. Vạch giữa cột 2 và cột 3 thì giữ, vì cột 3 là chuyện khác
   (tổn thất và khả dụng). */
.dash-card:nth-child(3n+1) { border-right: 0; }
/* Dải chỉ tiêu TRONG NGÀY, chiếm trọn một hàng ngay trên biểu đồ công suất.
   Dùng `auto-fit` chứ không chia cứng 5 cột: ở khung hẹp năm ô tự xuống dòng thành
   ba rồi hai, khỏi phải viết thêm ngưỡng cho riêng dải này. Viền dưới dày để nó dính
   liền vào biểu đồ bên dưới - đây là phần tóm tắt của chính biểu đồ đó, không phải
   một khối rời. */
/* Viết `.dash-grid > .dash-kpis-day` chứ không phải `.dash-kpis-day`: dải này cũng
   mang lớp `.dash-kpis`, mà cả ba bậc co giãn lẫn lớp `.dash-export` đều nhắm vào
   `.dash-kpis` để chia 2|3|2 - dùng bộ chọn một lớp là bị chúng đè, dải năm ô biến
   thành ba cột. */
.dash-grid > .dash-kpis-day { grid-column: 1 / -1;
                 grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
                 border-top: 1px solid var(--line);
                 border-bottom: 2px solid var(--dash-rule); }
.dash-kpis-day .dash-kpi:last-child { border-right: 0; }

/* Thẻ Comments đứng riêng một ô nên bỏ khung xanh nhạt bên trong - hai lớp khung
   lồng nhau cho một đoạn chữ là thừa. Giữ nền và vạch trái để vẫn nhận ra ngay đây
   là nhận định của người trực chứ không phải số đo. */
.dash-summary .dash-comment { margin-top: 0; }
.dash-empty { margin: 0; color: var(--ink-soft); font-size: 13px; font-style: italic; }

/* Tổn thất của chính ngày báo cáo, đặt giữa bảng theo tháng và vành khuyên cả năm. */
.dash-today-loss { margin: 10px 0 2px; font-size: 13px; color: var(--ink-soft);
                   text-align: center; font-variant-numeric: tabular-nums; }
.dash-today-loss b { color: var(--ink); font-weight: 700; }

/* Thẻ chiếm TRỌN một hàng. Biểu đồ công suất trong ngày có 144 mốc 10 phút - nhồi vào
   một cột hẹp thì các mốc giờ dính nhau; cho nó cả hàng dưới cùng là vừa đủ thở, mà
   hàng đó cũng không còn thẻ nào khác để xếp cạnh. */
.dash-wide { grid-column: 1 / -1; border-right: 0; }
.dash-card h4 { margin: 0 0 8px; font-size: 15px; color: #000;
                text-align: center; }
/* Tiêu đề khối nhận định to hơn tiêu đề các thẻ số. Viết `.dash-grid .dash-summary h4`
   chứ không phải `.dash-summary h4`: các bậc co giãn ở cuối tệp có cùng độ ưu tiên
   với `.dash-card h4` và nằm sau, nên bộ chọn một lớp sẽ bị chúng thu nhỏ theo. */
.dash-grid .dash-summary h4 { font-size: 17px; }
/* Tiêu đề hai biểu đồ căn về đầu dòng và viết hoa như bản Excel: hình vẽ bắt đầu từ
   mép trái, tiêu đề nằm giữa thì mắt phải nhảy vào giữa rồi lại ra mép để đọc trục. */
.dash-card h4.dash-h-left { text-align: left; text-transform: uppercase;
                            font-weight: 700; letter-spacing: .02em; }

.dash-rings { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.dash-ring-box { text-align: center; min-width: 0; }
.dash-ring-box h4 { margin-bottom: 3px; }
.dash-ring { width: 100%; max-width: 200px; height: auto; }
/* 20px là cỡ lớn nhất còn lọt LÒNG vành khuyên: "127,03%" ở 22px rộng 88,6px trong
   khi lòng trong chỉ 84px, chữ đè lên vòng "vượt kế hoạch". */
.dash-ring-val  { font: 700 20px/1 system-ui, sans-serif; fill: #000; }
.dash-ring-over { font: 600 10.5px/1 system-ui, sans-serif; fill: #a04d05; }
/* Hai dòng dưới vành khuyên là sản lượng và doanh thu so với kế hoạch - đây mới là
   con số người xem đọc để kết luận, nên CON SỐ đậm và đen, còn dấu "/" với tên đơn
   vị để nhạt. Trước đây cả dòng cùng một màu xám nên số chìm lẫn vào đơn vị. */
.dash-ring-sub { margin: 3px 0 0; font-size: 13px; color: var(--ink-soft);
                 font-variant-numeric: tabular-nums; }
.dash-ring-sub b { font-weight: 700; font-size: 14.5px; color: var(--ink); }
.dash-ring-sub span { color: var(--ink-soft); font-size: 12.5px; }

.dash-svg { width: 100%; height: auto; display: block; }
/* Số trên hai trục để ĐEN chứ không xám: dashboard này còn được chụp màn hình dán
   vào nhóm chat rồi xem trên điện thoại, chữ xám nhạt là mất hẳn. */
.dash-tick { font: 11.5px system-ui, sans-serif; fill: #14261c; }
.dash-axis { font: 600 12px system-ui, sans-serif; fill: #14261c; }
/* Nhãn số trên biểu đồ có VIỀN TRẮNG (paint-order: stroke) vì nhãn kế hoạch nhiều
   khi rơi vào thân cột xanh đậm; không có viền thì chữ chìm vào nền cột. */
.dash-val  { font: 600 11px system-ui, sans-serif; fill: #14261c;
             stroke: #fff; stroke-width: 3px; paint-order: stroke;
             stroke-linejoin: round; }
.dash-val-bar  { fill: #003f8f; }   /* đúng màu cột */
/* Khung hẹp (thẻ dưới ~500px): 12 cặp số ở cỡ 11px sẽ đè lên nhau, nên hạ một nấc
   xuống 9px. Vẫn đọc được, và hơn hẳn cách cũ là để nguyên khung vẽ 680 rồi kéo giãn
   - lúc đó chữ ra 5-6px. Mốc trục cũng hạ theo cho cân. */
/* Số phần trăm dưới trục: nhỏ hơn nhãn sản lượng một nấc vì nó là thông tin phụ
   trợ - thanh màu mới là thứ đọc trước, con số chỉ để xác nhận. Màu đặt trực tiếp
   trên từng thẻ theo đạt/hụt nên không khai `fill` ở đây. */
.dash-ratio { font-size: 9.5px; font-weight: 700; }
.dash-svg.is-tight .dash-val  { font-size: 9px; stroke-width: 2.5px; }
/* Đặt SAU quy tắc `.dash-val` ở trên: nhãn phần trăm mang cả hai lớp, mà hai bộ chọn
   này cùng độ ưu tiên nên cái viết sau mới thắng. Để trước là nó bị kéo về 9px và
   nhãn hai số lẻ chạm nhau ở khổ laptop. */
.dash-svg.is-tight .dash-ratio { font-size: 8.5px; }
.dash-svg.is-tight .dash-tick { font-size: 10px; }
.dash-svg.is-tight .dash-axis { font-size: 11px; }
.dash-val-plan { fill: #b03a76; }   /* cùng họ hồng với đường kế hoạch */
.dash-val-rev  { fill: #b03a76; }   /* cùng họ hồng với đường doanh thu */
.dash-legend { display: flex; flex-wrap: wrap; gap: 14px; justify-content: center;
               margin-top: 5px; font-size: 13px; color: var(--ink-soft); }
.dash-legend-top { margin: 0 0 6px; }
/* Thanh màu dài hẳn ra: 11px quá ngắn để nhận ra sắc độ, nhất là hai màu gần nhau. */
.dash-legend i { display: inline-block; width: 28px; height: 5px; border-radius: 3px;
                 margin-right: 7px; vertical-align: middle; }

/* ---- ô chỉ dẫn theo con trỏ ---- */
.dash-hover-wrap { position: relative; }
.dash-tip {
  position: absolute; pointer-events: none; z-index: 5;
  background: rgba(255, 255, 255, .97); border: 1px solid var(--line);
  border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, .12);
  padding: 6px 9px; font-size: 11.5px; line-height: 1.55; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.dash-tip b { color: var(--green-900); }
.dash-tip span { display: block; color: var(--ink-soft); }
.dash-tip i { display: inline-block; width: 9px; height: 3px; border-radius: 2px;
              margin-right: 5px; vertical-align: middle; }

.dash-av td { text-align: right; font-variant-numeric: tabular-nums; }
.dash-av th { text-align: left; font-weight: 500; }
.dash-av-farm th, .dash-av-farm td { font-weight: 700; font-size: 16px;
                                     color: var(--green-900); }
.dash-av-group th, .dash-av-group td { font-weight: 600; }
.dash-av tr.is-full td { background: #d7ecd9; }

/* --- phần trụ, bản gọn --- */
.dash-av-ok { margin: 8px 0 0; font-size: 13.5px; font-weight: 600;
              color: var(--green-700); }
.dash-av-head { margin: 10px 0 4px; font-size: 13px; font-weight: 700;
                color: #b3261e; }
/* Trụ chưa đạt: nền đỏ nhạt để nổi hẳn khỏi ba dòng tổng hợp phía trên. Đây là dòng
   người trực phải xử lý, không phải dòng để đọc lướt. */
.dash-av-low th, .dash-av-low td { background: #fdecea; }
.dash-av-low td { font-weight: 700; color: #b3261e; }

/* Khối Top 5 nằm dưới bảng Availability trong cùng một thẻ, ngăn bằng một vạch mảnh:
   cùng chủ đề "trụ nào có vấn đề" nhưng khác kỳ - trên là hôm nay, dưới là cả năm. */
.dash-top5 { margin-top: 12px; padding-top: 10px;
             border-top: 1px solid var(--line); }
/* Cùng cỡ chữ với tiêu đề thẻ (`.dash-card h4`) - đây là tiêu đề của một khối ngang
   hàng, không phải chú thích phụ. Ba bậc co giãn ở cuối tệp thu nó theo cùng nhịp. */
.dash-top5 h5 { margin: 0 0 6px; font-size: 15px; font-weight: 600; color: #000; }
.dash-val-tot { fill: #000; }

/* Comments là chỗ người trực viết nhận định, không phải số đo - nên tách hẳn khỏi
   bảng số bằng một khung riêng, NỀN VÀNG NHẠT (user chốt 28/08/2026).
   Trên trang này vàng cũng là màu của ô phải điền ở tab Nhập liệu, nhưng dashboard
   không có ô nhập nào nên không lẫn được; đổi lại nhận định nổi hẳn giữa một trang
   toàn số. Cỡ chữ lớn hơn phần còn lại vì đây là câu KẾT LUẬN của cả ngày. */
.dash-comment { margin-top: 12px; font-size: 15px; background: #fff8e1;
                border: 1px solid #ecd9a0; border-left: 4px solid #e0a800;
                border-radius: 8px; padding: 11px 14px; }
.dash-comment p { margin: 0; white-space: pre-wrap; color: var(--ink); line-height: 1.55; }

/* Nhận định tự động: danh sách gạch đầu dòng trên nền vàng nhạt như khối bình luận
   cũ - vẫn là "chỗ đọc chữ" giữa một trang toàn số. */
.dash-insight { margin: 0; padding: 11px 14px 11px 30px; font-size: 14.5px;
                line-height: 1.55; background: #fff8e1; color: var(--ink);
                border: 1px solid #ecd9a0; border-left: 4px solid #e0a800;
                border-radius: 8px; }
.dash-insight li { margin: 0 0 5px; }
.dash-insight li:last-child { margin-bottom: 0; }
/* Lời người trực để tách hẳn khỏi nhận định máy, nền trắng viền mảnh: đọc là biết
   ngay câu nào của ai. */
.dash-comment-man { background: #fff; border-color: var(--line);
                    border-left-color: #8a8a8a; font-size: 13.5px; }
.dash-comment-man b { font-size: 12.5px; color: var(--ink-soft); }

/* Bảng trong dashboard đọc từ xa, không phải để tra cứu - cỡ chữ lớn hơn bảng
   thường của các tab khác. */
.dash-card .rp-table { font-size: 14px; }
.dash-card .rp-table th, .dash-card .rp-table td { padding: 6px 7px; }

/* Bảng kẻ ô đầy đủ như Excel: mỗi ô một khung, không phải chỉ gạch chân từng dòng.
   Với bảng 12 dòng số như Energy loss thì kẻ ô giúp mắt bám đúng cột khi đọc ngang. */
.dash-tbl { border-collapse: collapse; width: 100%; }
.dash-tbl th, .dash-tbl td { border: 1px solid #b9c6bd; }
.dash-tbl thead th { background: var(--green-50); color: var(--green-900);
                     font-weight: 700; text-align: center; }
.dash-tbl tbody th { background: #fbfdfb; font-weight: 500; }
.dash-tbl tfoot th, .dash-tbl tfoot td { background: var(--green-50);
                                         font-weight: 700; border-top: 2px solid var(--dash-rule); }
.dash-tbl tr.is-current td, .dash-tbl tr.is-current th { background: #ddeee0; }
/* Daily Summary không có thead - hàng nào cũng là nhãn + số, kẻ ô như nhau. */
.dash-summary .dash-tbl td { text-align: right; }
.dash-summary .dash-tbl td.rp-unit { text-align: left; color: var(--ink-soft);
                                     width: 52px; }
.dash + .rp-source { margin-top: 8px; }

/* ---- các bậc co giãn, đo theo bề ngang THẬT của dashboard ----
   Đo bằng @container chứ không @media: @media đo bề ngang CỬA SỔ, trong khi dashboard
   còn bị cây điều hướng ~236px ăn mất. Cửa sổ 1400px thì dashboard chỉ còn ~1100px,
   chưa chạm ngưỡng @media nào nên không bậc nào kích hoạt - con số 25px tràn ra khỏi
   ô và nhãn bị bẻ giữa từ ("Performan/ce").

   BA CỘT LÀ BỐ CỤC CHÍNH, GIỮ CÀNG LÂU CÀNG TỐT. Đây là bố cục của file Excel gốc và
   là thứ người dùng quen; xuống hai cột là các thẻ đảo chỗ, đọc lại từ đầu. Nên khi
   chật thì THU CHỮ trước, chỉ bỏ ba cột khi thật sự không đủ chỗ (ba cột cần tối thiểu
   210+290+175 = 675px cộng viền và lề). */

/* Bậc 1 - vẫn ba cột nhưng đã chật: chỉ thu chữ, giữ nguyên bố cục. Bảy ô chỉ tiêu
   là chỗ vỡ trước tiên vì con số ở đây to nhất trang. */
@container dash (max-width: 1330px) {
  /* Biểu tượng là thứ hy sinh đầu tiên: nó chỉ trang trí, còn nhãn và con số mới là
     thông tin. Ẩn theo MỘT ngưỡng duy nhất ở đây, không ẩn/hiện qua lại theo từng
     bậc - kéo cửa sổ mà biểu tượng lúc mất lúc hiện thì trông như lỗi. */
  .dash-kpi-ico  { display: none; }
  .dash-kpi-value { font-size: 20px; }
  .dash-kpi-unit  { font-size: 11.5px; }
  .dash-kpi-label { font-size: 12.5px; }
  .dash-card h4, .dash-top5 h5 { font-size: 14px; }
  .dash-legend    { font-size: 12px; gap: 10px; }
  .dash-head h3   { font-size: 17px; }
  .dash-card .rp-table { font-size: 13px; }
  .dash-card .rp-table th, .dash-card .rp-table td { padding: 5px 6px; }
}

/* Bậc 2 - ba cột đã rất chật nhưng vẫn hơn là đảo bố cục: thu chữ thêm một nấc. */
@container dash (max-width: 950px) {
  .dash-kpi-value { font-size: 18px; }
  .dash-kpi-unit  { font-size: 11px; }
  .dash-kpi-label { font-size: 12px; }
  .dash-kpi       { padding: 8px 9px; }
  .dash-card      { padding: 9px 10px; }
  .dash-card h4, .dash-top5 h5 { font-size: 13.5px; }
  .dash-card .rp-table { font-size: 12.5px; }
  .dash-card .rp-table th, .dash-card .rp-table td { padding: 4px 5px; }
  .dash-ring-sub   { font-size: 12px; }
  .dash-ring-sub b { font-size: 13px; }
}

/* Bậc 3 - ba cột hết chỗ thật (dưới 675px + lề): xuống hai cột. Mỗi ô rộng ra nên
   trả lại cỡ chữ. */
@container dash (max-width: 760px) {
  .dash-grid, .dash-kpis { grid-template-columns: 1fr 1fr; }
  .dash-card:nth-child(3n),
  .dash-card:nth-child(3n+1) { border-right: 2px solid var(--dash-rule); }
  .dash-card:nth-child(2n) { border-right: 0; }
  /* Hàng KPI hết chỗ chia 2|3|2 thì cho nhóm ba ô xuống dòng riêng. */
  .dash-kpi-grp:last-child { grid-column: 1 / -1; border-right: 0;
                             border-top: 1px solid var(--line); }
  .dash-kpi-value { font-size: 21px; }
  .dash-kpi-label { font-size: 13px; }
  .dash-card h4, .dash-top5 h5 { font-size: 14.5px; }
}

/* Bậc 4 - một cột. */
@container dash (max-width: 560px) {
  .dash-grid, .dash-kpis { grid-template-columns: 1fr; }
  .dash-card { border-right: 0; }
  .dash-kpi-grp { border-right: 0; border-bottom: 1px solid var(--line); }
}

/* Bậc 5 - khung rất hẹp (điện thoại): nhóm ba ô chia trong 300px thì mỗi ô còn
   khoảng 100px, con số 21px tràn ra ngoài. */
@container dash (max-width: 420px) {
  .dash-kpi-value { font-size: 18px; }
  .dash-kpi-label { font-size: 12.5px; }
  .dash-kpi { padding: 7px 8px; }
}

/* Bảng trong dashboard KHÔNG được cuộn. `.rp-grid-wrap` chặn cao 62vh cho các tab tra
   cứu (bảng ở đó có hàng nghìn dòng), nhưng bảng Energy loss chỉ có 12 tháng cộng dòng
   Sum - cuộn ở đây là giấu mất tháng 11, 12 và chính dòng tổng. Trên laptop màn thấp
   62vh chỉ còn hơn 400px nên nó cuộn thật.
   CHỈ gỡ chặn chiều cao, GIỮ `overflow: auto` của quy tắc gốc: bỏ luôn overflow thì
   bảng rộng hơn thẻ sẽ tràn ra ngoài thay vì cuộn ngang. */
.dash .rp-grid-wrap { max-height: none; }

/* ---- bố cục RIÊNG cho ảnh xuất ra: NẰM NGANG, ba cột dọc như Excel (07/10/2026) ----
   Ảnh gửi nhóm Viber lãnh đạo và được mở trên LAPTOP / MÀN 24" (user chốt ưu tiên hai
   loại này). Trình xem ảnh thu ảnh cho LỌT CẢ HAI CHIỀU cửa sổ, nên ảnh phải NẰM NGANG
   gần 16:9 mới phủ kín khung xem (ảnh dọc kiểu web: chữ còn 5-6px).
   Bố cục theo đúng dashboard Excel gốc user gửi làm mẫu - ba CỘT DỌC, khổ 1920px:

     | vành khuyên | 10 ngày gần nhất              | Energy loss  |
     |             | sản lượng theo tháng          |              |
     | Insight     | dải chỉ tiêu trong ngày       | Availability |
     |             | công suất / nhiệt / gió       | + Top 5      |

   daily.js downloadDashboard chuyển thẻ vào ba khung `.xuat-cot` trên BẢN SAO. Cột
   giữa rộng gần nửa ảnh (2fr) để nhãn ngày, nhãn % không dính chùm; ba thẻ biểu đồ là
   `flex: 1 1 0` - chia đều chỗ thừa của cột, rồi daily.js vẽ lại mỗi biểu đồ cao đúng
   bằng ô của nó (Excel kéo biểu đồ lấp đầy ô, ảnh cũ thì thừa khoảng trắng dưới hình).
   Đã thử và bỏ: lưới 4 cột, hai biểu đồ đứng cạnh nhau - user chê "co cụm".

   Hàng KPI trên cùng chia đúng 1,05 | 2 | 0,95 như ba cột nên vạch ngăn trước cột phải
   chạy thẳng một đường từ hàng KPI xuống đáy. minmax(0, ..fr): `1fr` trần có chặn dưới
   là bề ngang nội dung, bảng rộng một chút là cột phình ra và hai lưới lệch nhau.
   Đổi TÊN khung đo của bản sao: không bậc `@container dash` nào (viết cho màn hình
   hẹp) được áp vào ảnh - ảnh luôn giữ cỡ chữ gốc. */
.dash.dash-export { container-name: dash-anh; }
.dash-export .dash-kpis:not(.dash-kpis-day),
.dash-export .dash-grid {
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 2fr) minmax(0, .95fr);
}
.dash-export .xuat-cot { display: flex; flex-direction: column; min-width: 0; }
.dash-export .xuat-cot > * { border-right: 0; }
.dash-export .xuat-giua { border-right: 2px solid var(--dash-rule); }
/* Ba biểu đồ chia chỗ theo độ CẦN cao: biểu đồ tháng còn dải tỉ lệ % dưới trục (90px cố
   định trong dash.js barLine) nên được phần lớn nhất, không thì vùng cột chỉ còn ~70px. */
.dash-export .xuat-giua > .dash-chart { flex: 1 1 0; position: relative; }
.dash-export .xuat-giua > .dash-c-days { flex-grow: .9; }
.dash-export .xuat-giua > .dash-c-bars { flex-grow: 1.25; }
.dash-export .xuat-giua > .dash-c-line { flex-grow: .85; }
/* Chú giải đứng CÙNG HÀNG với tiêu đề (tiêu đề trái, chú giải phải): mỗi biểu đồ được
   thêm ~28px chiều cao - cột giữa chồng ba biểu đồ nên từng px đều quý. */
.dash-export .xuat-giua > .dash-chart .dash-legend-top {
  position: absolute; top: 11px; right: 13px; margin: 0;
}
/* Ảnh cao tối thiểu ~1.140px trên khổ 1.920 (tỉ lệ ~1,68): đủ chỗ cho ba biểu đồ cột giữa,
   vẫn gần khổ màn hình laptop 16:9 / 16:10. Thấp hơn thì biểu đồ dẹt lép. */
.dash-export .dash-grid { min-height: 960px; }
.dash-export .xuat-trai > .dash-summary,
.dash-export .xuat-phai > .dash-avail { flex: 1 1 auto; border-bottom: 0; }
.dash-export .xuat-giua > .dash-c-line { border-bottom: 0; }
/* Dải năm chỉ tiêu trong ngày: hết là con trực tiếp của lưới nên phải tự chia năm ô. */
.dash-export .xuat-giua > .dash-kpis-day {
  grid-template-columns: repeat(5, minmax(0, 1fr));
  border-top: 1px solid var(--line); border-bottom: 2px solid var(--dash-rule);
}
/* Nhãn không xuống dòng ("Average Wind Speed" từng chiếm hai dòng, dải cao thêm 28px). */
.dash-export .xuat-giua > .dash-kpis-day .dash-kpi-label { white-space: nowrap; font-size: 13.5px; }
.dash-export .dash-kpi-grp { border-right: 0; border-bottom: 0; border-top: 0;
                             grid-column: auto; }
.dash-export .dash-kpi-grp:nth-child(2) { border-right: 2px solid var(--dash-rule); }
/* Insight là phần CHỮ lãnh đạo đọc kỹ nhất, mà cột trái thường còn trống dưới nó (chiều
   cao ảnh do cột phải quyết định) - dùng chỗ đó cho chữ to hơn web. */
.dash-export .dash-insight { font-size: 16px; }
.dash-export .dash-comment-man { font-size: 15px; }
/* Vành khuyên to ra cho cân với cột: trên web chặn 200px. */
.dash-export .dash-ring { max-width: 225px; }
/* Bảng dài không được cuộn trong ảnh - ảnh không cuộn được, phần khuất là mất hẳn. */
.dash-export .rp-grid-wrap { max-height: none; overflow: visible; }
/* Chiều cao ảnh do cột phải (Energy loss 13 dòng + Availability) quyết định - bớt đệm
   dòng bảng để ảnh về gần 16:9. */
.dash-export .dash-card .rp-table { line-height: 1.4; }
.dash-export .dash-card .rp-table th,
.dash-export .dash-card .rp-table td { padding-top: 3px; padding-bottom: 3px; }
/* Chữ TRONG biểu đồ to hơn trên web: trên laptop ảnh hiện ở ~70% nên mốc trục 11,5px
   còn 8px. Đặt sau các quy tắc `.dash-svg.is-tight` (cùng độ ưu tiên + một lớp) nên
   thắng cả khi biểu đồ đang ở chế độ chật. */
.dash-export .dash-svg .dash-tick { font-size: 13.5px; }
.dash-export .dash-svg .dash-axis { font-size: 14px; }
.dash-export .dash-svg .dash-val  { font-size: 12.5px; }
.dash-export .dash-svg .dash-ratio { font-size: 11.5px; }
.dash-export .dash-legend { font-size: 14px; }
/* ======================= Quản lý công việc ======================= */
/* Màu ngữ nghĩa (trạng thái, quá hạn) tách riêng khỏi màu nhấn xanh của trang: xanh
   là nhận diện, còn đỏ/hổ phách phải luôn có nghĩa "cần để mắt". Dùng lại đúng
   #b3261e mà trang đang dùng cho lỗi, không thêm sắc đỏ thứ hai. */
#jobCard {
  --job-late:  #b3261e; --job-late-bg:#fdecea;
  --job-doing: #b45309; --job-doing-bg:#fff8e1;
  --job-todo:  #6b7d74; --job-todo-bg:#eef2f0;
  --job-done:  #15803d; --job-done-bg:#f0fdf4;
}

.job-range { font-weight: 600; color: var(--ink-soft); white-space: nowrap;
  font-variant-numeric: tabular-nums; }
.job-views { display: inline-flex; gap: 4px; margin-left: 6px; }
.job-tab { font: inherit; font-size: 13px; cursor: pointer; border-radius: 99px;
  border: 1px solid var(--line); background: transparent; color: var(--ink-soft);
  padding: 4px 12px; }
.job-tab:hover { border-color: var(--green-600); }
.job-tab.is-on { background: var(--green-900); border-color: var(--green-900);
  color: #fff; font-weight: 600; }

/* -------- dải tóm tắt -------- */
.job-stats { display: grid; gap: 8px; margin: 10px 0 12px;
  grid-template-columns: repeat(5, minmax(0, 1fr)); }
.job-stat { background: #fff; border: 1px solid var(--line); border-radius: 10px;
  padding: 8px 11px; display: flex; flex-direction: column; gap: 1px; }
.job-stat .k { font-size: 10.5px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-soft); }
.job-stat .v { font-size: 22px; font-weight: 700; line-height: 1.15;
  font-variant-numeric: tabular-nums; }
.job-stat.is-late { background: var(--job-late-bg); border-color: var(--job-late); }
.job-stat.is-late .k, .job-stat.is-late .v { color: var(--job-late); }
.job-rail { grid-column: 1 / -1; display: flex; align-items: center; gap: 12px;
  background: #fff; border: 1px solid var(--line); border-radius: 10px;
  padding: 9px 13px; }
.job-rail .k { font-size: 10.5px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-soft); white-space: nowrap; }
.job-rail .pct { font-weight: 700; color: var(--green-700); min-width: 54px;
  text-align: right; font-variant-numeric: tabular-nums; }

.job-bar { flex: 1; display: block; height: 7px; border-radius: 99px;
  background: #e6ede9; overflow: hidden; min-width: 40px; }
.job-bar > i { display: block; height: 100%; background: var(--green-600); }

/* -------- khung nhìn theo người -------- */
.job-scroll { overflow-x: auto; padding-bottom: 6px; }
.job-cols { display: flex; gap: 10px; min-width: max-content; align-items: flex-start; }
.job-col { width: 244px; flex: 0 0 244px; background: #fff;
  border: 1px solid var(--line); border-radius: 12px; overflow: hidden; }
.job-col > header { background: var(--green-900); color: #eaf6ee; padding: 9px 11px;
  display: flex; flex-direction: column; gap: 5px; }
.job-col .role { font-size: 10px; font-weight: 700; letter-spacing: .1em; opacity: .8; }
.job-col .who { font-weight: 700; font-size: 13.5px; line-height: 1.25; }
.job-col .mini { display: flex; flex-wrap: wrap; gap: 8px; font-size: 11.5px;
  opacity: .92; font-variant-numeric: tabular-nums; }
.job-col .mini .tre { color: #ffc9c4; font-weight: 700; }
.job-col .job-bar { background: rgba(255,255,255,.25); height: 5px; }
.job-cards { padding: 9px; display: flex; flex-direction: column; gap: 8px; }
.job-empty { margin: 4px 2px; font-size: 12.5px; font-style: italic;
  color: var(--ink-soft); }

/* Vạch màu bên trái = ƯU TIÊN, viên thuốc = TRẠNG THÁI. Hai kênh riêng, đọc được
   cùng lúc mà không phải tra chú giải. */
.job-card { border: 1px solid var(--line); border-left: 4px solid var(--job-todo);
  border-radius: 9px; background: #f7faf8; padding: 8px 9px;
  display: flex; flex-direction: column; gap: 6px; }
.job-card.p-cao  { border-left-color: var(--job-late); }
.job-card.p-tb   { border-left-color: var(--job-doing); }
.job-card.p-thap { border-left-color: var(--job-todo); }
.job-card.is-late { background: var(--job-late-bg); }
.job-card .t { font-weight: 600; font-size: 13px; line-height: 1.35; }
.job-card .meta { display: flex; flex-wrap: wrap; gap: 4px 8px; font-size: 11.5px;
  color: var(--ink-soft); font-variant-numeric: tabular-nums; align-items: center; }
.job-card .prog { display: flex; align-items: center; gap: 7px; }
.job-card .prog .n { font-size: 11.5px; font-weight: 700; min-width: 36px;
  text-align: right; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.job-card .note { font-size: 11.5px; color: var(--ink-soft); }
.job-act { display: flex; justify-content: flex-end; }

.job-pill { display: inline-flex; align-items: center; gap: 5px; border-radius: 99px;
  padding: 1px 8px; font-size: 11px; font-weight: 700; }
.job-pill::before { content: ""; width: 6px; height: 6px; border-radius: 99px;
  background: currentColor; }
.job-pill.s-chua { background: var(--job-todo-bg);  color: var(--job-todo); }
.job-pill.s-dang { background: var(--job-doing-bg); color: var(--job-doing); }
.job-pill.s-xong { background: var(--job-done-bg);  color: var(--job-done); }
.job-late { background: var(--job-late-bg); color: var(--job-late); border-radius: 99px;
  padding: 1px 8px; font-size: 11px; font-weight: 700; }

/* -------- khung nhìn theo tuần -------- */
table.job-week { border-collapse: collapse; min-width: 900px; width: 100%;
  background: #fff; }
table.job-week th, table.job-week td { border: 1px solid var(--line);
  padding: 7px 8px; vertical-align: top; text-align: left; }
table.job-week thead th { background: var(--green-900); color: #eaf6ee;
  font-size: 11.5px; letter-spacing: .05em; text-transform: uppercase; }
table.job-week thead th.is-today { background: var(--green-700); }
table.job-week thead th .d { display: block; font-size: 11px; opacity: .85;
  font-weight: 600; letter-spacing: 0; text-transform: none;
  font-variant-numeric: tabular-nums; }
table.job-week tbody th { background: #f4f8f5; font-weight: 600; font-size: 12.5px;
  width: 178px; white-space: nowrap; }
table.job-week tbody th small { display: block; font-weight: 700; font-size: 9.5px;
  letter-spacing: .1em; color: var(--ink-soft); }
table.job-week td.is-today { background: var(--green-50); }

.job-chip { display: block; border-left: 3px solid var(--job-todo);
  border-radius: 6px; background: #f7faf8; padding: 3px 6px; margin-bottom: 4px;
  font-size: 11.5px; line-height: 1.3; }
.job-chip:last-child { margin-bottom: 0; }
.job-chip.p-cao  { border-left-color: var(--job-late); }
.job-chip.p-tb   { border-left-color: var(--job-doing); }
.job-chip.p-thap { border-left-color: var(--job-todo); }
.job-chip.is-click { cursor: pointer; }
.job-chip.is-click:hover { background: var(--green-50); }
.job-chip.is-click:focus-visible { outline: 2px solid var(--green-600);
  outline-offset: 1px; }
.job-chip b { font-weight: 600; }
.job-chip .st { display: block; font-size: 10px; font-weight: 700;
  font-variant-numeric: tabular-nums; }
.job-chip .st.s-chua { color: var(--job-todo); }
.job-chip .st.s-dang { color: var(--job-doing); }
.job-chip .st.s-xong { color: var(--job-done); }
.job-chip .st.s-late { color: var(--job-late); }

/* Ô ca trực lấy từ lịch trực ngay bên dưới - cùng ký hiệu, cùng ý nghĩa. */
.job-duty { display: inline-block; min-width: 18px; text-align: center;
  border-radius: 5px; font-size: 10px; font-weight: 700; padding: 1px 5px;
  margin: 0 4px 4px 0; background: var(--green-900); color: #eaf6ee; }
.job-duty.d-P { background: var(--job-todo-bg);  color: var(--job-todo); }
.job-duty.d-Q { background: var(--job-doing-bg); color: var(--job-doing); }
.job-duty.d-T { background: var(--job-done-bg);  color: var(--job-done); }

/* -------- chú giải -------- */
.job-legend { display: flex; flex-wrap: wrap; gap: 8px 22px; margin-top: 10px;
  font-size: 12px; color: var(--ink-soft); }
.job-leg-group { display: inline-flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.job-leg-group > b { font-size: 10.5px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; }
.job-leg { display: inline-flex; align-items: center; gap: 5px; }
.job-sw { width: 12px; height: 12px; border-radius: 3px; display: inline-block; }
.job-sw.p-cao  { background: var(--job-late); }
.job-sw.p-tb   { background: var(--job-doing); }
.job-sw.p-thap { background: var(--job-todo); }

/* -------- hộp giao việc -------- */
.job-modal { position: fixed; inset: 0; z-index: 60; display: flex;
  align-items: center; justify-content: center; padding: 20px;
  background: rgba(12, 30, 20, .42); }
.job-form { background: #fff; border-radius: 14px; box-shadow: var(--shadow);
  padding: 18px 20px; width: min(560px, 100%); max-height: 90vh; overflow-y: auto;
  display: grid; gap: 11px 14px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.job-form h3 { grid-column: 1 / -1; margin: 0 0 2px; font-size: 16px;
  color: var(--green-900); }
.job-form .f { display: flex; flex-direction: column; gap: 4px; }
.job-form .f.wide { grid-column: 1 / -1; }
.job-form label { font-size: 10.5px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-soft); }
.job-form input, .job-form select, .job-form textarea {
  font: inherit; color: var(--ink); background: #f7faf8; border: 1px solid var(--line);
  border-radius: 9px; padding: 7px 9px; width: 100%; }
.job-form textarea { resize: vertical; min-height: 50px; }
.job-form input:disabled, .job-form select:disabled, .job-form textarea:disabled {
  background: #eef2f0; color: var(--ink-soft); cursor: not-allowed; }
.job-form input:focus-visible, .job-form select:focus-visible,
.job-form textarea:focus-visible { outline: 2px solid var(--green-600);
  outline-offset: 1px; border-color: var(--green-600); }
.job-warn { grid-column: 1 / -1; margin: 0; font-size: 12.5px;
  color: var(--job-doing); }
.job-warn:empty { display: none; }
.job-form-act { grid-column: 1 / -1; display: flex; gap: 8px; align-items: center;
  flex-wrap: wrap; }
.job-err { font-size: 12.5px; color: var(--job-late); }
.ghost-btn.danger { color: var(--job-late); border-color: rgba(179, 38, 30, .35); }
.ghost-btn.danger:hover { background: var(--job-late-bg); }
.ghost-btn.xs, .gate-btn.xs { font-size: 12px; padding: 3px 9px; }

@media (max-width: 860px) {
  .job-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .job-form { grid-template-columns: 1fr; }
}

/* ---- cột "Hằng ngày" cuối bảng tuần ----
   Việc chạy suốt thứ 2 → thứ 6 dồn về đây thay vì lặp ở cả năm cột. Tách bằng một
   vạch đậm và nền hơi khác: nó là loại việc KHÁC (thường xuyên), không phải một
   ngày thứ sáu nữa - để cùng màu cùng viền là mắt đọc thành "cột thứ 7". */
table.job-week { min-width: 1180px; }
table.job-week thead th.is-daily,
table.job-week td.is-daily { border-left: 3px solid var(--green-700); }
table.job-week thead th.is-daily { background: var(--green-700); }
table.job-week td.is-daily { background: #f4f8f5; width: 240px; }
table.job-week td.is-daily:empty::after { content: "—"; color: var(--ink-soft);
  font-size: 12px; }

/* ---- ô tích "việc hằng ngày" trong form ---- */
.job-daily-tick { flex-direction: row !important; align-items: center; gap: 8px;
  background: #f4f8f5; border: 1px solid var(--line); border-radius: 9px;
  padding: 8px 10px; }
.job-daily-tick input { width: auto; margin: 0; accent-color: var(--green-700); }
.job-daily-tick label { text-transform: none !important; letter-spacing: 0 !important;
  font-size: 13px !important; font-weight: 500 !important; color: var(--ink) !important;
  cursor: pointer; }

/* ---- trạng thái thứ tư: "Đã rời lịch" ----
   Màu xanh xám, cố ý KHÁC hẳn ba màu kia: xanh lá = xong, hổ phách = đang làm,
   đỏ = quá hạn, xám = chưa bắt đầu. "Đã rời lịch" không tốt cũng không xấu, nó chỉ
   là "tạm gác" - nên cần một sắc riêng, không mượn lại sắc nào đang mang nghĩa khác. */
#jobCard { --job-roi: #45688f; --job-roi-bg: #eef3f9; }

.job-stats { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.job-stat.is-roi { background: var(--job-roi-bg);
  border-color: rgba(69, 104, 143, .35); }
.job-stat.is-roi .k, .job-stat.is-roi .v { color: var(--job-roi); }

.job-pill.s-roi { background: var(--job-roi-bg); color: var(--job-roi); }
.job-chip .st.s-roi { color: var(--job-roi); }
.job-card .job-pill.s-roi ~ .job-late { display: none; }

/* Ô tiến độ bị vô hiệu khi chọn "Đã rời lịch" - làm mờ cả nhãn để thấy rõ là cả cụm
   không dùng tới, chứ không phải ô nhập bị hỏng. */
.job-form .f.is-off { opacity: .5; }
.job-form .f.is-off label { text-decoration: line-through; }

@media (max-width: 860px) {
  .job-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Chip trong khung tuần bấm được -> phải TRÔNG như bấm được. Khung tuần nay là khung
   mặc định, nên đây là chỗ người ta cập nhật tiến độ nhiều nhất; không có dấu hiệu gì
   thì họ tưởng phải sang khung "theo người" mới sửa được. */
.job-chip.is-click:hover { background: var(--green-50);
  box-shadow: 0 0 0 1px var(--green-600) inset; }
.job-chip.is-click:hover .st { text-decoration: underline; }
/* ---- dòng Deadline ----
   Tách rời khỏi dòng trạng thái vì là thông tin KHÁC LOẠI: trạng thái nói "đang tới
   đâu", deadline nói "phải xong khi nào". Việc không có hạn thì dòng này rỗng và tự
   biến mất - 79/128 việc trong lịch tuần là việc thường xuyên, ghi "không có hạn"
   lên từng cái chỉ thêm nhiễu. */
.job-dl:empty { display: none; }
.job-dl { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 6px;
  font-size: 11px; font-variant-numeric: tabular-nums; color: var(--ink-soft);
  border-top: 1px dashed var(--line); padding-top: 4px; margin-top: 1px; }
.job-dl .k { font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  font-size: 9.5px; color: var(--ink-soft); }
.job-dl .v { font-weight: 600; }
.job-dl.is-late { color: var(--job-late); border-top-color: rgba(179, 38, 30, .3); }
.job-dl.is-late .k, .job-dl.is-late .v { color: var(--job-late); }
.job-dl .tre { font-weight: 700; color: var(--job-late); }

.job-chip .job-dl { font-size: 10px; padding-top: 3px; }
.job-chip .job-dl .k { font-size: 9px; }

/* Chú thích dưới ô Deadline trong form. */
.job-hint { font-size: 11.5px; color: var(--ink-soft); line-height: 1.35;
  margin-top: 2px; }
/* Ô "Hoàn thành" tô xanh lá, cùng cách với "Đã rời lịch" (xanh xám) và "Quá hạn"
   (đỏ): ba ô mang NGHĨA thì có màu, còn "Tổng việc" / "Chưa bắt đầu" / "Đang làm"
   để trung tính. Dùng lại đúng --job-done của viên thuốc trạng thái, không đặt sắc
   xanh thứ hai. */
.job-stat.is-xong { background: var(--job-done-bg);
  border-color: rgba(21, 128, 61, .35); }
.job-stat.is-xong .k, .job-stat.is-xong .v { color: var(--job-done); }
/* ---------------- hộp thư (inbox.js) ----------------
   Khung thư đặt ABSOLUTE bên trong .topbar chứ không fixed: .topbar có backdrop-filter,
   mà backdrop-filter biến phần tử đó thành "khối chứa" của mọi con fixed - fixed ở
   đây cũng chỉ là absolute đội lốt. z-index cho thanh trên cùng để khung thư đè lên
   các cột sticky của bảng báo cáo (z-index 1-2), nhưng vẫn nằm dưới hộp thoại (60). */
.topbar { position: relative; z-index: 40; }

.inbox-btn {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: 10px; border: 1px solid var(--line);
  background: #fff; color: var(--green-700); cursor: pointer;
}
.inbox-btn:hover { background: var(--green-50); }
.inbox-badge {
  position: absolute; top: -6px; right: -6px; min-width: 18px; height: 18px;
  padding: 0 5px; border-radius: 9px; background: #dc2626; color: #fff;
  font-size: 11px; font-weight: 700; line-height: 18px; text-align: center;
}

.inbox-panel {
  position: absolute; top: calc(100% + 6px); right: 18px;
  width: min(560px, calc(100vw - 32px)); max-height: min(72vh, 720px);
  display: flex; flex-direction: column;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: 0 16px 48px rgba(20, 83, 45, .22);
}
.inbox-panel[hidden] { display: none; }
.inbox-top {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 12px 14px; border-bottom: 1px solid var(--line); color: var(--green-900);
}
.inbox-top-actions { display: flex; align-items: center; gap: 8px; }
.inbox-close {
  border: 0; background: transparent; font-size: 22px; line-height: 1; cursor: pointer;
  color: var(--ink-soft); padding: 0 4px;
}
.inbox-list { overflow-y: auto; padding: 6px; }
.inbox-empty { padding: 28px 12px; text-align: center; color: var(--ink-soft); font-size: 13px; }

.inbox-item {
  border: 1px solid var(--line); border-left-width: 4px; border-radius: 10px;
  margin: 6px 4px; background: #fff;
}
.inbox-item.muc-ok        { border-left-color: #16a34a; }
.inbox-item.muc-canh_bao  { border-left-color: #d97706; }
.inbox-item.muc-loi       { border-left-color: #dc2626; }
.inbox-item.muc-cho_duyet { border-left-color: #2563eb; }
.inbox-item.muc-info      { border-left-color: #94a3b8; }
.inbox-item.chua-doc { background: #f8fbf9; }
.inbox-item.chua-doc .inbox-title { font-weight: 650; }

.inbox-head {
  width: 100%; display: grid; grid-template-columns: auto 1fr auto; gap: 8px;
  align-items: center; padding: 10px 12px; border: 0; background: transparent;
  cursor: pointer; text-align: left; font: inherit; color: var(--ink);
}
.inbox-title { font-size: 13.5px; overflow-wrap: anywhere; }
.inbox-time { font-size: 11.5px; color: var(--ink-soft); white-space: nowrap; }
.inbox-tag {
  font-size: 11px; font-weight: 650; padding: 2px 7px; border-radius: 999px;
  white-space: nowrap;
}
.tag-ok        { background: #dcfce7; color: #166534; }
.tag-canh_bao  { background: #fef3c7; color: #92400e; }
.tag-loi       { background: #fee2e2; color: #991b1b; }
.tag-cho_duyet { background: #dbeafe; color: #1e40af; }
.tag-info      { background: #f1f5f9; color: #334155; }

.inbox-body { padding: 0 12px 12px; font-size: 13px; color: var(--ink); }
.inbox-text .md-para { margin: 6px 0; white-space: pre-wrap; }
.inbox-text code {
  background: var(--green-50); padding: 1px 5px; border-radius: 5px; font-size: 12px;
}
.inbox-status {
  margin-top: 10px; padding: 7px 10px; border-radius: 8px; font-size: 12.5px;
  background: #f1f5f9; color: #334155;
}
.inbox-status.st-cho_duyet { background: #dbeafe; color: #1e40af; }
.inbox-status.st-da_duyet  { background: #dcfce7; color: #166534; }
.inbox-status.st-tu_choi,
.inbox-status.st-loi       { background: #fee2e2; color: #991b1b; }

.inbox-actions { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.inbox-reason {
  width: 100%; box-sizing: border-box; padding: 7px 10px; font: inherit; font-size: 13px;
  border: 1px solid var(--line); border-radius: 8px;
}
.inbox-buttons { display: flex; gap: 8px; flex-wrap: wrap; }
.inbox-ok, .inbox-no {
  padding: 8px 14px; border-radius: 8px; font: inherit; font-size: 13px;
  font-weight: 600; cursor: pointer;
}
.inbox-ok { background: var(--green-700); color: #fff; border: 1px solid var(--green-700); }
.inbox-ok:hover { background: var(--green-900); }
.inbox-no { background: #fff; color: #991b1b; border: 1px solid #fca5a5; }
.inbox-no:hover { background: #fef2f2; }
.inbox-ok:disabled, .inbox-no:disabled { opacity: .55; cursor: default; }
.inbox-result { padding: 8px 10px; border-radius: 8px; font-size: 12.5px; }
.inbox-result.dang-chay  { background: #f1f5f9; color: #334155; }
.inbox-result.thanh-cong { background: #dcfce7; color: #166534; }
.inbox-result.that-bai   { background: #fee2e2; color: #991b1b; }

@media (max-width: 640px) {
  .inbox-panel { right: 8px; }
  .inbox-head { grid-template-columns: 1fr auto; }
  .inbox-tag { grid-column: 1 / -1; justify-self: start; }
}

/* Nút xoá từng thư: đứng cạnh nút mở thư, mờ cho tới khi rê chuột vào - không để mỗi
   dòng một dấu × đậm nét làm rối cả danh sách. Trên điện thoại không có "rê chuột" nên
   luôn hiện rõ. */
.inbox-row { display: flex; align-items: stretch; }
.inbox-row .inbox-head { flex: 1; min-width: 0; }
.inbox-del {
  flex: none; width: 34px; border: 0; background: transparent; cursor: pointer;
  font-size: 18px; line-height: 1; color: var(--ink-soft); opacity: .35;
  border-radius: 0 10px 10px 0;
}
.inbox-item:hover .inbox-del { opacity: .8; }
.inbox-del:hover { opacity: 1; color: #b91c1c; background: #fef2f2; }
.inbox-del-read { color: #b91c1c; }
.inbox-item.dang-xoa { opacity: .4; pointer-events: none; }
@media (hover: none) { .inbox-del { opacity: .8; } }

/* ---------------- tài khoản: đổi / đặt lại mật khẩu (account.js) ---------------- */
/* Dùng lại khung .gate/.gate-card của trang đăng nhập, thêm nền mờ phía sau. */
.acc-modal { z-index: 80; background: rgba(15, 40, 25, .35); }
.acc-modal .gate-card { position: relative; }
.acc-modal .acc-wide { max-width: 860px; }
.acc-x { position: absolute; top: 10px; right: 12px; }
.acc-ok {
  background: var(--green-50); border: 1px solid var(--line); color: var(--green-900);
  border-radius: 9px; padding: 9px 12px; font-size: 13.5px; margin-bottom: 12px;
}
.acc-table-wrap { max-height: 60vh; overflow: auto; }
.acc-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.acc-table th, .acc-table td {
  border-bottom: 1px solid var(--line); padding: 7px 8px; text-align: left;
  white-space: nowrap;
}
.acc-table th { color: var(--ink-soft); font-weight: 600; }
.acc-tag { font-size: 12px; color: var(--ink-soft); }
.acc-tag.tmp { color: #b45309; font-weight: 600; }
.acc-tag.off { color: #b91c1c; }
@media (max-width: 640px) {
  .acc-table th:nth-child(3), .acc-table td:nth-child(3) { display: none; }
}

/* ================= Thành phần dùng chung (ui.js, 06/10/2026) =================
   Hộp xác nhận và thông báo nhanh thay cho confirm()/alert() của trình duyệt. Nổi trên
   mọi lớp khác, kể cả form công việc/lịch họp (z-index 80) và khung thư (40). */
.ui-modal {
  position: fixed; inset: 0; z-index: 120; display: flex; align-items: center;
  justify-content: center; padding: 16px; background: rgba(12, 30, 20, .45);
  animation: ui-hien .14s ease-out;
}
.ui-modal.is-dong { opacity: 0; transition: opacity .12s; }
.ui-hop {
  width: min(440px, 100%); background: #fff; border-radius: 14px;
  box-shadow: 0 18px 50px rgba(12, 30, 20, .28); padding: 20px 22px 16px;
  border-top: 4px solid var(--green-700); animation: ui-noi .16s ease-out;
}
.ui-hop.is-nguy { border-top-color: #c62828; }
.ui-hop h3 { margin: 0 0 8px; font-size: 16px; color: var(--green-900); }
.ui-hop.is-nguy h3 { color: #a01d1d; }
.ui-hop-nd { font-size: 13.5px; color: var(--ink); }
.ui-hop-nd p { margin: 0 0 8px; white-space: pre-line; }
.ui-hop-nd ul { margin: 0 0 8px; padding-left: 18px; }
.ui-hop-nd li { margin: 2px 0; font-variant-numeric: tabular-nums; }
.ui-hop-nd .ui-hop-gc { color: var(--ink-soft); font-size: 12.5px; }
.ui-hop-nut { display: flex; justify-content: flex-end; gap: 10px; margin-top: 14px; }
.ui-nut {
  font: inherit; font-size: 13.5px; font-weight: 600; border-radius: 9px;
  padding: 8px 16px; cursor: pointer; border: 1px solid transparent;
}
.ui-nut-chinh { background: var(--green-700); color: #fff; }
.ui-nut-chinh:hover { background: var(--green-900); }
.ui-nut-nguy { background: #c62828; color: #fff; }
.ui-nut-nguy:hover { background: #a01d1d; }
.ui-nut-phu { background: #fff; color: var(--ink); border-color: var(--line); }
.ui-nut-phu:hover { border-color: var(--green-600); }
.ui-nut:focus-visible { outline: 3px solid rgba(22, 163, 74, .45); outline-offset: 2px; }

.ui-bao-khung {
  position: fixed; right: 18px; bottom: 18px; z-index: 130; display: flex;
  flex-direction: column; gap: 8px; align-items: flex-end; pointer-events: none;
  max-width: min(420px, calc(100vw - 32px));
}
.ui-bao {
  pointer-events: auto; display: flex; align-items: flex-start; gap: 10px;
  background: #fff; color: var(--ink); border-radius: 11px; padding: 10px 10px 10px 12px;
  box-shadow: 0 10px 30px rgba(12, 30, 20, .22); border-left: 4px solid var(--green-600);
  font-size: 13.5px; line-height: 1.45; animation: ui-truot .18s ease-out;
}
.ui-bao.is-loi { border-left-color: #c62828; }
.ui-bao.is-tin { border-left-color: #2563eb; }
.ui-bao.is-tat { opacity: 0; transform: translateY(6px); transition: all .2s; }
.ui-bao-icon {
  flex: none; width: 20px; height: 20px; border-radius: 50%; display: inline-flex;
  align-items: center; justify-content: center; font-size: 12px; font-weight: 700;
  color: #fff; background: var(--green-600); margin-top: 1px;
}
.ui-bao.is-loi .ui-bao-icon { background: #c62828; }
.ui-bao.is-tin .ui-bao-icon { background: #2563eb; }
.ui-bao-chu { flex: 1; white-space: pre-line; }
.ui-bao-x {
  flex: none; border: 0; background: none; cursor: pointer; color: var(--ink-soft);
  font-size: 18px; line-height: 1; padding: 0 2px;
}
@keyframes ui-hien { from { opacity: 0; } to { opacity: 1; } }
@keyframes ui-noi { from { transform: translateY(8px) scale(.98); opacity: 0; }
                    to { transform: none; opacity: 1; } }
@keyframes ui-truot { from { transform: translateY(10px); opacity: 0; }
                      to { transform: none; opacity: 1; } }
@media (max-width: 640px) {
  .ui-bao-khung { left: 16px; right: 16px; bottom: 16px; align-items: stretch; }
  .ui-hop-nut { flex-direction: column-reverse; }
  .ui-nut { width: 100%; padding: 10px 16px; }
}
@media (prefers-reduced-motion: reduce) {
  .ui-modal, .ui-hop, .ui-bao { animation: none; }
}

/* ---- Tab Data: trạng thái ô khi sửa (06/10/2026) ---- */
.wb-in.is-doi { border-color: #f0a400; box-shadow: 0 0 0 2px rgba(240, 164, 0, .18); }
.wb-in.is-sai { border-color: #c62828; box-shadow: 0 0 0 2px rgba(198, 40, 40, .15); }
/* Dòng vừa lưu sáng lên rồi nhạt dần - người sửa thấy ngay kết quả nằm ở đâu. */
tr.dm-vua-luu > td, tr.dm-vua-luu > th { animation: dm-sang 2.4s ease-out; }
@keyframes dm-sang { 0%, 30% { background: #fff3c4; } 100% { background: transparent; } }
.dm-phim { margin-left: auto; font-size: 11.5px; color: var(--ink-soft); }
.dm-rong { text-align: center !important; color: var(--ink-soft); padding: 18px 8px !important;
           white-space: normal !important; }
.wb-btn:disabled { background: #9db8a5; cursor: progress; }
/* Bảng công tơ nằm trong cột hẹp: cho chữ xuống dòng thay vì cắt cụt nhãn. */
.dm-cong-to .wb-grid { white-space: normal; }
.dm-cong-to .wb-grid th, .dm-cong-to .wb-grid td { text-align: left; vertical-align: top; }
.dm-cong-to .wb-grid td:first-child { white-space: nowrap; font-weight: 600; }
#dmKh tfoot td { font-variant-numeric: tabular-nums; }
@media (prefers-reduced-motion: reduce) { tr.dm-vua-luu > td { animation: none; } }

/* ---- Tab Tổng hợp sự cố: cột CHỮ căn trái (06/10/2026) ----
   Quy tắc chung `.wb-grid td` căn phải là cho cột số. Bảng này 8 cột đầu và cột cuối
   là chữ - "Nguyên nhân" căn phải thì câu dài dạt sang mép phải, đọc rất mệt. Nguyên
   nhân cho xuống dòng trong khung rộng vừa phải để bảng bớt phải cuộn ngang. */
#incTable .wb-grid th:nth-child(-n+8), #incTable .wb-grid td:nth-child(-n+8),
#incTable .wb-grid th:last-child, #incTable .wb-grid td:last-child { text-align: left; }
#incTable .wb-grid td:nth-child(8) { white-space: normal; min-width: 260px; max-width: 420px; }

/* ---- Thanh công cụ trong thẻ (Schedule...): cho xuống hàng trên màn hình hẹp ----
   Trước đây không xuống hàng: điện thoại 390px cắt mất nút "Lịch họp" và nhãn tuần ở
   mép trái, còn "+ Giao việc" bị bẻ ba dòng. */
.card-tools { flex-wrap: wrap; justify-content: flex-end; }
.card-tools > * { white-space: nowrap; }

/* ---- Thanh điều hướng trên điện thoại (06/10/2026) ----
   Năm mục điều hướng bị bẻ chữ hai dòng ("Hỏi / đáp", "Live / Dashboard") và phần đầu
   trang chiếm ~220px trên màn hình 844px. Nay: một hàng cuộn ngang, chữ không bẻ; dòng
   thông tin đồng bộ tài liệu (kỹ thuật) ẩn trên điện thoại. */
.tab { white-space: nowrap; }
@media (max-width: 760px) {
  .topbar { gap: 6px 10px; padding: 8px 12px; }
  .brand-sub-row { display: none; }
  .brand .logo { width: 34px; height: 34px; }
  .tabs { order: 3; flex: 1 0 100%; overflow-x: auto; flex-wrap: nowrap;
          scrollbar-width: none; -webkit-overflow-scrolling: touch; margin: 0 -4px; }
  .tabs::-webkit-scrollbar { display: none; }
  .tab { padding: 7px 13px; font-size: 13.5px; }
  .account { gap: 8px; }
}

/* Live Dashboard: nhắc khi số liệu mới nhất đã cũ (power.js). */
.pw-stale { margin: 0 0 10px; padding: 7px 12px; border-radius: 8px; font-size: 13px;
            background: #fff8e1; border-left: 3px solid #f0b400; color: #6b4a00; }

/* Danh bạ: số gọi được (tel:) và ô tìm nhanh (roc.js, 06/10/2026). */
a.roc-tel { color: var(--green-700); text-decoration: none; white-space: nowrap; }
a.roc-tel:hover { text-decoration: underline; }
.roc-tim { width: min(360px, 100%); margin: 0 0 10px; padding: 7px 11px; font: inherit;
           font-size: 13.5px; border: 1px solid var(--line); border-radius: 9px;
           background: #fff; color: var(--ink); }
.roc-tim:focus { outline: 2px solid var(--green-600); outline-offset: -1px; }
.job-tuan { display: inline-flex; align-items: center; gap: 8px; }
/* Tên nhà máy cạnh nút "Daily Report" - chỉ cần khi cây thu gọn trên màn hình hẹp. */
.rp-chon { display: none; font-weight: 500; color: var(--ink); white-space: nowrap;
           overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 820px) { .rp-chon { display: inline; } }
.dm-cong-to .wb-grid thead th { white-space: nowrap; }
/* Dải tab của báo cáo trên điện thoại: một hàng vuốt ngang thay vì bốn hàng chồng nhau
   (10 tab ở bề ngang 390px chiếm gần nửa màn hình đầu). */
@media (max-width: 760px) {
  .wb-tabs { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
             -webkit-overflow-scrolling: touch; padding-top: 2px; }
  .wb-tabs::-webkit-scrollbar { display: none; }
  .wb-tab { white-space: nowrap; flex: none; top: 0; }
}

/* ================= Menu tài khoản (account.js, 06/10/2026) =================
   Một nút ảnh đại diện thay cho hàng link "Đổi mật khẩu · Đăng xuất". Khung menu đặt
   absolute trong .topbar (thanh này có backdrop-filter nên fixed cũng chỉ là absolute). */
.acc-wrap { position: relative; }
.acc-nut {
  display: inline-flex; align-items: center; gap: 8px; max-width: 240px;
  padding: 3px 10px 3px 3px; border: 1px solid var(--line); border-radius: 999px;
  background: #fff; cursor: pointer; font: inherit; font-size: 13px; color: var(--ink);
}
.acc-nut:hover, .acc-nut[aria-expanded="true"] { border-color: var(--green-600);
                                                 background: var(--green-50); }
.acc-nut:focus-visible { outline: 3px solid rgba(22, 163, 74, .4); outline-offset: 2px; }
.acc-avatar {
  flex: none; width: 30px; height: 30px; border-radius: 50%; display: inline-flex;
  align-items: center; justify-content: center; background: var(--green-700);
  color: #fff; font-size: 12px; font-weight: 700; letter-spacing: .03em;
}
.acc-avatar.lon { width: 42px; height: 42px; font-size: 15px; }
.acc-ten { max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acc-caret { font-size: 10px; color: var(--ink-soft); }
.acc-menu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 45; min-width: 270px;
  background: #fff; border: 1px solid var(--line); border-radius: 12px; padding: 6px;
  box-shadow: 0 14px 40px rgba(12, 30, 20, .2); animation: ui-noi .14s ease-out;
}
.acc-menu-dau { display: flex; align-items: center; gap: 12px; padding: 10px 10px 12px;
                border-bottom: 1px solid var(--line); margin-bottom: 4px; }
.acc-menu-ai { display: flex; flex-direction: column; min-width: 0; line-height: 1.35; }
.acc-menu-ai b { font-size: 14px; color: var(--ink); overflow: hidden;
                 text-overflow: ellipsis; white-space: nowrap; }
.acc-menu-ai > span { font-size: 12px; color: var(--ink-soft); overflow: hidden;
                      text-overflow: ellipsis; }
.acc-menu-ai > .acc-menu-tag {
  align-self: flex-start; margin-top: 5px; font-size: 11px; font-weight: 600;
  color: var(--green-700); background: var(--green-50); border: 1px solid var(--line);
  border-radius: 999px; padding: 1px 8px;
}
.acc-muc {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px;
  border: 0; border-radius: 8px; background: none; cursor: pointer; text-align: left;
  font: inherit; font-size: 13.5px; color: var(--ink);
}
.acc-muc svg { flex: none; color: var(--ink-soft); }
.acc-muc:hover, .acc-muc:focus-visible { background: var(--green-50); outline: none; }
.acc-muc-ra, .acc-muc-ra svg { color: #b3261e; }
.acc-menu-ke { height: 1px; background: var(--line); margin: 4px 2px; }
@media (max-width: 760px) {
  .acc-ten, .acc-caret { display: none; }
  .acc-nut { padding: 2px; }
}

/* ================= Cây Daily Report + chọn nhà máy (06/10/2026) =================
   Cây chỉ còn BA LOẠI HÌNH, thụt vào dưới "Daily Report" như mục con (đường kẻ dọc dẫn
   mắt). Nhà máy chọn ở tên nhà máy trên tiêu đề - daily.js tieuDeNhaMay. */
.rp-kinds { display: flex; flex-direction: column; gap: 2px;
            margin: 2px 0 4px 17px; padding-left: 8px; border-left: 2px solid var(--line); }
a.rp-kind { text-decoration: none; }
.rp-kind.is-active { background: var(--green-700); color: #fff; }
.rp-kind.is-active .rp-count { background: rgba(255, 255, 255, .18); color: #fff;
                               border-color: transparent; }
.rp-sap { margin-left: auto; font-size: 11px; font-style: italic; color: var(--ink-soft); }

/* Lề âm đặt ở KHUNG BỌC chứ không ở nút: đặt ở nút thì bề ngang tự co của khung hụt
   đúng 9px và tên bị bẻ hai dòng ("Ia / Bang"). Lề âm để chữ thẳng hàng với dòng dưới. */
.rp-nm { position: relative; display: inline-block; max-width: 100%; margin-left: -9px; }
.rp-nm-nut {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  font: inherit; color: inherit; background: none; cursor: pointer;
  border: 1px solid transparent; border-radius: 8px; padding: 1px 8px;
  white-space: nowrap; text-align: left;
}
.rp-nm-nut:hover, .rp-nm-nut[aria-expanded="true"] { background: var(--green-50);
                                                    border-color: var(--line); }
.rp-nm-nut:focus-visible { outline: 3px solid rgba(22, 163, 74, .4); outline-offset: 1px; }
.rp-nm-caret { font-size: 11px; color: var(--green-700); }
.rp-nm-ds {
  position: absolute; left: 0; top: calc(100% + 4px); z-index: 30;
  width: max-content; min-width: 270px; max-width: min(340px, calc(100vw - 40px));
  max-height: min(420px, 70vh); overflow: auto; padding: 6px;
  background: #fff; border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 14px 40px rgba(12, 30, 20, .2); animation: ui-noi .14s ease-out;
}
.rp-nm-dau { padding: 6px 10px 5px; font-size: 11.5px; font-weight: 400;
             color: var(--ink-soft); }
.rp-nm-muc { display: flex; flex-direction: column; padding: 7px 10px; border-radius: 8px;
             text-decoration: none; color: var(--ink); }
.rp-nm-muc b { font-size: 14px; font-weight: 600; }
.rp-nm-muc small { font-size: 11.5px; font-weight: 400; color: var(--ink-soft); }
a.rp-nm-muc:hover, a.rp-nm-muc:focus-visible { background: var(--green-50); outline: none; }
.rp-nm-muc.is-on, a.rp-nm-muc.is-on:hover { background: var(--green-700); color: #fff; }
.rp-nm-muc.is-on small { color: rgba(255, 255, 255, .8); }
.rp-nm-muc.is-tat { opacity: .45; cursor: default; }

/* ================= Co giãn theo màn hình (07/10/2026, học theo nsmo.vn) =================
   User so với dashboard tổng hợp của NSMO: laptop, màn 24" hay TV 70" đều "vừa phải,
   không vỡ, không lớn quá, không nhỏ quá". Hai việc:
   1. Dashboard co giãn NGUYÊN KHỐI bằng `zoom` - daily.js coGianDashboard.
   2. Khổ laptop (821-1599px): cây Daily Report nằm NGANG thành một hàng trên báo cáo.
      Cột trái 236px + khe 18px ăn gần 1/5 bề ngang laptop 1366px, trong khi cây giờ chỉ
      còn ba loại hình - đủ gọn để nằm một hàng. Báo cáo được thêm ~250px. Phải khớp
      với RP_NGANG trong daily.js. */
@media (min-width: 821px) and (max-width: 1599px) {
  .rp-wrap { grid-template-columns: 1fr; gap: 12px; }
  .rp-nav { position: static; display: flex; align-items: center; flex-wrap: wrap;
            gap: 4px 10px; padding: 6px 8px; }
  .rp-report { width: auto; cursor: default; padding: 6px 4px 6px 8px; }
  .rp-report:hover { background: none; }
  .rp-report .rp-caret { display: none; }
  .rp-kinds { flex-direction: row; flex-wrap: wrap; gap: 4px; margin: 0; padding: 0 0 0 12px;
              border-left: 2px solid var(--line); }
  .rp-kind { width: auto; padding: 6px 14px; gap: 8px; }
}
/* Tầng TV / màn rất rộng: ui.js datZoomManHinh đặt `--zg` = bề ngang ÷ 1920 (tối thiểu
   1). Màn 1920px trở xuống không đổi gì. Khối nằm trong khung cuộn được phóng, chính
   khung cuộn thì không - khung cuộn phóng là chiều cao của nó bị nhân theo. */
.topbar, #view-reports > .panel, #view-dashboard > .panel,
.ui-hop, .ui-bao-khung { zoom: var(--zg, 1); }

/* Ô nhập số kiểu Việt Nam (ui.js, 07/10/2026): chữ số đều bề ngang. KHÔNG ép căn lề -
   tab Nhập liệu cố ý căn trái, tab Data căn phải; sai khuôn (chấm làm dấu thập phân) tô đỏ. */
input.o-so { font-variant-numeric: tabular-nums; }
input.o-so.is-sai-so { border-color: #c0392b; background: #fdecea; }

/* ================= Báo cáo ngày ĐIỆN MẶT TRỜI (solar.js, 07/10/2026) =================
   Dùng lại toàn bộ khung dashboard điện gió (.dash, .dash-kpis, .dash-grid...) - chỉ thêm
   mấy khối riêng của mặt trời. */
/* Hệ số sẵn sàng thiết bị: lưới Inv x-1 | Inv x-2 | MBA x như ô P9:U17 sheet "Bao cao". */
.sol-tb th { font-weight: 500; white-space: nowrap; }
.sol-tb td { text-align: right; font-variant-numeric: tabular-nums; }
.sol-tb td.is-low { background: #fdecea; color: #b3261e; font-weight: 700; }
/* Hàng PV / STATION / DZ: hệ số ghép của cả nhà máy, tách khỏi các hàng thiết bị. */
.sol-tb tr.sol-tram > * { border-top: 2px solid var(--line, #d0d7de); }
/* Thông số vận hành trong ngày: 6 ô nhỏ hai hàng, như khối B19:H23. */
.sol-ts-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.sol-ts { border: 1px solid var(--line); border-radius: 8px; padding: 6px 8px;
          display: flex; flex-direction: column; min-width: 0; }
.sol-ts span { font-size: 12px; color: var(--ink-soft); }
.sol-ts b { font-size: 17px; font-variant-numeric: tabular-nums; }
.sol-ts small { font-size: 11px; color: var(--ink-soft); }
.dash-card h4.sol-nx { margin-top: 12px; }
/* Nhận xét dài trong bảng Thống kê: cắt bớt, rê chuột xem đủ. */
.sol-cm { display: inline-block; max-width: 280px; white-space: nowrap; overflow: hidden;
          text-overflow: ellipsis; vertical-align: bottom; }
/* Ảnh dashboard MẶT TRỜI (daily.js veAnhDashboard + ANH_MT trong solar.js): cột phải là
   bảng thiết bị (vài hàng) rồi bảng tổn thất 12 tháng. Luật chung cho thẻ .dash-avail
   giãn hết phần thừa (hợp với lưới tua-bin điện gió) thì ở đây đẩy bảng tổn thất xuống
   đáy, chừa khoảng trắng lớn ở giữa. Đảo lại: thẻ thiết bị giữ đúng cao, thẻ tổn thất
   giãn và kéo cao các hàng của bảng để lấp kín cột. */
.dash-export.sol-dash .xuat-phai > .dash-avail { flex: 0 0 auto;
  border-bottom: 2px solid var(--dash-rule); }
.dash-export.sol-dash .xuat-phai > .dash-loss { flex: 1 1 auto; display: flex;
  flex-direction: column; border-bottom: 0; }
.dash-export.sol-dash .xuat-phai > .dash-loss .rp-grid-wrap { flex: 1 1 auto; display: flex; }
.dash-export.sol-dash .xuat-phai > .dash-loss .rp-table { flex: 1 1 auto; height: 100%; }

/* ================= Báo cáo ngày THUỶ ĐIỆN (hydro.js) =================
   Tab Raw data / Data dùng chung khung bảng; tab Báo cáo (27/10/2026) dựng lại ĐÚNG sheet
   "Bao cao" của file V25C - xem đầu khối "Báo cáo (dashboard)" trong hydro.js. */
.td-raw-chart { margin: 4px 0 12px; border: 1px solid var(--line); border-radius: 8px; }
.td-bg td { text-align: right; font-variant-numeric: tabular-nums; }
.td-bg tr.is-current th, .td-bg tr.is-current td { font-weight: 700; background: #eef6ff; }

.td-tools { display: flex; justify-content: flex-end; margin: 0 0 8px; }
/* Lưới 20 cột = cột D..W của sheet, mỗi cột rộng đúng số pt trong file. Nền xanh nhạt bao
   quanh = cột A..C, X và dòng 45 của file. */
.dash.td-xl {
  --td-cot: 99fr 97.5fr 147.8fr 123fr 102.8fr 120fr repeat(6, 67.5fr) repeat(4, 112.5fr)
            109.5fr 100.5fr 89.2fr 97.5fr;
  --td-navy: #1F3864; --td-dam: #002060; --td-xanh: #4472C4; --td-cam: #ED7D31;
  --td-o: #8EA9DB; --td-ke: 2px solid #000; --td-ke-mong: 1.5px solid #000;
  container-name: td; background: #DDEBF7; border-radius: 0; color: #000;
  padding: 18px 26px 28px; font-family: Arial, "Segoe UI", sans-serif; line-height: 1.25;
}
.td-xl > * { background: #fff; }
.td-xl > *:last-child { margin-bottom: 0; }
.td-tieu-de { border: var(--td-ke); text-align: center; font-weight: 700; font-size: 12.5px;
              padding: 7px; }
.td-vach { height: 8px; border-left: var(--td-ke); border-right: var(--td-ke);
           border-top: 4px solid var(--td-xanh); border-bottom: 1.5px solid var(--td-xanh); }
.td-hang { display: grid; grid-template-columns: var(--td-cot);
           border-left: var(--td-ke); border-right: var(--td-ke); }
.td-o { min-width: 0; }

/* D3:W4 - ngày, MNDBT, tên nhà máy, công suất, số tổ máy, giá, logo. */
.td-dau { align-items: center; min-height: 92px; border-bottom: var(--td-ke); }
.td-dau > .td-o { align-self: stretch; display: flex; align-items: center; }
.td-ngay-l { justify-content: center; text-align: center; font-weight: 700; font-size: 13px;
             color: var(--td-navy); }
.td-ngay { font-weight: 700; font-size: 13.5px; padding-left: 8px; border-right: var(--td-ke); }
.td-dau > .td-mndbt { flex-direction: column; align-items: flex-start; justify-content: space-around;
                      padding: 6px 14px; border-right: var(--td-ke); }
.td-mndbt span { font-weight: 700; font-size: 13px; color: var(--td-navy); }
.td-mndbt b { font-size: 17px; color: var(--td-navy); padding-left: 26px; }
.td-dau > .td-ten { justify-content: center; text-align: center; color: var(--td-xanh);
                    font-weight: 700; font-size: 30px; padding: 0 10px; }
.td-dau > .td-tt { flex-direction: column; justify-content: center; gap: 8px; text-align: center; }
.td-tt span { font-weight: 700; font-size: 12.5px; white-space: nowrap; }
.td-tt b { color: var(--td-xanh); font-size: 24px; white-space: nowrap; }
.td-tt.td-gia b { font-size: 14.5px; }
.td-dau > .td-logo { justify-content: center; }
.td-logo img { width: 56px; }

/* E5:W8 - tám chỉ tiêu; dòng 9 là vạch đôi. */
.td-kpi { border-bottom: 5px double #000; }
.td-k { position: relative; display: flex; flex-direction: column; justify-content: center;
        align-items: center; gap: 10px; min-height: 80px; padding: 8px 6px; text-align: center;
        border-right: var(--td-ke); }
.td-k:last-child { border-right: 0; }
.td-k-nhan { font-weight: 700; font-size: 13px; color: var(--td-navy); }
.td-k-gt { display: flex; align-items: center; justify-content: center; gap: 12px;
           font-weight: 700; font-size: 16.5px; white-space: nowrap; }
.td-k-gt img { height: 32px; }
.td-k-gt i { font-size: 13px; padding-left: 22px; }
/* Ảnh nằm trọn cột D (cột điện) / cột G (túi tiền) như file - --anh là bề rộng cột đó. */
.td-k.co-anh { align-items: flex-start; text-align: left; padding-left: calc(var(--anh) + 8px); }
.td-k-anh { position: absolute; left: 0; top: 50%; transform: translateY(-50%);
            width: var(--anh); height: 58px; object-fit: contain; }
.td-k.is-cam .td-k-gt { color: var(--td-cam); }

/* D10:W28 - luỹ kế tháng / năm, công suất + mực nước, tổn thất doanh thu theo tháng. */
.td-than1 { border-bottom: var(--td-ke); }
.td-lk { display: flex; flex-direction: column; padding: 4px 8px 10px; border-right: var(--td-ke); }
.td-lk h4 { margin: 0; text-align: center; font-size: 13px; color: var(--td-navy); }
.td-vong { flex: 1; display: grid; grid-template-columns: 1fr 1fr; gap: 4px;
           align-content: center; }
.td-vong h5 { margin: 6px 0 2px; text-align: center; font-size: 13px; }
.td-vong > div > div { display: flex; justify-content: center; }
.td-lk-d { display: grid; grid-template-columns: 1fr 16px 1fr 1fr; align-items: baseline;
           gap: 4px; margin-top: 6px; font-size: 12.5px; white-space: nowrap; }
.td-lk-d b:first-child { text-align: right; }
.td-lk-d i { font-style: normal; font-weight: 700; text-align: center; }
.td-lk-d span { font-weight: 700; text-align: center; }
.td-bd { padding: 4px 8px 6px; border-right: var(--td-ke); }
.td-bd h4 { margin: 2px 0 4px; text-align: center; font-size: 14px; }
.td-svg { display: block; max-width: 100%; height: auto; margin: 0 auto; }
/* Khung ô chỉ dẫn ôm sát hình: vòng luỹ kế nằm giữa ô rộng hơn nó, khung rộng cả ô thì
 * ô chỉ dẫn (tính toạ độ theo mép hình) lệch sang trái đúng bằng phần lề. */
.td-xl .dash-hover-wrap { width: fit-content; max-width: 100%; margin: 0 auto; }
.td-trong { margin: 40px 12px; color: var(--ink-soft); text-align: center; }
.td-tt-bang { padding: 4px 8px 10px; }
.td-tt-bang h4 { margin: 0 0 4px; text-align: center; font-size: 13px; color: var(--td-navy); }
.td-tt-bang table { width: 100%; border-collapse: collapse; font-size: 12.5px; text-align: center;
                    font-variant-numeric: tabular-nums; }
.td-tt-bang th, .td-tt-bang td { border: var(--td-ke-mong); padding: 1px 4px; font-weight: 400; }
.td-tt-bang thead th, .td-tt-bang tfoot th, .td-tt-bang tfoot td { font-weight: 700; }
.td-tt-bang tfoot th, .td-tt-bang tfoot td { padding: 5px 4px; }

/* Dòng 29 - ba tiêu đề mục. */
.td-muc { border-bottom: var(--td-ke); }
.td-muc h4 { margin: 0; padding: 10px 6px; text-align: center; font-size: 15.5px;
             color: var(--td-dam); border-right: var(--td-ke); }
.td-muc h4:last-child { border-right: 0; }
.td-muc h4.td-muc-bd { color: var(--td-navy); font-size: 14.5px; }

/* D30:W44 - chi tiết sản xuất ngày + nhận xét, doanh thu theo tháng, chỉ số sẵn sàng. */
.td-than2 { border-bottom: var(--td-ke); }
.td-ct { display: flex; flex-direction: column; border-right: var(--td-ke); }
.td-ct-bang { width: 100%; border-collapse: collapse; table-layout: fixed; }
.td-ct-bang th, .td-ct-bang td { border: var(--td-ke-mong); padding: 6px 4px; text-align: center;
                                 font-weight: 700; font-variant-numeric: tabular-nums; }
.td-ct-bang tr > :first-child { border-left: 0; }
.td-ct-bang tr > :last-child { border-right: 0; }
.td-ct-bang thead th { border-top: 0; padding: 10px 4px; font-size: 13.5px; color: var(--td-navy); }
.td-ct-bang tbody th { text-align: left; font-size: 13.5px; color: var(--td-dam); }
.td-ct-bang tbody td { font-size: 15px; color: var(--td-navy); }
.td-ct-bang .is-ngay th, .td-ct-bang .is-ngay td { color: var(--td-cam); }
.td-ct-bang .is-du td:nth-of-type(1) { color: var(--td-cam); }
.td-ct-bang .is-du th, .td-ct-bang .is-du td { padding-top: 10px; padding-bottom: 10px; }
.td-nx-tieu { padding: 3px; text-align: center; font-weight: 700; font-size: 15px;
              color: var(--td-dam); border-bottom: var(--td-ke); }
.td-nx { flex: 1; min-height: 120px; padding: 4px 6px; font-size: 13px; white-space: pre-wrap; }
.td-chan { display: grid; grid-template-columns: 14.35% 14.13% 21.42% 1fr; align-items: stretch;
           min-height: 46px; border-top: var(--td-ke); font-size: 12.5px; }
.td-chan > span { display: flex; align-items: center; justify-content: center; text-align: center;
                  padding: 2px 4px; }
.td-chan-tt { background: #D9E1F2; color: #000099; font-weight: 700; font-size: 13px;
              border-right: var(--td-ke); }
.td-chan-ng { font-weight: 700; font-size: 14px; }
.td-ss table { width: 100%; height: 100%; border-collapse: collapse; table-layout: fixed; }
.td-ss th, .td-ss td { border: var(--td-ke-mong); padding: 4px 6px; font-size: 12px;
                       font-weight: 700; font-variant-numeric: tabular-nums; }
.td-ss tr > :first-child { border-left: 0; }
.td-ss tr > :last-child { border-right: 0; }
.td-ss tr:first-child > * { border-top: 0; }
.td-ss th { text-align: center; }
.td-ss td { text-align: right; background: var(--td-o); }
.td-ss .is-con th { color: var(--td-xanh); }
.td-ss .is-nm th { height: 96px; font-size: 12.5px; }
.td-ss .is-nm td { font-size: 17px; text-align: center; }

/* Màn hẹp (máy tính bảng, điện thoại - dashboard không zoom dưới 1000px): ba vùng xếp
   chồng, các ô chỉ tiêu hai cột. Lưới của file chỉ giữ ở màn đủ rộng. */
@container td (max-width: 980px) {
  /* Vạch ngăn bằng KHE 2px trên nền đen thay cho viền từng ô: ô xếp lại bao nhiêu cột
     cũng không phải tính ô nào kẻ vạch phải / vạch trên. */
  .td-hang { grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 2px; background: #000;
             border-bottom: var(--td-ke); }
  .td-hang > * { grid-column: auto / span 6 !important; border: 0 !important; background: #fff; }
  .td-dau > .td-o, .td-kpi > .td-k, .td-than1 > .td-lk { grid-column: auto / span 3 !important; }
  .td-dau { min-height: 0; }
  .td-dau > .td-ten { order: -1; grid-column: 1 / -1 !important; font-size: 22px; padding: 10px; }
  .td-dau > .td-logo { display: none; }
  .td-dau > .td-mndbt b { padding-left: 0; }
  .td-kpi { border-bottom: var(--td-ke); }
  .td-muc { display: none; }
  .td-than2 > .td-bd::before { content: "Doanh thu thủy điện theo tháng (triệu đồng)";
    display: block; text-align: center; font-weight: 700; color: var(--td-navy); padding: 8px 0 2px; }
  .td-ct-bang tr > :first-child { border-left: 0; }
}
/* Điện thoại: vẫn hai cột ô (đỡ dài trang), bỏ ảnh biểu tượng, chữ nhỏ một nấc; hai khối
   luỹ kế xếp chồng cho vòng đủ to. */
@container td (max-width: 560px) {
  .td-than1 > .td-lk { grid-column: 1 / -1 !important; }
  .td-k-anh { display: none; }
  .td-k.co-anh { align-items: center; text-align: center; padding-left: 6px; }
  .td-k { min-height: 70px; gap: 6px; }
  .td-k-nhan, .td-tt span, .td-mndbt span, .td-ngay-l { font-size: 12px; }
  .td-k-gt { font-size: 14.5px; white-space: normal; }
  .td-k-gt i { padding-left: 8px; }
  .td-tt b { font-size: 18px; }
  .td-tt.td-gia b { font-size: 13px; white-space: normal; }
  .td-dau > .td-ten { font-size: 19px; }
  .td-lk-d { font-size: 12px; }
  .td-ct-bang thead th { font-size: 11.5px; padding: 8px 2px; }
  .td-ct-bang tbody th { font-size: 12px; }
  .td-ct-bang tbody td { font-size: 13.5px; }
  .td-bd { padding: 4px 2px 6px; }
}
@media (max-width: 700px) { .dash.td-xl { padding: 8px; } }

/* ---- Nhập liệu thuỷ điện (hydro_nhap.js, 28/10/2026) ---- */
.hn .hn-luoi { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
               gap: 8px 10px; }
.hn .hn-o { display: flex; flex-direction: column; gap: 3px; font-size: 12px; color: var(--ink-soft); }
.hn .hn-o input, .hn .hn-o textarea { font: inherit; font-size: 13.5px; color: var(--ink);
  border: 1px solid var(--line); border-radius: 7px; padding: 6px 8px; background: #fff;
  min-width: 0; }
.hn .hn-o-rong { grid-column: span 2; }
.hn .hn-o.is-tinh input, .hn .hn-o.is-tinh textarea, .hn .hn-o input:disabled,
.hn .hn-o textarea:disabled { background: #f3f5f2; color: var(--ink); }
.hn .hn-o.is-tinh span::after { content: " · tự tính"; color: var(--green-700); }
.hn-raw-wrap { max-height: 460px; overflow: auto; }
.hn-raw th, .hn-raw td { padding: 2px 6px; }
.hn-raw thead th { position: sticky; top: 0; background: #f1f6f2; z-index: 1; }
.hn-raw input { width: 100%; min-width: 80px; font: inherit; font-size: 13px; border: 1px solid var(--line);
                border-radius: 5px; padding: 3px 6px; text-align: right; }
.hn-raw input[data-c="V"] { text-align: left; }
.hn-raw input:disabled { background: #f3f5f2; }
.hn-tu { color: var(--ink-soft); font-size: 12px; }
.hn-dan { margin: 0 0 10px; }
.hn-dan textarea { width: 100%; font: 12.5px/1.4 monospace; margin: 6px 0; }
.hn-sc { border: 1px dashed var(--line); border-radius: 9px; padding: 8px 10px; margin-bottom: 10px; }
.hn-sc-dau { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; }
.hn-sc-tinh { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 8px; font-size: 12.5px; }
.hn-sc-tinh i { font-style: normal; color: var(--ink-soft); margin-right: 5px; }
.wb-btn.is-nho { padding: 3px 10px; font-size: 12px; }
.hn-nut { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin: 6px 0 14px; }
.hn-kq2 { display: grid; grid-template-columns: minmax(220px, 300px) 1fr; gap: 14px; margin-top: 10px;
          align-items: start; }
.hn-ss caption { text-align: left; font-weight: 600; padding-bottom: 4px; }
.hn-ss td { text-align: right; }
.hn-muoi td { text-align: right; }
@media (max-width: 700px) {
  .hn .hn-luoi { grid-template-columns: 1fr 1fr; }
  .hn-kq2 { grid-template-columns: 1fr; }
}
