@layer legacy {
/* =====================================================================
   LỊCH — MỘT NƠI DUY NHẤT QUYẾT ĐỊNH HÌNH HỌC
   =====================================================================
   Trước file này, hình học của lưới lịch được khai báo ở BỐN lớp chồng
   nhau trong styles.css: lớp "thẻ nổi" đầu tiên, lớp đại tu "một mặt
   phẳng, chỉ có vạch chia", lớp vá lại riêng cho dạng Tuần, rồi
   calendar-card-layout.css. Riêng `.task-item` có ba khối định nghĩa gốc
   (dòng 1368 / 4547 / 5006 của bản cũ) đặt ba giá trị padding khác nhau.
   Kết quả trên màn hình là phần dư của ba hướng thiết kế — không ai đoán
   được một thay đổi sẽ ra gì, nên mọi lần sửa đều thành một lớp đè mới.

   Nay 59 khối luật dùng bộ chọn TRẦN của lịch (.grid, .day-col, .task-item,
   .task-list, .day-footer, .completed-group…) được gom về đây theo ĐÚNG
   thứ tự nguồn cũ. Vì file này nạp sau cùng và không stylesheet nào phía
   sau khai báo cùng bộ chọn trần đó, kết quả tính toán của Mục A giống hệt
   bản trước khi gom — đây là điều kiện để việc gom không đổi một pixel nào.

   Sửa hình học của lịch thì sửa Ở ĐÂY. Đừng thêm luật .day-col/.task-item
   trần vào styles.css nữa; tests/cssCascadeIntegrity.test.js chặn việc đó.

   MỤC 0 — token thẻ ngày + dạng Agenda / Hôm nay (chuyển nguyên khối từ
           dashboard.css 2026-09-27, đặt TRƯỚC Mục A để giữ thứ tự nguồn cũ)
   MỤC A — lớp nền hợp nhất (nguyên trạng, gom từ styles.css)
   MỤC B — bù thứ tự cho luật @media từng thắng lớp nền
   MỤC C — hợp đồng dạng Tuần / Ngày (thiết kế mới)
   ===================================================================== */

/* ===================== MỤC 00 — LUẬT LỊCH GOM TỪ styles.css =====================
   Chuyển nguyên văn (kèm chú thích đứng ngay trước) từ styles.css (2026-09-27, Gói 1
   Lát 4): mọi luật mà class định danh chỉ do mã Lịch sinh ra. Giữ đúng thứ tự tương
   đối cũ và đặt TRƯỚC MỤC 0 (khối gốc từ dashboard.css — vốn nạp sau styles.css).
   Luật nào từng thắng nhờ thứ tự nguồn so với file nạp giữa hai vị trí đã được
   kiểm bằng snapshot computed style (xem commit). */

.month-week-row {
  width: 100%; min-height: var(--ui-control-h-compact); padding: var(--ui-resizer-line);
  border: var(--ui-stroke-thin) solid transparent; border-radius: var(--ui-radius-control);
  background: transparent; color: var(--ui-text-primary); cursor: pointer;
  font-family: inherit; text-align: center;
  transition: background-color var(--ui-duration-fast), border-color var(--ui-duration-fast), box-shadow var(--ui-duration-fast);
}

.month-week-row:hover { background: rgba(var(--ui-surface-fill-rgb), .62); }

.month-week-row:focus-visible {
  outline: var(--ui-focus-ring-width) solid var(--ui-accent); outline-offset: calc(-1 * var(--ui-focus-ring-width));
}

.month-week-row.selected {
  background: color-mix(in srgb, var(--ui-accent) 13%, rgb(var(--ui-surface-raised-rgb)));
  border-color: color-mix(in srgb, var(--ui-accent) 78%, transparent);
}

.month-week-row.displayed:not(.selected) {
  border-color: rgba(var(--ink), .2);
}

.month-week-number,
.month-day {
  min-width: 0; min-height: var(--ui-control-h-compact); display: grid; place-items: center;
  border-radius: var(--ui-radius-sm);
  font-size: var(--fs-micro); line-height: var(--lh-none); font-variant-numeric: tabular-nums;
}

button.month-day {
  border: none; background: transparent; color: inherit; padding: 0; cursor: pointer;
}

button.month-day:hover {
  background: color-mix(in srgb, var(--ui-accent) 13%, rgb(var(--ui-surface-raised-rgb)));
}

.month-day.selected-day {
  font-weight: var(--fw-semibold);}

.month-week-number {
  justify-self: stretch; color: var(--ui-text-secondary); font-size: var(--fs-micro); font-weight: var(--fw-semibold);
  border-right: var(--ui-stroke-thin) solid rgba(var(--ink), .09); border-radius: 0;
}

.month-week-row.selected .month-week-number { color: var(--ui-accent); }

.month-week-row.current-week .month-week-number {
  color: var(--tone-green-fg); background: var(--tone-green-bg);
  border-right-color: transparent; border-radius: var(--ui-radius-control);
}

.month-day { justify-self: center; width: var(--ui-control-h-compact); color: var(--ui-text-primary); font-weight: var(--fw-semibold); }

.month-day.outside-month { color: var(--ui-text-muted); opacity: .38; }

.month-day.today {
  color: var(--ui-text-on-accent); background: var(--tone-green-bar); font-weight: var(--fw-semibold);
  border: var(--ui-resizer-line) solid color-mix(in srgb, var(--ui-text-on-accent) 82%, transparent);
  border-radius: var(--ui-radius-full);
}

/* =====================================================================
   GRID — week rail, day headers, day cards, tasks, events, progress
   Structural grid mechanics (columns/rows/subgrid) are unchanged from the
   original layout; only colour/spacing tokens below are new.
   ===================================================================== */

/* .scrolling-multi-week đã bỏ tác dụng: dạng Tháng luôn phải vừa một màn
   hình, không có ngưỡng nào để chuyển sang cuộn. */
.grid.multi-week.scrolling-multi-week { --week-row-min: 0px; }

.multi-week-shared-header,
.week-section {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  column-gap: var(--cell-gap);
  min-width: 0; min-height: 0; height: 100%; align-items: stretch;
  /* Deliberately NOT `overflow: hidden`. A .day-col fills this row exactly
     (height: 100%), so on hover its `transform: translateY(-2px)` lifts its
     top edge 2px outside this box — clipping here ate exactly the hovered
     card's 2px top border while leaving left/right/bottom intact, which is
     what read as "viền trên mỏng hơn hai bên". Each card already clips its
     own content with its own `overflow: hidden`; this row must not clip. */
}

/* Design: dayHeadRow is a direct child of the window with its own
   `padding: '0 10px'` — its background/border run edge-to-edge with the
   window, only the label text sits 10px in.

   Our header instead lives inside .grid.multi-week so its day columns can
   subgrid-align with the cards below, and that grid carries its own 10px
   left/right padding meant for the cards (which the design insets through a
   *separate* wrapper, gridWrap, not the header). Sitting inside that padding
   left the header's own background/border short of the window edge — the gap
   in the screenshot.

   A negative margin on the header itself looked like the fix but measured
   wrong: subgrid tracks are resolved against the item's own margin box, not
   the parent's padding box, so shifting the box shifted the columns with it —
   confirmed by `.multi-week-corner`'s rect landing 10px left of `.week-rail`'s
   below it once tried. The ::before here bleeds the background only, via
   absolute positioning that neither participates in the grid nor moves the
   real subgrid children, so TUẦN / THỨ HAI / etc. stay exactly where the
   tracks put them. */
.multi-week-shared-header {
  position: sticky; top: 0; z-index: 6; /* audit-keep: thứ tự chồng lớp cục bộ phải giữ đúng số so với hàng xóm cùng ngữ cảnh xếp chồng, thang layer không có bậc tương ứng */
  align-items: stretch; padding: 0;
}

.multi-week-shared-header::before {
  content: ''; position: absolute; z-index: -1;
  top: 0; bottom: 0;
}

/* A week is a hard visual and layout boundary. Its implicit grid row used to
   be `auto`, so expanding a long completed list could make a day taller than
   the parent row and paint over the following week. */
.week-section {
  grid-template-rows: minmax(0, 1fr);
  overflow: hidden;
}

.week-rail {
  min-width: 0; min-height: 0; overflow: hidden; text-align: center;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}

.week-rail-week { line-height: var(--lh-flat); text-shadow: var(--shade-shadow); }

.week-rail-range { text-shadow: var(--shade-shadow); }

.week-rail-current {
  border-radius: var(--dt-dimension-radius-full);
  letter-spacing: .4px;
}

/* ---------- Day cards ---------- */
.day-col::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  z-index: -1;
  pointer-events: none;
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
}

html[data-material="solid"] .day-col::before {
  display: none;
}

.day-col.today-highlighted .day-name { color: var(--tone-green-fg); }

/* Số ngày là chữ, không phải nút. Bản cũ khoác cho nó một viên nền
   rgba(--sf-row) rồi phủ thêm text-shadow: hai thứ đó cộng lại vẽ ra một cái
   hộp có mép sẫm quanh con số ("viền đen trong số"), trong khi thông tin
   "hôm nay" đã có viên pill xanh riêng ngay bên dưới nói rồi. */
.day-col.today-highlighted .day-num {
  text-shadow: none;
}

.grid.multi-week .day-chip.empty { display: none; }

.grid.multi-week .day-footer { padding: 0; gap: 0; border-top: none; background: transparent; overflow: hidden; border-radius: 0 0 var(--ui-radius-panel) var(--ui-radius-panel); }

.grid.multi-week .day-count { display: none; }

/* Birthday/event items should stay at top of the card, not centered.
   Only the empty-hint (+) icon centers itself within the available space. */
.grid.multi-week .day-col.is-empty .task-list { justify-content: flex-start; }

.day-col.is-empty:hover .empty-hint { opacity: 1; }

.empty-hint:hover {
  transform: translateY(-2px);
  box-shadow: var(--elev-2);
  border-color: var(--ui-accent);
  color: var(--ui-accent);
}

/* State feedback is intentionally brief: the data is already persisted while
   this old row animates, then the grid performs one atomic reorder. */
.task-item.task-state-completing {
  animation: task-gravity-complete 360ms cubic-bezier(.45, 0, .85, .45) both; /* audit-keep: chuyển động biên đạo riêng (keyframes), không thuộc nhịp giao diện chuẩn */
  transition-duration: var(--ui-duration-standard);
  pointer-events: none;
}

.task-item.task-state-restoring {
  animation: task-lift-restore 360ms cubic-bezier(.18, .8, .25, 1) both; /* audit-keep: chuyển động biên đạo riêng (keyframes), không thuộc nhịp giao diện chuẩn */
  transition-duration: var(--ui-duration-standard);
  pointer-events: none;
}

.task-item.task-land-complete {
  animation: task-land-complete 240ms cubic-bezier(.2, 0, 0, 1) both; /* audit-keep: chuyển động biên đạo riêng (keyframes), không thuộc nhịp giao diện chuẩn */
}

.task-item.task-rise-restore {
  animation: task-rise-restore 280ms cubic-bezier(.18, .8, .25, 1) both; /* audit-keep: chuyển động biên đạo riêng (keyframes), không thuộc nhịp giao diện chuẩn */
}

.task-prefix:empty { display: none; }

.task-item.done .task-prefix { color: var(--done-ink); }

.task-repeat-icon,
.task-meeting-icon {
  display: inline-flex; align-items: center; justify-content: center;
  vertical-align: -0.12em;
  width: var(--task-icon-size); height: var(--task-icon-size);
  letter-spacing: 0;
  line-height: var(--lh-none);
}

.task-repeat-icon svg {
  width: var(--task-icon-svg-size);
  height: var(--task-icon-svg-size);
}

.task-meeting-icon svg { display: block; width: var(--task-icon-svg-size); height: var(--task-icon-svg-size); }

/* Decorative priority marker: a full-height color bar flush with the card's
   own left edge (like a Kanban label strip) instead of sitting inline before
   the text, so the text column keeps its full width. Stays fully inside the
   row's own box — unlike a bleeding shape, this needs no allowance for
   .task-list's overflow-y:auto (which per spec forces overflow-x to auto
   too, clipping anything that tries to escape the row). The left corners
   share the card's own radius so the bar reads as part of the card, not a
   shape overlapping it. */
.linked-note-status {
  flex: 0 0 auto;
  height: var(--task-icon-size);
  vertical-align: -0.12em;
  line-height: var(--lh-none);
}

.gcal-event-item .linked-note-status, .outlook-event-item .linked-note-status { pointer-events: auto; }

.linked-note-status:focus-visible { outline: var(--ui-stroke-thick) solid var(--ui-accent); outline-offset: var(--ui-stroke-thick); border-radius: var(--ui-radius-sm); }

.task-item.done .linked-note-status { color: var(--done-ink); opacity: .72; }

/* Bell icon for tasks whose text carries a recognized "17h30"-style time.
   margin-right matches .task-item's grid gap (6px) so the number prefix,
   bell, and text all sit at the same even spacing. */
.task-meeting-icon {
  margin-right: var(--task-icon-gap, var(--ui-space-1)); font-size: var(--task-meeting-font); line-height: var(--lh-none); opacity: .85;
}

/* .task-meeting-icon.is-past removed to keep the bell yellow */
.task-item.done .task-meeting-icon { filter: grayscale(1); opacity: .45; }

.task-item.done .task-repeat-icon { color: var(--done-ink); opacity: 1; }

.task-repeat-icon {
  margin-right: var(--task-icon-gap, var(--ui-space-1));
  color: var(--ui-text-secondary); opacity: .8;
}

.task-repeat-icon svg { display: block; }

.task-repeat-icon.is-redo { font-size: 1.12em; font-weight: var(--fw-semibold); color: var(--done-ink); }

.progress-fill.all-done { background: var(--tone-green-bar); }

.day-count.all-done { color: var(--tone-green-fg); }

/* ---------- Google Calendar & Birthday events ---------- */
.gcal-event-item > :not(.event-prefix-slot, .calendar-item-more, .linked-note-status) { pointer-events: none; }

.gcal-event-item :is(.event-box, .task-box, .calendar-item-more, .linked-note-status) { pointer-events: auto; }

.gcal-event-item.is-holiday { background: var(--tone-orange-bg); color: var(--tone-orange-fg); }

/* renderer.js puts a 🎂 / 🎆 / 📅 emoji in here. The design file draws an
   abstract square in this slot, but that is a placeholder for "an icon goes
   here" — painting a background over it would hide the real one. */
.gcal-event-icon {
  flex-shrink: 0; align-items: center; justify-content: center;
  line-height: var(--lh-none);
}

.gcal-event-body { display: flex; align-items: flex-start; text-align: left; min-width: 0; flex: 1; width: 100%; }

/* ---------- Outlook Calendar events ---------- */
.outlook-event-item > :not(.event-prefix-slot, .calendar-item-more, .linked-note-status) { pointer-events: none; }

.outlook-event-item :is(.event-box, .task-box, .calendar-item-more, .linked-note-status) { pointer-events: auto; }

.outlook-event-icon {
  flex-shrink: 0; align-items: center; justify-content: center;
  line-height: var(--lh-none);
}

.outlook-event-icon svg { display: block; width: 100%; height: 100%; }

.outlook-event-icon.platform-calendar { color: var(--ui-brand-calendar); }

.outlook-event-icon.platform-teams { color: var(--ui-brand-teams); }

.outlook-event-icon.platform-zoom { color: var(--ui-brand-zoom); }

.outlook-event-icon.platform-online { color: var(--ui-accent); }

.outlook-event-icon.platform-webex { color: var(--ui-brand-webex); }

.outlook-event-body { display: flex; align-items: flex-start; text-align: left; min-width: 0; flex: 1; width: 100%; }

.event-prefix-slot {
  position: absolute;
  left: var(--ui-space-2);
  top: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

/* Như .task-prefix: icon nguồn lịch chỉ để nhìn. Khi rê chuột nó mờ về
   opacity 0 → tạo stacking context, và vì đứng sau .event-box trong DOM nên
   phủ lên ô tích — cú bấm "hoàn thành" rơi vào icon rồi nổi lên thẻ. */
.event-prefix-slot > :not(.event-box) {
  pointer-events: none;
  transition: opacity var(--ui-duration-fast);
}

.gcal-event-item:hover .event-prefix-slot > :not(.event-box),
.outlook-event-item:hover .event-prefix-slot > :not(.event-box),
.gcal-event-item:focus-within .event-prefix-slot > :not(.event-box),
.outlook-event-item:focus-within .event-prefix-slot > :not(.event-box),
.gcal-event-item.event-done .event-prefix-slot > :not(.event-box),
.outlook-event-item.event-done .event-prefix-slot > :not(.event-box) {
  opacity: 0;
}

/* Events and tasks share the pill time chip styling with clock icon */
:is(.task-time-label, .event-time-label) {
  display: inline-flex;
  align-items: center;
  gap: var(--ui-space-0-5);
  padding: 0 var(--ui-space-1);
  margin-right: var(--ui-space-1);
  border-radius: var(--ui-radius-pill);
  background: var(--tone-orange-bg);
  color: var(--tone-orange-fg);
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  line-height: var(--lh-none, 1);
  height: calc(var(--task-effective-font) * 1.22);
  box-sizing: border-box;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  vertical-align: middle;
}

.task-time-clock-icon {
  width: calc(var(--task-effective-font) * 0.85);
  height: calc(var(--task-effective-font) * 0.85);
  flex-shrink: 0;
  display: block;
}

:is(.task-item.done, .gcal-event-item.event-done, .outlook-event-item.event-done) :is(.task-time-label, .event-time-label) {
  background: var(--ux-fill);
  color: var(--done-ink);
}

.gcal-event-item .event-box, .outlook-event-item .event-box {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  pointer-events: auto;
  flex-shrink: 0;
  margin-right: 0;
}

.gcal-event-item:hover .event-box, .outlook-event-item:hover .event-box,
.gcal-event-item:focus-within .event-box, .outlook-event-item:focus-within .event-box,
.gcal-event-item.event-done .event-box, .outlook-event-item.event-done .event-box {
  opacity: 1;
}

/* Event Animation Overrides (matches task animations) */
.gcal-event-item.task-state-completing, .outlook-event-item.task-state-completing {
  animation: task-gravity-complete 360ms cubic-bezier(.45, 0, .85, .45) both; /* audit-keep: chuyển động biên đạo riêng (keyframes), không thuộc nhịp giao diện chuẩn */
  transition-duration: var(--ui-duration-standard);
  pointer-events: none;
}

.gcal-event-item.task-state-restoring, .outlook-event-item.task-state-restoring {
  animation: task-lift-restore 360ms cubic-bezier(.18, .8, .25, 1) both; /* audit-keep: chuyển động biên đạo riêng (keyframes), không thuộc nhịp giao diện chuẩn */
  transition-duration: var(--ui-duration-standard);
  pointer-events: none;
}

.gcal-event-item.task-land-complete, .outlook-event-item.task-land-complete {
  animation: task-land-complete 240ms cubic-bezier(.2, 0, 0, 1) both; /* audit-keep: chuyển động biên đạo riêng (keyframes), không thuộc nhịp giao diện chuẩn */
}

.gcal-event-item.task-rise-restore, .outlook-event-item.task-rise-restore {
  animation: task-rise-restore 280ms cubic-bezier(.18, .8, .25, 1) both; /* audit-keep: chuyển động biên đạo riêng (keyframes), không thuộc nhịp giao diện chuẩn */
}

.snake-border-svg {
  display: none !important;
}



/* A task/event priority is more specific than the time-to-meeting state: the
   animated border must match its left priority marker whenever one is set. */










/* ---------- Meeting Bell Alert: Nền đỏ bo tròn + Rung lắc nhẹ ----------
   Nền --ui-danger-solid: icon trắng trên --ui-danger của Tối (đỏ hồng nhạt) chỉ ≈2:1. */
:is(.task-item.alert-warning, .task-item.alert-urgent, .outlook-event-item.alert-warning, .outlook-event-item.alert-urgent) .task-meeting-icon,
:is(.task-item.alert-warning, .task-item.alert-urgent) .task-meeting-icon:not(.is-past) {
  display: inline-flex !important;
  min-width: var(--ui-icon-md);
  box-shadow: var(--meeting-alert-glow);
  transform-origin: 50% 0;}
/* Quầng sáng màu trạng thái (glow) của chuông họp theo chế độ — không phải bậc độ nổi. */
:root { --meeting-alert-glow: 0 2px 6px rgba(var(--ui-danger-rgb), 0.45); } /* audit-keep: quầng sáng màu trạng thái (glow), không phải bậc độ nổi */
html[data-mode="dark"] { --meeting-alert-glow: 0 2px 8px rgba(var(--ui-danger-rgb), 0.55); } /* audit-keep: quầng sáng màu trạng thái (glow), không phải bậc độ nổi */


:is(.task-item.alert-warning, .task-item.alert-urgent, .outlook-event-item.alert-warning, .outlook-event-item.alert-urgent) .task-meeting-icon svg,
:is(.task-item.alert-warning, .task-item.alert-urgent) .task-meeting-icon:not(.is-past) svg {
  stroke: var(--ui-text-on-accent);
  fill: none;
  stroke-width: 2.3;
  display: block !important;}



/* Hitbox expansion (hysteresis) to prevent translateY hover flickering loops */
.day-col::after, .task-item::after, .gcal-event-item::after, .outlook-event-item::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: calc(-1 * var(--ui-space-1)); height: var(--ui-space-1); z-index: -1; pointer-events: none;
}

.day-col:not(.drag-over):hover::after,
.task-item:not(.dragging):hover::after, 
.gcal-event-item:hover::after, 
.outlook-event-item:hover::after {
  pointer-events: auto;
}

/* .calendar-refreshing chỉ tắt transition trong khung dựng lại (luật đầu mục
   GRID). KHÔNG làm mờ lưới: lớp này bật/tắt trong 1 khung hình ở mỗi nhịp đồng
   bộ Google/Outlook, còn `.grid` có transition opacity — mờ ở đây là một cú
   chớp nhạt lặp lại trên toàn lịch. */

.grid.multi-week.scrolling-multi-week { --week-row-min: 0px; }

.multi-week-shared-header { border-bottom: var(--ui-resizer-line) solid var(--ux-divider); }

.multi-week-shared-header::before {
  left: 0;
  right: 0;
  border-bottom: 0;
  background: var(--ux-base);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.shared-day-label { border-left: var(--ui-stroke-thin) solid transparent; }

.shared-day-label.weekend { color: var(--ui-text-muted); }

.week-section { border-radius: 0; }

.week-section + .week-section { border-top: var(--ui-stroke-thin) solid var(--ui-divider); }

.week-rail {
  gap: var(--ui-space-1);
  padding: var(--ui-space-3-5) var(--ui-space-1);
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.week-rail-week { color: var(--ui-text-secondary); font-size: var(--fs-body); font-weight: var(--fw-semibold); }

.current-week-section .week-rail-week { color: var(--ui-text-secondary); }

.week-rail-range {
  margin-top: 0;
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  line-height: var(--lh-flat);
  writing-mode: vertical-rl;
  transform: rotate(180deg);
}

.week-rail-current {
  margin-top: var(--ui-space-px);
  padding: var(--ui-space-0-5) var(--ui-space-1-5);
  color: var(--ui-success);
  background: var(--ui-success-soft);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
}

.day-col::before { display: none; }

html[data-material="glass"]:root .day-col { box-shadow: var(--cal-day-shadow); }

.day-col:not(.drag-over):hover {
  z-index: auto;
}

.day-col.today-highlighted {
  border: 0;
  border-left: var(--ui-stroke-thin) solid var(--ui-divider);
  background: transparent;
}

.day-col.drag-over {
  background: var(--ui-selected);
  box-shadow: inset 0 0 0 var(--ui-focus-ring-width) var(--ui-accent);
}

.day-col.today-highlighted .day-num,
html:root .day-col.today-highlighted .day-num {
  color: var(--ui-text-on-accent);
  background: var(--ui-success);
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
}

.day-chip.all-done { color: var(--ui-success); background: var(--ui-success-soft); }

.day-col.today-highlighted .day-chip { color: var(--ui-success); background: var(--ui-success-soft); }

.empty-hint::before { content: '+  Thêm việc'; font-size: var(--fs-caption); font-weight: var(--fw-semibold); }

.day-col.is-empty:hover .empty-hint { border-color: var(--ui-divider); }

/* Hover không đổi nền thẻ — chỉ giữ filter:none để chặn brightness() kế thừa. */
.gcal-event-item:hover,
.outlook-event-item:hover { filter: none; }

.gcal-event-item.is-birthday { color: var(--ui-birthday-text); background: var(--ui-birthday-fill); }

/* Kính: thẻ họp KHÔNG tự blur — cột ngày (.day-col::before) đã blur nền phía sau,
   blur thêm từng thẻ là blur-chồng-blur (mắt không phân biệt) nhưng tạo một lớp
   compositing/raster cho MỖI sự kiện, tuần dày lịch là giật khi cuộn/chuyển màn.
   Đồng nhất với thẻ việc (vốn không blur). */
html[data-material="glass"] .gcal-event-item,
html[data-material="glass"] .outlook-event-item {
  box-shadow: none;
}

/* Each displayed item owns a stable pastel background derived from its
   persistent ID. The foreground is deliberately not part of this mapping:
   task text always uses the standard ink, while icons/priority dots carry
   their own semantic colour. */
:is(.task-item, .gcal-event-item, .outlook-event-item).item-tone-blue {
  --task-row-bg: var(--tone-blue-bg);
}

:is(.task-item, .gcal-event-item, .outlook-event-item).item-tone-purple {
  --task-row-bg: var(--tone-purple-bg);
}

:is(.task-item, .gcal-event-item, .outlook-event-item).item-tone-pink {
  --task-row-bg: var(--tone-pink-bg);
}

:is(.task-item, .gcal-event-item, .outlook-event-item).item-tone-orange {
  --task-row-bg: var(--tone-orange-bg);
}

:is(.task-item, .gcal-event-item, .outlook-event-item).item-tone-green {
  --task-row-bg: var(--tone-green-bg);
}


.task-box:hover { border-color: var(--ui-accent); background: var(--ui-selected); }

.task-item.done .task-box { color: var(--ui-success); background: transparent; border-color: var(--ui-success); }

.task-prefix.mode-text { display: none; }

.task-item :is(.task-repeat-icon, .task-meeting-icon, .meeting-overlap-icon) {
  flex: 0 0 auto;
  align-self: center;
  margin-right: 0;
}

.task-text.has-inline-metadata :is(.task-repeat-icon, .task-meeting-icon, .meeting-overlap-icon) {
  display: inline-flex;
  vertical-align: -0.12em;
  margin-right: var(--task-icon-gap, var(--ui-space-1));
}

.meeting-overlap-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ui-warning);
  cursor: help;
}

.meeting-overlap-icon svg {
  display: block;
  width: var(--task-icon-svg-size);
  height: var(--task-icon-svg-size);
}

.outlook-event-body .meeting-overlap-icon,
.gcal-event-body .meeting-overlap-icon {
  display: inline-flex;
  vertical-align: -0.12em;
  margin-left: var(--task-icon-gap, var(--ui-space-1));
}

.day-overlap-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--ui-space-0-5) var(--ui-space-1-5);
  margin-left: var(--spacing-2xs, var(--ui-space-1));
  border-radius: var(--ui-radius-control);
  background: color-mix(in srgb, var(--ui-warning) 16%, transparent);
  color: var(--ui-warning);
  cursor: help;
}

.day-overlap-chip svg {
  display: block;
  width: 1em;
  height: 1em;
}

.task-item.has-meeting-overlap:not([class*="has-priority-"]),
.gcal-event-item.has-meeting-overlap:not([class*="has-priority-"]),
.outlook-event-item.has-meeting-overlap:not([class*="has-priority-"]) {
  border-left: var(--ui-stroke-thick) solid var(--ui-warning);
}

/* Giờ giấc là CHỮ đứng cùng dòng tên việc, không phải nhãn rời: giữ cùng
   baseline (inline + line-height kế thừa) để STT / giờ / tên việc thẳng hàng. */
.task-text.has-inline-metadata .task-time-label {
  vertical-align: middle;
  margin-right: var(--ui-space-1);
}

/* Every calendar view, including Today, shares one semantic colour system for
   task metadata — dùng token tone (tự đổi sáng/tối), bỏ hex cứng + fork dark. */
.week-task-view:not(.done) .task-repeat-icon { color: var(--tone-blue-fg); opacity: 1; }

.week-task-view:not(.done) .task-meeting-icon { color: var(--tone-pink-fg); opacity: 1; }

.completed-toggle:hover { color: var(--ui-text-secondary); background: color-mix(in srgb, var(--ui-hover) 46%, transparent); }

/* Một dòng, cắt bằng ellipsis. Bản cũ để chữ tự xuống dòng: ở cột ngày hẹp
   (tuần / cửa sổ chia đôi / 150%) "Đã hoàn tất" xuống 3 dòng, còn badge số +
   chevron thì canh giữa theo align-items:center nên đè lên dòng 2 — đúng cái
   "chữ chồng chữ" trong ảnh. */
.completed-chevron {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: center;
  width: var(--dt-dimension-icon-header);
  height: var(--dt-dimension-icon-header);
  flex: 0 0 var(--dt-dimension-icon-header);
  line-height: 0;
  transition: transform var(--ui-duration-standard) var(--motion-standard);
}

.completed-chevron-svg {
  display: block;
  width: var(--ui-icon-dense);
  height: var(--ui-icon-dense);
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.completed-group.is-collapsed .completed-chevron { transform: rotate(90deg); }

.completed-list[hidden] { display: none; }

/* Chân cột đã có thanh tiến độ chạy ngang hết bề rộng — kẻ thêm một đường
   1px ngay trên nó là vẽ hai đường song song cách nhau 8px cho cùng một
   ranh giới. Thanh tiến độ giữ vai trò đó, đường kẻ bỏ. */
.grid.multi-week .day-footer { display: none; }

.grid[data-view-mode="week"] .day-col,
.grid.multi-week .day-col {
  border: var(--ui-stroke-thin) solid var(--cal-day-border);
  border-radius: var(--cal-day-radius);
  background: var(--cal-day-surface);
  box-shadow: var(--cal-day-shadow);
}

.grid[data-view-mode="week"] .day-col:hover {
  border-color: var(--cal-day-border);
  background: var(--cal-day-surface);
  box-shadow: var(--cal-day-shadow);
}

.grid.multi-week .day-col:hover {
  border-color: var(--cal-day-border);
}

.grid[data-view-mode="week"] .day-col.today-highlighted,
.grid.multi-week .day-col.today-highlighted {
  border: var(--ui-stroke-thin) solid var(--cal-day-border);
  box-shadow: var(--cal-day-shadow);
}

.grid[data-view-mode="week"] .day-col:not(.today-highlighted) .day-num { background: transparent; }

.grid.multi-week .week-section {
  background: transparent;
}

.grid.multi-week .week-rail {
  width: var(--rail-w);
}

.grid.multi-week .day-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-space-1);
  line-height: 1;
}

.grid.multi-week .day-num {
  line-height: 1;
  background: transparent;
}

.grid.multi-week :is(.day-overlap-chip, .day-work-flag) { display: none !important; }

.grid.multi-week .multi-week-more-items:focus-visible {
  color: var(--ui-accent);
  background: transparent;
  outline: var(--ui-stroke-thin) solid color-mix(in srgb, var(--ui-accent) 42%, transparent);
  outline-offset: var(--ui-stroke-thin);
}

/* WCAG 2.2 SC 1.4.11: ô tích là điểm bấm tần suất cao nhất của lịch, nên có
   thêm một quầng mờ ngoài viền — viền mảnh 2px alone có thể không đủ 3:1 trên
   vài nền màu, quầng solid phía sau bù lại mà không cần đổi token dùng chung. */
:is(.task-box, .event-box):focus-visible {
  outline-color: var(--ui-accent);
  outline-offset: var(--ui-stroke-thick);
  box-shadow: 0 0 0 calc(var(--ui-focus-ring-width) * 2) color-mix(in srgb, var(--ui-accent) 22%, transparent);
}

.gcal-event-icon,
.outlook-event-icon {
  display: inline-flex;
  margin: 0 var(--ui-space-1) 0 0;
  vertical-align: -2px;
}

.gcal-event-icon,
.outlook-event-icon {
  width: var(--task-icon-size);
  height: var(--task-icon-size);
  font-size: var(--task-meta-font);
}

.task-item:hover .task-prefix,
.task-item:focus-within .task-prefix { opacity: 0; }

/* =====================================================================
   PHÂN ĐOẠN TRONG CỘT NGÀY — nhãn buổi + vạch "bây giờ"
   Dựng bởi components/dayColumnGroups.js như một lượt hậu kỳ trên DOM đã
   sắp xong. Cả hai đều là phần tử trang trí thuần: không nhận sự kiện
   chuột, nên không cắt vùng thả của kéo-thả chạy trên .task-list.
   ===================================================================== */
.day-group-head {
  display: flex;
  /* .task-list là flex-column: không khoá lại thì nhãn bị ép co trong một
     cột nhiều việc và chữ viết hoa 9px bị cắt mất phần chân. */
  flex: 0 0 auto;
  align-items: center;
  gap: var(--ui-density-gap);
  padding: var(--ui-density-gap) var(--ui-density-pad-row) 0;
  pointer-events: none;
  user-select: none;
}

/* Nhãn đầu tiên sát ngay mép trên của vùng cuộn thì thừa một khoảng thở
   mà cột ngày vốn đã rất chật không có để cho. */
.day-group-head:first-child { padding-top: 0; }

.day-group-label {
  flex: 0 0 auto;
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-none);
  letter-spacing: var(--ls-caps-lg);
  white-space: nowrap;
}

/* Nhãn viết hoa đã tự nó là ranh giới. Kéo thêm một vạch ngang hết bề rộng
   cột cho MỖI nhãn nghĩa là một ngày ba buổi có ba đường kẻ, cộng vạch "bây
   giờ" và kẻ chân vùng "Đã hoàn tất" thành năm đường trong một cột hẹp —
   đúng chỗ rối mà người dùng thấy. Giữ phần tử trong DOM (dayColumnGroups.js
   vẫn dựng nó) nhưng không vẽ gì, để nó chỉ còn là khoảng đệm bên phải nhãn. */
.day-group-rule {
  flex: 1 1 auto;
  min-width: 0;
  height: 0;
  background: none;
}

/* ---------- Smart Live Now-Marker (Vạch Thời Gian Hiện Tại) ---------- */
.day-now-line {
  position: relative;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--ui-space-1-5);
  width: 100%;
  box-sizing: border-box;
  margin: var(--ui-space-1) 0;
  padding: 0 var(--ui-space-0-5);
  pointer-events: none;
  z-index: var(--ui-layer-control);
}

.day-now-pill {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: var(--ui-space-1);
  padding: var(--ui-space-0-5) var(--ui-space-2);
  border-radius: var(--dt-dimension-radius-full);
  background: var(--ui-accent-solid);
  color: var(--ui-text-on-accent);
  box-shadow: 0 1.5px 4px rgba(var(--ui-accent-rgb), 0.35); /* audit-keep: quầng sáng màu trạng thái (glow), không phải bậc độ nổi */
  line-height: 1;
}

.day-now-dot {
  width: var(--ui-space-1);
  height: var(--ui-space-1);
  border-radius: var(--ui-radius-circle);
  background: currentColor;
  box-shadow: 0 0 3px rgba(var(--ui-white-rgb), 0.8); /* audit-keep: vật liệu kính: highlight và độ sâu nhiều lớp theo --t, không thuộc bậc elevation đơn */
  animation: nowDotPulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; /* audit-keep: chuyển động biên đạo riêng (keyframes), không thuộc nhịp giao diện chuẩn */
}

.day-now-time {
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.day-now-rule {
  flex: 1 1 auto;
  min-width: 0;
  height: var(--ui-space-0-5);
  border-radius: var(--ui-radius-xs);
  background: linear-gradient(90deg, var(--ui-accent) 0%, rgba(var(--ui-accent-rgb), 0.35) 65%, transparent 100%);
}


/* Chỉ dạng xem Tuần: 7 cột nằm ngang cùng một hàng nên bề ngang là tài
   nguyên có tổng cố định — cột cuối tuần trống trả lại chỗ cho T2–T6.
   Nhiều tuần / Agenda / Ngày có cách chia khác nên không áp dụng. */
.grid:not(.multi-week):not(.agenda-view):not(.today-view) .day-col.weekend { flex: .82; }

/* =====================================================================
   ĐẦU CỘT NGÀY — số ngày là thông tin chính, tên thứ là phụ
   Trước đây hai thứ cùng cỡ 12px và số ngày còn bị bọc trong một vòng
   tròn nền xám, nên vòng tròn hút mắt hơn cả con số bên trong nó.
   ===================================================================== */
.grid[data-view-mode="week"] .day-num,
.grid.multi-week .day-num {
  min-width: 0;
  height: auto;
  padding: 0;
  border-radius: 0;
  font-weight: var(--fw-semibold);
}

.grid[data-view-mode="week"] .day-num { font-size: var(--fs-body); }

/* Dạng Tháng chật hơn hẳn: 11px là đủ đọc (mẫu dùng 11.5), 14px như dạng
   Tuần sẽ đẩy phần đầu thẻ cao lên và ăn mất một dòng công việc trong ô. */
.grid.multi-week .day-num { font-size: var(--fs-caption); }

.grid[data-view-mode="week"] .day-name {
  /* AT-UI 2026: tên thứ là nhãn chính của cột → body (14 / Lớn 18). */
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  color: var(--ui-text-secondary);
}

/* Tên thứ đã lên hàng tiêu đề chung phía trên lưới tháng, không lặp lại
   trong từng thẻ nữa — thẻ chỉ còn số ngày. */
.grid.multi-week .day-name { display: none; }

/* Hôm nay: bỏ vòng tròn tô đầy ở CẢ dạng Tuần lẫn dạng Tháng, thay bằng
   nền nhạt ở phần đầu cột + số màu nhấn. Vòng tròn là một hộp cố định
   26×26 nên nó chống lại mọi thay đổi cỡ chữ: khi con số to lên nó bị
   bóp thành hình bầu dục và cắt mất chữ số. Nền + màu chữ co giãn theo
   cỡ chữ nên không có ràng buộc đó. */
.grid[data-view-mode="week"] .day-col.today-highlighted .day-num,
.grid.multi-week .day-col.today-highlighted .day-num,
html:root .grid[data-view-mode="week"] .day-col.today-highlighted .day-num,
html:root .grid.multi-week .day-col.today-highlighted .day-num {
  background: transparent;
  color: var(--ui-accent);
}

.grid[data-view-mode="week"] .day-col.today-highlighted .day-head,
.grid.multi-week .day-col.today-highlighted .day-head {
  background: transparent;
}

.grid[data-view-mode="week"] .day-col.today-highlighted .day-name { color: var(--ui-accent); }

/* Ngân sách huy hiệu theo bề ngang thật của từng dạng xem.

   Một hàng việc có thể mang tới bốn thứ trước tiêu đề (giờ · lặp ↻ · trùng lịch
   ◎ · ghi chú 📄). Ở ô ngày của dạng Tháng (~130px) bốn thứ đó ăn gần hết hàng
   và tiêu đề — thứ DUY NHẤT giúp nhận ra việc — là thứ bị cắt.

   KHÔNG thu nhỏ icon bằng px ở đây: cỡ icon đã suy ra từ --task-effective-font
   ngay bên dưới, nên Tuần/Tháng vốn đã có icon nhỏ hơn Ngày/Danh sách và vẫn co
   theo cỡ chữ hệ điều hành. Chốt px sẽ vừa phá hợp đồng đó vừa đè lên khai báo
   đến sau (cssCascadeIntegrity.test.js bắt đúng ca này). Thứ cắt được là SỐ
   LƯỢNG huy hiệu, không phải kích thước.

   Dạng Tháng: bỏ hẳn hai huy hiệu CHỈ MANG TIN (lặp lại, có ghi chú). Hai thứ
   còn lại — trùng lịch và chuông sắp tới giờ — là CẢNH BÁO nên luôn hiện. Hai
   thứ bị bỏ vẫn đọc được ở dạng Tuần/Ngày và trong tooltip của hàng. */
.grid.multi-week .task-item :is(.task-repeat-icon, .linked-note-status) { display: none; }

.grid.today-view,
.grid.agenda-view { --task-effective-font: var(--fs-body); }

/* Dạng Tháng chỉ giữ icon + tiêu đề. Giờ giấc đã có ở dạng Tuần và dạng
   Ngày; trong ô tháng nó đẩy tiêu đề xuống dòng hai và làm ô chỉ chứa
   được một nửa số việc. */
.grid.multi-week :is(.task-time-label, .event-time-label) { display: none; }

.grid.multi-week .multi-week-shared-header::before {
  background: transparent;
  border-bottom: 0;
}

.grid.multi-week .day-head {
  min-height: 0;
  padding: var(--ui-space-px) var(--ui-density-pad-card) 0;
}

.grid.multi-week .priority-edge { display: none; }

.grid.multi-week .week-section {
  column-gap: var(--cell-gap);
  border: 0;
  border-radius: 0;
}

.grid.multi-week .week-section + .week-section { border-top: 0; }

/* Shared bright day card: no grey fill in Light mode. */
.grid.multi-week .day-col {
  border: var(--ui-stroke-thin) solid var(--cal-day-border);
  border-radius: var(--cal-day-radius);
  background: var(--cal-day-surface);
  box-shadow: var(--cal-month-day-shadow);
  padding: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}


.grid.multi-week .day-col:hover {
  border: var(--ui-stroke-thin) solid var(--cal-day-border);
  background: var(--cal-day-surface);
  box-shadow: var(--cal-month-day-shadow);
}

.grid.multi-week .day-num {
  font-weight: var(--fw-normal);
  color: var(--ui-text-primary);
}

.grid.multi-week .day-col.today .day-num,
.grid.multi-week .day-col.today-highlighted .day-num {
  color: var(--ui-accent);
  font-weight: var(--fw-semibold);
}

.grid.multi-week .day-col.outside-month,
html:root .grid.multi-week .day-col.outside-month,
html:root #grid.multi-week .day-col.outside-month:not(.drag-over):hover {
  border-color: var(--cal-day-border);
  opacity: 1;}

.grid.multi-week .day-col.outside-month .day-num {
  color: var(--ui-text-muted);
  font-weight: var(--fw-normal);
}

/* Nút bật/tắt cột T7–CN — xem renderWeekendToggle() trong calendarGrid.js.

/* Nút bật/tắt cột T7–CN — xem renderWeekendToggle() trong calendarGrid.js.

   ĐỊNH VỊ CỐ ĐỊNH Ở GÓC DƯỚI BÊN PHẢI (position: fixed) để khi cuộn ngang
   (overflow-x: auto ở compact/tight), nút luôn ghim cố định ở góc màn hình,
   không bị trôi theo các cột ngày khi cuộn ngang. */
/* Công tắc T7/CN là .ui-btn phụ bật/tắt sm (aria-pressed = đang hiện cột cuối tuần,
   GĐ F 01/10/2026); ở đây chỉ vị trí nổi góc dưới phải. */
/* Nổi TRÊN dải chân cột (BA 2026-10-09): bản cũ đè lên "✓ xong/tổng" của cột cuối. */
.weekend-toggle {
  position: fixed;
  right: var(--ui-space-3-5);
  bottom: calc(var(--ui-space-6) + var(--ui-size-lg));
  z-index: var(--ui-layer-header);
  gap: var(--ui-space-1-5);
}

/* Dạng Tháng: nằm trong hàng tên thứ (sticky = khối chứa), canh giữa dọc, sát mép phải. */
.weekend-toggle.is-in-header {
  position: absolute;
  top: 50%;
  right: var(--ui-space-2);
  bottom: auto;
  transform: translateY(-50%);
}

.weekend-toggle-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}

.weekend-toggle-icon svg {
  display: block;
  width: 1em;
  height: 1em;
}

.weekend-toggle-label {
  display: inline-block;
  font-weight: var(--fw-semibold, 600);
}

/* Số việc đang bị giấu — chỉ có ở trạng thái đang ẩn. */
.weekend-toggle-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 var(--ui-space-1-5);
  border-radius: var(--ui-radius-full);
  background: var(--ui-accent-solid);
  color: var(--ui-text-on-accent);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
}

.grid.multi-week .task-priority-dot {
  display: block;
  flex: 0 0 auto;
  width: calc(var(--fs-caption) * 0.36);
  height: calc(var(--fs-caption) * 0.36);
  border-radius: var(--ui-radius-circle);
  align-self: center;
  margin: 0;
}

.grid.multi-week .task-priority-dot.is-none {
  background: var(--tone-blue-bar);
}

.grid.multi-week :is(.gcal-event-icon, .outlook-event-icon) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--fs-caption);
  height: var(--fs-caption);
  font-size: var(--fs-caption);
  margin: 0;
  padding: 0;
  line-height: 1;
}

/* The reference has one standard ink for all task titles. Background alone
   identifies an item; semantic colour is reserved for its tiny markers. */

/* Task and calendar titles use the system's normal text weight in every
   primary calendar view. Event containers may be bold for old layouts, so
   set the actual readable title instead of relying on inheritance. */

/* A Month row must never change geometry on hover.  The former expanded-title
   treatment promoted the title to an absolutely positioned popup at the same
   time that the trailing action button appeared.  It could therefore escape
   the day card and overlap both the action and the adjacent day.  Full text
   remains available through the existing title tooltip; hover only reveals
   the in-row action. */
.grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item):hover {
  z-index: var(--ui-layer-control);
}

.grid.multi-week .task-meta-right {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  align-self: center;
  gap: var(--ui-space-0-5);
  color: var(--ui-text-muted);
  line-height: 1;
}

.grid.multi-week .task-meta-right :is(.task-repeat-icon, .task-meeting-icon, .linked-note-status, .meeting-overlap-icon) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: center;
  vertical-align: middle;
  width: var(--fs-caption);
  height: var(--fs-caption);
  line-height: 1;}

.grid.multi-week .task-meta-right svg {
  display: block;
  width: var(--fs-caption);
  height: var(--fs-caption);}

.grid.multi-week .day-divider { display: none !important; }

.grid.multi-week .day-chip { display: none !important; }

.grid.multi-week .task-list {
  overflow: hidden;
}

/* Không gạch ngang việc hoàn thành; màu chữ lấy từ --month-done-ink (calendar.css MỤC D). */
.grid.multi-week .task-item.done .task-text,
.grid.multi-week :is(.gcal-event-item, .outlook-event-item).event-done :is(.gcal-event-title, .outlook-event-title) {
  text-decoration: none;}



.grid.multi-week .multi-week-more-items {
  margin: 0;
  margin-left: auto;
  padding: 0;
  border: 0;
  border-radius: 0;
  color: var(--ui-accent);
  font-size: var(--fs-caption);
  font-weight: var(--fw-normal, 400);
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;}

.grid.multi-week .multi-week-more-items:hover {
  color: var(--ui-accent);
  text-decoration: underline;}

.grid.multi-week .week-rail {
  gap: var(--ui-space-px);
  padding: 0 var(--ui-space-0-5);
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  cursor: pointer;
}

.grid.multi-week .week-rail:hover .week-rail-week { color: var(--ui-accent); }

.grid.multi-week .week-rail-week {
  font-size: var(--fs-caption);
  font-weight: var(--fw-normal);
  color: var(--ui-text-muted);
}

.grid.multi-week .week-rail-range { display: none; }

.grid.multi-week .week-rail-current { display: none !important; }

.grid.multi-week .multi-week-shared-header { border-bottom: 0; }

.grid.multi-week :is(.multi-week-corner, .shared-day-label) {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 var(--ui-density-pad-card);
  font-size: var(--fs-caption);
  font-weight: var(--fw-normal);
  color: var(--ui-text-secondary);
  letter-spacing: var(--ls-tight);
  text-transform: none;
}

.grid.multi-week .multi-week-corner { font-size: var(--fs-caption); }

.task-priority-dot {
  flex: 0 0 auto;
  width: calc(var(--fs-caption) * 0.45);
  height: calc(var(--fs-caption) * 0.45);
  border-radius: var(--ui-radius-circle);
}

.task-priority-dot.is-none { background: rgba(var(--ink), .22); }

.grid.multi-week .task-box { display: none; }

/* Cụm phụ trợ dồn phải của dạng Ngày/Agenda: nhãn dự án + icon trạng thái.
   Đứng sau .task-text (đang flex:1) nên tự bị đẩy sát mép phải, ngay
   trước nút "…". */
.task-meta-right {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: var(--ui-space-1-5);
  margin-left: var(--ui-space-2);
  color: var(--ui-text-muted);
}

.task-meta-right .task-tags { margin-left: 0; }

/* =====================================================================
   ĐẦU CỘT DẠNG TUẦN — 30px, có số đếm và kẻ chân như mẫu
   ===================================================================== */

.grid[data-view-mode="week"] .day-chip {
  display: block;
  margin-left: auto;
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  color: var(--ui-text-muted);
}

.grid[data-view-mode="week"] .day-chip.empty { display: none; }

/* Dòng tạo việc ở đáy cột: .ui-btn nhẹ sm (rê/nhấn/focus do component); bố cục
   theo dạng xem ở @layer modules cuối file. */

/* A drawn undo icon has stable metrics on every Windows font stack. */
.task-undo-svg,
.task-repeat-svg {
  display: block;
  width: var(--ui-icon-xs);
  height: var(--ui-icon-xs);
  overflow: visible;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  transform: translate(.2px, .1px);
}

.task-repeat-svg { width: 1em; height: 1em; }

html:not([data-material="glass"]) .day-col:not(.drag-over):hover { background: var(--cal-day-surface); }

html:not([data-material="glass"]) :is(.gcal-event-item, .outlook-event-item, .task-item) { border-radius: var(--ui-radius-control); }

html:not([data-material="glass"]) .task-box { border-radius: var(--ui-radius-control); }

html:not([data-material="glass"]) .completed-toggle { border-radius: 0; }

/* Glass's own `.grid` rules above zero out the top
   inset (glass: margin-top 6px + padding-top 0),
   which left day/week/month cards touching .topbar directly in every
   alternate view for glass — Fluent never overrode .grid's padding,
   so it kept the base 10px top inset and never showed the problem. Multi-
   week's own sticky shared header (.multi-week-shared-header) already runs
   fine with this same 10px top inset under Fluent — its flush-to-the-window
   look comes from the ::before edge-bleed above, not from zero grid padding
   — so restoring the inset here for glass is not expected to
   reintroduce that old bug. */
/* Ngày KHÔNG nằm trong danh sách: .grid.today-view tự có lề trên = lề dưới
   (--ui-space-3-5, yêu cầu BA); ép padding-top ở đây làm lề trên 8px còn lề
   dưới 14px — lệch nhau chỉ riêng ở vật liệu Glass. */
html[data-material="glass"] :is(.grid[data-view-mode="week"], .grid.multi-week) { margin-top: var(--ui-space-2); padding-top: var(--ui-space-2); }

html[data-material="glass"] .day-col { border-left-color: rgba(var(--ink), .10); }

html[data-material="glass"] .day-col:not(.drag-over):hover {
  background: var(--cal-day-surface);
  box-shadow: var(--cal-day-shadow);
}

/* Keep Month on the same elevation contract after Glass's generic day rule. */
html:root .grid.multi-week .week-section { background: transparent; }

html:root .grid.multi-week .day-col { box-shadow: var(--cal-month-day-shadow); }

html:root .grid.multi-week .day-col:not(.drag-over):hover {
  border: var(--ui-stroke-thin) solid var(--cal-day-border);
  background: var(--cal-day-surface);
  box-shadow: var(--cal-month-day-shadow);
}

/* BA (2026-09-07): Tắt hiện border xanh, không đổi màu nền, không đổi bóng khi hover vào các card tại tất cả các dạng xem ngày tuần tháng, agenda.
   Viền, nền, bóng giữ NGUYÊN đúng bằng lúc nghỉ.
   Selector qua `#grid` (id) để chắc chắn thắng mọi rule `.day-col:hover` phía trên. */
html:root #grid .day-col:not(.drag-over):hover {
  background: var(--cal-day-surface);
  border-color: var(--cal-day-border);
  box-shadow: var(--cal-day-shadow);
}

html:root #grid.multi-week .day-col:not(.drag-over):hover {
  box-shadow: var(--cal-month-day-shadow);
}

html:root #grid.agenda-view .agenda-day:not(.drag-over):hover {
  background: var(--view-panel-bg);
  border-color: var(--ux-border);
  box-shadow: var(--view-panel-shadow);
}

/* Dạng "Hôm nay": thẻ nhìn thấy được là `.today-main`, còn `.today-day` bên
   trong nghỉ ở nền TRONG SUỐT (xem ~L7094). Ghim lại đúng nền lúc nghỉ (trong suốt)
   cho mọi trạng thái hover; viền/bóng của `.today-highlighted` vẫn giữ nguyên. */
html:root #grid .today-main .today-day:not(.drag-over):hover {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
}

html:root #grid :is(.today-main, .today-rail-card, .today-backlog-rail):not(.drag-over):hover {
  background: var(--cal-day-surface);
  border-color: var(--cal-day-border);
  box-shadow: var(--cal-day-shadow);
}

html[data-material="glass"] :is(.gcal-event-item, .outlook-event-item) {
  border: 0;
  box-shadow: none;
}

/* Global override for day column in week/month views
   BA (2026-09-07): Bỏ header xanh (top accent stripe) và không đổ bóng lớn trên ngày hôm nay.
   Giữ nguyên border và box-shadow như thẻ ngày thường lúc nghỉ. */
html .day-col.today-highlighted,
.day-col.today-highlighted {
  box-shadow: var(--cal-day-shadow);
  border-color: var(--cal-day-border);
}

html .grid.multi-week .day-col.today-highlighted,
.grid.multi-week .day-col.today-highlighted {
  box-shadow: var(--cal-month-day-shadow);
}

/* Today Main View */
html .today-main .today-day.today-highlighted,
.today-main .today-day.today-highlighted {
  box-shadow: none;
  border-color: transparent;
}

/* Gravity drop effect for completed tasks */
.task-land-complete {
  animation: gravityDrop 0.5s cubic-bezier(0.55, 0.085, 0.68, 0.53) forwards; /* audit-keep: chuyển động biên đạo riêng (keyframes), không thuộc nhịp giao diện chuẩn */
}

.task-rise-restore {
  animation: antiGravityRise var(--ui-duration-slow) var(--ui-ease) forwards;
}

/* =====================================================================
   UNIFIED CALENDAR ITEM EXPERIENCE
   One information order and one action model across Today, Agenda, Week
   and Multi-week. View-specific density remains intentional.
   ===================================================================== */
:is(.task-item, .gcal-event-item, .outlook-event-item) {
  position: relative;
  min-height: max(var(--ui-size-touch), var(--ui-row-height));
  padding-right: 42px; /* audit-keep: chừa chỗ cho icon/nút cuối ô nhập, rộng theo nút */
  transition: background-color var(--ui-duration-fast) var(--motion-standard),
    box-shadow var(--ui-duration-standard) var(--motion-standard),
    opacity var(--ui-duration-standard) var(--motion-standard),
    transform var(--ui-duration-standard) var(--motion-standard);
}

:is(.task-item, .gcal-event-item, .outlook-event-item):hover,
:is(.task-item, .gcal-event-item, .outlook-event-item):focus-within {
  padding-right: 42px; /* audit-keep: chừa chỗ cho icon/nút cuối ô nhập, rộng theo nút */
}

:is(.task-item, .gcal-event-item, .outlook-event-item):active:not(.dragging) {
  transform: none !important;
}

/* Hàng sự kiện Google/Outlook ở dạng Ngày về nền cơ bản của thẻ. Nền xanh
   --ui-event-fill khiến hàng lịch nổi hơn cả công việc thật, trong khi
   chúng chỉ là thông tin tham chiếu. Loại sự kiện vẫn nhận ra được qua
   icon bên trái và cạnh ưu tiên. */
.grid.today-view :is(.gcal-event-item, .outlook-event-item),
.today-main :is(.gcal-event-item, .outlook-event-item),
.grid.agenda-view .agenda-day :is(.gcal-event-item, .outlook-event-item) {
  background: transparent;
}

.grid.today-view :is(.gcal-event-item, .outlook-event-item):hover,
.today-main :is(.gcal-event-item, .outlook-event-item):hover,
.grid.agenda-view .agenda-day :is(.gcal-event-item, .outlook-event-item):hover {
  background: transparent;
}

.grid.agenda-view .agenda-day :is(.task-item, .gcal-event-item, .outlook-event-item):hover,
.grid.agenda-view .agenda-day :is(.task-item, .gcal-event-item, .outlook-event-item):focus-within {
  padding-right: 44px; /* audit-keep: chừa chỗ cho icon/nút cuối ô nhập, rộng theo nút */
}

/* Chiều cao hàng: để nội dung tự quyết, không đặt sàn.
   Sàn cũ max(34px, --ui-row-height) và bản ghi đè 48px ngay dưới nó là
   nguyên nhân thật của việc lưới Tuần/Tháng dày hơn hẳn thiết kế mẫu —
   mẫu dùng ~32px cho Tuần và ~19px cho Tháng, đều nhỏ hơn sàn.
   Đây cũng là khối đứng SAU cùng trong file cho các selector này, nên mọi
   ghi đè đặt phía trên đều thua cascade; phải sửa tại chỗ. */
.grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item) {
  min-height: 0;
  padding: var(--ui-space-0-5) var(--ui-density-pad-card);
  background: transparent;
  border-radius: var(--ui-radius-control);
}

.grid.multi-week .task-list {
  padding: var(--ui-space-px) var(--ui-density-pad-card) var(--ui-space-0-5);
  /* density-gap × .4 ra 1,6px lệch lưới; bậc nửa 2px gần nhất (AT-UI 2026). */
  gap: var(--ui-space-0-5);
}

/* Completed-group inside multi-week: compact, collapsed by default,
   constrained to its day column so it never pushes the week row height. */
.grid.multi-week .completed-group {
  margin-top: var(--ui-space-0-5);
  gap: var(--ui-space-px);
}

.grid.multi-week .completed-group.is-push-bottom {
  margin-top: auto;
}

.grid.multi-week .completed-toggle {
  min-height: var(--ui-size-sm);
  padding: 0 var(--ui-space-1);
  font-size: var(--fs-caption);
  border-top-color: var(--ui-divider);
}

.grid.multi-week .completed-list {
  gap: var(--ui-space-px);
  max-height: var(--dt-dimension-layout-120);
  overflow-y: auto;
}

.grid.multi-week .completed-list .task-item {
  min-height: max(var(--dt-dimension-row-list-dense), var(--ui-row-height));
  padding: var(--ui-space-px) var(--ui-space-1-5) var(--ui-space-px) var(--ui-space-2);
  font-size: var(--fs-caption);
}

/* Hide only the checkbox at rest — the number/bullet (.task-prefix) stays. */
:is(.grid[data-view-mode="week"], .grid.multi-week) .task-box {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--ui-duration-fast) var(--motion-standard);
}

:is(.grid[data-view-mode="week"], .grid.multi-week) :is(.task-item, .gcal-event-item, .outlook-event-item):hover .task-box,
:is(.grid[data-view-mode="week"], .grid.multi-week) :is(.task-item, .gcal-event-item, .outlook-event-item):focus-within .task-box {
  opacity: 1;
  pointer-events: auto;
}

/* Hide the prefix number/bullet on hover so it doesn't conflict with checkbox */
:is(.grid[data-view-mode="week"], .grid.multi-week) :is(.task-item):hover .task-prefix,
:is(.grid[data-view-mode="week"], .grid.multi-week) :is(.task-item):focus-within .task-prefix {
  opacity: 0;
}

:is(.grid[data-view-mode="week"], .grid.multi-week) .calendar-item-more {
  opacity: 0;
}

:is(.grid[data-view-mode="week"], .grid.multi-week) :is(.task-item, .gcal-event-item, .outlook-event-item):hover .calendar-item-more,
:is(.grid[data-view-mode="week"], .grid.multi-week) :is(.task-item, .gcal-event-item, .outlook-event-item):focus-within .calendar-item-more,
:is(.grid[data-view-mode="week"], .grid.multi-week) .calendar-item-more:focus-visible {
  opacity: 1;
}

/* The prefix lane is the generous completion target. Its visual mark remains
   compact, so easier clicking does not make the row look heavier. */
.task-box,
.gcal-event-item .event-box,
.outlook-event-item .event-box {
  border-radius: var(--ui-radius-circle);
  box-shadow: none;}

.task-box::before {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  width: var(--ui-icon-sm);
  height: var(--ui-icon-sm);
  box-sizing: border-box;
  border: var(--ui-stroke-thick) solid var(--ui-text-muted);
  border-radius: var(--ui-radius-circle);
  background: color-mix(in srgb, rgb(var(--ui-surface-raised-rgb)) 78%, transparent);
  transform: translate(-50%, -50%);
  transition: border-color var(--ui-duration-fast) var(--motion-standard),
    background-color var(--ui-duration-fast) var(--motion-standard),
    box-shadow var(--ui-duration-fast) var(--motion-standard);
}

.task-box:hover::before,
.task-box:focus-visible::before {
  border-color: var(--ui-accent);
  background: var(--ui-selected);
  box-shadow: 0 0 0 calc(var(--ui-focus-ring-width) * 1.5) color-mix(in srgb, var(--ui-accent) 14%, transparent);
}

.task-item.done .task-box::before,
.gcal-event-item.event-done .event-box::before,
.outlook-event-item.event-done .event-box::before {
  border-color: var(--ui-success);
}

.task-box:focus-visible,
.calendar-item-more:focus-visible {
  outline: var(--ui-stroke-thick) solid var(--ui-focus-ring);
  outline-offset: var(--ui-stroke-thin);
}

.task-item.mode-number .task-box,
.task-item.mode-bullet .task-box { opacity: 0; }

.task-item.done .task-prefix { opacity: 0; }

.task-item.done .task-box { opacity: .72; }

.task-item:hover .task-box,
.task-item:focus-within .task-box { opacity: 1; }

.task-undo-svg { position: relative; z-index: 1; }

.event-prefix-slot {
  width: var(--ui-size-md);
}

.gcal-event-body,
.outlook-event-body { margin-left: 37px; } /* audit-keep: hình học riêng của khối, nằm giữa hai bậc thang (chênh hơn 2px) */

/* Reading views use the same two visual lanes for tasks and calendar events:
   source icon with the task number, then time/content on one shared column. */
.grid.agenda-view .agenda-day :is(.gcal-event-item, .outlook-event-item) {
  padding-left: var(--ui-space-3);
}

.grid.agenda-view .agenda-day .event-prefix-slot {
  left: var(--ui-space-3);
  width: var(--ui-size-md);
}

.grid.agenda-view .agenda-day :is(.gcal-event-body, .outlook-event-body) {
  margin-left: calc(var(--ui-space-8) + var(--task-inline-gap));
}

.gcal-event-item .event-box,
.outlook-event-item .event-box { opacity: 0; }

/* Task and calendar-event rows (Day/Today, Week, Month/Multi-week, Agenda)
   are square-cornered (see .task-item, and week/multi-week's own
   border-radius:0 override) specifically so this flush-left placement is
   safe here — no rounded row or clipping ancestor to cut it into a curve. */
.task-item .priority-edge,
.gcal-event-item .priority-edge,
.outlook-event-item .priority-edge,
.backlog-item .priority-edge {
  left: 0;
}

/* .today-backlog-rail ("Trễ hạn") clips to its own rounded corner and the
   bottom row sits flush against it (no inner bottom padding — see the
   :last-child comment above), so only that one row's marker needs to taper
   into the same curve instead of being clipped at a hard edge. The 3px
   width caps how much of this ever actually shows. */
.backlog-list .backlog-item:last-child .priority-edge {
  border-radius: 0 0 0 var(--view-panel-radius);
}

.linked-note-status {
  width: auto;
  min-height: calc(var(--task-effective-font) * 1.2);
  margin-right: 0;
  color: var(--tone-purple-fg);
  background: var(--tone-purple-bg);
  border-radius: var(--ui-radius-control);
  padding: 0 var(--ui-space-1);
  cursor: pointer;
  pointer-events: auto !important;
  opacity: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  transition: transform var(--ui-duration-fast) var(--motion-standard), filter var(--ui-duration-fast) var(--motion-standard);
}

.linked-note-status:hover {
  color: var(--tone-purple-fg);
  filter: brightness(0.92);
  transform: none;
}

.linked-note-status svg {
  width: calc(var(--task-effective-font) * 1.05);
  height: calc(var(--task-effective-font) * 1.05);
  display: block;
  pointer-events: none;
}

/* Căn thẳng hàng & phóng to icon ở Dạng xem Ngày & Agenda */
:is(.today-workspace, .grid[data-view-mode="today"], .grid[data-view-mode="day"], .grid.agenda-view, .grid[data-view-mode="agenda"], .today-main) .task-meta-right {
  display: inline-flex;
  align-items: center;
  gap: var(--ui-space-1);
  margin-left: auto;
}

:is(.today-workspace, .grid[data-view-mode="today"], .grid[data-view-mode="day"], .grid.agenda-view, .grid[data-view-mode="agenda"], .today-main) .task-meta-right :is(.linked-note-status, .task-repeat-icon, .task-meeting-icon, .meeting-overlap-icon) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
  min-height: calc(var(--task-effective-font) * 1.2);
  border-radius: var(--ui-radius-control);
  line-height: var(--lh-snug);
  font: var(--fw-semibold) var(--fs-caption)/var(--lh-snug) var(--app-font);}

:is(.today-workspace, .grid[data-view-mode="today"], .grid[data-view-mode="day"], .grid.agenda-view, .grid[data-view-mode="agenda"], .today-main) .task-meta-right :is(.linked-note-status, .task-repeat-icon, .task-meeting-icon, .meeting-overlap-icon) svg {
  width: calc(var(--task-effective-font) * 1.05);
  height: calc(var(--task-effective-font) * 1.05);
  display: block;
}

/* The Today backlog is its own renderer rather than a .task-item row. Keep
   its metadata in the same visual language so overdue work does not lose the
   project, time, or existing-note context carried by the primary calendar. */
.backlog-item-meta {
  min-width: 0;
}

.backlog-item-meta .task-tags {
  min-width: 0;
  margin-left: auto;
  order: 1;
  overflow: hidden;
  justify-content: flex-end;
}

.backlog-item-meta .backlog-item-when {
  order: 2;
  margin-left: 0;
  display: inline-flex;
  align-items: center;
  gap: var(--ui-space-1);
  flex: 0 0 auto;
}

.backlog-item-meta .task-tag {
  max-width: none;
}

.backlog-item-meta .linked-note-status {
  flex: 0 0 auto;
  margin: 0;
  color: var(--tone-purple-fg);
  background: var(--tone-purple-bg);
  border-radius: var(--ui-radius-control);
  padding: 0 var(--ui-space-1);
}

.backlog-item-time {
  display: inline-flex;
  align-items: center;
  gap: var(--ui-space-0-5);
  padding: 0 var(--ui-space-1);
  border-radius: var(--ui-radius-pill);
  background: var(--tone-orange-bg);
  color: var(--tone-orange-fg);
  flex: 0 0 auto;
  font-family: var(--app-font);
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  line-height: var(--lh-none, 1);
  height: calc(var(--task-effective-font) * 1.22);
  box-sizing: border-box;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  vertical-align: middle;
}

.backlog-item-time svg,
.backlog-item-time .task-time-clock-icon {
  width: calc(var(--task-effective-font) * 0.85);
  height: calc(var(--task-effective-font) * 0.85);
  flex-shrink: 0;
  display: block;
}

.backlog-item-meta .backlog-item-date {
  flex: 0 0 auto;
  white-space: nowrap;
  font-size: var(--task-meta-font, calc(var(--task-effective-font, var(--font-task)) * .85));
  font-variant-numeric: tabular-nums;
}

/* One stable trailing action replaces the separate note, priority and
   processing controls. It remains faintly discoverable without hover. */
.calendar-item-more svg { pointer-events: none; }

:is(.task-item, .gcal-event-item, .outlook-event-item, .backlog-item):hover .calendar-item-more,
:is(.task-item, .gcal-event-item, .outlook-event-item, .backlog-item):focus-within .calendar-item-more {
  color: var(--ui-text-primary);
  opacity: 1;
}

.calendar-item-more:hover {
  color: var(--ui-accent);
  background: color-mix(in srgb, var(--ui-accent) 18%, var(--ux-overlay));
  box-shadow: var(--elev-2);
}

.backlog-item { padding-right: 44px; } /* audit-keep: chừa chỗ cho icon/nút cuối ô nhập, rộng theo nút */

/* Unified, keyboard-navigable action menu. Forty-four-pixel rows make every
   choice easy to acquire with mouse, touchpad or touch. */
.calendar-action-menu {
  position: fixed;
  z-index: var(--layer-popover, 1200);
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  overflow: auto;
  overscroll-behavior: contain;
  color: var(--ui-text-primary);
  background: var(--ux-overlay);
  border: var(--ui-stroke-thin) solid var(--ui-divider);
  opacity: 0;
  transform: scale(var(--ui-motion-scale-popover));
  transform-origin: top right;
  transition: opacity var(--ui-duration-fast) var(--motion-standard), transform var(--ui-duration-fast) var(--motion-standard);
}

.calendar-action-menu.opens-up {
  flex-direction: column-reverse;
  transform-origin: bottom right;
}

.calendar-action-menu.is-open { opacity: 1; transform: scale(1); }

.calendar-action-menu-heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-space-1-5);
  min-width: 0;
  box-sizing: border-box;
}

.calendar-action-menu-title {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  color: var(--ui-text-primary);
  font: var(--fw-semibold) var(--fs-body)/var(--lh-snug) var(--app-font);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Nút Đóng là .ui-btn nhẹ icon md (cùng kiểu nút đóng dialog). */
.calendar-action-menu-close {
  flex: 0 0 auto;
  margin: 0 calc(-1 * var(--ui-space-0-5)) 0 0;
}

.calendar-action-menu-section {
  border-top: var(--ui-stroke-thin) solid var(--ui-divider);
  color: var(--ui-text-muted);
  font: var(--fw-overline) var(--fs-caption)/var(--lh-overline) var(--app-font);
}

.calendar-action-menu-heading + .calendar-action-menu-section {
  margin-top: 0;
  border-top: 0;
}

/* The body's DOM order is fixed (most-used group first); when the popover
   flips to open above its anchor, reversing the flex stacking here keeps
   the most-used group closest to the cursor and "Xóa" farthest either way.
   Each .calendar-action-menu-group keeps its own normal top-down order
   (header above its items) regardless of this reversal. */
.calendar-action-menu-body { display: flex; flex-direction: column; }

.calendar-action-menu-body.opens-up { flex-direction: column-reverse; }

.calendar-action-menu-body.opens-up .calendar-action-menu-group-danger {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

.calendar-action-menu-body.opens-up > .calendar-action-menu-group:first-child {
  border-top: var(--ui-stroke-thin) solid var(--ui-divider);
  margin-top: var(--ui-space-1);
  padding-top: var(--ui-space-1);
}

.calendar-action-menu.opens-up .calendar-action-menu-heading {
  border-top: var(--ui-stroke-thin) solid var(--ui-divider);
  margin-top: var(--ui-space-1);
  padding: var(--ui-space-1) var(--ui-space-0-5) var(--ui-space-0-5) var(--ui-space-2);
}

.calendar-action-menu-group { display: flex; flex-direction: column; }

.calendar-action-menu-group:first-child > .calendar-action-menu-section {
  margin-top: 0;
  border-top: 0;
}

/* Unlabeled group separator — just a thin rule, no uppercase caption. */
.calendar-action-menu-divider {
  margin: var(--ui-space-0-5) var(--ui-space-1-5);
  border-top: var(--ui-stroke-thin) solid var(--ui-divider);
}

.calendar-action-menu-group-danger {
  margin-top: var(--ui-space-1);
  padding-top: var(--ui-space-1);
  border-top: var(--ui-stroke-thin) solid var(--ui-divider);
}

.calendar-action-menu-item {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;
  border: 0;
  color: var(--ui-text-primary);
  background: transparent;
  font: var(--fw-medium) var(--fs-body)/var(--lh-snug) var(--app-font);
  text-align: left;
  cursor: pointer;
}

.calendar-action-menu-item > * { position: relative; z-index: 1; }

.calendar-action-menu-item svg {
  color: var(--ui-text-secondary);
}

.calendar-action-menu-item:hover,
.calendar-action-menu-item:focus-visible {
  color: var(--ui-accent);
  background: color-mix(in srgb, var(--ui-accent) 11%, transparent);
  outline: 0;
}

.calendar-action-menu-item:hover svg,
.calendar-action-menu-item:focus-visible svg { color: currentColor; }

/* Gợi ý phím tắt chữ cái, đẩy về mép phải hàng (kiểu menu ngữ cảnh chuẩn). */
.calendar-action-menu-item .calendar-action-menu-shortcut {
  margin-left: auto;
  padding-left: var(--ui-space-3);
  color: var(--ui-text-muted);
  font: var(--fw-normal) var(--fs-body)/var(--lh-snug) var(--app-font);
}

.calendar-action-menu-item.is-danger { color: var(--ui-danger); }

.calendar-action-menu-item.is-danger:hover,
.calendar-action-menu-item.is-danger:focus-visible {
  background: color-mix(in srgb, var(--ui-danger) 12%, transparent);
}

.calendar-action-menu-custom label {
  display: block;
  margin-bottom: var(--ui-space-1-5);
  color: var(--ui-text-secondary);
  font: var(--fw-semibold) var(--fs-caption)/var(--lh-tight) var(--app-font);
}

.calendar-action-menu-custom > div { display: flex; gap: var(--ui-space-1-5); }

.calendar-action-menu-custom input,
.calendar-action-menu-custom button {
  box-sizing: border-box;
  border-radius: var(--ui-radius-control);
  font: var(--fw-semibold) var(--fs-body)/var(--lh-none) var(--app-font);
}

.calendar-action-menu-custom input {
  min-width: 0;
  flex: 1;
  padding: 0 var(--ui-space-2);
  color: var(--ui-text-primary);
  background: rgba(var(--ui-surface-fill-rgb), .6);
  border: var(--ui-stroke-thin) solid var(--ui-divider);
}

.calendar-action-menu-custom button {
  padding: 0 var(--ui-space-3);
  border: 0;
  color: var(--ui-text-on-accent);
  background: var(--ui-accent-solid);
  cursor: pointer;
}

.calendar-action-menu-custom button:focus-visible {
  outline: var(--ui-focus-ring-width) solid var(--ui-focus-ring);
  outline-offset: var(--ui-focus-ring-offset);
}

.calendar-action-menu-custom input:focus-visible {
  outline: none;
  border-color: var(--ux-control-border-active);
  box-shadow: var(--ui-control-ring);
}

/* Priority choices are part of the same interaction-size system. */
.calendar-action-menu {
  padding: var(--ui-space-1);
  border-radius: var(--ui-radius-panel);
  box-shadow: var(--elev-4);
}

.calendar-action-menu-heading { padding: var(--ui-space-0-5) var(--ui-space-0-5) var(--ui-space-1) var(--ui-space-2); }

.calendar-action-menu-section { padding: var(--ui-space-1) var(--ui-space-1-5) var(--ui-space-0-5); font-size: var(--fs-caption); margin-top: var(--ui-space-0); }

/* BA 29/09/2026: mục menu = cỡ control md 32 (Fluent MenuItem), trước ra 26px lệch thang. */
.calendar-action-menu-item { box-sizing: border-box; min-height: var(--ui-size-md); padding: 0 var(--ui-space-2); border-radius: var(--ui-radius-control); font-size: var(--fs-body); gap: var(--ui-space-1-5); }

.calendar-action-menu-item svg { width: var(--ui-icon-xs); height: var(--ui-icon-xs); flex: 0 0 var(--ui-icon-xs); }

.calendar-action-menu-item.is-check svg { color: var(--ui-success, var(--tone-green-fg)); }

.calendar-action-menu-item.is-undo svg { color: var(--ui-warning, var(--tone-orange-fg)); }

.calendar-action-menu-item.is-edit svg { color: var(--ui-accent); }

.calendar-action-menu-item.is-note svg { color: var(--tone-blue-fg); }

.calendar-action-menu-item.is-tomorrow svg { color: var(--tone-purple-fg); }

.calendar-action-menu-item:is(.is-move, .is-monday, .is-calendar) svg { color: var(--tone-blue-fg); }

.calendar-action-menu-custom {
  margin: var(--ui-space-1) 0 var(--ui-space-0);
  padding: var(--ui-space-2);
  border-radius: var(--ui-radius-control);
  background: rgba(var(--ui-surface-fill-rgb), .55);
}

.calendar-action-menu-custom input,
.calendar-action-menu-custom button { min-height: var(--ui-size-md); font-size: var(--fs-body); }

.calendar-action-menu-custom button {
  box-shadow: 0 3px 10px color-mix(in srgb, var(--ui-accent) 23%, transparent); /* audit-keep: quầng sáng màu trạng thái (glow), không phải bậc độ nổi */
}

/* BA 10/10/2026: một hàng "Giờ [Từ] → [Đến] ×", không khung lồng khung.
   Cụm cao đúng một ô nhập size.sm; ô giờ là ô chữ 24h gõ tắt (calendarActionMenu.js,
   utils/timeEntry.js) — ô type=time native theo Region Windows nên hay ra 12h
   kèm ô SA/CH. Nhãn đặt cùng hàng, lề ngang bằng mục menu (space.2). */
.calendar-task-time-editor {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  margin: 0 0 var(--ui-space-1);
  padding: 0 var(--ui-space-2);
  color: var(--ui-text-secondary);
  font: var(--fw-semibold) var(--fs-caption)/var(--lh-none) var(--app-font);
  box-sizing: border-box;
}

.calendar-task-time-label { flex: 0 0 auto; white-space: nowrap; }

/* BA 10/10/2026 (lượt 2): cả vùng "[Từ] → [Đến] ×" là MỘT ô nhập — dùng khung
   ghép .ui-field-group--sm chuẩn (cao, viền, nền, hover, focus-within, nút ×
   từ component), hai ô con trong suốt. Ở đây chỉ chia bề rộng + căn chữ số. */
.calendar-task-time-input-wrap {
  flex: 1 1 auto;
  min-width: 0;
}
.calendar-task-time-input-wrap:has([aria-invalid="true"]) { border-color: var(--ui-danger); }

/* Hai ô con chia đều phần còn lại thay vì ghim px để cỡ Lớn không cắt chữ số phút. */
.calendar-task-time-input-wrap > .calendar-task-time-input {
  flex: 1 1 0;
  min-width: 0;
  color: var(--ui-text-primary);
  font: var(--fw-semibold) var(--fs-caption)/var(--lh-none) var(--app-font);
  text-align: center;
  font-variant-numeric: tabular-nums;
  outline: none;
}
.calendar-task-time-input::placeholder { color: var(--ui-text-muted); }
.calendar-task-time-input[aria-invalid="true"] { color: var(--ui-danger); }
/* Ô "Đến" khoá khi chưa có giờ đầu: chữ muted, không dùng opacity (ARS-1). */
.calendar-task-time-input:disabled { color: var(--ui-text-muted); cursor: not-allowed; }

.calendar-task-time-sep { color: var(--ui-text-muted); font-size: var(--fs-caption); flex: 0 0 auto; }

/* "×" xoá giờ là .ui-btn nhẹ icon sm + --danger-hover, cỡ do khung ghép sm lo. */
.calendar-task-time-clear { flex: 0 0 auto; }

/* The task menu owns priority and rescheduling in one compact surface.
   Color-only swatches (no label text) — the option's `title` carries the
   name for hover/tooltip and screen readers instead. */
.calendar-priority-choices {
  display: flex;
  align-items: center;
  gap: var(--ui-space-1-5);
  padding: var(--ui-space-px) var(--ui-space-1) var(--ui-space-1);
}

/* Ô ưu tiên là .ui-swatch (vùng bấm 24, vòng 16, đang chọn = vòng nhấn; GĐ F
   01/10/2026); chấm màu ưu tiên nằm giữa vòng. */
.calendar-priority-choice {
  display: grid;
  place-items: center;
  background-color: var(--ui-surface-raised);
}

.calendar-priority-dot { width: var(--ui-space-2-5); height: var(--ui-space-2-5); border-radius: var(--ui-radius-circle); background: var(--ui-text-muted); }


.calendar-move-more { padding-top: var(--ui-space-px); }

.calendar-move-more.hidden { display: none; }

/* Tags share the task's text flow: no reserved column, so untagged rows keep
   exactly their former width. */
.task-tags { display: inline-flex; align-items: center; gap: var(--ui-space-0-5); margin-left: var(--task-icon-gap, var(--ui-space-1)); vertical-align: middle; white-space: nowrap; }

/* Cỡ và chiều cao của nhãn đo bằng cỡ chữ của chính hàng việc. Bản cũ chốt
   9px/17px cho mọi dạng xem: ở dạng Ngày (chữ 15px) nhãn nhỏ như chú thích,
   ở dạng Tháng (chữ ~10px) nhãn lại cao gần bằng cả dòng chữ. */
.task-tag { display: inline-flex; align-items: center; min-height: calc(var(--task-effective-font) * 1.15); max-width: none; padding: 0 var(--ui-space-1-5); border-radius: var(--ui-radius-control); color: color-mix(in srgb, var(--tag-color) 78%, var(--ui-text-primary)); background: color-mix(in srgb, var(--tag-color) 16%, transparent); font-family: var(--app-font); font-size: calc(var(--task-effective-font) * .78); font-weight: var(--fw-semibold); line-height: calc(var(--task-effective-font) * 1.15); }

/* Nhãn chỉ mang tên dự án: màu nền/chữ của chip đã đủ phân biệt, không vẽ thêm chấm màu. */
.task-tag-more { color: var(--ui-text-secondary); font: var(--fw-semibold) var(--fs-micro)/var(--lh-none) var(--app-font); }

.task-item.done .task-tags { opacity: .52; }

.calendar-tag-picker { display: flex; flex-wrap: wrap; gap: var(--ui-space-1); padding: var(--ui-space-px) var(--ui-space-px) var(--ui-space-1); color: var(--ui-text-secondary); font: var(--fw-semibold) var(--fs-micro)/var(--lh-snug) var(--app-font); }

.calendar-tag-choice { position: relative; display: inline-flex; align-items: center; gap: var(--ui-space-1); min-height: var(--ui-size-sm); max-width: 100%; padding: var(--ui-space-0-5) var(--ui-space-1-5); border: var(--ui-stroke-thin) solid var(--ui-divider); border-radius: var(--ui-radius-control); color: var(--ui-text-secondary); background: rgb(var(--ui-surface-raised-rgb)); font: var(--fw-semibold) var(--fs-micro)/var(--lh-none) var(--app-font); cursor: pointer; }

.calendar-tag-choice > * { position: relative; z-index: 1; }

.calendar-tag-choice i { width: var(--ui-space-2); height: var(--ui-space-2); border-radius: var(--ui-radius-circle); background: var(--tag-color); flex: 0 0 auto; }

.calendar-tag-choice.is-selected { color: var(--ui-text-primary); border-color: color-mix(in srgb, var(--tag-color) 55%, var(--ui-divider)); background: color-mix(in srgb, var(--tag-color) 12%, rgb(var(--ui-surface-raised-rgb))); }

@media (pointer: coarse) {
  .calendar-item-more { opacity: .8; }
  .calendar-action-menu-item { min-height: var(--ui-space-12); }
}

@media (prefers-reduced-motion: reduce) {
    :is(.task-item, .gcal-event-item, .outlook-event-item):active:not(.dragging) { transform: none; }
}

:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid.multi-week) :is(.task-item, .gcal-event-item, .outlook-event-item) {
  gap: var(--cal-lead-gap);
  padding-left: calc(var(--task-effective-font) * 0.45);
}

:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid.multi-week) :is(.task-item, .gcal-event-item, .outlook-event-item)[class*="has-priority-"] {
  padding-left: calc(var(--task-effective-font) * 0.45);
}

/* Số thứ tự đứng CÙNG MỘT DÒNG với giờ giấc và tên việc, nên phải dùng đủ bộ
   ba của cùng vai đó. Trước đây nó lấy cỡ chữ đúng nhưng line-height 1 (trong
   khi dòng chữ là 1.35) và weight 500 (trong khi tên việc bị ép về 400), lại
   là phần tử absolute canh giữa làn — ba thứ cộng lại làm hộp chữ của nó thấp
   hơn hẳn hộp chữ bên cạnh, mắt đọc ra "số nhỏ hơn chữ" dù cùng px.
   max-width 24px cũng bỏ: làn đã có bề rộng riêng, cap px cứng ở đây chỉ cắt
   số 2 chữ số khi cỡ chữ lớn. */
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid.multi-week) .task-prefix {
  font-size: var(--task-effective-font);
  font-weight: var(--fw-semibold);
  line-height: var(--task-line-height, 1.35);
  max-width: var(--cal-lead-lane);
  font-variant-numeric: tabular-nums;
}

/* Chỉ thu bề rộng vùng bấm cho khớp làn hẹp; left/top/transform giữ nguyên
   mặc định (canh giữa làn) để ô tích và số vẫn đồng tâm. Rộng đúng
   làn + 2×gap nên mép phải dừng ngay chỗ chữ bắt đầu, không nuốt cú bấm vào
   chữ. */

/* Vòng tròn ô tích đo theo cỡ chữ việc để nằm gọn trong làn số (đã co theo
   font). Sàn 13px giữ đủ to để bấm ở cỡ chữ nhỏ nhất. */
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid.multi-week) .task-box::before {
  width: max(var(--ui-icon-xs), calc(var(--task-effective-font) * 1.28));
  height: max(var(--ui-icon-xs), calc(var(--task-effective-font) * 1.28));
}

/* Hàng lịch ngoài: bỏ làn absolute + margin-left 37px, đưa về đúng làn chung
   trong flow để nó thẳng hàng với task. Vẫn phải là position:relative vì
   .event-box bên trong là absolute canh giữa làn (dòng ~1380) — nhưng phải
   xoá left:8px/top:0/bottom:0 của bản absolute cũ, nếu không position
   :relative sẽ hiểu chúng thành offset và đẩy lệch cả icon lẫn ô tích.
   align-self:stretch cho làn cao bằng hàng, để ô tích (top:50%) canh giữa
   theo HÀNG chứ không theo riêng chiều cao icon. */
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid.multi-week) .event-prefix-slot {
  position: relative;
  left: auto;
  top: auto;
  bottom: auto;
  align-self: stretch;
  width: var(--cal-lead-lane);
  min-width: var(--cal-lead-lane);
  flex: 0 0 var(--cal-lead-lane);
  align-items: center;
  justify-content: center;
}

:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid.multi-week) :is(.gcal-event-body, .outlook-event-body) {
  margin-left: 0;
}

:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid.multi-week) :is(.gcal-event-icon, .outlook-event-icon) {
  margin-right: 0;
}

/* Như .task-box: chỉ thu bề rộng, giữ nguyên left/top/transform mặc định
   (canh giữa làn) để ô tích đồng tâm với icon nguồn lịch nó thay thế. */

/* Hàng phản chiếu việc dài ngày không có làn số (buildSpanMirrorRow không
   dựng .task-prefix-slot). Cho vạch span giữ đúng bề rộng làn để nó vào cùng
   một mép trái với hai loại hàng kia. */
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid.multi-week) .task-span-mirror .task-span-marker {
  margin-right: calc(var(--cal-lead-lane) - var(--ui-space-0-5));
}

/* Nhãn ở chế độ nhiều tuần trước đây bị rút thành chấm màu 6px trần, không
   đọc ra được dự án nào nếu không thuộc lòng bảng màu. Đổi thành chip chữ
   nhỏ dùng mã dự án — cùng cỡ diện tích nhưng mang thông tin thật. */
.task-tags-compact .task-tag {
  width: auto;
  min-height: var(--ui-space-4);
  max-width: var(--dt-dimension-layout-72);
  padding: 0 var(--ui-space-1);
  border-radius: var(--ui-radius-control);
  background: color-mix(in srgb, var(--tag-color) 16%, transparent);
  color: color-mix(in srgb, var(--tag-color) 78%, var(--ui-text-primary));
  font: var(--fw-semibold) var(--fs-caption)/15px var(--app-font);
}

/* Cỡ chữ và khung thẻ Dashboard: "THẺ CHUẨN" (@layer components) + "MÀN DASHBOARD" (@layer modules, dashboard.css) — GĐ4. */

/* Từ settings.css (vốn nạp SAU styles.css, TRƯỚC calendar.css): phải đứng sau mọi luật
   ở trên để vẫn thắng .grid[data-view-mode="week"] .day-name / .grid.multi-week .day-num
   (cùng độ đặc hiệu 0,3,0) như trước khi gom. */
/* Ngày không làm việc theo Lịch làm việc (cuối tuần đã có kiểu riêng; đây là
   ngày lễ và nghỉ đột xuất). Chỉ hạ tương phản nền, không đụng vào chữ của việc:
   người dùng vẫn tạo và đọc việc trong ngày lễ bình thường. */
/* ARS-1: hạ bằng màu chữ muted thay cho opacity (opacity .72 kéo chữ xuống
   2.9:1). Cùng độ ưu tiên và đứng trước rule ngày lễ nên số ngày lễ vẫn đỏ. */
.day-col.is-nonworking .day-num,
.day-col.is-nonworking .day-name,
.day-col.is-nonworking .view-date-meta { color: var(--ui-text-muted); }
.day-col.is-holiday-day .day-num { color: var(--ui-danger); }

/* ===================== MỤC 0 — TOKEN THẺ NGÀY + AGENDA / HÔM NAY =====================
   Chuyển NGUYÊN KHỐI từ dashboard.css (2026-09-27). dashboard.css nạp trước
   calendar.css, nên khối này được đặt ở ĐẦU file — mọi luật lịch sẵn có vẫn
   đứng sau nó như trước. Snapshot computed style 31 trạng thái (thêm Hôm nay +
   cửa sổ hẹp 720px) xác nhận không đổi hiển thị. */

/* Alternate calendar views -------------------------------------------------
   Week remains a dense matrix. Agenda is a continuous date rail + task stream;
   Today is a deliberate 8/4 workspace rather than one stretched week column. */
:root {
  /* Agenda co theo TRỤC CHỮ. Bản cũ chốt px nên ở cỡ chữ 125% chuỗi
     "Tháng 9 · 5 việc" nở ~25% trong một rail đứng yên và bị cắt. Mọi hộp bọc
     chữ ở khối này nhân --font-scale, đúng luật đang dùng cho thang --fs-*. */
  --agenda-date-width: calc(184px * var(--font-scale));
  --agenda-progress-width: calc(22px * var(--font-scale));
  --agenda-stream-max: calc(1240px * var(--font-scale));
  /* Vòng tròn số ngày + chiều cao tối thiểu của thẻ ngày. Tách thành token để
     bản gốc, bản "hôm nay" và bản glass không thể trôi lệch nhau — trước đây ba
     nơi cùng chép tay 36px/110px/14px 16px 47px. */
  /* Lề ngang dùng CHUNG cho lưới agenda và thanh tuần nằm ngoài nó. Khai ở
     :root vì hai phần tử không còn quan hệ cha–con sau khi thanh tuần được đưa
     ra khỏi vùng cuộn. */
  --agenda-gutter: clamp(var(--ui-space-3), 5vw, 88px);
  /* Lưới agenda có `scrollbar-gutter: stable` nên Chromium chừa sẵn máng cuộn
     bên phải, rộng đúng ::-webkit-scrollbar = --ui-scrollbar-w. Thanh tuần
     không cuộn nên không tự chừa, phải cộng cùng con số này để phần nội dung
     căn giữa của nó thẳng hàng với thẻ ngày. */
  --agenda-scroll-reserve: var(--ui-scrollbar-w);
  --agenda-daynum-size: calc(32px * var(--font-scale));
  --agenda-day-min-h: calc(76px * var(--font-scale));
  --agenda-head-pad-b: calc(28px * var(--font-scale));
  /* Shared day-card contract. Day, Week and Month all consume these tokens;
     the reference is the bright, lightly elevated week selector in topbar. */
  --cal-day-surface: rgb(var(--ui-surface-raised-rgb));
  --cal-day-border: rgba(var(--ink), .10);
  --cal-day-shadow: var(--elev-2);
  --cal-day-shadow-hover: var(--cal-day-shadow);
  /* Dense Month rows must not accumulate six aligned drop-shadows into a
     grey horizontal band. Keep a local halo while preserving elevation. */
  --cal-month-day-shadow: 0 1px 2px rgba(var(--ui-shadow-rgb), .045), 0 0 5px rgba(var(--ui-shadow-rgb), .035);
  --cal-month-day-shadow-hover: var(--cal-month-day-shadow);
  --cal-day-radius: var(--ui-radius-panel);
  /* Dạng Tháng: nền ô của tháng đang xem / tháng liền kề. Tối: tháng đang xem
     đậm (lõm), tháng liền kề nhạt; Sáng đảo lại (khai ở khối light bên dưới). */
  --cal-month-in-surface: var(--ux-sunken);
  --cal-month-out-surface: var(--cal-day-surface);
  --view-panel-bg: var(--cal-day-surface);
  --view-panel-border: var(--cal-day-border);
  --view-panel-shadow: var(--cal-day-shadow);
  --view-panel-radius: var(--cal-day-radius);
  --view-muted-surface: color-mix(in srgb, rgb(var(--ui-surface-fill-rgb)) 48%, transparent);
}
html[data-mode="light"] {
  --cal-day-surface: var(--ux-raised);
  --cal-day-border: rgba(var(--ui-scrim-rgb), .09);
  --cal-month-in-surface: var(--cal-day-surface);
  --cal-month-out-surface: var(--ux-sunken);
}

/* Hình nền bật: cột ngày Tuần/Tháng về đúng bậc thẻ L3 (--ux-raised =
   rgba(sf-card, --a-content)) thay vì rgb() ĐỤC ghim cứng. Kết hợp với
   --surface-page: transparent (xem hợp đồng hình nền ở khối token ~16322),
   cột là lớp DUY NHẤT chắn hình nền → lộ ~22% ở Kính trong, kín ở Đục.
   Fluent trước đây lộ hình nền chỉ do một quirk software compositing, không
   phải hành vi có chủ đích. Hợp đồng khả đọc giữ nguyên: --a-content ≥ .78 + scrim. */
html.has-wallpaper {
  --cal-day-surface: var(--ux-raised);
}
/* Chế độ Sáng + hình nền: cột lịch là lớp DUY NHẤT chắn wallpaper (khác thẻ
   Notics ngồi trên canvas trắng đục), nên ở --a-content-light .86 nó blend
   với trời mây tối và trông xám hơn hẳn thẻ note → BA muốn cột lịch sáng đều
   như Notics. Đọc --ux-overlay (bậc L4, ở has-wallpaper[light] = trắng .95,
   xem ~L16478) thay vì --ux-raised .86: giữ hệ token, không ghim hex, vẫn chừa
   ~5% cho bóng + specular kính đọc ra. CHỈ cột lịch — thân trang / pane / scrim
   vẫn theo hợp đồng hình nền .86/.40, chế độ Tối vẫn để wallpaper lộ như cũ. */
html.has-wallpaper[data-mode="light"] {
  --cal-day-surface: var(--ux-overlay);
}

/* --view-panel-radius theo --cal-day-radius (khai ở :root) — bỏ 8px ghim cứng chỉ ở bậc khác
   Kính (BA 11/10/2026): một bán kính cho mọi bậc vật liệu. */
html:not([data-material="glass"]) {
  --cal-day-radius: var(--ui-radius-panel);
}
html[data-material="glass"] {
  --cal-day-shadow: inset 0 1px 0 rgba(var(--ui-white-rgb),.58), 0 7px 20px rgba(var(--ui-shadow-rgb), .10);
  --cal-day-shadow-hover: var(--cal-day-shadow);
  --cal-month-day-shadow: inset 0 1px 0 rgba(var(--ui-white-rgb),.58), 0 1px 3px rgba(var(--ui-shadow-rgb), .05);
  --cal-month-day-shadow-hover: var(--cal-month-day-shadow);
}
html[data-material="glass"][data-mode="dark"] {
  --cal-day-shadow: inset 0 1px 0 rgba(var(--ui-white-rgb),.10), 0 7px 20px rgba(var(--ui-black-rgb),.22);
  --cal-day-shadow-hover: var(--cal-day-shadow);
  --cal-month-day-shadow: inset 0 1px 0 rgba(var(--ui-white-rgb),.08), 0 1px 3px rgba(var(--ui-black-rgb),.22);
  --cal-month-day-shadow-hover: var(--cal-month-day-shadow);
}

/* Agenda: a single reading flow. The date rail is stable while task/event
   content gets the useful width; sparse days no longer reserve card height. */
/* `html` để đặc hiệu (0,3,1) vượt `html[data-material="glass"] .grid`
   (0,2,1) — rule đó ép `padding: 0 8px 8px` cho MỌI dạng xem lịch, nên ở hệ
   Kính toàn bộ lề của agenda bị xoá: mất luôn khoảng thở dưới thanh tiêu đề và
   lề ngang tụt từ --agenda-gutter về 8px. Thắng bằng đặc hiệu, không bằng
   !important. */
html .grid.agenda-view {
  display: grid;
  grid-auto-rows: max-content;
  align-content: start;
  gap: var(--ui-space-3);
  justify-items: center;
  /* Lề ngang hẹp lại (124px → 88px): agenda là dạng xem để ĐỌC NHIỀU, nhường
     bề ngang cho nội dung thay vì cho khoảng trắng hai bên. Khai thành BIẾN vì
     thanh tiêu đề tuần phải tràn hết viền (xem .agenda-week-anchor) — chép lại
     công thức clamp ở hai nơi là cách chắc chắn để hai nơi trôi lệch nhau. */
  /* Đệm trên = đúng nhịp gap giữa hai thẻ ngày: tiêu đề tuần nay cũng là một
     thẻ (xem .agenda-week-anchor), nên thẻ tuần → thẻ ngày đầu cách nhau bằng
     thẻ ngày → thẻ ngày. */
  padding: var(--ui-space-3) var(--agenda-gutter) var(--ui-space-4);
  overflow-x: hidden;
  overflow-y: auto;
  scrollbar-gutter: stable;}
/* Thanh cuộn: hợp đồng chung ui-scrollbar.css. KHÔNG khai scrollbar-width/
   scrollbar-color ở đây: Chromium 121+ gặp một trong hai là bỏ qua toàn bộ
   ::-webkit-scrollbar (BA báo "Danh sách không có thanh cuộn", 2026-09-28). */
.grid.agenda-view .agenda-day {
  display: grid;
  grid-template-columns: var(--agenda-date-width) minmax(0, 1fr);
  grid-template-rows: auto;
  width: 100%;
  max-width: var(--agenda-stream-max);
  justify-content: center;
  /* Cao theo NỘI DUNG. Bản cũ chốt 112px nên một ngày hai việc vẫn chiếm đúng
     chiều cao của một ngày sáu việc — nguồn chính của "nhiều khoảng trắng". */
  min-height: var(--agenda-day-min-h);
  height: auto;
  /* Thẻ nằm trong tấm thân trang: chỉ tách lớp bằng NỀN (Fluent — một lớp một
     cách phân tách), không thêm viền. Viền trong suốt giữ nguyên hình học. */
  border: var(--ui-stroke-thin) solid transparent;
  border-radius: var(--view-panel-radius);
  background: var(--view-panel-bg);
  box-shadow: var(--view-panel-shadow);
  overflow: hidden;
}
.grid.agenda-view .agenda-day:not(.drag-over):hover { background: var(--view-panel-bg); }
.grid.agenda-view .agenda-day.drag-over { background: var(--ui-selected); box-shadow: inset 0 0 0 var(--ui-focus-ring-width) var(--ui-accent); }
.grid.agenda-view .agenda-day .day-head {
  grid-column: 1;
  grid-row: 1;
  position: relative;
  top: auto;
  align-self: stretch;
  min-height: var(--agenda-day-min-h);
  margin: 0;
  /* Đệm dưới chỉ đủ chừa chỗ cho thanh tiến độ ở chân rail, không hơn. */
  padding: var(--ui-space-3) var(--ui-space-4) var(--agenda-head-pad-b);
  display: grid;
  grid-template-columns: var(--agenda-daynum-size) minmax(0, 1fr);
  grid-template-rows: auto auto;
  align-content: start;
  justify-content: start;
  column-gap: var(--ui-space-2);
  row-gap: var(--ui-space-0-5);
  border: 0;
  border-right: var(--ui-stroke-thin) solid var(--ux-divider);
  border-radius: var(--ui-radius-panel) 0 0 var(--ui-radius-panel);
  background: color-mix(in srgb, rgb(var(--ui-surface-raised-rgb)) 82%, rgb(var(--ui-surface-fill-rgb)));
}
.grid.agenda-view .agenda-day .day-name {
  grid-column: 2;
  grid-row: 1;
  color: var(--ui-text-primary);
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  letter-spacing: 0;
  text-transform: none;
}
.grid.agenda-view .agenda-day .day-num {
  grid-column: 1;
  grid-row: 1 / span 2;
  min-width: var(--agenda-daynum-size);
  width: var(--agenda-daynum-size);
  height: var(--agenda-daynum-size);
  padding: 0;
  display: grid;
  place-items: center;
  border-radius: var(--ui-radius-circle);
  background: var(--ux-fill);
  color: var(--ui-text-primary);
  font-size: var(--fs-title);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-none);
}
/* Keep today's date legible in the vertical-week stream.  This belongs beside
   the Agenda base rules so its cascade is stable for every design system. */
.grid.agenda-view .agenda-day.today-highlighted .day-head {
  min-height: var(--agenda-day-min-h);
  padding: var(--ui-space-3) var(--ui-space-4) var(--agenda-head-pad-b);
  border-radius: var(--view-panel-radius) 0 0 var(--view-panel-radius);}
.grid.agenda-view .agenda-day.today-highlighted {
  border-color: var(--ux-border);
  box-shadow: var(--view-panel-shadow);
}
.grid.agenda-view .agenda-day.today-highlighted .day-name {
  color: var(--ui-text-primary);
  font-weight: var(--fw-semibold);
}
.grid.agenda-view .agenda-day.today-highlighted .day-num {
  background: var(--ui-accent-solid);
  font-size: var(--fs-title);
  font-weight: var(--fw-semibold);}
.grid.agenda-view .agenda-day.today-highlighted .view-date-meta {
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
}
.grid.agenda-view .agenda-day .view-date-meta {
  grid-column: 2;
  grid-row: 2;
  align-self: start;
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  line-height: var(--lh-snug);
  white-space: nowrap;
}
.grid.agenda-view .agenda-day .day-divider { display: none; }
.grid.agenda-view .agenda-day .task-list {
  grid-column: 2;
  grid-row: 1;
  /* Lề trái và lề phải BẰNG NHAU. Bản cũ đẩy dòng việc sang trái rồi chặn bề
     rộng bằng --agenda-stream-max, nên mọi khoảng dư dồn hết về bên phải. Nay
     ô lưới được lấp đầy và khoảng cách do padding sinh ra — đối xứng theo định
     nghĩa, ở mọi bề rộng cửa sổ. */
  width: 100%;
  justify-self: stretch;
  min-height: 0;
  margin-left: 0;
  padding: var(--ui-space-3) var(--ui-space-4);
  flex: 0 0 auto;
  overflow: visible;
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-0-5);
}
.grid.agenda-view .agenda-day .task-item,
.grid.agenda-view .agenda-day :is(.gcal-event-item, .outlook-event-item) { width: 100%; }
.grid.agenda-view .agenda-day .task-item,
html.monochrome-task-rows .grid.agenda-view .agenda-day .task-item {
  min-height: max(var(--ui-size-lg), var(--ui-row-height));
  padding: var(--ui-space-1) var(--ui-space-3);
  background: transparent;
  border: 0;
  border-radius: var(--ui-radius-control);
}
.grid.agenda-view .agenda-day .task-item:hover,
.grid.agenda-view .agenda-day .task-item:focus-within {
  background: var(--ux-hover);
}
.grid.agenda-view .task-item.done .task-time-label,
.today-main .task-item.done .task-time-label { color: var(--done-ink); }
.grid.agenda-view .task-item.mode-number .task-text,
.grid.agenda-view .task-item.mode-bullet .task-text,
.today-main .task-item.mode-number .task-text,
.today-main .task-item.mode-bullet .task-text { margin-left: 0; }
.grid.agenda-view .agenda-day .empty-hint {
  margin: var(--ui-space-1-5) 0;
  opacity: .72;
  pointer-events: none;
}
.grid.agenda-view .agenda-day .day-footer {
  grid-column: 1;
  grid-row: 1;
  align-self: end;
  z-index: 1;
  width: auto;
  min-height: 0;
  margin: 0 var(--ui-space-4) var(--ui-space-2);
  padding: 0;
  flex-direction: row;
  align-items: center;
  justify-content: stretch;
  gap: var(--ui-space-2);
  border-top: 0;
  background: transparent;
}

/* A compact week anchor makes the vertical stream readable after a long
   scroll, while the actual work stays in a deliberately bounded centre
   column.  It is part of the grid so it scrolls with the view, then pins
   beneath the top navigation when it reaches that edge. */
/* Thanh tuần của dạng Danh sách.

   Nó là ANH EM của #grid (xem #agendaWeekBar trong index.html), KHÔNG nằm trong
   vùng cuộn. Đặt bên trong rồi dính bằng position:sticky thì thanh cuộn chạy
   dọc cả đoạn ngang thanh tiêu đề, và dải bị thụt vào đúng bề rộng máng cuộn —
   đúng hai thứ trông sai trên màn hình. Ra ngoài thì thanh cuộn bắt đầu ngay
   dưới dải và dải chạm được hai mép, giống thanh tiêu đề của Dự án. */
/* Thanh tuần bám ĐÚNG khung của nội dung bên dưới, không tràn ra mép cửa sổ.

   Bản trước cho dải chạy hết bề ngang `.app`, nên nó đè lên vùng bo góc của
   cửa sổ và lấn qua mép phải của thanh điều hướng — trông như tràn ra ngoài
   app, trong khi mọi thứ khác của dạng xem đều nằm gọn trong khung. Nay dải
   dùng CHUNG hai ràng buộc với thẻ ngày: lề `--agenda-gutter` và trần
   `--agenda-stream-max`, tự căn giữa. Không thể lệch khung, và badge "TUẦN 36"
   luôn thẳng hàng với mép trái các thẻ ở mọi bề rộng cửa sổ. */
.agenda-week-bar {
  flex: 0 0 auto; position: relative; z-index: 7; /* audit-keep: thứ tự chồng lớp cục bộ phải giữ đúng số so với hàng xóm cùng ngữ cảnh xếp chồng, thang layer không có bậc tương ứng */
  /* width:100% + border-box trên một flex item của .app: bề rộng ĐÚNG BẰNG vùng
     nội dung của app (đã trừ thanh điều hướng), đệm nằm bên trong. Không có
     phép cộng nào có thể làm nó vượt ra ngoài khung cửa sổ — đây chính là chỗ
     bản trước sai: nó dùng width: calc(100% + gutter*2) cộng margin âm để "tràn
     viền", và phần tràn đó đè lên vùng bo góc của cửa sổ. */
  /* Lề NGOÀI phải bằng đúng lề của mọi phần tử vỏ khác. .topbar nhận
     `margin: var(--shell-gap) var(--shell-gap) 0` và mọi trang thân nhận
     `margin: 0 var(--shell-gap) var(--shell-gap)` từ khối khung vỏ ở cuối file;
     thanh này không nằm trong danh sách `:is(...)` đó nên trước đây margin = 0
     và nó thò ra 8px mỗi bên so với topbar và lưới — ĐO ĐƯỢC: topbar/grid
     l=67 r=1591, thanh l=59 r=1599. Nó cũng là đoạn TRÊN của cùng một khung
     viền, nên mang viền trái/phải giống thân trang và không bo góc. */
  width: auto;
  box-sizing: border-box;
  /* KHÔNG có margin dưới. Khoảng thở dưới dải phải nằm TRONG lưới (padding-top)
     để chính canvas tô nó; đặt bằng margin thì dải 8px đó rơi ra ngoài cả hai
     hộp và lộ nền #app — đo được rgba(250,249,245,.47) so với canvas .86, đúng
     vệt trong suốt ngay dưới header. */
  margin: 0 var(--shell-gap) 0 var(--shell-gap);
  padding-left: var(--agenda-gutter);
  /* Chừa đúng bằng máng cuộn của lưới, để hai khối căn giữa trùng mép nhau.
     --agenda-bar-pad-end do calendarGrid.js alignAgendaWeekBar đo từ máng cuộn
     thật (token chỉ là giá trị dự phòng, lệch phần lẻ pixel). */
  padding-right: var(--agenda-bar-pad-end, calc(var(--agenda-gutter) + var(--agenda-scroll-reserve)));
  /* Thẻ nổi (BA 11/10/2026): dải là phần đầu của thẻ thân trang — bo hai góc trên, không viền
     (khe đã tách thẻ khỏi nền bàn). Liền mạch đặt lại ở khối "CHẾ ĐỘ LIỀN MẠCH" (styles.css). */
  border: 0;
  border-radius: var(--ui-radius-window) var(--ui-radius-window) 0 0;
  padding-top: var(--ui-space-3);
  /* CÙNG nền với tấm thân trang (#grid) chứ không phải --ux-overlay: dải là
     anh em của #grid, không có nội dung nào cuộn dưới nó, nên không cần đục.
     Nền overlay cũ (sáng hơn hẳn canvas) biến cả dải thành một băng xám góc
     vuông chen giữa topbar bo góc và lưới — BA báo "header không bo tròn". */
  background: var(--surface-page);
}
.agenda-week-bar.hidden { display: none; }
/* Thanh tuần là anh em của #grid nên router (PAGE_ID_BY_VIEW) không ẩn hộ khi
   chuyển sang Notics/Dự án — nó sẽ treo lại trên đầu màn hình khác. Gắn vào
   chính thuộc tính mà router đã đặt trên <html>. */
html:not([data-view="calendar"]) .agenda-week-bar { display: none; }
/* Khung và nền do .agenda-week-bar lo. Ở đây chỉ chặn NỘI DUNG đúng bằng trần
   của thẻ ngày rồi căn giữa — dải và lưới cùng một lề `--agenda-gutter` và cùng
   một trần, nên badge "TUẦN 36" thẳng hàng mép trái các thẻ ở mọi bề rộng. */
.agenda-week-anchor {
  width: 100%;
  max-width: var(--agenda-stream-max);
  margin-inline: auto;
  min-height: var(--ui-size-touch);
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-space-4);
  /* Thẻ tiêu đề tuần: cùng khuôn thẻ ngày bên dưới (nền, bo góc, bóng, viền
     trong suốt), cùng trần --agenda-stream-max nên hai mép thẳng hàng. Đệm
     ngang bằng đệm .day-head để badge "TUẦN" thẳng cột với số ngày. */
  padding: var(--ui-space-2) var(--ui-space-4);
  border: var(--ui-stroke-thin) solid transparent;
  border-radius: var(--ui-radius-panel);
  background: var(--view-panel-bg);
  box-shadow: var(--view-panel-shadow);
}
/* Khi đã cuộn (calendarGrid.js syncAgendaWeekBarScrolled): nội dung chạy sát
   đáy thẻ tuần, hai góc bo dưới để lộ khe giữa thẻ và dòng chảy. Vuông đáy +
   nét chia mảnh: thẻ tuần thành đầu của cột nội dung, nét chia cho biết còn
   nội dung ở trên. Chưa cuộn thì giữ thẻ bo đủ 4 góc.
   - Bỏ bóng đổ: bóng 7px/20px của thẻ nổi rơi thẳng lên nội dung bên dưới
     thành dải xám mờ (chỉ lộ ở Sáng, Tối thì chìm vào nền) — BA 06/10/2026
     "màu không đồng bộ". Nét chia đã đủ tách lớp.
   - Bề mặt Phẳng: thẻ ngày có viền --cal-day-border hai bên, thẻ tuần viền
     trong suốt → hai mép cột không nối thành một đường ("nhìn bị lệch").
     Đã cuộn thì thẻ tuần mang cùng viền hai bên + đáy với thẻ ngày. */
.agenda-week-anchor {
  transition: border-radius var(--ui-duration-fast) var(--ui-ease), border-color var(--ui-duration-fast) var(--ui-ease), box-shadow var(--ui-duration-fast) var(--ui-ease);
}
.agenda-week-bar.is-scrolled .agenda-week-anchor {
  border-end-start-radius: 0;
  border-end-end-radius: 0;
  border-bottom-color: var(--ux-divider);
  box-shadow: none;
}
html[data-calendar-surface="flat"] .agenda-week-bar.is-scrolled .agenda-week-anchor {
  border-inline-color: var(--cal-day-border);
  border-bottom-color: var(--cal-day-border);
}

.agenda-week-overview { min-width: 0; flex: 1 1 auto; display: flex; align-items: center; gap: var(--ui-space-2); }
.agenda-week-overview strong { color: var(--ui-text-primary); font-size: var(--fs-body); font-weight: var(--fw-bold); white-space: nowrap; }
.agenda-week-overview span { min-width: 0; overflow: hidden; color: var(--ui-text-secondary); font-size: var(--fs-body); font-weight: var(--fw-semibold); text-overflow: ellipsis; white-space: nowrap; }
/* Cùng khuôn với .project-weekly-badge để hai màn hình đọc ra là một họ. */
.agenda-week-badge {
  flex: none; padding: var(--ui-space-0-5) var(--ui-space-2); border-radius: var(--ui-radius-control);
  font: var(--fw-semibold) var(--fs-micro)/var(--lh-tight) var(--app-font);
  background: color-mix(in srgb, var(--ui-accent) 15%, transparent); color: var(--ui-accent);
}
.agenda-week-metrics { display: flex; align-items: center; gap: clamp(var(--ui-space-4), 2.4vw, var(--ui-space-10)); flex: 0 0 auto; }
.agenda-week-metric { display: flex; align-items: baseline; gap: var(--ui-space-1); white-space: nowrap; }
.agenda-week-metric strong { color: var(--ui-text-primary); font-size: var(--fs-title); font-weight: var(--fw-heavy); line-height: var(--lh-none); }
.agenda-week-metric span { color: var(--ui-text-secondary); font-size: var(--fs-caption); font-weight: var(--fw-semibold); }
/* #dc2626 cứng chỉ đạt 3.46:1 trên card Dark (không có biến thể Dark riêng,
   nên Dark dùng chung màu Light) — dưới ngưỡng AA 4.5:1 cho một con số việc
   quá hạn đáng chú ý. var(--ui-danger) đạt 5.44:1 Light / 8.23:1 Dark. */
.agenda-week-metric.is-priority strong { color: var(--ui-danger); }
/* Accent thuần chỉ 4.31:1 trên thẻ tuần ở Tối + Kính phủ nền trắng (gate ARS-1,
   04/10/2026). Pha 30% chữ chính: vẫn đọc ra màu xanh, Tối ≈ 5.5:1, Sáng đậm hơn. */
.agenda-week-metric.is-meetings strong { color: color-mix(in srgb, var(--ui-accent) 70%, var(--ui-text-primary)); }
.agenda-week-metric.is-completed strong { color: var(--ui-success); }
/* Số 0 không mang tín hiệu: chữ phụ, không đỏ/xanh (AT-CALM — báo cáo UX 10/10/2026). */
.agenda-week-metric.is-zero strong { color: var(--ui-text-muted); }
.grid.agenda-view .day-footer .progress-track {
  width: auto;
  min-height: var(--ui-space-1);
  height: var(--ui-space-1);
  flex: 1 1 auto;
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  border-radius: var(--dt-dimension-radius-full);
}
.grid.agenda-view .day-footer .progress-fill {
  height: 100%;
  flex: 0 0 auto;
  border-radius: var(--dt-dimension-radius-full);}
.grid.agenda-view .day-footer .day-count {
  font-size: var(--fs-caption);
  line-height: var(--lh-none);
  text-align: center;
  white-space: nowrap;
}
.grid.agenda-view :is(.task-item, .gcal-event-item, .outlook-event-item) { min-height: max(var(--ui-size-lg), var(--ui-row-height)); }
.grid.agenda-view .task-text {
  font-size: var(--task-effective-font, var(--font-task));
  font-weight: var(--fw-normal);
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
}
.grid.agenda-view .task-prefix {
  font-size: var(--task-effective-font, var(--font-task));
  font-weight: var(--fw-medium);
}
.grid.agenda-view :is(.gcal-event-item, .outlook-event-item) {
  min-height: max(var(--ui-size-lg), var(--ui-row-height));
  padding: var(--ui-space-1) var(--ui-space-3);
  font-size: var(--task-effective-font, var(--font-task));
  font-weight: var(--fw-normal);
}
.grid.agenda-view :is(.gcal-event-title, .outlook-event-title) {
  font-size: inherit;
  font-weight: var(--fw-normal);
  line-height: var(--lh-snug);
}
.grid.agenda-view .completed-toggle {
  min-height: var(--ui-size-md);
  font-size: var(--fs-caption);
}
html[data-material="glass"] .grid.agenda-view .agenda-day .day-head {
  align-self: stretch;
  min-height: var(--agenda-day-min-h);
  margin: 0;
  padding: var(--ui-space-3) var(--ui-space-4) var(--agenda-head-pad-b);
  border: var(--ui-stroke-thin) solid var(--ux-divider);
  border-right: var(--ui-stroke-thin) solid var(--ux-divider);
  border-radius: var(--view-panel-radius) 0 0 var(--view-panel-radius);
  background: rgba(var(--ui-surface-fill-rgb), .42);
  box-shadow: inset 0 1px 0 light-dark(rgba(var(--ui-white-rgb),.26), rgba(var(--ui-white-rgb),.08)); /* audit-keep: vật liệu kính: highlight và độ sâu nhiều lớp theo --t, không thuộc bậc elevation đơn */
}

/* Today: primary task stream plus a compact information rail.
   Dùng `html` để đặc hiệu (0,3,1) vượt `html[data-material="glass"] .grid` (0,2,1).
   - AT-UI Rhythm (BA duyệt 10/10/2026): bỏ lề hai bên 7vw (tới 134px ở 1920 — ba cột bị
     ép giữa hai dải wallpaper trống trong khi bên trong chật). Đệm đều bốn phía và khe
     giữa cột cùng một nhịp --ui-rhythm-panel (16 / Thoáng 24). */
html .grid.today-view,
.grid.today-view {
  display: block;
  padding: var(--ui-rhythm-panel);
  overflow: hidden;}
.today-workspace {
  width: 100%;
  max-width: none;
  height: 100%;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 0px minmax(0, 4fr) minmax(0, 3fr);
  gap: var(--ui-rhythm-panel);
  align-items: stretch;
  transition: grid-template-columns var(--ui-duration-standard) var(--ui-ease), width var(--ui-duration-standard) var(--ui-ease);
}

.today-backlog-rail {
  display: flex;
  flex-direction: column;
  gap: 0;
  overflow-y: auto;
  padding-right: var(--ui-space-1);
}
.backlog-group-header {
  display: flex;
  align-items: center;
  min-height: var(--ui-space-12);
  padding: var(--ui-space-2) var(--ui-space-3-5);
  box-sizing: border-box;
  border-bottom: var(--ui-stroke-thin) solid var(--stroke);
}
.backlog-group-header span.title {
  display: inline-flex;
  align-items: center;
  gap: var(--ui-space-2);
  font-size: var(--fs-title);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-tight);
  color: var(--ui-text-primary);
}
.backlog-group-header span.title::before { content: ''; width: var(--ui-space-2); height: var(--ui-space-2); border-radius: var(--ui-radius-circle); background: var(--ui-danger); }
.backlog-group-header span.count {
  min-width: var(--ui-space-5);
  height: var(--ui-space-5);
  display: inline-grid;
  place-items: center;
  margin-left: var(--ui-space-2);
  border-radius: var(--ui-radius-circle);
  /* Cặp cứng #fee2e2/#dc2626 chỉ đạt 3.95:1 (dưới AA 4.5:1) và không có biến
     thể Dark — badge vẫn hồng nhạt/đỏ y hệt trên nền tối. Cặp token đã tuning
     sẵn theo công thức nền/chữ chuẩn, đạt 4.76:1 Light / 7.94:1 Dark. */
  background: var(--ui-danger-bg);
  color: var(--ui-danger);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
}
/* AT-UI Rhythm (BA 10/10/2026): màu/nền/cỡ lấy từ nút Chữ chuẩn (.ui-btn--text --sm,
   ui-button.css) — ở đây chỉ còn vị trí trong hàng tiêu đề. */
.backlog-batch-toggle {
  margin-left: auto;
}
.backlog-batch-toggle svg { width: var(--ui-icon-sm); height: var(--ui-icon-sm); }
.backlog-batch-toggle + .count {
  margin-left: var(--ui-space-2);
}
.backlog-batch-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ui-space-2);
  padding: var(--ui-space-0-5) var(--ui-space-4) var(--ui-space-4);
  border-bottom: var(--ui-stroke-thin) solid var(--ui-divider);
}
.backlog-batch-toolbar-head {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-space-3);
}
.backlog-batch-summary {
  color: var(--ui-text-primary);
  font: var(--fw-semibold) var(--fs-body)/var(--lh-snug) var(--app-font);
}
/* Nút "Bỏ chọn" và các nút hàng loạt dùng .ui-btn (v3, BA 10/10/2026: --text sm,
   --secondary/--primary/--danger-text md); ô ngày dùng .ui-input. Ở đây chỉ còn bố cục. */
.backlog-batch-group {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  min-width: 0;
}
.backlog-batch-date {
  min-width: var(--dt-dimension-layout-128);
  width: auto;
}
.backlog-selection-box {
  appearance: none;
  flex: 0 0 auto;
  width: var(--ui-icon-sm);
  height: var(--ui-icon-sm);
  margin: 0 var(--ui-space-1) 0 0;
  border: var(--ui-stroke-thick) solid var(--ui-text-secondary);
  border-radius: var(--ui-radius-control);
  background: transparent;
  cursor: pointer;
}
.backlog-selection-box:checked {
  border-color: var(--ui-accent);
  background: var(--ui-accent);
  box-shadow: inset 0 0 0 calc(var(--ui-focus-ring-width) * 1.5) var(--view-panel-bg);
}
.backlog-selection-box:focus-visible {
  outline: var(--ui-stroke-thick) solid var(--ui-accent);
  outline-offset: var(--ui-stroke-thick);
}
@media (max-width: 620px) {
  .backlog-batch-action { flex: 1 1 calc(50% - var(--ui-space-1)); }
  .backlog-batch-group { flex: 1 1 100%; }
  .backlog-batch-date { flex: 1 1 55%; }
}
/* Override Dark riêng này từng bị bỏ sót khi tokenize block gốc phía trên —
   #ef4444 trên --sf-danger-bg Dark chỉ đạt 4.28:1, dưới AA 4.5:1. Giờ base
   rule đã dùng var(--ui-danger) (tự đổi theo data-mode), override này thành
   thừa — xóa hẳn thay vì để một giá trị khác lặng lẽ thắng đè lên. */
.backlog-list {
  display: flex;
  flex-direction: column;
  padding: var(--ui-space-1-5) var(--ui-space-3);
  gap: var(--ui-space-0-5);
}
.backlog-list.is-hidden {
  display: none;
}
.today-backlog-rail .backlog-item,
.backlog-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--task-icon-gap, var(--ui-space-1-5));
  min-height: var(--task-row-height);
  padding: var(--ui-space-1) 44px var(--ui-space-1) var(--ui-space-2-5); /* audit-keep: chừa chỗ cho icon/nút cuối ô nhập, rộng theo nút */
  background: transparent;
  border-bottom: 0;
  transition: background var(--ui-duration-fast) var(--ui-ease), border-color var(--ui-duration-fast) var(--ui-ease);
  border-radius: var(--ui-radius-control);
}
.backlog-list .backlog-item:last-child { border-bottom: none; }
.backlog-item:hover {
  background: var(--ux-hover);
}
.backlog-item-title {
  flex: 1;
  min-width: 0;
  min-height: 0;
  line-height: var(--lh-normal);
  font-family: var(--app-font);
  font-size: var(--task-effective-font, var(--font-task));
  font-weight: var(--fw-normal);
  color: var(--ui-text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.backlog-item-meta {
  display: inline-flex;
  align-items: center;
  gap: var(--ui-space-1-5);
  flex: 0 0 auto;
  margin-left: auto;
  font-family: var(--app-font);
  font-size: var(--task-meta-font, calc(var(--task-effective-font, var(--font-task)) * .87));
}
.backlog-item-date {
  font-family: var(--app-font);
  font-size: var(--task-meta-font, calc(var(--task-effective-font, var(--font-task)) * .87));
  font-weight: var(--fw-semibold);
}
/* #ef4444 riêng cho Dark chỉ đạt 4.44:1 trên card — dưới AA 4.5:1. Gộp về
   var(--ui-danger) (đã tự đổi theo data-mode) thay vì giữ hai màu tay: Light
   5.44:1, Dark 8.23:1. */
/* Thoáng–Gọn (BA 10/10/2026): nhóm "Trễ hạn" đã có chấm đỏ + số đỏ ở tiêu đề; ngày
   của từng việc là chữ phụ, không lặp màu đỏ ở mỗi dòng. */
.backlog-item-date.is-overdue {
  color: var(--ui-text-secondary);
  font-weight: var(--fw-normal);
}
.backlog-item-date.is-today {
  color: var(--ui-success);
}

.backlog-item .task-box {
  opacity: 0;
  transition: opacity var(--ui-duration-fast) var(--ui-ease);
}
.backlog-item:hover .task-box, .backlog-item:focus-within .task-box {
  opacity: 1;
}
.today-backlog-rail,
.today-main,
.today-rail-card {
  border: var(--ui-stroke-thin) solid var(--cal-day-border);
  border-radius: var(--cal-day-radius);
  background: var(--cal-day-surface);
  box-shadow: var(--cal-day-shadow);
}
.today-main { min-width: 0; min-height: 0; display: flex; overflow: hidden; }
.today-main .today-day {
  width: 100%;
  height: 100%;
  border: 0;
  border-radius: inherit;
  background: transparent;
  box-shadow: none;
}
.today-main .today-day.today-highlighted { border: 0; background: transparent; box-shadow: none; }
/* Một dòng, không vòng tròn — theo thiết kế mẫu (thanh 34px, một dòng
   "Thứ Ba, 25 tháng 8 năm 2026"). Bản cũ là khối 76px xếp chồng với vòng
   tròn 44px, ăn mất đúng hai hàng việc ở đầu danh sách — chỗ đắt nhất
   của màn hình.
   Sửa thẳng tại khối này chứ không ghi đè từ chỗ khác: đây là khối
   .today-main .day-head đứng SAU trong file nên mọi override đặt phía
   trên đều thua cascade. */
.today-main .today-day .day-head {
  min-height: var(--ui-space-12);
  padding: var(--ui-space-2) var(--ui-space-3-5);
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: var(--ui-space-1-5);
  border-bottom: var(--ui-resizer-line) solid var(--ux-divider);
  border-radius: 0;
  background: transparent;
}
.today-main .today-day .day-name {
  color: var(--ui-text-primary);
  font-size: var(--fs-title);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-tight);
}
.today-main .today-day .view-date-meta {
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
}
/* Tiền tố html[data-mode] là bắt buộc, không phải cho đẹp: quy tắc tô nền
   xanh cho ngày hôm nay được khai ở
   `html[data-mode="light"] .day-col.today-highlighted .day-num` — độ ưu
   tiên (0,4,1). Nếu chỉ viết `.today-main .today-day.today-highlighted
   .day-num` thì chỉ được (0,4,0) và thua, số 26 vẫn dính viên nền xanh. */
html:root .today-main .today-day .day-num,
html:root .today-main .today-day.today-highlighted .day-num {
  order: -1;
  min-width: 0;
  width: auto;
  height: auto;
  padding: 0;
  border-radius: 0;
  color: var(--ui-text-primary);
  background: transparent;
  font-size: var(--fs-title);
  font-weight: var(--fw-semibold);
}
/* Ngày tháng dồn về mép phải, giống chỗ "1/8 hoàn tất" của thiết kế mẫu. */
.today-main .today-day .view-date-meta { margin-left: auto; }
.today-main .today-day .task-list {
  flex: 1;
  min-height: 0;
  padding: var(--ui-space-1-5) var(--ui-space-3);
  gap: var(--ui-space-0-5);
  overflow-x: hidden;
  overflow-y: auto;
}
.today-main .today-day .task-item {
  min-height: max(var(--ui-size-md), calc(var(--task-effective-font, var(--font-task)) * 2));
  padding: var(--ui-space-0-5) var(--ui-space-2);
  background: transparent;
  border-bottom: 0;
  border-radius: var(--ui-radius-control);
}
.today-main .task-text {
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
}
/* Footer cột Hôm nay (vạch tiến độ + "Thêm") và thanh công cụ Ghi chú trong ngày cùng đáy
   nên chung MỘT chiều cao dải → vạch đỉnh hai bên thẳng hàng (BA 11/10/2026). */
.today-workspace { --today-footer-band-h: calc(var(--ui-size-sm) + 2 * var(--ui-space-2)); }
.today-main .today-day .day-footer { box-sizing: border-box; block-size: var(--today-footer-band-h); min-block-size: var(--today-footer-band-h); padding: var(--ui-space-2) var(--ui-space-3-5); background: transparent; }

.today-rail {
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-2);
  /* Không tự cuộn nữa — xem .today-rail-scroll. Rail chính giữ overflow:visible
     để box-shadow/quầng focus của today-note-box (con cuối, áp sát đáy) không
     bị cắt cụt bởi chính khung chứa nó. */
  overflow: visible;
}
.today-rail-scroll {
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-2);
  overflow-y: auto;
}
.today-rail-card { padding: var(--ui-space-2-5) var(--ui-space-3); }
.today-rail-eyebrow {
  margin-bottom: var(--ui-space-2);
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-weight: var(--fw-overline);
}
.today-progress-row { display: flex; align-items: center; gap: var(--ui-space-3); }
.today-progress-ring {
  position: relative;
  width: var(--dt-dimension-layout-64);
  height: var(--dt-dimension-layout-64);
  flex: 0 0 var(--dt-dimension-layout-64);
  display: grid;
  place-items: center;
  border-radius: var(--ui-radius-circle);
  background: conic-gradient(from 0deg, var(--ui-warning), var(--ui-success) var(--today-progress, 0deg), var(--view-muted-surface) 0);
}
.today-progress-ring::after {
  content: '';
  position: absolute;
  inset: var(--ui-space-1-5);
  border-radius: var(--ui-radius-circle);
  background: rgb(var(--ui-surface-raised-rgb));
}
.today-progress-ring strong { position: relative; z-index: 1; color: var(--ui-text-primary); font-size: var(--fs-body); font-weight: var(--fw-bold); }
.today-progress-copy { min-width: 0; display: flex; flex-direction: column; gap: var(--ui-space-1); }
.today-progress-copy strong { color: var(--ui-text-primary); font-size: var(--fs-body); font-weight: var(--fw-semibold); }
.today-progress-copy span { color: var(--ui-text-muted); font-size: var(--fs-caption); line-height: var(--lh-snug); }

.today-segmented-bar {
  display: flex;
  height: var(--ui-space-1-5);
  border-radius: var(--ui-radius-sm);
  background: var(--view-muted-surface);
  margin-top: var(--ui-space-4);
  overflow: hidden;
  gap: var(--ui-space-0-5);
}
.today-segmented-bar > div { height: 100%; }
.today-segmented-bar .seg-done { background: var(--ui-success); }
.today-segmented-bar .seg-timed { background: var(--ui-warning); }
.today-segmented-bar .seg-remain { background: var(--ui-text-muted); }

.today-metric-grid { margin-top: var(--ui-space-3-5); display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--ui-space-2); }
.today-metric {
  min-width: 0;
  padding: var(--ui-space-3) var(--ui-space-1-5);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--ui-space-1-5);
  border-radius: calc(var(--view-panel-radius) - 4px); /* audit-keep: bán kính nội tiếp = bán kính khối ngoài trừ đệm/viền, phải đổi theo khối cha */
  background: var(--view-panel-bg);
  border: var(--ui-stroke-thin) solid var(--ui-divider);
}
.metric-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--ui-size-md);
  height: var(--ui-size-md);
  border-radius: var(--ui-radius-control);
  margin-bottom: var(--ui-space-0-5);
}
.metric-icon svg { width: var(--dt-dimension-icon-header); height: var(--dt-dimension-icon-header); }
.metric-remain .metric-icon { background: var(--ui-category-blue-bg); color: var(--ui-category-blue-fg); }
.metric-timed .metric-icon { background: rgba(var(--ui-warning-rgb), 0.1); color: var(--ui-warning); }
.metric-event .metric-icon { background: var(--ui-category-purple-bg); color: var(--ui-category-purple-fg); }
.today-metric strong { color: var(--ui-text-primary); font-size: var(--fs-title-lg); font-weight: var(--fw-bold); line-height: var(--lh-none); }
.today-metric span { display: none; }
.today-next-time { display: block; color: var(--ui-accent); font-size: var(--fs-title-lg); font-weight: var(--fw-semibold); line-height: var(--lh-none); font-variant-numeric: tabular-nums; }
.today-next-text { margin-top: var(--ui-space-2); color: var(--ui-text-secondary); font-size: var(--fs-body); font-weight: var(--fw-medium); line-height: var(--lh-snug); }
.today-next-text.is-empty { color: var(--ui-text-muted); font-size: var(--fs-caption); font-weight: var(--fw-normal); }
.today-event-list { display: flex; flex-direction: column; gap: var(--ui-space-1); }
.today-event-brief {
  position: relative;
  width: 100%;
  min-width: 0;
  min-height: var(--ui-size-md);
  padding: var(--ui-space-1-5) var(--ui-space-2) var(--ui-space-1-5) var(--ui-space-3);
  display: grid;
  grid-template-columns: 49px minmax(0, 1fr);
  align-items: center;
  gap: var(--ui-space-1-5);
  border: 0;
  border-radius: calc(var(--view-panel-radius) - 6px); /* audit-keep: bán kính nội tiếp = bán kính khối ngoài trừ đệm/viền, phải đổi theo khối cha */
  background: var(--view-muted-surface);
  color: var(--ui-text-primary);
  text-align: left;
  cursor: pointer;
  overflow: hidden;
}
.today-event-brief::before {
  content: '';
  position: absolute;
  inset: var(--ui-space-1-5) auto var(--ui-space-1-5) 0;
  width: var(--ui-space-1);
  border-radius: 0 var(--ui-radius-sm) var(--ui-radius-sm) 0;
  background: var(--ui-accent);
}
.today-event-brief.source-outlook::before { background: var(--tone-blue-bar); }
.today-event-brief:hover { background: var(--ui-hover); }
.today-event-brief:focus-visible { outline: var(--ui-stroke-thick) solid var(--ui-focus-ring); outline-offset: var(--ui-stroke-thin); }
.today-event-time {
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.today-event-brief strong {
  min-width: 0;
  overflow: hidden;
  color: var(--ui-text-primary);
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.today-event-more,
.today-event-empty { margin-top: var(--ui-space-2); color: var(--ui-text-muted); font-size: var(--fs-caption); line-height: var(--lh-snug); }
 /* audit-keep: vật liệu kính: highlight và độ sâu nhiều lớp theo --t, không thuộc bậc elevation đơn */
 /* audit-keep: vật liệu kính: highlight và độ sâu nhiều lớp theo --t, không thuộc bậc elevation đơn */

.today-note-box {
  display: flex;
  flex-direction: column;
  flex: 1 1 0px;
  min-height: var(--dt-dimension-layout-144);
  /* Cùng vật liệu với .today-rail-card (BA 2026-10-15): không viền riêng, đồng bộ cả cột phải. */
  border: var(--ui-stroke-thin) solid var(--cal-day-border);
  border-radius: var(--cal-day-radius);
  background: var(--cal-day-surface);
  box-shadow: var(--cal-day-shadow);
  overflow: hidden;
}
.today-note-box:focus-within { border-color: var(--ux-control-border-active); } /* Focus chỉ đổi viền sang mực trung tính (border.focus): không quầng sáng, không thêm bóng đổ. */
.today-note-editor {
  flex: 1 1 0px;
  min-height: var(--dt-dimension-layout-80);
  height: auto;
  overflow-y: auto;
  overscroll-behavior-y: contain;
  scrollbar-gutter: stable;
  padding: var(--ui-space-2-5) var(--ui-space-3);
  background: transparent;
  outline: none;
}
.today-note-editor .ql-editor { position: relative; min-height: 100%; padding: 0; color: var(--ui-text-primary); font-weight: var(--fw-medium); line-height: var(--lh-snug); outline: none; white-space: pre-wrap; overflow-wrap: anywhere; user-select: text; counter-reset: list-0 list-1 list-2 list-3; }
.today-note-editor .ql-editor.ql-blank::before {
  content: attr(data-placeholder);
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  color: var(--ui-text-muted);
  font-style: normal;
  pointer-events: none;
}
:is(.today-note-editor .ql-editor:focus, .today-note-box:focus-within .today-note-editor .ql-editor).ql-blank::before {
  display: none;
}
.today-note-editor .ql-editor :is(p, ol, ul) { margin: 0 0 .22em; padding: 0; }
.today-note-editor .ql-editor :is(p, h1, h2, h3, h4, h5, h6, blockquote, pre, table, hr) {
  counter-set: list-0 0 list-1 0 list-2 0 list-3 0;
  counter-reset: list-0 list-1 list-2 list-3;
}
.today-note-editor .ql-editor ol { padding-left: 1.5em; counter-reset: list-0 list-1 list-2 list-3; }
.today-note-editor .ql-editor li { position: relative; padding-left: 1.5em; list-style: none; }
.today-note-editor .ql-editor li > .ql-ui::before { display: inline-block; width: 1.2em; margin-left: -1.5em; margin-right: .3em; text-align: right; white-space: nowrap; }
.today-note-editor .ql-editor li[data-list="bullet"] > .ql-ui::before { content: "•"; }
/* Bộ đếm theo cấp — cùng công thức .notics-editor (notics.css): mỗi mục đặt lại
   các cấp SÂU hơn trong MỘT counter-set. Bản cũ tách rule cùng độ ưu tiên nên rule
   sau đè rule trước: danh sách con của mục "2." đánh tiếp c, d thay vì a. */
.today-note-editor .ql-editor li[data-list]:not([class*="ql-indent-"]) { counter-set: list-1 0 list-2 0 list-3 0; }
.today-note-editor .ql-editor li[data-list]:not([data-list="ordered"]):not([class*="ql-indent-"]) { counter-set: list-0 0 list-1 0 list-2 0 list-3 0; }
.today-note-editor .ql-editor li[data-list].ql-indent-1 { counter-set: list-2 0 list-3 0; }
.today-note-editor .ql-editor li[data-list]:not([data-list="ordered"]).ql-indent-1 { counter-set: list-1 0 list-2 0 list-3 0; }
.today-note-editor .ql-editor li[data-list].ql-indent-2 { counter-set: list-3 0; }
.today-note-editor .ql-editor li[data-list]:not([data-list="ordered"]).ql-indent-2 { counter-set: list-2 0 list-3 0; }
.today-note-editor .ql-editor li[data-list]:not([data-list="ordered"]):is(.ql-indent-3, .ql-indent-4, .ql-indent-5, .ql-indent-6, .ql-indent-7, .ql-indent-8) { counter-set: list-3 0; }
.today-note-editor .ql-editor li[data-list="ordered"] { counter-increment: list-0; }
.today-note-editor .ql-editor li[data-list="ordered"] > .ql-ui::before { content: counter(list-0, decimal) ". "; }
.today-note-editor .ql-editor li[data-list="ordered"].ql-indent-1 { counter-increment: list-1; }
.today-note-editor .ql-editor li[data-list="ordered"].ql-indent-1 > .ql-ui::before { content: counter(list-1, lower-alpha) ". "; }
.today-note-editor .ql-editor li[data-list="ordered"].ql-indent-2 { counter-increment: list-2; }
.today-note-editor .ql-editor li[data-list="ordered"].ql-indent-2 > .ql-ui::before { content: counter(list-2, lower-roman) ". "; }
.today-note-editor .ql-editor li[data-list="ordered"]:is(.ql-indent-3, .ql-indent-4, .ql-indent-5, .ql-indent-6, .ql-indent-7, .ql-indent-8) { counter-increment: list-3; }
.today-note-editor .ql-editor li[data-list="ordered"]:is(.ql-indent-3, .ql-indent-4, .ql-indent-5, .ql-indent-6, .ql-indent-7, .ql-indent-8) > .ql-ui::before { content: counter(list-3, decimal) ". "; }
.today-note-editor .ql-editor .ql-indent-1:not(.ql-direction-rtl) { padding-left: 3em; }
.today-note-editor .ql-editor li.ql-indent-1:not(.ql-direction-rtl) { padding-left: 4.5em; }
.today-note-editor .ql-editor .ql-indent-2:not(.ql-direction-rtl) { padding-left: 6em; }
.today-note-editor .ql-editor li.ql-indent-2:not(.ql-direction-rtl) { padding-left: 7.5em; }
.today-note-toolbar { flex-shrink: 0; display: flex; align-items: center; gap: var(--ui-space-1-5); box-sizing: border-box; block-size: var(--today-footer-band-h, auto); padding: 0 var(--ui-space-2-5); border-top: var(--ui-stroke-thin) solid var(--ui-divider); }
.today-note-toolbar .ql-formats { display: inline-flex; gap: var(--ui-space-0-5); padding-right: var(--ui-space-1-5); border-right: var(--ui-stroke-thin) solid var(--ui-divider); }
.today-note-toolbar .ql-formats:last-child { padding-right: 0; border-right: 0; }
.today-note-toolbar button { width: var(--ui-editor-toolbar-control); height: var(--ui-editor-toolbar-control); padding: 0; border: var(--ui-stroke-thin) solid transparent; border-radius: var(--ui-radius-control); color: var(--ui-text-secondary); background: transparent; font: var(--fw-semibold) var(--fs-body)/var(--lh-none) var(--app-font); cursor: pointer; }
.today-note-toolbar button:hover, .today-note-toolbar button.ql-active { color: var(--ui-accent); border-color: color-mix(in srgb, var(--ui-accent) 38%, var(--ui-divider)); background: rgba(var(--ui-accent-rgb), .10); }

@media (max-width: 960px) {
  .today-workspace { grid-template-columns: 0px minmax(0, 1fr) 230px; gap: var(--ui-space-2-5); }
  .today-workspace.has-backlog { grid-template-columns: minmax(280px, .85fr) minmax(0, 1fr) 230px; }
  .today-progress-row { align-items: flex-start; }
  .today-progress-ring { width: var(--dt-dimension-layout-56); height: var(--dt-dimension-layout-56); flex-basis: var(--dt-dimension-layout-56); }
  .today-metric-grid { grid-template-columns: 1fr; }
  .today-metric { flex-direction: row; justify-content: space-between; }
}
@media (max-width: 760px) {
  .today-workspace { height: auto; grid-template-columns: 0px minmax(0, 1fr); }
  .today-main { min-height: var(--dt-component-calendar-today-compact-min-height); }
  .today-metric-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .today-metric { flex-direction: column; justify-content: initial; }
  /* Đặt ở :root, không ở .grid.agenda-view: thanh tuần nay nằm NGOÀI lưới nên
     không thừa kế biến từ đó nữa. */
  :root { --agenda-gutter: var(--ui-space-3); }
  .agenda-week-anchor {
    gap: var(--ui-space-2);
  }
  .agenda-week-metrics { justify-content: flex-end; gap: var(--ui-space-3); }
  .agenda-week-metric strong { font-size: var(--fs-title-lg); }
  .grid.agenda-view .agenda-day {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto auto;
  }
  .grid.agenda-view .agenda-day .day-head,
  html[data-material="glass"] .grid.agenda-view .agenda-day .day-head {
    grid-column: 1;
    grid-row: 1;
    min-height: var(--ui-size-touch);
    margin: 0;
    padding: var(--ui-space-2) var(--ui-space-1);
    grid-template-columns: auto auto 1fr;
    grid-template-rows: auto;
    align-items: center;
    border: 0;
    border-bottom: var(--ui-stroke-thin) solid var(--ui-divider);
    border-radius: 0;
    background: transparent;
    box-shadow: none;
  }
  .grid.agenda-view .agenda-day .day-name,
  .grid.agenda-view .agenda-day .day-num,
  .grid.agenda-view .agenda-day .view-date-meta { grid-row: 1; }
  .grid.agenda-view .agenda-day .day-name { grid-column: 1; }
  .grid.agenda-view .agenda-day .day-num { grid-column: 2; font-size: var(--fs-title); }
  .grid.agenda-view .agenda-day .view-date-meta { grid-column: 3; justify-self: end; align-self: center; }
  .grid.agenda-view .agenda-day .task-list {
    grid-column: 1;
    grid-row: 2;
    width: 100%;
    max-width: none;
    margin-left: 0;
    padding: var(--ui-space-2) var(--ui-space-3);
  }
  .grid.agenda-view .agenda-day .day-footer {
    grid-column: 1;
    grid-row: 3;
    width: 100%;
    min-height: 0;
    padding: var(--ui-space-1) 0 0;
    flex-direction: row;
    align-items: center;
  }
  .grid.agenda-view .day-footer .progress-track {
    width: auto;
    height: var(--ui-space-1);
    min-height: 0;
    flex-direction: row;
    justify-content: flex-start;
  }
  .grid.agenda-view .day-footer .progress-fill { height: 100%;}
}
@media (max-width: 820px) {
  .widget-menu-panel.view-mode-panel { right: calc(-1 * var(--dt-dimension-layout-72)); width: min(var(--dt-dimension-layout-256), calc(100vw - var(--ui-space-6))); }
}

/* --- MỤC 0 (tiếp) — responsive dạng Hôm nay, chuyển từ responsive-layout.css.
   Trước đây file đó nạp SAU dashboard.css nên các luật này thắng luật nền Hôm
   nay cùng độ đặc hiệu; giữ đúng quan hệ đó bằng cách đặt chúng ngay sau. --- */
/* TODAY / TASK -------------------------------------------------------------- */
.grid.today-view {
  container-type: inline-size;
  container-name: today-layout;
}
/* A container cannot query and restyle itself.  The page-level scroll owner
 * therefore needs the matching viewport rule; the component children below
 * still use the available workspace width through the container query. */
@media (max-width: 760px) {
  :is(html .grid.today-view, .grid.today-view) {
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}

.today-workspace.has-backlog {
  max-width: none;
  width: 100%;
  grid-template-columns: minmax(0, 3fr) minmax(0, 4fr) minmax(0, 3fr);
}
.today-workspace.has-backlog.is-collapsed-rail {
  max-width: none;
  width: 100%;
  grid-template-columns: 38px minmax(0, 4fr) minmax(0, 3fr);
}
.today-workspace:not(.has-backlog) {
  max-width: var(--dt-dimension-layout-1120);
  width: calc(100% - clamp(var(--ui-panel-pad), 4vw, calc(var(--ui-panel-pad) * 3)) * 2);
  margin-inline: auto;
  grid-template-columns: minmax(0, 4fr) minmax(0, 3fr);
}
.today-workspace:not(.has-backlog) .today-backlog-rail { display: none; }
.today-rail-scroll { padding-right: 0; }
.today-rail-card { min-width: 0; }

.today-workspace.has-backlog .today-backlog-rail {
  grid-column: auto;
  grid-row: auto;
}
.today-workspace.has-backlog .today-main { grid-column: auto; grid-row: auto; }
.today-workspace.has-backlog .today-rail { grid-column: auto; grid-row: auto; }

/* 3 cột trễ hạn / hôm nay / tiến độ giữ hàng ngang đến ngưỡng 50% màn hình (~720px).
 * Khi cửa sổ co xuống dưới 50% (<= 720px) mới chuyển sang sắp xếp trên dưới:
 * 1. trễ hạn / 2. hôm nay / 3. tiến độ hôm nay. */
@container today-layout (max-width: 720px) {
  :is(html .grid.today-view, .grid.today-view) {
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-inline: var(--ui-space-3);
  }
  .today-workspace,
  .today-workspace.has-backlog,
  .today-workspace.has-backlog.is-collapsed-rail,
  .today-workspace:not(.has-backlog) {
    height: auto;
    width: 100%;
    max-width: none;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
  }
  .today-workspace.has-backlog .today-backlog-rail,
  .today-workspace.has-backlog .today-main,
  .today-workspace.has-backlog .today-rail {
    grid-column: auto;
    grid-row: auto;
  }
  .today-workspace.has-backlog .today-backlog-rail { max-height: var(--dt-dimension-layout-256); }
  .today-workspace { align-items: start; padding-bottom: var(--ui-space-4-5); }
  .today-main {
    min-height: 0;
    height: auto;
    overflow: visible;
  }
  /* Có tiền tố `.grid[data-view-mode="today"]` để nặng hơn `.day-col.weekend`.
     Cột ngày là thẻ cắt nội dung (`overflow: hidden`) và luật đó nay sống ở
     styles/calendar.css — nạp SAU file này. `.today-main .today-day` chỉ nặng
     0,2,0, đúng bằng `.day-col.weekend`, nên vào Thứ Bảy và Chủ Nhật (cột hôm
     nay mang thêm lớp `.weekend`) nó hoà điểm rồi thua vì thứ tự nạp: trang
     Ngày ở khổ hẹp cụt mất phần việc tràn khỏi khung, chỉ vào cuối tuần. */
  .grid[data-view-mode="today"] .today-main .today-day {
    height: auto;
    min-height: 0;
    overflow: visible;
  }
  .grid[data-view-mode="today"] .today-main .today-day .task-list { overflow: visible; }
  .today-rail {
    min-height: 0;
    max-height: none;
  }
  /* Khổ hẹp: cả trang tự cuộn (.grid.today-view ở trên), không phải cột này
     — nếu .today-rail-scroll vẫn giữ overflow-y:auto riêng sẽ thành cuộn
     lồng cuộn (bánh xe chuột bị nuốt trong khung nhỏ khi lướt tới đó). */
  .today-rail-scroll {
    min-height: 0;
    max-height: none;
    overflow: visible;
  }
  .today-rail-card { width: 100%; }
  .today-metric-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .today-metric { flex-direction: column; justify-content: initial; }
  .today-note-box {
    width: 100%;
    min-height: var(--dt-dimension-layout-152);
    flex: 0 0 auto;
  }
  .today-note-editor {
    min-height: var(--dt-dimension-layout-104);
    max-height: var(--dt-dimension-layout-288);
  }
}

/* ===================== MỤC A — LỚP NỀN HỢP NHẤT ===================== */

.grid {
  flex: 1; display: grid; min-height: 0;
  overflow: hidden;
  /* Explicit stacking context above #app-background (position:absolute,
     z-index:0). Without this, .grid is a plain in-flow box with no stacking
     context of its own, and paint order between it and a sibling positioned
     element is left to the engine rather than declared — confirmed via
     DevTools to actually invert on this Chromium build (software
     compositing, --disable-gpu): a page's own opaque background painted
     correctly in the render tree (verified with getComputedStyle and a
     forced red !important test) while the wallpaper showed on screen
     instead, with zero pixels of the real content visible. Every primary
     content surface needs this same explicit z-index; seeing it work by
     accident on one page and not another is not something to rely on. */
  position: relative;
  z-index: 1;
}

.day-col {
  position: relative; isolation: isolate;
  flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; height: 100%; cursor: default;
  /* Ô ngày là thẻ L3 nổi trên nền lưới L2 — cùng bậc với thẻ ghi chú. */
  transform-origin: center;
}


.day-head {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between;
  gap: var(--ui-space-1-5); cursor: pointer;
}

.day-name {
  font-size: var(--font-title); font-weight: var(--fw-semibold); letter-spacing: .3px; color: var(--ui-text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; text-shadow: var(--shade-shadow);
}

.day-num {
  min-height: var(--ui-size-sm); display: flex; align-items: center; justify-content: center;
  line-height: var(--lh-none); flex: 0 0 auto; font-variant-numeric: tabular-nums;
}


.day-divider { display: none; }


.task-list {
  flex: 1; display: flex; flex-direction: column;
  overflow-x: hidden; overflow-y: auto;
  min-height: 0; cursor: cell;
}


.day-chip {
  display: none; flex: 0 0 auto; border-radius: var(--dt-dimension-radius-full);
  letter-spacing: var(--ls-wide); font-variant-numeric: tabular-nums;
}

.empty-hint {
  display: grid; place-items: center;
  font-weight: var(--fw-light);
  pointer-events: auto; opacity: 0; transition: opacity var(--ui-duration-fast) var(--ui-ease), transform var(--ui-duration-fast) var(--ui-ease), box-shadow var(--ui-duration-fast) var(--ui-ease);
  /* Self-center within the task-list flex column */
  margin: auto;
}

.task-item {
  position: relative;
  /* Flex + stretch instead of grid: .task-prefix-slot stretches to the row's
     full cross-axis size and centers box/prefix inside itself via top:50%,
     while .task-text uses align-self:center on its own natural (possibly
     multi-line) height. Both therefore center against the SAME line size,
     which is what actually guarantees they land on the same middle — grid's
     align-items:start plus matching line-heights only worked by coincidence
     when nothing threw the two columns' line-box math out of sync. */
  display: flex;
  flex-shrink: 0;
  /* Left padding is cut down on its own (not the shared --sf-pad-row token,
     which still governs the right/vertical padding) so the number sits
     close to the card's edge instead of floating in from it. */
  /* The priority control is absolutely positioned and overlays the trailing
     edge on hover/focus. It never reserves layout space, so revealing it
     cannot reflow the text or make the task row jump in height. */
  cursor: grab;
}

.task-prefix-slot {
  left: var(--ui-space-2); top: 0; bottom: 0;
  display: flex; align-items: center; justify-content: center;
}


.task-box {
  position: absolute; top: 50%;
  cursor: pointer; font-weight: var(--fw-semibold);
  pointer-events: auto;
  transition: opacity var(--ui-duration-fast) var(--ui-ease), border-color var(--ui-duration-fast) var(--ui-ease);
}


.task-prefix {
  line-height: var(--lh-none);
  white-space: nowrap; font-variant-numeric: tabular-nums; pointer-events: none;
}


.task-text {
  flex: 1;
  font-size: var(--task-effective-font, var(--font-task));
  letter-spacing: var(--ui-letter-spacing);
  transition: color var(--ui-duration-slow) var(--motion-standard),
    transform var(--ui-duration-fast) var(--motion-standard);
}

.priority-edge {
  position: absolute;
  /* Bo góc do rule .priority-edge phía dưới đặt; bản cũ viết
     "border-radius: inherit 0 0 inherit" — shorthand không nhận inherit nên
     trình duyệt bỏ nguyên khai báo (code chết). */
  pointer-events: none; z-index: 1;
}


.day-footer {
  flex: 0 0 auto; display: flex; align-items: center; gap: var(--ui-space-2); padding: var(--ui-space-2) var(--ui-space-3);
}

.progress-track {
  flex: 1; height: var(--ui-space-1); border-radius: var(--ui-radius-full); overflow: hidden;
  background: rgba(var(--ink), calc(0.10 + 0.10 * var(--t)));
}

.progress-fill { height: 100%; border-radius: 0 var(--ui-radius-full) var(--ui-radius-full) 0; background: var(--tone-blue-bar); transition: width var(--ui-duration-standard) var(--ui-ease); }

.day-count { font-size: var(--fs-caption); font-weight: var(--fw-semibold); letter-spacing: .3px; color: var(--ui-text-secondary); font-variant-numeric: tabular-nums; text-shadow: var(--shade-shadow); }

.gcal-event-item {
  position: relative;
  display: flex; align-items: center; justify-content: flex-start; text-align: left; width: 100%;
  flex-shrink: 0; cursor: pointer; user-select: none; -webkit-user-select: none;
  margin-bottom: 0;
  font-size: var(--task-effective-font, var(--font-task)); line-height: var(--task-line-height, 1.3);
}

.outlook-event-item {
  position: relative;
  display: flex; justify-content: flex-start; text-align: left; width: 100%;
  flex-shrink: 0; cursor: pointer; user-select: none; -webkit-user-select: none;
  margin-bottom: 0;
  font-size: var(--task-effective-font, var(--font-task)); line-height: var(--task-line-height, 1.3);
}

.grid {
  gap: 0;
  padding: 0 var(--ui-space-3) var(--ui-space-3);
  background: var(--ux-base);
  transition: opacity var(--ui-duration-standard) var(--motion-standard);
}


.day-col,
.day-col.weekend {
  border: 0;
  border-left: var(--ui-stroke-thin) solid var(--ui-divider);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  /* Clips this card's own task rows to its box. Deliberately plain
     `overflow` and NOT `contain: paint`: paint containment also clips the
     element's OWN outgoing box-shadow, which silently erased every card's
     drop shadow (--sf-card-shadow) and any outer hover ring. */
  overflow: hidden;
  transition: background-color var(--ui-duration-standard) var(--motion-standard);
}

.day-head {
  min-height: var(--ui-size-lg);
  padding: var(--ui-space-2) var(--ui-space-3) var(--ui-space-1-5);
}

.day-num {
  min-width: var(--ui-size-dense);
  height: var(--ui-size-dense);
  padding: 0;
  border-radius: var(--ui-radius-full);
  color: var(--ui-text-primary);
  background: transparent;
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  text-shadow: none;
}

.day-chip {
  padding: var(--ui-space-0-5) var(--ui-space-2);
  color: var(--ui-accent);
  background: var(--ui-selected);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  text-shadow: none;
}

.task-list {
  gap: var(--ui-space-0-5);
  padding: var(--ui-space-0-5) var(--ui-space-1) var(--ui-space-2);
}

.empty-hint {
  width: auto;
  min-width: var(--dt-dimension-layout-64);
  height: var(--ui-size-md);
  padding: 0 var(--ui-space-3);
  border: var(--ui-stroke-thin) dashed transparent;
  border-radius: var(--ui-radius-control);
  color: var(--ui-accent);
  font-size: 0;
  cursor: pointer;
}

.gcal-event-item,
.outlook-event-item {
  border-radius: var(--ui-radius-control);
  color: var(--ui-event-text);
  background: var(--ui-event-fill);
  font-weight: var(--fw-semibold);
  text-shadow: none;
  border: 0;
  box-shadow: none;
  transition: background-color var(--ui-duration-fast) var(--motion-standard), transform var(--ui-duration-instant) var(--motion-standard);
}

.outlook-event-item { align-items: center; }


.task-item {
  min-height: var(--ui-row-height);
  gap: var(--task-inline-gap);
  padding: var(--ui-space-1) var(--ui-space-2);
  border: 0;
  letter-spacing: var(--ui-letter-spacing);
  line-height: var(--task-line-height, 1.35);
  /* Square, not var(--ui-radius-control): the priority-edge marker sits flush
     against this row's own left edge, and this row clips children to its
     own radius (overflow:hidden below) — any rounding here would clip the
     marker's straight top/bottom corners into a curve. */
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  transition: color var(--ui-duration-standard) var(--motion-standard), background-color var(--ui-duration-fast) var(--motion-standard), opacity var(--ui-duration-standard) var(--motion-standard), box-shadow var(--ui-duration-standard) var(--motion-standard), transform var(--ui-duration-slow) var(--motion-standard);
}

.task-prefix-slot {
  position: relative;
  inset: auto;
  flex: 0 0 var(--ui-size-sm);
}

.task-box {
  left: 50%;
  width: var(--ui-icon-sm);
  height: var(--ui-icon-sm);
  border-radius: var(--ui-radius-full);
  color: var(--ui-success);
  background: transparent;
  border: var(--ui-stroke-thick) solid var(--ui-text-muted);
  font-size: var(--fs-micro);
  transform: translate(-50%, -50%);
}

.task-prefix {
  flex: 0 0 auto;
  color: var(--ui-text-secondary);
  font-size: var(--task-effective-font, var(--font-task));
  font-weight: var(--fw-medium);
  text-shadow: none;
}

.task-text {
  color: var(--ui-text-primary);
  font-weight: var(--fw-medium);
  line-height: var(--task-line-height, 1.45);
  text-shadow: none;
}



.completed-group {
  display: flex;
  flex-direction: column;
  flex: 0 0 auto;
  gap: var(--ui-space-0-5);
  min-width: 0;
  min-height: 0;
  margin-top: var(--ui-space-1);
}

.completed-group.is-push-bottom {
  margin-top: auto;
  /* Keep the conventional accordion order: heading first, rows below. The
     whole heading is the click target, so collapse/expand does not depend on
     aiming at the chevron alone. */
  flex-direction: column;
}

.completed-toggle {
  display: flex;
  align-items: center;
  gap: var(--ui-space-1-5);
  width: 100%;
  min-height: var(--ui-size-md);
  padding: 0 var(--ui-space-1-5);
  color: var(--ui-text-muted);
  background: transparent;
  border: 0;
  border-top: var(--ui-stroke-thin) solid var(--ui-divider);
  border-radius: 0;
  cursor: pointer;
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  text-align: left;
  transition: color var(--ui-duration-fast), background-color var(--ui-duration-fast);
}

.completed-label {
  flex: 1; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  line-height: var(--lh-tight);
}

.completed-count {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  height: var(--ui-space-4-5);
  line-height: 18px;
  font-variant-numeric: tabular-nums;
}

.completed-list {
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  gap: var(--ui-space-0-5);
  min-width: 0;
  min-height: 0;
}

.day-footer { border-top: 0; }

.task-item {
  height: auto;
  overflow: hidden;
  /* All leading controls share the text block's vertical centre. This stays
     correct for a one-line Week row and a wrapped Agenda/Today row. */
  align-items: center;
  padding-right: var(--ui-space-1);
}

.task-prefix-slot {
  align-self: stretch;
  min-height: var(--dt-dimension-row-list-dense);
  height: auto;
}

.task-text {
  display: block;
  min-width: 0;
  max-width: 100%;
  align-self: center;
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: normal;
  hyphens: auto;
}

.gcal-event-item,
.outlook-event-item {
  min-height: var(--ui-size-md);
  padding: var(--ui-space-1) var(--ui-space-2);
  gap: var(--ui-space-1);
  overflow: hidden;
}

.task-prefix {
  position: absolute;
  left: 50%;
  top: 50%;
  max-width: var(--ui-size-sm);
  transform: translate(-50%, -50%);
  opacity: 1;
  transition: opacity var(--ui-duration-fast) var(--motion-standard);
}

.task-box { opacity: .48; }

.task-list {
  overscroll-behavior: contain;
  /* Same reasoning as .grid.multi-week's scrollbar-gutter: without this, a
     card that newly needs its own inner scroll (e.g. a done task's height
     shifts when it's re-sorted to the bottom) narrows only its own text
     column right as it appears, instead of that width being reserved
     up front. */
  scrollbar-gutter: auto;
}

.priority-edge {
  inset: var(--ui-space-1) auto var(--ui-space-1) var(--ui-space-0-5);
}

.task-box {
  display: grid;
  place-items: center;
  padding: 0;
  line-height: 0;
}

.task-prefix-slot {
  width: var(--ui-size-md);
  min-width: var(--ui-size-md);
  flex-basis: var(--ui-size-md);
}

.priority-edge {
  left: var(--ui-space-0-5);
  top: 0;
  bottom: 0;
  width: var(--dt-component-calendar-item-priority-edge-width);
  border-radius: 0;
}

.calendar-item-more {
  position: absolute;
  /* Canh giữa dọc bằng inset + margin:auto, KHÔNG dùng transform:translateY.
     Token nhấn chung (button:active { transform: none !important }) từng xóa
     mất translateY khiến nút tụt xuống nửa dòng khi bấm — cách này miễn nhiễm. */
  top: 0;
  bottom: 0;
  right: var(--ui-space-1);
  margin: auto 0;
  z-index: var(--ui-layer-control);
  width: var(--ui-control-h-compact);
  height: var(--ui-control-h-compact);
  border-radius: var(--ui-radius-full);
  display: grid;
  place-items: center;
  padding: 0;
  border: var(--ui-stroke-thin) solid var(--ui-divider-subtle);
  box-shadow: var(--elev-1);
  color: var(--ui-text-secondary);
  background: var(--ux-overlay);
  cursor: pointer;
  pointer-events: auto !important;
  opacity: .38;
  transition: color var(--ui-duration-fast) var(--motion-standard),
    background-color var(--ui-duration-fast) var(--motion-standard),
    box-shadow var(--ui-duration-fast) var(--motion-standard),
    opacity var(--ui-duration-fast) var(--motion-standard);
}
.calendar-item-more::before {
  display: none;
  content: none;
}

/* ===================== MỤC B — BÙ THỨ TỰ @MEDIA =====================
   Hai luật này nằm trong @media ở styles.css và vốn đứng SAU lớp nền, nên
   chúng thắng. Lớp nền nay chuyển xuống dưới chúng, phải phát lại ở đây
   thì bề rộng đệm dưới 960px mới giữ nguyên như cũ. */
@media (max-width: 960px) {
  .grid { padding-inline: var(--ui-space-2); }
  .task-list { padding-inline: var(--ui-space-1); }
}
/* ===================== MỤC C — HỢP ĐỒNG TUẦN / NGÀY =====================
   Đây là nơi DUY NHẤT quyết định hình học của dạng Tuần và dạng Ngày.

   Nguyên tắc: mỗi phần tử có ĐÚNG MỘT ô trong một lưới, không phần tử nào
   được định vị tuyệt đối rồi bắt phần tử khác chừa chỗ bằng padding. Bản
   trước dựng thẻ việc bằng flex-wrap + hai lớp phủ absolute (ô tích bên
   trái, nút "…" bên phải) và bù trừ bằng `padding-inline-end` trên chữ —
   nên không có làn nào thẳng hàng giữa các thẻ, và 16px bề ngang bị giữ
   vĩnh viễn cho một nút chỉ hiện khi rê chuột.
   ===================================================================== */

/* ---------------------------------------------------------------------
   C1 · LƯỚI TUẦN
   Hai vùng xếp dọc: N làn dải việc dài ngày ở trên (renderGrid đặt
   --week-span-lanes), rồi hàng bảy cột ngày.
   --------------------------------------------------------------------- */
/* HAI HÀNG CỐ ĐỊNH, KHÔNG TÍNH TOÁN.
   Bản đầu dựng `repeat(var(--week-span-lanes, 0), auto) minmax(0, 1fr)` rồi
   đặt cột ngày ở `grid-row: -2 / -1`. Cách đó có hai điểm gãy, và cả hai đều
   gãy IM LẶNG:
     · số hàng phụ thuộc một biến do JS ghi. Biến đó lỡ rỗng hay không phải số
       thì `repeat()` hỏng, cả khai báo `grid-template-rows` bị bỏ, lưới còn
       không hàng tường minh nào — và `-2 / -1` lúc đó trỏ đi đâu là chuyện của
       thuật toán tự đặt chỗ, không còn là chuyện của thiết kế.
     · `-2 / -1` đọc ngược từ cuối lưới TƯỜNG MINH, nên ý nghĩa của nó đổi theo
       chính cái biến ở trên.
   Kết quả quan sát được: dải việc dài ngày rơi xuống ĐÁY lưới và bảy cột ngày
   bị co lại phía trên.
   Nay lưới luôn có đúng hai hàng — hàng dải (tự co về 0 khi không có dải nào)
   và hàng cột ngày — và cả hai đều là số nguyên viết thẳng. Số làn dải là
   chuyện riêng bên trong .week-span-band, không leo ra ngoài lưới nữa. */
.grid[data-view-mode="week"] {
  grid-template-rows: auto minmax(0, 1fr);
  align-items: stretch;
  /* row-gap = 0: khi tuần không có dải dài ngày, hàng 1 co về 0 nhưng khe
     giữa hai hàng vẫn còn, đẩy cột ngày xuống thêm một nhịp → lề trên lớn hơn
     lề trái. Khoảng cách dưới dải do chính .week-span-band tự mang. */
  row-gap: 0;
  column-gap: var(--ui-space-2);
  padding: var(--ui-space-2);
  background: var(--ux-base);
}
.grid[data-view-mode="week"] > .day-col {
  grid-row: 2;
}

/* ---------------------------------------------------------------------
   C2 · CỘT NGÀY — ba hàng cố định: đầu / thân cuộn / chân.
   Chân cột dựng cho MỌI ngày, kể cả ngày trống, nên bảy cột luôn thẳng
   đáy và nút "Thêm" luôn ở cùng một chỗ. Bản trước chỉ dựng chân khi cột
   có việc, còn nút Thêm thì trôi theo nội dung — cùng một nút xuất hiện
   ở ba độ cao khác nhau trên cùng một màn hình.
   --------------------------------------------------------------------- */
.grid[data-view-mode="week"] .day-col {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  min-height: 0;
}

.grid[data-view-mode="week"] .day-head {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--ui-space-2);
  /* Đầu cột là control (nhấp đúp tạo việc): chiều cao bám thang size.lg (40 / Lớn 50)
     thay vì cộng dồn chữ + đệm ra 38px lệch thang (AT-UI 2026). */
  box-sizing: border-box;
  min-height: var(--ui-size-lg);
  padding: var(--ui-space-2);
  border-bottom: var(--ui-stroke-thin) solid var(--ui-divider);
}
/* Nhãn phụ của ngày (ngoại lệ nghỉ/làm bù, cảnh báo trùng giờ) dạt về mép
   phải để cặp "số + thứ" giữ nguyên vị trí ở cả bảy cột. */
.grid[data-view-mode="week"] .day-head > :is(.day-work-flag, .day-overlap-chip) {
  margin-left: auto;
}
.grid[data-view-mode="week"] .day-head > .day-work-flag ~ .day-overlap-chip {
  margin-left: 0;
}

.grid[data-view-mode="week"] .task-list {
  display: flex;
  flex-direction: column;
  gap: var(--ui-card-gap);
  min-height: 0;
  padding: var(--ui-space-2);
  overflow-x: hidden;
  overflow-y: auto;
}

/* Ngăn "Đã hoàn tất" thôi ghim đáy. `margin-top: auto` đẩy nó xuống chân
   vùng cuộn và để lại một khoảng trắng giữa cột đúng bằng phần chưa dùng
   — đó là cái hố giữa mỗi cột trong bản cũ. Nó là phần tiếp theo của danh
   sách, nên đứng ngay sau việc cuối cùng. */
:is(.grid[data-view-mode="week"], .grid[data-view-mode="today"])
  .completed-group.is-push-bottom {
  margin-top: var(--ui-space-1);
}

/* ---------------------------------------------------------------------
   C3 · CHÂN CỘT — một dòng, ba ô: [＋ Thêm] [thanh tiến độ] [xong/tổng].
   Tỉ lệ hoàn tất chỉ nói MỘT lần ở đây; chip done/total ở đầu cột đã gỡ.
   --------------------------------------------------------------------- */
.grid[data-view-mode="week"] .day-footer {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--ui-space-2);
  padding: var(--ui-space-1) var(--ui-space-2);
  border-top: var(--ui-stroke-thin) solid var(--ui-divider);
}
.grid[data-view-mode="week"] .day-footer .progress-track {
  height: var(--ui-space-1);
}
.grid[data-view-mode="week"] .day-footer .day-count {
  display: block;
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  text-shadow: none;
}
.grid[data-view-mode="week"] .day-footer .day-count.all-done {
  color: var(--ui-success);
}
/* Ngày chưa có việc nào: chân cột chỉ còn lời mời thêm việc, không vẽ một
   thanh tiến độ 0% và một con số "0/0" vô nghĩa. */
.grid[data-view-mode="week"] .day-footer.is-empty {
  grid-template-columns: minmax(0, 1fr);
}
/* Giai đoạn 2 (tạo việc inline): .day-inline-create là vỏ bọc để JS chọn giữa
   nút và ô nhập. Ở trạng thái NÚT nó dùng display:contents — biến mất khỏi
   lưới, .day-add-hint trở thành đúng Ô 1 như trước đây, không phải sửa lại
   grid-template-columns ba cột ở trên. Ở trạng thái Ô NHẬP (.is-editing) nó
   PHẢI có hộp thật (position: relative) để làm điểm neo cho panel gợi ý —
   display:contents không tạo hộp nên không neo được gì lên nó. Chân cột lúc
   này đổi về một cột duy nhất và ẩn thanh tiến độ/số liệu, nhường trọn bề
   ngang cho ô nhập thay vì bị bóp chung một hàng với chúng. */
.day-inline-create:not(.is-editing) { display: contents; }
.day-inline-create.is-editing { position: relative; width: 100%; }
.grid[data-view-mode="week"] .day-footer.is-inline-editing {
  grid-template-columns: minmax(0, 1fr);
}
.day-footer.is-inline-editing .progress-track,
.day-footer.is-inline-editing .day-count {
  display: none;
}
.day-inline-create-input {
  display: block;
  width: 100%;
  min-width: 0;
  flex: 1 1 auto;
  border: var(--ui-stroke-thin) solid var(--ui-accent);
  border-radius: var(--ui-radius-control);
  background: var(--ux-base);
  color: var(--ui-text-primary);
  font: inherit;
  font-size: var(--fs-caption);
  padding: var(--ui-space-1-5) var(--ui-space-2);
  outline: none;
}
.day-inline-create-input:focus-visible {
  outline: none;
  box-shadow: var(--ui-control-ring);
}
.day-inline-create-input::placeholder {
  color: var(--ui-text-muted);
}
/* Chân cột nằm sát đáy cột — panel mở XUỐNG như QuickAdd sẽ bị cắt bởi mép
   dưới màn hình, nên mở NGƯỢC LÊN TRÊN. Kế thừa khung/màu/bóng từ
   .quick-tag-suggestions (đã có ở styles.css), chỉ đổi hướng neo. */
.day-inline-suggest {
  top: auto;
  bottom: calc(100% + var(--ui-space-1-5));
  left: 0;
  width: min(var(--dt-dimension-layout-288), calc(100vw - var(--ui-space-8)));
  z-index: var(--ui-layer-control);
}

/* ---------------------------------------------------------------------
   C4 · THẺ VIỆC / SỰ KIỆN — một lưới hai cột, hai hàng.
     lead | body      ô tích + số thứ tự  |  giờ + tiêu đề
     lead | meta      (trải suốt)         |  tag + trạng thái
   Nút "…" KHÔNG chiếm ô nào: nó phủ lên góc phải trên khi rê chuột, nền
   đục bằng nền thẻ. Nhờ vậy chữ lấy lại trọn bề ngang lúc nghỉ.
   --------------------------------------------------------------------- */
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  :is(.task-item, .gcal-event-item, .outlook-event-item) {
  position: relative;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: var(--cal-lead-lane, 18px) minmax(0, 1fr);
  grid-template-rows: minmax(var(--ui-control-h-compact), auto) auto;
  grid-template-areas:
    "lead body"
    "lead meta";
  align-items: start;
  /* Khe làn dẫn ↔ thân = bậc spacing (không suy từ cỡ chữ: 14 × .45 × .5 = 3,15px lệch thang). */
  column-gap: var(--ui-space-1);
  row-gap: var(--ui-space-1, var(--ui-space-0-5));
  min-height: max(var(--ui-control-h-standard), calc(var(--task-effective-font) * 2));
  padding: var(--ui-space-1, var(--ui-space-1)) var(--ui-space-2);
  /* Làn ưu tiên rộng cố định ở MỌI thẻ, kể cả thẻ chưa đặt ưu tiên — thẻ chưa
     đặt giữ màu trong suốt. Hai lý do:
       · bề dày cố định giữ cho chữ của mọi thẻ khởi đầu ở cùng một mép trái;
         đổi bề dày theo trạng thái sẽ làm cả cột chữ so le nhau 3px.
       · màu chỉ xuất hiện khi dữ liệu có priority; task thường không phải mang
         thêm một vạch xám chỉ để lấp chỗ. Bề rộng vẫn được giữ trong layout. */
  border: 0;
  border-inline-start: var(--ui-calendar-priority-edge-width) solid transparent;
  border-radius: var(--ui-radius-control);
  box-shadow: none;
  overflow: hidden;
}
/* Thẻ không có hàng meta: bỏ hàng thứ hai (và row-gap đi kèm) rồi căn khối
   nội dung vào giữa chiều cao tối thiểu của thẻ. Tiêu đề một dòng nhờ đó
   không bị dính mép trên; tiêu đề hai dòng đã lấp đầy thẻ nên không đổi. */
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  :is(.task-item, .gcal-event-item, .outlook-event-item):not(:has(> .calendar-item-footer)) {
  grid-template-rows: minmax(var(--ui-control-h-compact), auto);
  grid-template-areas: "lead body";
  align-content: center;
}
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  :is(.task-item, .gcal-event-item, .outlook-event-item):not(:has(> .calendar-item-footer))
  > :is(.task-text, .gcal-event-title, .outlook-event-title, .gcal-event-body, .outlook-event-body) {
  align-self: center;
}
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"]) .task-item {
  background: var(--ux-raised);
}
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  :is(.gcal-event-item, .outlook-event-item) {
  background: var(--ui-event-fill);
}

/* Hover chung giữ nguyên hình học: không dựng border thật nên chữ không dịch.
   Dạng Tháng tiếp tục chỉ đổi nền như contract compact hiện có. */
:is(.grid.today-view, .grid[data-view-mode="today"], .grid[data-view-mode="day"], .grid[data-view-mode="week"], .grid.multi-week, .grid.agenda-view)
  :is(.task-item, .gcal-event-item, .outlook-event-item, .backlog-item):not(.dragging):hover,
:is(.grid.today-view, .grid[data-view-mode="today"], .grid[data-view-mode="day"], .grid[data-view-mode="week"], .grid.multi-week, .grid.agenda-view)
  :is(.task-item, .gcal-event-item, .outlook-event-item, .backlog-item):not(.dragging):focus-within {
  outline: none;
  box-shadow: none;
  background: var(--ux-hover);
}
/* Ngày / Tuần / Agenda / Trễ hạn: card nghỉ không viền, chỉ card đang tương
   tác mới có vòng inset trung tính. Inset không chiếm layout và vẫn giữ riêng
   cạnh màu ưu tiên. Tháng bị loại khỏi selector để không đổi contract compact. */
:is(
  .grid.today-view,
  .grid[data-view-mode="today"],
  .grid[data-view-mode="day"],
  .grid[data-view-mode="week"],
  .grid.agenda-view,
  .grid[data-view-mode="agenda"],
  .today-backlog-rail
) :is(.task-item, .gcal-event-item, .outlook-event-item, .backlog-item):not(.dragging):hover,
:is(
  .grid.today-view,
  .grid[data-view-mode="today"],
  .grid[data-view-mode="day"],
  .grid[data-view-mode="week"],
  .grid.agenda-view,
  .grid[data-view-mode="agenda"],
  .today-backlog-rail
) :is(.task-item, .gcal-event-item, .outlook-event-item, .backlog-item):not(.dragging):focus-within {
  outline: var(--ui-calendar-interaction-ring-width) solid var(--ui-focus-ring);
  outline-offset: calc(var(--ui-calendar-interaction-ring-width) * -1);
}

:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  :is(.task-prefix-slot, .event-prefix-slot) {
  grid-area: lead;
  position: relative;
  inset: auto;
  width: var(--cal-lead-lane, var(--ui-space-4-5));
  min-width: 0;
  height: auto;
  min-height: var(--ui-control-h-compact);
  align-self: start;
  justify-self: center;
  flex: 0 0 auto;
}
/* Ô tích nằm TRONG làn dẫn (calendarGrid.js gắn nó vào .task-prefix-slot),
   nên nó và số thứ tự dùng chung một tâm và hoán đổi bằng opacity. Bản cũ
   để ô tích làm con trực tiếp của thẻ với `left: 50%`, tức là căn giữa
   theo cả THẺ chứ không theo làn dẫn, rồi phải có một luật riêng kéo nó
   về `left: 4px` để trông như đang ở đúng chỗ. */
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  :is(.task-prefix-slot, .event-prefix-slot) :is(.task-box, .event-box) {
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  :is(.task-text, .gcal-event-title, .outlook-event-title) {
  grid-area: body;
  display: -webkit-box;
  align-self: start;
  min-width: 0;
  max-width: 100%;
  margin: 0;
  padding-inline-end: 0;
  overflow: hidden;
  overflow-wrap: anywhere;
  white-space: normal;
  text-align: start;
  line-height: var(--task-line-height, 1.4);
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  text-overflow: clip;
}
/* `margin-left: 37px` của thân sự kiện là cách bản cũ chừa chỗ cho làn dẫn
   khi làn đó còn định vị tuyệt đối. Trong lưới thẻ, làn dẫn đã là một CỘT
   thật, nên khoảng lề đó cộng thêm lần thứ hai và đẩy chữ sự kiện lệch hẳn
   so với chữ công việc ngay bên trên nó. */
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  :is(.gcal-event-body, .outlook-event-body) {
  grid-area: body;
  min-width: 0;
  margin-left: 0;
}

/* Hàng thứ hai chỉ tồn tại khi có dữ liệu thật. Việc không tag, không
   trạng thái vẫn là một thẻ một dòng. */
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  .calendar-item-footer {
  grid-area: meta;
  display: flex;
  align-items: center;
  gap: var(--ui-space-1);
  min-width: 0;
  padding: 0;
  overflow: hidden;
}
/* Trạng thái neo TRÁI, tag dồn về bên phải trong cùng (BA chốt 2026-09-12). */
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  .calendar-item-footer-statuses {
  order: 1;
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: flex-start;
  gap: calc(var(--ui-space-1) * 1.25);
  margin-left: 0;
  white-space: nowrap;
}
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  .calendar-item-footer-tags {
  order: 2;
  display: flex;
  flex: 0 1 auto;
  justify-content: flex-end;
  gap: var(--ui-space-1);
  min-width: 0;
  margin: 0;
  margin-left: auto;
  overflow: hidden;
}
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  .calendar-item-footer .task-tags {
  display: flex;
  flex-wrap: nowrap;
  justify-content: flex-end;
  gap: var(--ui-space-1);
  max-width: 100%;
  margin: 0;
  margin-left: auto;
  overflow: hidden;
}
.calendar-item-month-tags {
  display: flex;
  align-items: center;
  margin-left: auto;
  flex-shrink: 0;
}
.calendar-item-month-tags .task-tags {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--ui-space-1);
}
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .today-main)
  :is(.task-item, .gcal-event-item, .outlook-event-item):hover,
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .today-main)
  :is(.task-item, .gcal-event-item, .outlook-event-item):focus-within {
  padding-right: var(--ui-space-2);
}

/* ---------------------------------------------------------------------
   C5 · HUY HIỆU TRẠNG THÁI
   --------------------------------------------------------------------- */
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid[data-view-mode="agenda"], .grid.agenda-view)
  .calendar-item-status {
  display: inline-flex;
  width: auto;
  height: auto;
  min-width: 0;
  min-height: calc(var(--task-effective-font) * 1.2);
  align-items: center;
  justify-content: center;
  gap: var(--ui-space-1);
  margin: 0;
  padding: 0 var(--ui-space-1);
  border: 0;
  border-radius: var(--ui-radius-control);
  background: var(--ux-fill);
  color: var(--ui-text-secondary);
  font: var(--fw-semibold) var(--fs-caption)/var(--lh-snug) var(--app-font);
  vertical-align: middle;
  cursor: pointer;
  box-sizing: border-box;
}
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid[data-view-mode="agenda"], .grid.agenda-view)
  .calendar-item-status:hover {
  filter: brightness(0.92);
}
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid[data-view-mode="agenda"], .grid.agenda-view)
  .calendar-item-status svg {
  flex: 0 0 auto;
  width: calc(var(--task-effective-font) * 1.05);
  height: calc(var(--task-effective-font) * 1.05);
  display: block;
}
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid[data-view-mode="agenda"], .grid.agenda-view)
  .calendar-item-status.is-conflict {
  color: var(--ui-warning);
  background: color-mix(in srgb, var(--ui-warning) 14%, transparent);
}
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid[data-view-mode="agenda"], .grid.agenda-view)
  .calendar-item-status.is-repeat {
  color: var(--ui-accent);
  background: color-mix(in srgb, var(--ui-accent) 12%, transparent);
}
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid[data-view-mode="agenda"], .grid.agenda-view)
  .calendar-item-status.is-due {
  color: var(--ui-warning);
  background: color-mix(in srgb, var(--ui-warning) 12%, transparent);
}
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid[data-view-mode="agenda"], .grid.agenda-view)
  .alert-urgent .calendar-item-status.is-due {
  color: var(--ui-danger);
  background: color-mix(in srgb, var(--ui-danger) 12%, transparent);
}
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  .calendar-item-status.is-note {
  color: var(--tone-purple-fg);
  background: var(--tone-purple-bg);
}
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  .calendar-item-status-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Dạng Tuần + Ngày: huy hiệu chỉ còn ICON (BA 2026-10-09 thêm dạng Ngày — chữ
   "Lặp"/"Note" chiếm cả một dòng; nghĩa vẫn ở title/aria-label). Chuẩn hóa kích
   thước đồng bộ, mở rộng vùng bấm (hitbox) và giãn cách 5px để thao tác chính xác. */
:is(.grid[data-view-mode="week"], .grid[data-view-mode="today"]) .calendar-item-status-label {
  display: none;
}
.grid[data-view-mode="week"] .calendar-item-status {
  min-width: calc(var(--task-effective-font) * 1.35);
  height: calc(var(--task-effective-font) * 1.35);
  padding: 0 calc(var(--ui-space-1) * 0.5);
  box-sizing: border-box;
}

/* ---------------------------------------------------------------------
   C6 · LÀN ƯU TIÊN — tô màu chính viền trái của thẻ.
   --------------------------------------------------------------------- */
:is(
  .grid:is([data-view-mode="today"], [data-view-mode="week"], [data-view-mode="agenda"]),
  .today-backlog-rail
) :is(.task-item, .gcal-event-item, .outlook-event-item, .backlog-item) .priority-edge {
  display: none;
}
:is(
  .grid:is([data-view-mode="today"], [data-view-mode="week"], [data-view-mode="agenda"]),
  .today-backlog-rail
) :is(.task-item, .gcal-event-item, .outlook-event-item, .backlog-item).has-priority-urgent {
  border-inline-start-color: var(--ui-danger);
}
:is(
  .grid:is([data-view-mode="today"], [data-view-mode="week"], [data-view-mode="agenda"]),
  .today-backlog-rail
) :is(.task-item, .gcal-event-item, .outlook-event-item, .backlog-item).has-priority-important {
  border-inline-start-color: var(--ui-warning);
}
:is(
  .grid:is([data-view-mode="today"], [data-view-mode="week"], [data-view-mode="agenda"]),
  .today-backlog-rail
) :is(.task-item, .gcal-event-item, .outlook-event-item, .backlog-item).has-priority-normal {
  border-inline-start-color: var(--ui-success);
}
:is(
  .grid:is([data-view-mode="today"], [data-view-mode="week"], [data-view-mode="agenda"]),
  .today-backlog-rail
) :is(.task-item, .gcal-event-item, .outlook-event-item, .backlog-item).has-priority-personal {
  border-inline-start-color: var(--ui-accent);
}
/* Khay tồn đọng không đi qua lưới thẻ ở C4 nên phải được cấp bề dày viền
   trái ngay tại đây. Dạng Danh sách cũng cần, nhưng luật của nó phải nằm
   SAU `border: 0` ở C11 — xem chú thích tại đó. */
.today-backlog-rail .backlog-item:is(
  .has-priority-urgent, .has-priority-important, .has-priority-normal, .has-priority-personal
) {
  border-inline-start-style: solid;
  border-inline-start-width: var(--ui-calendar-priority-edge-width);
}

/* ---------------------------------------------------------------------
   C7 · NÚT HÀNH ĐỘNG — phủ góc, không chiếm bề ngang.
   --------------------------------------------------------------------- */
.grid[data-view-mode] .calendar-item-more svg {
  width: var(--ui-icon-control);
  height: var(--ui-icon-control);
}
/* Nút đã thu theo chiều cao dòng chữ tiêu đề (xem khối ngay dưới) — icon
   cũng phải thu theo tỉ lệ đó, nếu không icon cố định 16px sẽ chật cứng
   trong một nút chỉ còn ~17–19px ở cỡ chữ mặc định. */
:is(.grid[data-view-mode], .today-workspace, .today-backlog-rail)
  .calendar-item-more svg {
  width: calc(var(--task-effective-font) * .85);
  height: calc(var(--task-effective-font) * .85);
  max-width: var(--ui-icon-control);
  max-height: var(--ui-icon-control);
}
/* BẪY ĐÃ SẬP MỘT LẦN (2026-09-12): `top: 2px; right: 2px` định vị nút này
   theo GÓC CỦA CẢ THẺ, không theo hàng tiêu đề. Với thẻ có tag/huy hiệu —
   tức có hàng meta thứ hai — mép dưới của nút (2px + 22px = 24px từ đỉnh
   thẻ) gần như trùng khít mép trên của hàng meta (đo được cách nhau chưa
   tới nửa pixel). Ở màn hình DPI lẻ (125%…) hoặc khi hàng tiêu đề dài hơn
   một chút, nút và huy hiệu Ghi chú/badge bên dưới ĐÈ LÊN NHAU thật.

   Cách sửa không phải "đẩy xuống thêm vài px" — số px an toàn hôm nay có
   thể lại thiếu ở cỡ chữ hay hàng meta khác. Thay vào đó KHOÁ nút vào ĐÚNG
   Ô LƯỚI "body" (hàng tiêu đề): `grid-area` trên một phần tử `position:
   absolute` biến chính ô lưới đó thành containing block của nó (đặc tính
   chuẩn của CSS Grid, không phải mẹo vặt) — mép dưới của nút khi đó
   KHÔNG THỂ vượt quá mép dưới của hàng tiêu đề, bất kể bo tròn số hay cỡ
   chữ. Kích thước nút dùng hằng số chuẩn token `--ui-control-h-compact`
   (22px) đồng bộ toàn bộ khay Ngày và Trễ hạn. */
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  :is(.task-item, .gcal-event-item, .outlook-event-item) .calendar-item-more {
  position: absolute;
  grid-area: body;
  /* Canh nút "…" theo tỷ lệ chuẩn Design Token (top: 4px, right: 4px từ mép card):
     - top: 0 trong ô body (vốn cách mép trên card đúng padding-top: var(--ui-space-1) = 4px),
       giúp nút cao 24px nằm gọn trong hàng tiêu đề (min-height: 24px) không bị đè hàng meta.
     - right: calc(var(--ui-space-1) * -1) bù lại padding-inline-end 8px của card,
       đưa nút về cách mép phải card đúng var(--ui-space-1) = 4px.
     Tỷ lệ lề góc: 4px : 4px (1:1), cân đối và không dính sát mép trên. */
  top: 0;
  right: calc(var(--ui-space-1) * -1);
  bottom: auto;
  left: auto;
  margin-block: 0;
  width: var(--ui-control-h-compact);
  height: var(--ui-control-h-compact);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--ui-radius-full);
  border: var(--ui-stroke-thin) solid var(--ui-divider-subtle);
  box-shadow: var(--elev-1);
  background: var(--ux-overlay);
  z-index: var(--ui-layer-control);
  opacity: 0;
  visibility: hidden;
  transform: none;
}
.task-meeting-icon .calendar-item-status-label {
  display: none;
}
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  :is(.task-item, .gcal-event-item, .outlook-event-item):hover .calendar-item-more,
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  :is(.task-item, .gcal-event-item, .outlook-event-item):focus-within .calendar-item-more,
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  .calendar-item-more:focus-visible {
  opacity: 1;
  visibility: visible;
}
.calendar-item-more:focus-visible {
  outline: var(--ui-focus-ring-width) solid var(--ui-focus-ring);
  outline-offset: calc(var(--ui-focus-ring-offset) * -1);
}
:is(.grid[data-view-mode], .today-workspace, .today-backlog-rail)
  :is(.task-item, .gcal-event-item, .outlook-event-item, .backlog-item)
  .calendar-item-more:hover {
  color: var(--ui-accent);
  background: color-mix(in srgb, var(--ui-accent) 18%, var(--ux-overlay));
  box-shadow: var(--elev-2);
}
:is(.grid[data-view-mode], .today-workspace, .today-backlog-rail)
  :is(.task-item, .gcal-event-item, .outlook-event-item, .backlog-item)
  .calendar-item-more:active {
  color: var(--ui-accent);
  background: color-mix(in srgb, var(--ui-accent) 26%, var(--ux-overlay));
  box-shadow: var(--elev-1);
  filter: brightness(0.92);
}
:is(.grid[data-view-mode="multiWeek"], .grid[data-view-mode="agenda"]) .calendar-item-more {
  position: absolute;
  top: 0;
  bottom: 0;
  margin-block: auto;
  right: var(--ui-space-1);
  width: var(--ui-control-h-compact);
  height: var(--ui-control-h-compact);
  border-radius: var(--ui-radius-full);
  border: var(--ui-stroke-thin) solid var(--ui-divider-subtle);
  box-shadow: var(--elev-1);
  background: var(--ux-overlay);
  z-index: var(--ui-layer-control);
  opacity: 0;
  visibility: hidden;
}
:is(.grid[data-view-mode="multiWeek"], .grid[data-view-mode="agenda"])
  :is(.task-item, .gcal-event-item, .outlook-event-item):hover .calendar-item-more,
:is(.grid[data-view-mode="multiWeek"], .grid[data-view-mode="agenda"])
  :is(.task-item, .gcal-event-item, .outlook-event-item):focus-within .calendar-item-more,
:is(.grid[data-view-mode="multiWeek"], .grid[data-view-mode="agenda"])
  .calendar-item-more:focus-visible {
  opacity: 1;
  visibility: visible;
}
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  .task-item:hover .task-prefix-slot .task-box,
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  .task-item:focus-within .task-prefix-slot .task-box,
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  .task-item.done .task-prefix-slot .task-box,
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  :is(.gcal-event-item, .outlook-event-item):hover .event-box,
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  :is(.gcal-event-item, .outlook-event-item):focus-within .event-box,
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
  :is(.gcal-event-item, .outlook-event-item).event-done .event-box {
  opacity: 1;
  pointer-events: auto;
}

/* ---------------------------------------------------------------------
   C8 · VẠCH NGĂN "ĐÃ GẮN GIỜ ↔ CHƯA GẮN GIỜ" (dạng Tuần)
   Thay cho ba nhãn SÁNG / CHIỀU / LINH HOẠT. Ba nhãn đó chỉ bật khi cột
   có ≥3 việc có giờ và chạm ≥2 buổi, nên cùng một tuần có cột ba nhãn,
   cột hai nhãn, cột không nhãn — bảy cột không còn chung bộ xương, mà
   mỗi nhãn lại ăn trọn một dòng của cột vốn đã hẹp.
   --------------------------------------------------------------------- */
.day-flex-divider {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--ui-space-1);
  margin-top: var(--ui-space-1);
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  pointer-events: none;
  user-select: none;
}
.day-flex-divider::after {
  content: "";
  flex: 1;
  height: var(--ui-resizer-line);
  background: var(--ui-divider);
}

/* ---------------------------------------------------------------------
   C9 · DẢI VIỆC DÀI NGÀY
   Một việc trải nhiều ngày là MỘT dải liên tục vắt ngang các cột, không
   phải bảy hàng giống hệt nhau ở đỉnh bảy cột. Con số "ngày 7/12" cũng
   biến mất khỏi lưới: nó cùng hình dạng với chip "xong 4/12" nên hai
   nghĩa khác hẳn nhau lại trông như một.
   --------------------------------------------------------------------- */
/* Dải nằm trong một khung con trải hết bảy cột và mượn ĐÚNG các đường cột của
   lưới cha bằng `subgrid` — nên mép dải luôn trùng mép cột ở mọi khổ màn hình,
   kể cả khi lưới chuyển sang cuộn ngang. Gói chúng vào một khung riêng thay vì
   thả thẳng vào lưới còn có một tác dụng phòng thủ: dù việc xếp làn bên trong
   có sai thế nào thì nó cũng không đẩy được cột ngày đi chỗ khác. */
.week-span-band {
  grid-row: 1;
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  grid-auto-rows: auto;
  row-gap: var(--ui-space-0-5);
  min-width: 0;
  margin-block-end: var(--ui-space-1);
}
.week-span-bar {
  position: relative;
  z-index: var(--ui-layer-raised);
  grid-row: var(--span-lane, 1);
  grid-column: var(--span-col, 1) / span var(--span-len, 1);
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  min-width: 0;
  min-height: max(var(--ui-size-sm), calc(var(--fs-caption) * 2));
  padding: 0 calc(var(--ui-space-2) + var(--ui-space-1));
  border: var(--ui-stroke-thick) solid var(--ui-accent);
  border-radius: var(--ui-radius-pill);
  background: var(--ux-raised);
  color: var(--ui-text-primary);
  cursor: pointer;
  overflow: hidden;
  text-align: start;
  font-family: inherit;
}
.week-span-bar:hover,
.week-span-bar:focus-visible {
  border-color: var(--ui-accent);
  background: var(--ui-hover);
}
.week-span-bar.has-priority-urgent { border-color: var(--ui-danger); }
.week-span-bar.has-priority-important { border-color: var(--ui-warning); }
.week-span-bar.has-priority-normal { border-color: var(--ui-success); }
.week-span-bar.has-priority-personal { border-color: var(--ui-accent); }
/* Việc dài ngày luôn giữ chuẩn bo tròn hình viên thuốc pill (BA chốt 2026-09-12).
   Khi bị cắt bởi mép tuần thì vẫn giữ bo tròn 100%, nét viền trái/phải đứt nhẹ để báo hiệu nối dài. */
.week-span-bar.is-continued-before {
  border-left-style: dashed;
}
.week-span-bar.is-continued-after {
  border-right-style: dashed;
}
/* Kéo dải (GĐ6): hai vùng nắm mép nằm trong phần đệm ngang của dải nên không
   che chữ; thân dải kéo để dời cả khoảng. touch-action: none để pointer drag
   chạy cả trên màn cảm ứng thay vì cuộn trang.
   Bề rộng vùng nắm CỐ Ý dùng --ui-space-1-5 (6px), KHÔNG dùng --ui-resizer-hit
   (24px, token của splitter panel lớn): đã thử đổi sang --ui-resizer-hit khi
   gộp nhánh magical-tesla-bvrsr3 (2026-09-27) — hai tay nắm 24px trên một dải
   ngắn (2-3 cột) đè rộng vào giữa, khiến `event.target.closest('[data-span-edge]')`
   trật ra ngoài vùng nắm thật và cú kéo bị hiểu nhầm thành kéo THÂN (dời cả
   khoảng) thay vì kéo MÉP — `weekSpanDrag.spec.js` bắt được ngay. Bar này có
   overflow: hidden nên rộng thêm không "an toàn" như tưởng, phải đo lại bằng
   E2E trước khi đổi token, không suy diễn từ tên token.
   .week-span-grip nằm HẲN TRONG mép bar (inset-inline, không đẩy nửa ra
   ngoài như splitter cột thường) vì .week-span-bar có overflow: hidden để
   cắt gọn text/sọc ngày nghỉ — một tay nắm định vị âm sẽ bị cắt mất phần
   ngoài và trở nên không bấm/kéo được dù getBoundingClientRect() vẫn báo
   đúng toạ độ. */
.week-span-bar:has(.week-span-grip) { touch-action: none; }
.week-span-grip {
  position: absolute;
  inset-block: 0;
  width: var(--ui-space-1-5);
  cursor: ew-resize;
}
.week-span-grip.is-start { inset-inline-start: 0; }
.week-span-grip.is-end { inset-inline-end: 0; }
.week-span-bar.is-dragging {
  cursor: grabbing;
  user-select: none;
  box-shadow: var(--ui-elevation-2);
}
/* Ngày nghỉ nằm giữa dải hiện mờ ngay trên chính dải, nên thông tin "hôm
   đó không làm" không mất khi bỏ bảy hàng gương. */
.week-span-days {
  position: absolute;
  inset: 0;
  display: flex;
  pointer-events: none;
}
.week-span-day {
  flex: 1 1 0;
  min-width: 0;
}
.week-span-day.is-offday {
  background: repeating-linear-gradient(
    135deg,
    var(--ux-fill) 0 4px,
    transparent 4px 8px
  );
}
.week-span-title {
  position: relative;
  z-index: 1;
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
}
.week-span-range {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.week-span-more {
  grid-row: var(--span-lane, 1);
  grid-column: 1 / -1;
  justify-self: start;
  padding: 0 var(--ui-space-2);
  border: 0;
  background: transparent;
  color: var(--ui-text-muted);
  font-family: inherit;
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  cursor: pointer;
}
.week-span-more:hover { color: var(--ui-accent); }

/* ---------------------------------------------------------------------
   C10 · DẠNG NGÀY — dùng lại nguyên hợp đồng thẻ ở trên.
   --------------------------------------------------------------------- */
.grid[data-view-mode="today"] .today-day .task-list {
  gap: var(--ui-card-gap, var(--ui-list-row-gap));
  padding: var(--ui-space-1) var(--ui-space-2) var(--ui-space-2);
}
.grid[data-view-mode="today"] .today-day :is(.task-item, .gcal-event-item, .outlook-event-item) {
  position: relative;
}
/* Hộp ghi chú là thẻ co giãn cuối cùng của dạng Ngày, kể cả khi trống. */
.grid[data-view-mode="today"] .today-note-box {
  flex: 1 1 var(--ui-list-row-min);
  min-height: var(--dt-dimension-layout-144);
}

/* Khay tồn đọng: hình hộp GIỐNG HỆT nhau ở trạng thái nghỉ, rê chuột và
   focus bàn phím, đồng bộ height, padding và typography với thẻ việc hôm nay. */
.today-backlog-rail .backlog-item,
.today-backlog-rail .backlog-item:hover,
.today-backlog-rail .backlog-item:focus-within {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  row-gap: var(--ui-space-1, var(--ui-space-1));
  min-width: 0;
  min-height: max(var(--ui-control-h-standard), calc(var(--task-effective-font) * 2.2));
  padding: var(--ui-space-1) var(--ui-space-2);
  border: 0;
  border-inline-start: var(--ui-calendar-priority-edge-width) solid transparent;
}
.today-backlog-rail .backlog-item:has(> .backlog-selection-box) {
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: var(--ui-space-2);
}
.today-backlog-rail .backlog-selection-box {
  grid-column: 1;
  grid-row: 1 / span 2;
  align-self: start;
}
.today-backlog-rail .backlog-item-primary {
  grid-row: 1;
  min-width: 0;
  padding-inline-end: var(--ui-control-h-compact);
}
/* Hàng meta canh trái ngay dưới tiêu đề (đọc liền mạch: tag · ngày), không đẩy
   sang mép phải (BA 10/10/2026). */
.today-backlog-rail .backlog-item-meta {
  grid-row: 2;
  display: flex;
  width: 100%;
  min-width: 0;
  align-items: center;
  justify-content: flex-start;
  gap: var(--ui-space-2);
  margin-left: 0;
}
.today-backlog-rail .backlog-item-meta .task-tags {
  margin-left: 0;
  justify-content: flex-start;
}
.today-backlog-rail .backlog-item:has(> .backlog-selection-box)
  :is(.backlog-item-primary, .backlog-item-meta) {
  grid-column: 2;
}
.today-backlog-rail .backlog-item-title {
  font-family: var(--app-font);
  font-size: var(--task-effective-font, var(--font-task));
  line-height: var(--task-line-height, 1.4);
  font-weight: var(--fw-normal);
  display: -webkit-box;
  overflow: hidden;
  overflow-wrap: anywhere;
  white-space: normal;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  text-overflow: clip;
}
.today-backlog-rail .backlog-item-when {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: var(--ui-space-2);
  margin-left: 0;
  white-space: nowrap;
}
.today-backlog-rail .backlog-item .calendar-item-more {
  top: var(--ui-space-1);
  right: var(--ui-space-1);
  bottom: auto;
  margin: 0;
  width: var(--ui-control-h-compact);
  height: var(--ui-control-h-compact);
  border-radius: var(--ui-radius-full);
  border: var(--ui-stroke-thin) solid var(--ui-divider-subtle);
  box-shadow: var(--elev-1);
  background: var(--ux-overlay);
  z-index: var(--ui-layer-control);
  /* Trễ hạn: ẩn hẳn nút "…" khi chưa hover, giống khay Ngày/Tuần. */
  opacity: 0;
  visibility: hidden;
}
.today-backlog-rail .backlog-item:is(:hover, :focus-within) .calendar-item-more {
  opacity: 1;
  visibility: visible;
}

/* ---------------------------------------------------------------------
   C11 · DẠNG DANH SÁCH — giữ danh sách một cột, lề rộng.
   --------------------------------------------------------------------- */
.grid[data-view-mode="agenda"] .agenda-day .task-list {
  /* Lề trong hai bên danh sách việc: 2 × (2 × space-4), rồi nới thêm 10%. */
  --agenda-current-inline-padding: calc(var(--ui-space-4) * 2 * 2 * 1.1);
  gap: var(--ui-list-row-gap);
  padding-inline: var(--agenda-current-inline-padding);
}
/* BẪY `html.monochrome-task-rows` — đọc trước khi sửa bất cứ luật hàng việc nào.

   Rất nhiều luật hàng việc trong styles.css được viết thành cặp:

       .grid.agenda-view .agenda-day .task-item,
       html.monochrome-task-rows .grid.agenda-view .agenda-day .task-item { … }

   Vế thứ hai có thêm một phần tử (`html`) nên nặng 0,4,1 thay vì 0,4,0. Lớp
   `monochrome-task-rows` BẬT MẶC ĐỊNH, nên trên thực tế vế nặng hơn mới là vế
   đang chạy. Một luật mới viết ở calendar.css với 0,4,0 sẽ thua dù nạp sau —
   và thua một cách hoàn toàn im lặng: DevTools vẫn liệt kê nó là "matched",
   `element.matches()` vẫn trả về true, chỉ giá trị tính ra là của luật kia.
   Đây là lý do làn ưu tiên của dạng Danh sách "không chịu ăn" suốt một lượt
   sửa: bề dày viền được khai đúng, đủ đặc hiệu theo cách đếm thông thường,
   nhưng vẫn bị `border: 0` của vế monochrome đè.

   Cách xử lý: viết thành CẶP y hệt khuôn của luật cũ — một vế thường và một vế
   có `html.monochrome-task-rows` — để hoà đúng 0,5,1 rồi thắng bằng thứ tự nạp.
   KHÔNG dùng !important: cái đó chỉ đẩy cùng một cuộc cãi nhau xuống lần sau. */
html .grid[data-view-mode="agenda"] .agenda-day :is(.task-item, .gcal-event-item, .outlook-event-item),
html.monochrome-task-rows .grid[data-view-mode="agenda"] .agenda-day :is(.task-item, .gcal-event-item, .outlook-event-item) {
  min-height: max(var(--ui-list-row-min), var(--ui-row-height));
  padding-block: var(--ui-space-1);
  border: 0;
  /* Làn ưu tiên khai NGAY TRONG khối này, không tách ra một luật riêng cho
     `.has-priority-*`. Bề dày viền trái và `border: 0` phải nằm cùng một khối
     thì mới hết cãi nhau về độ đặc hiệu — mỗi lần tách ra là một lần phải đếm
     lại điểm và đếm sai (`[data-view-mode]` nặng ngang một lớp, rất dễ quên).
     Khuôn này giống hệt thẻ Tuần/Ngày ở C4: bề dày cố định, màu trong suốt khi
     không có ưu tiên, và C6 chỉ việc tô màu. */
  border-inline-start: var(--ui-calendar-priority-edge-width) solid transparent;
  border-radius: var(--ui-radius-control);
  overflow: hidden;
}
html .grid[data-view-mode="agenda"] .agenda-day :is(.task-item, .gcal-event-item, .outlook-event-item).has-priority-urgent,
html.monochrome-task-rows .grid[data-view-mode="agenda"] .agenda-day :is(.task-item, .gcal-event-item, .outlook-event-item).has-priority-urgent {
  border-inline-start-color: var(--ui-danger);
}
html .grid[data-view-mode="agenda"] .agenda-day :is(.task-item, .gcal-event-item, .outlook-event-item).has-priority-important,
html.monochrome-task-rows .grid[data-view-mode="agenda"] .agenda-day :is(.task-item, .gcal-event-item, .outlook-event-item).has-priority-important {
  border-inline-start-color: var(--ui-warning);
}
html .grid[data-view-mode="agenda"] .agenda-day :is(.task-item, .gcal-event-item, .outlook-event-item).has-priority-normal,
html.monochrome-task-rows .grid[data-view-mode="agenda"] .agenda-day :is(.task-item, .gcal-event-item, .outlook-event-item).has-priority-normal {
  border-inline-start-color: var(--ui-success);
}
html .grid[data-view-mode="agenda"] .agenda-day :is(.task-item, .gcal-event-item, .outlook-event-item).has-priority-personal,
html.monochrome-task-rows .grid[data-view-mode="agenda"] .agenda-day :is(.task-item, .gcal-event-item, .outlook-event-item).has-priority-personal {
  border-inline-start-color: var(--ui-accent);
}
.grid[data-view-mode="agenda"] .agenda-day.is-empty {
  min-height: var(--ui-list-row-min);
}
.grid[data-view-mode="agenda"] .agenda-day.is-empty .day-head,
html[data-material="glass"] .grid[data-view-mode="agenda"] .agenda-day.is-empty .day-head,
.grid[data-view-mode="agenda"] .agenda-day.is-empty.today-highlighted .day-head {
  min-height: var(--ui-list-row-min);
  /* Đệm ngang bằng ngày có việc (space-4) để số ngày thẳng cột — 12px cũ lệch trái 4px. */
  padding: var(--ui-space-2) var(--ui-space-4);
  align-content: center;
}
.grid[data-view-mode="agenda"] .agenda-day.is-empty .task-list {
  align-self: stretch;
  justify-content: center;
  padding-block: var(--ui-space-1);
  padding-inline: var(--agenda-current-inline-padding);
}
.grid[data-view-mode="agenda"] .agenda-day.is-empty .empty-hint {
  margin: 0;
}
.grid[data-view-mode="agenda"] .agenda-day.is-empty .day-footer {
  display: none;
}
:is(html[data-layout-mode="medium"], html[data-layout-mode="compact"], html[data-layout-mode="tight"])
  .grid[data-view-mode="agenda"] .task-item {
  flex-wrap: wrap;
  row-gap: var(--ui-space-1);
}
:is(html[data-layout-mode="medium"], html[data-layout-mode="compact"], html[data-layout-mode="tight"])
  .grid[data-view-mode="agenda"] .task-meta-right {
  flex: 1 0 100%;
  box-sizing: border-box;
  justify-content: flex-start;
  margin-left: 0;
  padding-left: calc(var(--ui-control-h-compact) + var(--task-inline-gap));
}

/* ---------------------------------------------------------------------
   C12 · DẠNG THÁNG — giữ mật độ tổng quan.
   --------------------------------------------------------------------- */
.grid[data-view-mode="multiWeek"] .multi-week-more-items {
  /* BA 2026-09-12: "+N việc" phải NGANG HÀNG với số ngày — .day-head là flex
     row align-items:center, nhưng chữ nút nhỏ hơn (--fs-3xs) so với số ngày
     (--fs-xs) nên align-self:flex-end cũ kéo nó lệch xuống đáy hàng, dính
     gần line đầu tiên của thân ngày thay vì cùng dòng với số ngày. */
  align-self: center;
  max-width: 100%;
  margin: 0;
  margin-left: auto;
  text-align: right;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--ui-accent);
  font-size: var(--fs-caption);
  font-weight: var(--fw-normal, 400);
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
}
.grid[data-view-mode="multiWeek"] .multi-week-more-items:hover {
  color: var(--ui-accent);
  background: transparent;
  text-decoration: underline;
}
.grid[data-view-mode="multiWeek"] :is(.task-item, .gcal-event-item, .outlook-event-item) {
  border-radius: var(--ui-radius-control);
}
.grid[data-view-mode="multiWeek"] .calendar-item-more {
  right: var(--ui-space-1);
  width: var(--ui-control-h-compact);
  height: var(--ui-control-h-compact);
  border-radius: var(--ui-radius-full);
}
.grid[data-view-mode="multiWeek"] .calendar-item-more svg {
  width: calc(var(--task-effective-font) * .85);
  height: calc(var(--task-effective-font) * .85);
}
.grid[data-view-mode="multiWeek"]
  :is(.task-item, .gcal-event-item, .outlook-event-item)
  :is(.task-repeat-icon, .linked-note-status, .meeting-overlap-icon) {
  display: none;
}
.grid[data-view-mode="multiWeek"]
  :is(.task-item, .outlook-event-item):not(.alert-urgent) .task-meeting-icon {
  display: none;
}

/* ---------------------------------------------------------------------
   C13 · MÀN HÌNH HẸP / CẢM ỨNG
   --------------------------------------------------------------------- */
:is(html[data-layout-mode="compact"], html[data-layout-mode="tight"])
  .grid[data-view-mode="week"] .task-list {
  padding: var(--ui-space-1);
}
:is(html[data-layout-mode="compact"], html[data-layout-mode="tight"])
  .grid[data-view-mode="week"] .day-head {
  min-height: var(--ui-size-md);
  padding: var(--ui-space-1) var(--ui-space-2);
}
@media (pointer: coarse) {
  :is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
    :is(.task-item, .gcal-event-item, .outlook-event-item) .calendar-item-more {
    opacity: .8;
    visibility: visible;
  }
  :is(.grid[data-view-mode="today"], .grid[data-view-mode="week"])
    :is(.task-prefix-slot .task-box, .event-prefix-slot .event-box) {
    opacity: .8;
    pointer-events: auto;
  }
}

/* ---------------------------------------------------------------------
   C14 · Popover xem lướt "+N việc" của Tháng (Giai đoạn 3)
   Cùng khung .calendar-action-menu, chỉ thêm hàng thay cho nút hành động.
   --------------------------------------------------------------------- */
.calendar-day-preview-list {
  max-height: min(var(--dt-dimension-layout-360), 60vh);
  overflow-y: auto;
}
.calendar-day-preview-empty {
  padding: var(--ui-space-3) var(--ui-space-2);
  color: var(--ui-text-muted);
  font-size: var(--fs-body);
  text-align: center;
}
.calendar-day-preview-item {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  width: 100%;
  min-height: var(--ui-size-lg);
  padding: var(--ui-space-1-5) var(--ui-space-3);
  border: 0;
  border-radius: var(--ui-radius-control);
  background: transparent;
  color: var(--ui-text-primary);
  font: var(--fw-medium) var(--fs-body)/var(--lh-snug) var(--app-font);
  text-align: left;
  cursor: pointer;
}
.calendar-day-preview-item:hover,
.calendar-day-preview-item:focus-visible {
  color: var(--ui-accent);
  background: color-mix(in srgb, var(--ui-accent) 11%, transparent);
  outline: 0;
}
.calendar-day-preview-item.is-done {
  color: var(--ui-text-muted);
  text-decoration: line-through;
}
.calendar-day-preview-text {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.calendar-day-preview-time {
  flex: 0 0 auto;
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------
   C15 · Nút nổi "Về hôm nay" của Danh sách (Giai đoạn 3)
   position: fixed theo viewport (không phải theo #grid) — đơn giản và đủ
   dùng vì #grid chiếm gần trọn vùng nội dung chính, nav rail hẹp không kéo
   lệch tâm đáng kể. JS (updateAgendaTodayFloatVisibility) toggle .hidden.
   --------------------------------------------------------------------- */
.agenda-today-float {
  position: fixed;
  left: 50%;
  bottom: calc(var(--ui-space-6) + var(--ui-space-1));
  transform: translateX(-50%);
  z-index: var(--layer-popover);
  display: flex;
  align-items: center;
  gap: var(--ui-space-1);
  padding: var(--ui-space-2) var(--ui-space-4);
  border: var(--ui-stroke-thin) solid var(--ui-border, var(--stroke));
  border-radius: var(--ui-radius-pill);
  background: var(--ux-overlay);
  color: var(--ui-text-primary);
  font: var(--fw-semibold) var(--fs-body)/var(--lh-none) var(--app-font);
  box-shadow: var(--elev-3);
  cursor: pointer;
}
/* Nút là anh em của #grid nên router không ẩn hộ khi rời Lịch; khi #grid bị ẩn,
   JS đo được rect rỗng và tưởng thẻ hôm nay đã cuộn khuất → nút treo trên
   Notebook/Project. Gắn vào data-view giống .agenda-week-bar. */
html:not([data-view="calendar"]) .agenda-today-float { display: none; }
.agenda-today-float svg { width: var(--ui-icon-sm); height: var(--ui-icon-sm); }
.agenda-today-float:hover,
.agenda-today-float:focus-visible {
  color: var(--ui-accent);
  border-color: var(--ui-accent);
}

/* ===================== MỤC D — DẠNG THÁNG CƠ BẢN =====================
   Kiểu lịch để bàn: một bảng phẳng, ô ngày liền nhau, chỉ vạch 1px chia ô;
   không bóng, không bo góc, không khe. Việc là một dòng chữ: chấm ưu tiên
   + giờ + tiêu đề + tag, không nền màu. Thêm việc gõ thẳng trong ô.

   Bóng/bo góc/khe tắt bằng TOKEN tại gốc lưới (mọi luật cũ của dạng Tháng
   đều đọc qua ba token này, kể cả các luật !important), không đè từng luật.
   Viền chỉ vẽ phải + dưới cho mỗi ô, ô đầu hàng thêm trái, hàng đầu thêm
   trên — nên hai ô cạnh nhau không bao giờ ra vạch đôi. Bộ chọn mang #grid
   để thắng các luật hover/today cũ vẫn gán `border: 1px solid` bốn cạnh. */
.grid.multi-week {
  --cell-gap: var(--ui-flat-gap);
  --cal-day-radius: var(--ui-flat-radius-inner);
  --cal-month-day-shadow: var(--ui-flat-shadow);
  /* Làn dẫn đủ rộng cho ô tích — chấm ưu tiên/icon nằm giữa lúc nghỉ. */
  --month-lead-lane: var(--task-control-size);
  /* Việc/họp đã xong (khi lọc "Tất cả") đọc bằng chữ xanh; tone tự đổi sáng/tối. */
  --month-done-ink: var(--tone-green-fg);
}
html #grid.multi-week :is(.task-item.done, .event-done) :is(.task-time-label, .event-time-label) {
  color: var(--month-done-ink);
}
/* Nền ô tháng đang xem / tháng liền kề đọc từ --cal-month-in/out-surface
   (dashboard.css: Tối tháng đang xem đậm, Sáng tháng đang xem trắng). Đổi
   token tại ô, không đè luật. */
html #grid.multi-week .day-col:not(.outside-month) {
  --cal-day-surface: var(--cal-month-in-surface);
}
html #grid.multi-week .day-col.outside-month {
  --ux-sunken: var(--cal-month-out-surface);
}
html #grid.multi-week .day-col {
  border-style: solid;
  border-color: var(--cal-day-border);
  border-width: 0 var(--ui-flat-divider-w) var(--ui-flat-divider-w) 0;
  transform: none;
}
html #grid.multi-week .week-rail + .day-col { border-left-width: var(--ui-flat-divider-w); }
html #grid.multi-week .week-section[data-week-position="1"] .day-col { border-top-width: var(--ui-flat-divider-w); }
/* Bảng sát khung thân (BA 2026-10-07): #grid đã mang viền trái/phải/dưới + bo
   đáy và tự cắt tràn, nên bỏ lề lưới và bỏ cạnh ngoài của bảng — cột cuối
   không kẻ phải, hàng cuối không kẻ dưới, ô không bo góc. Hàng tên thứ và cột
   số tuần là hàng/cột tiêu đề của bảng: vạch trên hàng 1 + vạch trái cột đầu
   ngăn chúng với ô ngày. */
html #grid.multi-week { padding: 0; scrollbar-gutter: auto; }
html #grid.multi-week .day-col { border-radius: 0; }
html #grid.multi-week .day-col:last-child { border-right-width: 0; }
html #grid.multi-week .week-section:last-of-type .day-col { border-bottom-width: 0; }
/* Hôm nay: chỉ số ngày màu nhấn, không vòng quanh ô — xem MỤC F. */

/* Dòng việc: không nền, không bo góc, không vạch sáng kính, không làm mờ ảnh
   nền phía sau (blur tạo dải sẫm trên hình nền); rê chuột mới tô nhẹ. */
/* Nội dung chiếm tối đa bề ngang: làn dẫn sát lề trái ô, khe nhỏ; nền rê
   chuột bo tròn theo control. */
html #grid.multi-week .task-list {
  padding-inline: var(--ui-space-1);
}
html #grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item) {
  --task-row-bg: var(--ui-flat-row-bg);
  /* Lề trái: vòng ô tích hiện khi rê không dính mép nền hover (BA báo 2026-09-28). */
  padding-inline: var(--ui-flat-row-inset) var(--ui-space-1);
  gap: var(--ui-space-1);
  border-radius: var(--ui-flat-radius-item);
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
/* Tích xong ngay trong ô: rê chuột/focus vào dòng thì ô tích thế chỗ chấm
   ưu tiên (việc) hoặc icon nguồn lịch (họp), cùng một làn — chữ không xê dịch. */
html #grid.multi-week :is(.task-prefix-slot, .event-prefix-slot) {
  position: relative;
  justify-content: center;
}
html #grid.multi-week :is(.task-prefix-slot, .event-prefix-slot) .task-box {
  display: none;
}
html #grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item):is(:hover, :focus-within) :is(.task-prefix-slot, .event-prefix-slot) .task-box {
  /* Cỡ vùng bấm do hợp đồng .task-box chung quyết định; inset 0 + margin auto
     canh tâm vùng bấm đúng tâm làn dẫn. */
  display: grid;
  place-items: center;
  position: absolute;
  inset: 0;
  margin: auto;
  opacity: 1;
  transform: none;
}
html #grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item):is(:hover, :focus-within) :is(.task-priority-dot, .gcal-event-icon, .outlook-event-icon) {
  visibility: hidden;
}
/* Nút "…" cùng hình với ô tích (cỡ, viền, nền), khít mép phải dòng — đối
   xứng ô tích ở mép trái. Nút cũ cao hơn dòng nên bị dòng cắt mất trên/dưới. */
html #grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item) .calendar-item-more {
  right: 0;
  width: calc(var(--task-effective-font) * 1.28);
  height: calc(var(--task-effective-font) * 1.28);
  border: var(--ui-stroke-thick) solid var(--ui-text-muted);
  /* Nền đục theo chế độ; nền bán trong suốt làm lộ màu tag nằm dưới nút. */
  background: var(--ui-surface-app);
  box-shadow: none;
  color: var(--ui-text-secondary);
}
html #grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item) .calendar-item-more:is(:hover, :focus-visible) {
  border-color: var(--ui-accent);
  color: var(--ui-accent);
  box-shadow: none;
}
html #grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item):hover {
  --task-row-bg: var(--ui-flat-row-hover);
}
/* Giờ là chữ màu cam đứng trước tiêu đề — không viên nền, không icon đồng hồ. */
html #grid.multi-week :is(.task-time-label, .event-time-label) {
  display: inline;
  /* Cùng đường chân chữ với tiêu đề; `middle` cũ làm giờ tụt ~1px. */
  vertical-align: baseline;
  line-height: inherit;
  height: auto;
  padding: 0;
  margin-right: var(--ui-space-1);
  background: transparent;
  color: var(--tone-orange-fg);
  font-size: inherit;
}
html #grid.multi-week .task-time-clock-icon { display: none; }

/* Nút "+" ở đầu ô: ẩn lúc nghỉ, hiện khi rê chuột vào ô hoặc focus bàn phím. */
.grid.multi-week .month-add-btn {
  order: 2;
  flex: 0 0 auto;
  display: inline-grid;
  place-items: center;
  width: calc(var(--fs-caption) * 1.5);
  height: calc(var(--fs-caption) * 1.5);
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: var(--ui-radius-full);
  background: transparent;
  color: var(--ui-text-muted);
  font: var(--fw-semibold) var(--fs-caption)/var(--lh-none) var(--app-font);
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--ui-duration-fast) var(--motion-standard), color var(--ui-duration-fast) var(--motion-standard);
}
.grid.multi-week .day-col:hover .month-add-btn,
.grid.multi-week .month-add-btn:focus-visible {
  opacity: 1;
}
.grid.multi-week .month-add-btn:hover,
.grid.multi-week .month-add-btn:focus-visible {
  color: var(--ui-accent);
  background: var(--ux-hover);
  outline: none;
}

/* Ô nhập nhanh nổi phủ đáy ô ngày — chiều cao hàng tuần không đổi. Ô và
   hàng tuần đang nhập thôi cắt tràn để bảng gợi ý thò ra ngoài được. */
.grid.multi-week .week-section:has(.day-col.is-inline-editing),
.grid.multi-week .day-col.is-inline-editing {
  overflow: visible;
  z-index: var(--ui-layer-control);
}
html #grid.multi-week .day-footer.month-inline-footer {
  display: block;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: var(--ui-space-1);
  border: 0;
  border-radius: 0;
  background: var(--cal-day-surface);
  overflow: visible;
}
html #grid.multi-week .month-inline-footer .day-inline-create-input {
  font-size: var(--task-effective-font);
}
html #grid.multi-week .month-inline-footer.opens-down .day-inline-suggest {
  top: calc(100% + var(--ui-space-1));
  bottom: auto;
}

/* ===================== MỤC E — CHUẨN FLAT SURFACE: DẠNG TUẦN =====================
   Chuẩn Flat Surface (token --ui-flat-*, ui-tokens.css; mẫu = dạng Tháng ở
   MỤC D) áp cho Tuần — BA chốt 2026-09-27. Bảy cột liền nhau thành một bảng:
   không khe, không bóng, một vạch chia giữa hai cột, chỉ bo 4 góc ngoài.
   Dòng việc như Tháng: không nền, không cạnh màu ưu tiên; chấm ưu tiên lúc
   nghỉ, ô tích khi rê (calendarGrid.js#flatLeadLane); giờ là chữ cam.
   Vẫn giữ hình học thẻ của Tuần (tiêu đề 2 dòng + hàng tag/trạng thái).

   Bật/tắt: html[data-calendar-surface="flat"] do index.js#syncViewModeControls
   ghi từ ô "Dạng xem Tháng" (tạm, chờ công tắc quản trị). Tắt ô đó thì
   Tuần về kiểu thẻ cũ nguyên vẹn — mọi luật dưới đây đều cần cờ này.
   #grid để thắng các luật MỤC C (0,3,0) mà không cần !important. */
html[data-calendar-surface="flat"] #grid[data-view-mode="week"] {
  --cell-gap: var(--ui-flat-gap);
  --cal-day-radius: var(--ui-flat-radius-inner);
  --cal-day-shadow: var(--ui-flat-shadow);
  --cal-day-shadow-hover: var(--ui-flat-shadow);
  /* Làn dẫn đủ rộng cho ô tích — cùng cỡ làn của Tháng. */
  --cal-lead-lane: var(--task-control-size);
  column-gap: var(--ui-flat-gap);
  /* Bảng sát khung thân (BA 2026-10-07): #grid đã mang viền trái/phải/dưới +
     bo đáy và tự cắt tràn, nên bỏ lề lưới; cột chỉ còn một vạch chia ở giữa.
     Tuần hẹp cuộn ngang (responsive-layout.css) với overflow-y: hidden — không
     bao giờ có thanh cuộn dọc, nên rãnh `both-edges` chỉ là khe trống hai mép. */
  padding: 0;
  scrollbar-gutter: auto;
}
html[data-calendar-surface="flat"] #grid[data-view-mode="week"] .day-col,
html[data-calendar-surface="flat"] #grid[data-view-mode="week"] .day-col:hover {
  border-style: solid;
  border-color: var(--cal-day-border);
  border-width: 0 var(--ui-flat-divider-w) 0 0;
  border-radius: 0;
  box-shadow: var(--ui-flat-shadow);
  transform: none;
}
/* Cột cuối nằm sát viền phải của khung thân — không kẻ thêm vạch. */
html[data-calendar-surface="flat"] #grid[data-view-mode="week"] .day-col:not(:has(+ .day-col)) {
  border-right-width: 0;
}
/* Hôm nay: chỉ số ngày màu nhấn, không vòng quanh ô — xem MỤC F. */
/* Vạch dư: đầu cột và chân cột không kẻ thêm đường ngăn bên trong ô. */
html[data-calendar-surface="flat"] #grid[data-view-mode="week"] .day-head {
  border-bottom-width: 0;
}
html[data-calendar-surface="flat"] #grid[data-view-mode="week"] .day-footer {
  border-top-width: 0;
}
html[data-calendar-surface="flat"] #grid[data-view-mode="week"] .task-list {
  padding: var(--ui-space-px) var(--ui-space-1) var(--ui-space-0-5);
  /* density-gap × .4 ra 1,6px lệch lưới; bậc nửa 2px gần nhất (AT-UI 2026). */
  gap: var(--ui-space-0-5);
}

/* Dòng việc/họp (Tuần, Ngày, Danh sách — BA chốt "chuyển như Tháng"): không
   nền, không cạnh ưu tiên, không vòng inset khi rê. */
html[data-calendar-surface="flat"] #grid[data-view-mode="week"] :is(.task-item, .gcal-event-item, .outlook-event-item) {
  min-height: var(--ui-control-h-compact);
  padding-block: var(--ui-space-0-5);
  padding-inline-end: var(--ui-space-1);
}
html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"]) :is(.task-item, .gcal-event-item, .outlook-event-item) {
  --task-row-bg: var(--ui-flat-row-bg);
  /* Lề trái: vòng ô tích (rộng hơn làn dẫn) hiện khi rê không dính mép nền
     hover (BA báo 2026-09-28). Ngày/Danh sách giữ sàn chiều cao riêng. */
  padding-inline-start: var(--ui-flat-row-inset);
  /* Làn dẫn đủ rộng cho vòng ô tích (như Tháng) — renderWeekDays ghi
     --cal-lead-lane hẹp hơn lên cột, khai lại ở chính dòng để thắng thừa kế. */
  --cal-lead-lane: var(--task-control-size);
  border-inline-start-width: 0;
  border-radius: var(--ui-flat-radius-item);
  background: var(--ui-flat-row-bg);
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"]) :is(.task-item, .gcal-event-item, .outlook-event-item):not(.dragging):is(:hover, :focus-within) {
  --task-row-bg: var(--ui-flat-row-hover);
  background: var(--ui-flat-row-hover);
  outline: none;
}

/* Làn dẫn: chấm ưu tiên (việc) / icon nguồn (họp) lúc nghỉ, ô tích thế chỗ
   khi rê/focus — cùng một tâm, chữ không xê dịch. */
html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"]) :is(.task-prefix-slot, .event-prefix-slot) {
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Danh sách: làn của họp vẫn là absolute (khác Ngày/Tuần đã đưa vào flow), và
   luật C cũ ghim nó ở `left: 12px` — trong khi dòng việc phẳng chỉ thụt
   --ui-flat-row-inset. Đo được: ô tích họp lệch phải 8px so với chấm/ô tích
   việc. Ghim lại đúng mép thụt và đúng bề rộng làn của dòng việc. */
html[data-calendar-surface="flat"] #grid[data-view-mode="agenda"] .agenda-day .event-prefix-slot {
  left: var(--ui-flat-row-inset);
  width: var(--ui-size-md); /* = bề rộng .task-prefix-slot */
}
/* Chấm ưu tiên Ngày/Tuần/Danh sách (+ khay Trễ hạn): 0.36em cũ ≈ 4px không
   đọc được màu mức ưu tiên. Bám --fs-xs nên tự phóng theo cỡ chữ; dạng
   Tháng giữ chấm nhỏ riêng vì hàng dày. */
html[data-calendar-surface="flat"] #grid {
  --cal-priority-dot-size: calc(var(--fs-caption) * 0.75);
}
html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"]) .task-priority-dot {
  display: block;
  flex: 0 0 auto;
  width: var(--cal-priority-dot-size);
  height: var(--cal-priority-dot-size);
  margin: 0;
  border-radius: var(--ui-radius-circle);
}
/* "Chưa đặt" = vòng rỗng: tô xanh cũ trùng màu mức "Cá nhân" (--ui-accent),
   không phân biệt được việc nào đã gắn ưu tiên. */
html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"]) .task-priority-dot.is-none {
  background: transparent;
  box-shadow: inset 0 0 0 var(--ui-stroke-thick) var(--ui-text-muted);
}
html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"]) :is(.task-item, .gcal-event-item, .outlook-event-item):is(:hover, :focus-within) :is(.task-priority-dot, .gcal-event-icon, .outlook-event-icon) {
  visibility: hidden;
}
/* Khay "Trễ hạn": cùng làn dẫn chấm ưu tiên như dòng việc dạng Ngày, bỏ cạnh
   trái màu (calendarTodayRail.js chỉ dựng chấm khi giao diện phẳng). Chấm
   canh giữa dòng chữ đầu của tiêu đề. */
html[data-calendar-surface="flat"] #grid .today-backlog-rail .backlog-item:has(> .task-priority-dot) {
  grid-template-columns: var(--cal-lead-lane) minmax(0, 1fr);
  column-gap: var(--cal-lead-gap);
  padding-inline-start: var(--ui-flat-row-inset);
  border-inline-start-width: 0;
}
html[data-calendar-surface="flat"] #grid .today-backlog-rail .backlog-item > .task-priority-dot {
  grid-column: 1;
  grid-row: 1;
  justify-self: center;
  margin-block-start: calc((var(--task-effective-font) * var(--task-line-height, 1.4) - var(--cal-priority-dot-size)) / 2);
}
html[data-calendar-surface="flat"] #grid .today-backlog-rail .backlog-item:has(> .task-priority-dot) :is(.backlog-item-primary, .backlog-item-meta) {
  grid-column: 2;
}
/* Rê/focus dòng Trễ hạn giống hệt dòng việc dạng Ngày khi phẳng: chỉ đổi nền,
   không vòng viền tương tác (luật vòng inset chung phía trên áp cả khay). */
html[data-calendar-surface="flat"] #grid .today-backlog-rail .backlog-item {
  border-radius: var(--ui-flat-radius-item);
}
html[data-calendar-surface="flat"] #grid .today-backlog-rail .backlog-item:not(.dragging):is(:hover, :focus-within) {
  background: var(--ui-flat-row-hover);
  outline: none;
}

/* Vạch "CHƯA GẮN GIỜ" lùi cùng --ui-flat-row-inset với dòng việc — trước đây
   nhãn dính mép cột còn dòng việc lùi vào (GĐ5.7). */
html[data-calendar-surface="flat"] #grid[data-view-mode="week"] .day-flex-divider {
  padding-inline-start: var(--ui-flat-row-inset);
}

/* Giờ là chữ cam đứng trước tiêu đề — không viên nền, không icon đồng hồ. */
html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"]) :is(.task-time-label, .event-time-label) {
  display: inline;
  vertical-align: baseline;
  line-height: inherit;
  height: auto;
  padding: 0;
  margin-right: var(--ui-space-1);
  border: 0;
  background: transparent;
  color: var(--tone-orange-fg);
  font-size: inherit;
}
html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"]) :is(.task-item.done, .event-done) :is(.task-time-label, .event-time-label) {
  color: var(--tone-green-fg);
}
html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"]) :is(.task-time-label, .event-time-label) .task-time-clock-icon {
  display: none;
}

/* ================ MỤC F — CHUẨN FLAT SURFACE: HÔM NAY · NGÀY · DANH SÁCH ================
   Hôm nay (BA 2026-10-07): bỏ vòng nhấn quanh ô ở Tuần/Tháng/Danh sách (bản
   2026-09-28 vẽ bằng ::after) — trên bảng liền nó là thêm một lớp viền. Chỉ
   SỐ NGÀY mang màu nhấn đậm; tên thứ giữ màu thường. --ui-accent tự đổi theo
   chế độ: Sáng xanh đậm, Tối xanh sáng (xanh đậm trên nền tối không đủ tương
   phản AA). Danh sách bỏ cả viên nền --ui-accent-solid sau con số. */
html #grid.multi-week .day-col:is(.today, .today-highlighted) .day-num,
html[data-calendar-surface="flat"] #grid[data-view-mode="week"] .day-col:is(.today, .today-highlighted) .day-num,
html[data-calendar-surface="flat"] #grid.agenda-view .agenda-day:is(.today, .today-highlighted) .day-num {
  background: transparent;
  color: var(--ui-accent);
  font-weight: var(--fw-semibold);
}
html[data-calendar-surface="flat"] #grid[data-view-mode="week"] .day-col:is(.today, .today-highlighted) .day-name {
  color: var(--ui-text-secondary);
}

/* Dạng Ngày: ba vùng Trễ hạn · Hôm nay · Tổng quan thành MỘT bảng phẳng —
   khung chung vẽ viền + bo 4 góc ngoài, các vùng cách nhau một vạch chia. Các
   thẻ của cột Tổng quan thành các khúc cách nhau vạch ngang. */
html[data-calendar-surface="flat"] #grid[data-view-mode="today"] .today-workspace {
  gap: var(--ui-flat-gap);
  border: var(--ui-flat-divider-w) solid var(--cal-day-border);
  border-radius: var(--ui-flat-radius-outer);
  background: var(--cal-day-surface);
  box-shadow: var(--ui-flat-shadow);
}
/* Luật THẺ CHUẨN (~L2512) ép nền/bóng ba vùng bằng !important nhưng ĐỌC QUA
   token, nên đổi token ngay trên các vùng con (khung chung giữ token gốc cho
   nền của nó) — cả luật hover (~L1554) cũng theo, không cần !important. */
html[data-calendar-surface="flat"] #grid[data-view-mode="today"] .today-workspace > :is(.today-backlog-rail, .today-main, .today-rail) {
  --cal-day-shadow: var(--ui-flat-shadow);
  --cal-day-surface: transparent;
}
html[data-calendar-surface="flat"] #grid[data-view-mode="today"] .today-workspace > :is(.today-backlog-rail, .today-main, .today-rail),
html[data-calendar-surface="flat"] #grid[data-view-mode="today"] :is(.today-rail-card, .today-note-box) {
  border: 0;
  border-radius: var(--ui-flat-radius-inner);
  background: transparent;
  box-shadow: var(--ui-flat-shadow);
}
html[data-calendar-surface="flat"] #grid[data-view-mode="today"] .today-workspace > :is(.today-main, .today-rail) {
  border-inline-start: var(--ui-flat-divider-w) solid var(--cal-day-border);
}
html[data-calendar-surface="flat"] #grid[data-view-mode="today"] .today-workspace:not(.has-backlog) > .today-main {
  border-inline-start-width: 0;
}
/* Hai đầu cột Trễ hạn / Hôm nay cùng một chiều cao (một control header + đệm
   dọc + vạch) để vạch dưới đầu cột chạy thẳng một đường qua cả bảng. */
html[data-calendar-surface="flat"] #grid[data-view-mode="today"] :is(.backlog-group-header, .today-main .today-day .day-head) {
  min-height: calc(var(--dt-dimension-control-header) + var(--ui-space-2) * 2 + var(--ui-flat-divider-w));
}
html[data-calendar-surface="flat"] #grid[data-view-mode="today"] :is(.today-rail, .today-rail-scroll) {
  gap: var(--ui-flat-gap);
}
html[data-calendar-surface="flat"] #grid[data-view-mode="today"] .today-rail-card + .today-rail-card,
html[data-calendar-surface="flat"] #grid[data-view-mode="today"] .today-rail-scroll + .today-note-box {
  border-top: var(--ui-flat-divider-w) solid var(--cal-day-border);
}
html[data-calendar-surface="flat"] #grid[data-view-mode="today"] .today-note-box:focus-within {
  box-shadow: var(--ui-surface-focus-line);
}
/* Hộp ghi chú áp sát góc dưới-phải của khung chung: bo theo góc ngoài (trừ
   viền khung) để vạch focus inset không vẽ thành góc vuông. */
html[data-calendar-surface="flat"] #grid[data-view-mode="today"] .today-note-box {
  border-end-end-radius: calc(var(--ui-flat-radius-outer) - var(--ui-flat-divider-w));
}
/* Dưới 720px ba vùng xếp chồng: vạch chia chuyển từ dọc sang ngang. */
@container today-layout (max-width: 720px) {
  html[data-calendar-surface="flat"] #grid[data-view-mode="today"] .today-note-box {
    border-end-start-radius: calc(var(--ui-flat-radius-outer) - var(--ui-flat-divider-w));
  }
  html[data-calendar-surface="flat"] #grid[data-view-mode="today"] .today-workspace > :is(.today-main, .today-rail) {
    border-inline-start-width: 0;
    border-top: var(--ui-flat-divider-w) solid var(--cal-day-border);
  }
  html[data-calendar-surface="flat"] #grid[data-view-mode="today"] .today-workspace:not(.has-backlog) > .today-main {
    border-top-width: 0;
  }
}

/* Dạng Danh sách: bỏ thẻ riêng từng ngày — các ngày liền nhau thành một bảng,
   cách nhau một vạch ngang; chỉ ngày đầu/cuối bo góc ngoài. Cột ngày bên trái
   giữ nguyên (nền nhạt + vạch dọc). Cặp `:hover` để hoà điểm luật hover cũ
   (html[data-mode] #grid.agenda-view .agenda-day:not(.drag-over):hover) rồi
   thắng bằng thứ tự nạp. */
html[data-calendar-surface="flat"] #grid.agenda-view {
  gap: var(--ui-flat-gap);
}
html[data-calendar-surface="flat"] #grid.agenda-view .agenda-day,
html[data-calendar-surface="flat"] #grid.agenda-view .agenda-day:not(.drag-over):hover {
  position: relative;
  border: var(--ui-flat-divider-w) solid var(--cal-day-border);
  border-top-width: 0;
  border-radius: var(--ui-flat-radius-inner);
  box-shadow: var(--ui-flat-shadow);
}
html[data-calendar-surface="flat"] #grid.agenda-view .agenda-day:not(.agenda-day + .agenda-day) {
  border-top-width: var(--ui-flat-divider-w);
  border-top-left-radius: var(--ui-flat-radius-outer);
  border-top-right-radius: var(--ui-flat-radius-outer);
}
html[data-calendar-surface="flat"] #grid.agenda-view .agenda-day:not(:has(~ .agenda-day)) {
  border-bottom-left-radius: var(--ui-flat-radius-outer);
  border-bottom-right-radius: var(--ui-flat-radius-outer);
}
html[data-calendar-surface="flat"] #grid.agenda-view .agenda-day .day-head,
html[data-calendar-surface="flat"] #grid.agenda-view .agenda-day.today-highlighted .day-head {
  border-radius: var(--ui-flat-radius-inner);
}

/* Kết thúc hợp đồng lịch ----------------------------------------------- */
} /* @layer legacy */

/* "＋ Thêm" chân cột ngày (.ui-btn nhẹ sm, GĐ F 01/10/2026) — chuyển nguyên từ
   legacy: bố cục theo dạng xem phải thắng component nên đứng ở layer modules.
   ARS-1: lùi thị giác bằng màu muted (≥ 4.5:1), không bằng opacity. */
@layer modules {
  .day-add-hint {
    flex: 0 0 auto;
    justify-content: flex-start;
    margin-top: var(--ui-space-0-5);
    color: var(--ui-text-muted);
    font-weight: var(--fw-medium);
  }
  .day-add-hint:is(:hover, :focus-visible) {
    color: var(--ui-text-primary);
  }
  /* WCAG 2.5.8: vùng bấm cao 24 (size.sm); margin âm bằng đúng padding dọc của
     .day-footer nên chân cột không cao thêm, chữ đứng nguyên chỗ. */
  .grid[data-view-mode="week"] .day-footer .day-add-hint {
    margin: calc(var(--ui-space-1) * -1) 0;
    padding: 0;
    font-size: var(--fs-body);
  }
  .grid[data-view-mode="week"] .day-footer .day-add-hint:is(:hover, :focus-visible) {
    color: var(--ui-accent);
    background: transparent;
  }
  /* Cột hẹp: rút về dấu cộng, vẫn giữ vùng bấm 24×24 (WCAG 2.5.8). */
  :is(html[data-layout-mode="compact"], html[data-layout-mode="tight"])
    .grid[data-view-mode="week"] .day-footer .day-add-hint {
    font-size: 0;
    min-width: var(--ui-size-sm);
    justify-content: center;
  }
  :is(html[data-layout-mode="compact"], html[data-layout-mode="tight"])
    .grid[data-view-mode="week"] .day-footer .day-add-hint::before {
    content: "＋";
    font-size: var(--fs-caption);
  }
  /* Công tắc T7/CN nổi TRÊN lưới (kính/hình nền): nền nút phụ và nền "đang bật"
     (accent 12% trong suốt) để lộ lưới phía sau, chữ còn 3.8–4.3:1 (ARS-1,
     readabilityStandard.spec.js). Nền đục bề mặt nổi, trạng thái bật pha trên nền đó. */
  .ui-btn.weekend-toggle {
    background-color: var(--ui-surface-raised);
  }
  .ui-btn.weekend-toggle:hover {
    background-color: color-mix(in srgb, var(--ui-text-primary) 6%, var(--ui-surface-raised));
  }
  .ui-btn.weekend-toggle[aria-pressed="true"] {
    background-color: color-mix(in srgb, var(--ui-accent) 10%, var(--ui-surface-raised));
  }
}

/* Khai báo từng là !important trong @layer legacy — chuyển sang layer cuối `overrides`
   (thắng mọi khai báo thường ở mọi layer, đúng như cờ important cũ), cùng selector, cùng
   thứ tự, cùng ngữ cảnh @media. Sinh tự động 01/10/2026 (KE-HOACH-DAT-CHUAN-QUOC-TE-UI GĐ B–E);
   thuộc tính ẩn/hiện/định vị giữ cờ important vì JS gắn nội tuyến. */
@layer overrides {
  .month-day.selected-day { background: var(--ui-accent-solid); color: var(--ui-text-on-accent); }
  .grid.calendar-refreshing .day-col, .grid.calendar-refreshing .task-item, .grid.calendar-refreshing .gcal-event-item, .grid.calendar-refreshing .outlook-event-item { transition: none; animation: none; }
  :is(.task-item.alert-warning, .task-item.alert-urgent, .outlook-event-item.alert-warning, .outlook-event-item.alert-urgent) .task-meeting-icon, :is(.task-item.alert-warning, .task-item.alert-urgent) .task-meeting-icon:not(.is-past) { align-items: center; justify-content: center; width: var(--ui-icon-md); height: var(--ui-icon-md); border-radius: var(--dt-dimension-radius-full); background: var(--ui-danger-solid); color: var(--ui-text-on-accent); animation: bellRingShake 2s cubic-bezier(0.36, 0.07, 0.19, 0.97) infinite; /* audit-keep: chuyển động biên đạo riêng (keyframes), không thuộc nhịp giao diện chuẩn */ opacity: 1; vertical-align: middle; padding: 0; margin-right: var(--task-icon-gap, var(--ui-space-1)); }
  .calendar-item-footer-statuses .task-meeting-icon { margin-right: 0; }
  :is(.task-item.alert-warning, .task-item.alert-urgent, .outlook-event-item.alert-warning, .outlook-event-item.alert-urgent) .task-meeting-icon svg, :is(.task-item.alert-warning, .task-item.alert-urgent) .task-meeting-icon:not(.is-past) svg { width: var(--ui-icon-xs); height: var(--ui-icon-xs); }
  html[data-motion="off"] :is(.alert-warning, .alert-urgent) .task-meeting-icon, html[data-motion="minimal"] :is(.alert-warning, .alert-urgent) .task-meeting-icon { animation: none; }
  :is(.task-item, .gcal-event-item, .outlook-event-item):not(.done):not(.event-done) :is(.task-text, .gcal-event-title, .outlook-event-title) { color: var(--ui-text-primary); }
  html[data-motion="off"] .day-now-dot, html[data-motion="minimal"] .day-now-dot { animation: none; }
  .grid.multi-week .day-col.today, .grid.multi-week .day-col.today-highlighted { background: var(--cal-day-surface); box-shadow: var(--cal-month-day-shadow); }
  .grid.multi-week .day-col.outside-month, html:root .grid.multi-week .day-col.outside-month, html:root #grid.multi-week .day-col.outside-month:not(.drag-over):hover { background: var(--ux-sunken); box-shadow: none; }
  .grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item):not(.done):not(.event-done) :is(.task-text, .gcal-event-title, .outlook-event-title) { color: var(--ui-text-primary); }
  :is(.grid[data-view-mode="today"], .grid.today-view, .grid[data-view-mode="day"], .grid[data-view-mode="week"], .grid.multi-week, .grid.agenda-view, .grid[data-view-mode="agenda"]) :is(.task-text, .gcal-event-title, .outlook-event-title, .backlog-item-title) { font-weight: var(--fw-normal); }
  .grid.multi-week .task-meta-right :is(.task-repeat-icon, .task-meeting-icon, .linked-note-status, .meeting-overlap-icon) { margin: 0; padding: 0; }
  .grid.multi-week .task-meta-right svg { margin: 0; }
  .grid.multi-week .task-item.done .task-text, .grid.multi-week :is(.gcal-event-item, .outlook-event-item).event-done :is(.gcal-event-title, .outlook-event-title) { color: var(--month-done-ink, var(--ui-text-primary)); opacity: 1; font-weight: var(--fw-normal); }
  .grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item).done, .grid.multi-week :is(.gcal-event-item, .outlook-event-item).event-done { opacity: 1; }
  .grid.multi-week .task-item.done .task-priority-dot { opacity: 1; }
  .grid.multi-week .multi-week-more-items { background: transparent; }
  .grid.multi-week .multi-week-more-items:hover { background: transparent; }
  .task-box, .gcal-event-item .event-box, .outlook-event-item .event-box { width: var(--ui-size-md); height: var(--ui-size-md); border: 0; background: transparent; }
  :is(.today-workspace, .grid[data-view-mode="today"], .grid[data-view-mode="day"], .grid.agenda-view, .grid[data-view-mode="agenda"], .today-main) .task-meta-right :is(.linked-note-status, .task-repeat-icon, .task-meeting-icon, .meeting-overlap-icon) { padding: 0 var(--ui-space-1); margin: 0; }
  @media (prefers-reduced-motion: reduce) {
    .calendar-action-menu, .calendar-action-menu.is-open, .calendar-item-more, :is(.task-item, .gcal-event-item, .outlook-event-item) { transition: none; animation: none; }
  }
  :is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid.multi-week) .task-box { width: calc(var(--cal-lead-lane) + var(--cal-lead-gap) * 2); }
  :is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid.multi-week) :is(.gcal-event-item, .outlook-event-item) .event-box { width: calc(var(--cal-lead-lane) + var(--cal-lead-gap) * 2); }
  :is(.today-backlog-rail, .today-main, .today-rail-card) { border-color: var(--cal-day-border); background: var(--cal-day-surface); box-shadow: var(--cal-day-shadow); }
  html .grid.agenda-view { grid-template-columns: minmax(0, 1fr); }
  .grid.agenda-view .agenda-day.today-highlighted .day-head { border: 0; border-right: var(--ui-stroke-thin) solid var(--ux-divider); background: transparent; box-shadow: none; }
  /* Chữ trắng chỉ cho viên nền accent của dạng thẻ; Danh sách phẳng chỉ tô số (MỤC F). */
  html:not([data-calendar-surface="flat"]) .grid.agenda-view .agenda-day.today-highlighted .day-num { color: var(--ui-text-on-accent); }
  html[data-material="glass"] .grid.agenda-view .agenda-day.today-highlighted .day-head { background: transparent; box-shadow: none; }
  .grid.agenda-view .day-footer .progress-fill { width: var(--progress-value, 0%); }
  html .grid.today-view, .grid.today-view { grid-template-columns: minmax(0, 1fr); }
  .today-note-editor, .today-note-editor .ql-editor, .today-note-editor .ql-editor :is(p, ol, ul, li) { font-family: var(--app-font); font-size: var(--fs-body); }
  @media (max-width: 760px) {
    .grid.agenda-view .day-footer .progress-fill { width: var(--progress-value, 0%); }
  }
}

/* ================ MỤC G — MÀN TRỐNG CỘT NGÀY (Ngày + Tuần) ================
   BA chốt 03/10/2026 (phương án C+B): cột không còn mục đang mở thì hiện hình
   minh họa nét màu nhấn; dạng Ngày thêm nền dòng kẻ sổ. Owner JS:
   components/calendar/calendarEmptyState.js. Khung chữ dùng lại .ux-empty-*
   (ui-components.css); ở đây chỉ chỉnh vị trí, cỡ hình và bản gọn của Tuần. */
@layer modules {
.today-day.has-empty-state > .task-list {
  /* Chỉ dạng Ngày (Tuần để trơn: cột có việc không có dòng kẻ, cột trống mà
     có thì bảy cột lệch tông). Dòng cách đúng một hàng việc, nhạt hơn vạch
     chia để đọc như trang sổ chứ không như bảng. */
  --day-empty-rule: color-mix(in srgb, var(--ux-divider) 55%, transparent);
  background-image: repeating-linear-gradient(
    to bottom,
    transparent 0,
    transparent calc(var(--task-row-height) - var(--ui-stroke-thin)),
    var(--day-empty-rule) calc(var(--task-row-height) - var(--ui-stroke-thin)),
    var(--day-empty-rule) var(--task-row-height)
  );
}
.day-col.has-empty-state .day-empty-state {
  flex: 1 1 auto;
  align-self: stretch;
  max-width: none;
  min-height: 0;
  margin: 0;
  padding: var(--ui-space-6) var(--ui-space-4);
}
.day-empty-art {
  display: flex;
  justify-content: center;
  width: var(--dt-dimension-layout-104);
  margin-bottom: var(--ui-space-3);
  color: var(--ui-accent);
}
.day-empty-art svg { width: 100%; height: auto; }
.day-empty-state .day-empty-title { margin-bottom: var(--ui-space-1); }
.day-empty-state .day-empty-desc { color: var(--ui-text-secondary); }
.day-empty-state .day-empty-cta .ux-kbd { margin-left: var(--ui-space-1); }
/* Ngày đã qua: lời nhắc thầm, không mời hành động. */
.day-empty-state.is-past .day-empty-art,
.day-empty-state.is-filtered .day-empty-art { color: var(--ui-text-muted); }
/* Tuần: cột hẹp — hình nhỏ + tiêu đề, không mô tả/nút (chân cột đã có ＋ Thêm). */
.day-empty-state.is-compact { padding: var(--ui-space-4) var(--ui-space-2); }
.day-empty-state.is-compact .day-empty-art { width: var(--dt-dimension-layout-56); margin-bottom: var(--ui-space-2); }
.day-empty-state.is-compact .day-empty-title {
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  color: var(--ui-text-secondary);
}
/* Dạng Ngày: nút giữa cột đã mời thêm việc → ẩn "＋ Thêm" ở chân cho khỏi
   nói hai lần; chân cột vẫn giữ chỗ (hợp đồng auto/1fr/auto) và hiện lại khi
   đang gõ (nút giữa cột mở chính ô nhập này). */
.today-day.has-empty-state:has(.day-empty-cta) > .day-footer:not(.is-inline-editing) { visibility: hidden; }
} /* @layer modules — MỤC G */

/* ================ MỤC H — LÀM GỌN NGÀY + TUẦN (BA 2026-10-09) ================
   Màn Task "dày, gây ngộp": số đã xong nói hai lần (ngăn "Đã hoàn tất" + thanh
   tiến độ xanh full cột), "＋ Thêm" thường trực ở mọi cột. Nay chân cột MỘT dòng:
   [＋ Thêm] … [✓ xong/tổng ›] (nút mở việc đã xong, calendarGrid.js
   `doneToggleInFooter`), thanh tiến độ thành vạch mảnh sát mép trên chân cột.
   Tuần: "＋ Thêm" chỉ hiện ở cột hôm nay, cột đang rê hoặc có focus bàn phím
   (giữ chỗ bằng visibility để bảy chân cột vẫn thẳng). Layer modules thắng các
   luật chân cột cũ ở legacy (MỤC C/E) mà không cần nâng specificity. */
@layer modules {
/* Không đặt `display` ở layer này: legacy còn ẩn chân cột/số liệu theo dạng xem và
   lúc đang gõ (tests/cssLayers.test.js). Tuần giữ lưới của MỤC C3, chỉ còn hai ô
   [＋ Thêm] [✓ xong/tổng] (vạch tiến độ định vị tuyệt đối, không chiếm ô); Ngày
   vốn là flex. */
:is(.grid[data-view-mode="week"], .grid[data-view-mode="today"]) .day-footer {
  position: relative;
  align-items: center;
  gap: var(--ui-space-2);
  border-top: 0;
}
.grid[data-view-mode="week"] .day-footer:not(.is-empty, .is-inline-editing) {
  grid-template-columns: minmax(0, 1fr) auto;
}
:is(.grid[data-view-mode="week"], .grid[data-view-mode="today"]) .day-footer > .progress-track {
  position: absolute;
  inset: 0 var(--ui-space-2) auto;
  flex: none;
  height: var(--ui-stroke-thick);
  border-radius: var(--ui-radius-full);
  background: var(--ui-divider-subtle);
}
/* Còn dở: phần đã xong màu nhấn; xong hết: vạch trung tính, không khối màu. */
:is(.grid[data-view-mode="week"], .grid[data-view-mode="today"]) .day-footer .progress-fill {
  border-radius: var(--ui-radius-full);
  background: var(--ui-accent);
}
:is(.grid[data-view-mode="week"], .grid[data-view-mode="today"]) .day-footer .progress-fill.all-done {
  background: var(--ui-divider);
}
:is(.grid[data-view-mode="week"], .grid[data-view-mode="today"]) .day-footer > :is(.completed-toggle, .day-count) {
  margin-left: auto;
}
:is(.grid[data-view-mode="week"], .grid[data-view-mode="today"]) .day-footer > .day-count {
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  text-shadow: none;
}
.completed-toggle.is-footer-toggle {
  flex: 0 0 auto;
  width: auto;
  min-height: var(--ui-size-sm);
  gap: var(--ui-space-1);
  padding: 0 var(--ui-space-1);
  border: 0;
  border-radius: var(--ui-radius-control);
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-variant-numeric: tabular-nums;
}
.completed-toggle.is-footer-toggle:is(:hover, :focus-visible) {
  color: var(--ui-text-primary);
  background: var(--ui-hover);
}
.completed-toggle.is-footer-toggle.all-done .completed-check { color: var(--ui-success); }
.completed-toggle.is-footer-toggle .completed-count { height: auto; line-height: var(--lh-tight); }
/* Thu gọn: mũi tên chỉ sang phải; mở: chỉ lên — danh sách mở phía trên chân cột. */
.completed-toggle.is-footer-toggle[aria-expanded="false"] .completed-chevron { transform: rotate(90deg); }
.day-footer.is-inline-editing > .completed-toggle { display: none; }
.grid[data-view-mode="week"] .day-col:not(.today, :hover, :has(:focus-visible)) > .day-footer:not(.is-inline-editing) .day-add-hint {
  visibility: hidden;
}
/* Tag dự án chạy ngay sau chữ tiêu đề (cùng dòng nếu vừa); bị cắt thì JS trả về
   hàng thứ hai (.is-moved, kiểu cũ ở MỤC C4). */
/* Cụm .task-inline-meta (calendarGrid.js#appendInlineMeta) = [icon trạng thái][tag]
   chạy ngay sau tiêu đề việc/lịch. Bị cắt thì JS dời nguyên cụm xuống hàng meta
   (.is-moved) — ở đó canh TRÁI như lúc còn trong dòng, không nhảy sang phải. */
.task-inline-meta {
  display: inline;
  margin-left: var(--ui-space-1);
}
.task-inline-meta:empty { display: none; }
.task-inline-meta.is-moved {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ui-space-1);
  min-width: 0;
  max-width: 100%;
  margin-left: 0;
}
.task-inline-meta.is-moved > .calendar-item-footer-tags { flex-wrap: wrap; min-width: 0; max-width: 100%; }
.task-inline-meta > :is(.calendar-item-footer-statuses, .calendar-item-footer-tags) {
  display: inline-flex;
  align-items: center;
  gap: var(--ui-space-1);
  margin: 0;
  vertical-align: middle;
}
.task-inline-meta > .calendar-item-footer-statuses + .calendar-item-footer-tags { margin-left: var(--ui-space-1); }
.task-inline-meta .task-tags { margin-left: 0; }
/* Icon trạng thái: icon trơn không nền; lặp/ghi chú màu chữ phụ, chỉ cảnh báo
   (trùng giờ, sắp/quá hạn) giữ màu cảnh báo. */
:is(.grid[data-view-mode="week"], .grid[data-view-mode="today"], .grid[data-view-mode="agenda"], .grid.agenda-view)
  .calendar-item-status:is(.is-repeat, .is-note, .is-conflict, .is-due) {
  background: transparent;
}
:is(.grid[data-view-mode="week"], .grid[data-view-mode="today"], .grid[data-view-mode="agenda"], .grid.agenda-view)
  .calendar-item-status:is(.is-repeat, .is-note) {
  color: var(--ui-text-muted);
}
:is(.grid[data-view-mode="week"], .grid[data-view-mode="today"], .grid[data-view-mode="agenda"], .grid.agenda-view)
  .calendar-item-status.is-note:is(:hover, :focus-visible) {
  color: var(--ui-accent);
}

/* Dòng đã xong (mọi dạng xem, BA 2026-10-09 "bỏ gạch ngang"): không gạch ngang,
   chữ + giờ cùng một màu "đã xong" (--done-ink), không xanh lá/cam. Ô tích lúc
   nghỉ chỉ là dấu ✓ nhỏ màu phụ, không vòng; rê/focus dòng mới hiện vòng + mũi
   tên hoàn tác (calendarGrid.js#paintUndoIcon dựng cả hai). */
:is(.gcal-event-item, .outlook-event-item).event-done :is(.gcal-event-title, .outlook-event-title) {
  text-decoration: none;
}
#grid:not(.multi-week) :is(.task-item.done, .event-done) :is(.task-time-label, .event-time-label) {
  color: var(--done-ink);
  background: transparent;
}
.task-done-check-svg {
  position: relative;
  z-index: 1;
  display: block;
  width: var(--ui-icon-xs);
  height: var(--ui-icon-xs);
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
:is(.task-item.done .task-box, .event-done .event-box) { color: var(--ui-text-muted); }
:is(.task-item.done .task-box, .event-done .event-box) .task-undo-svg { display: none; }
:is(.task-item.done .task-box, .event-done .event-box)::before {
  border-color: transparent;
  background: transparent;
}
:is(.task-item.done, .event-done):is(:hover, :focus-within) :is(.task-box, .event-box) { color: var(--ui-success); }
:is(.task-item.done, .event-done):is(:hover, :focus-within) :is(.task-box, .event-box)::before { border-color: var(--ui-success); }
:is(.task-item.done, .event-done):is(:hover, :focus-within) .task-done-check-svg { display: none; }
:is(.task-item.done, .event-done):is(:hover, :focus-within) .task-undo-svg { display: block; }

/* Cột phải dạng Ngày: tiêu đề nhóm chữ thường mờ, như nhãn buổi. */
.today-rail-eyebrow {
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  letter-spacing: normal;
  text-transform: lowercase;
}
.today-rail-eyebrow::first-letter { text-transform: uppercase; }

/* Dòng đã xong: dấu ✓ thay chỗ chấm ưu tiên (chấm vòng rỗng lộ sau ✓ thành "⊘"). */
#grid .task-item.done .task-priority-dot { visibility: hidden; }

/* Nhãn buổi + vạch "Chưa gắn giờ": chữ thường mờ thay chữ HOA giãn cách (đỡ ồn).
   Chuỗi trong mã giữ nguyên chữ hoa (khóa dịch i18nSystemCopy + test), chỉ đổi hiển thị. */
:is(.day-group-label, .day-flex-divider > span) {
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  letter-spacing: normal;
  text-transform: lowercase;
}
:is(.day-group-label, .day-flex-divider > span)::first-letter { text-transform: uppercase; }
.day-flex-divider { letter-spacing: normal; }

/* Danh sách (Agenda) — cùng khuôn Ngày/Tuần: ô ngày bên trái chỉ còn vạch tiến độ
   mảnh + "✓ xong/tổng ›"; "+ Thêm việc" của ngày trống chỉ hiện ở hôm nay / ngày
   đang rê / có focus bàn phím; icon trạng thái trơn trong cụm sau tiêu đề. */
.grid.agenda-view .day-footer .progress-track {
  min-height: 0;
  height: var(--ui-stroke-thick);
  background: var(--ui-divider-subtle);
}
.grid.agenda-view .day-footer .progress-fill { background: var(--ui-accent); }
.grid.agenda-view .day-footer .progress-fill.all-done { background: var(--ui-divider); }
.grid.agenda-view .day-footer > .completed-toggle { margin-left: auto; }
.grid.agenda-view .agenda-day:not(.today, :hover, :has(:focus-visible)) .empty-hint { visibility: hidden; }
.task-inline-meta :is(.task-repeat-icon, .task-meeting-icon, .meeting-overlap-icon, .linked-note-status) {
  background: transparent;
  box-shadow: none;
}
.task-inline-meta :is(.task-repeat-icon, .linked-note-status) { color: var(--ui-text-muted); }

/* Tháng: tag dự án chỉ hiện khi rê/focus dòng (BA 2026-10-09, plan GĐ4) — lúc nghỉ
   tiêu đề lấy lại trọn bề ngang ô; tên dự án vẫn ở chi tiết việc. Việc đã xong GIỮ
   chữ xanh (--month-done-ink): ở Tháng việc xong nằm xen việc chưa xong, không gạch
   ngang thì màu là thứ duy nhất phân biệt (khác Tuần/Ngày/Danh sách đã gom ngăn riêng). */
#grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item):not(:hover, :focus-within) .calendar-item-month-tags {
  display: none;
}

/* Giờ của việc/lịch: màu chữ phụ, đậm vừa — không tô cam mọi dòng (Tháng tô cả ngày
   tương lai). Cảnh báo sắp/quá giờ vẫn do huy hiệu chuông + viền nhắc họp đảm nhận.
   Áp ở cả hai bố cục (BA 11/10/2026): luật AT-CALM về màu không phụ thuộc Thẻ nổi/Liền mạch. */
html #grid :is(.task-time-label, .event-time-label) {
  color: var(--ui-text-secondary);
  font-weight: var(--fw-medium);
}
} /* @layer modules — MỤC H */
