@layer legacy {
* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
.hidden { display: none !important; }

/* =====================================================================
   TYPE SCALE — nguồn sự thật duy nhất cho typography toàn app.

   Trước đây file này có 485 chỗ hardcode `font-size: Npx`, 130 chỗ
   `line-height`, 300+ chỗ `font-weight` — không có thang bậc nào, nên mỗi
   màn hình trôi một kiểu (11 / 11.5 / 12 / 12.5px cùng đóng một vai).
   Thang dưới đây dựng từ chính phân bố đó: mỗi bậc là một giá trị đã có
   sẵn hàng chục lần trong file, các giá trị lẻ được snap về bậc gần nhất.

   Ba trục tách riêng (size / weight / line-height) thay vì gộp thành một
   token `font:` shorthand, vì phần lớn call-site chỉ cần đổi một trục —
   gộp lại sẽ buộc khai lại cả ba mỗi lần.

   AT-UI 2026 (04/10/2026): kích thước giao diện có hai mức rời rạc, ghi ở
   html[data-ui-scale="normal"|"large"]. Generator DTCG sinh bộ token mức Lớn
   (×1.25 cho chữ LẪN hình học). --font-scale giờ chỉ là HỆ SỐ của mức (1 hoặc
   1.25) — dùng cho literal px hiếm hoi chưa thành token và cho responsiveMode;
   tuyệt đối không nhân nó lên một token (token đã tự phóng → thành ×1.56).

   CÁCH B (chuẩn hóa 29/08/2026): "Cỡ chữ giao diện" (--font-scale) là TRỤC
   CHỦ, phóng cả chrome LẪN chữ nội dung/công việc. --font-task giờ được
   settingsPanel.js ghi ra px ĐÃ nhân --font-scale; --font-title bỏ hẳn vai
   trò trục riêng, chỉ còn là bậc --fs-md của ramp. Ô "Cỡ chữ ghi chú &
   công việc" (--content-scale) là DELTA nhân chồng, chỉ áp cho vùng đọc/soạn.
   ===================================================================== */
:root {
  --font-scale: 1;

  /* AT-UI Rhythm (BA duyệt 10/10/2026): bí danh theo CỠ (--fs-3xs…--fs-4xl) đã
     GỠ — mọi call-site dùng thẳng tên VAI TRÒ bên dưới. Không thêm lại tên theo
     cỡ; tests/uiRhythmCompliance.test.js chặn. */

  /* ---------------------------------------------------------------
     THANG THEO VAI TRÒ — dùng cho VÙNG ĐỌC NỘI DUNG.

     Thang --fs-* ở trên đặt tên theo CỠ (xs/sm/md), nên không nói cho ai
     biết ai được phép dùng bậc nào → 59% khai báo trôi hết về 10-11px và
     mỗi màn hình chọn một bậc khác nhau cho cùng một vai (tiêu đề hàng
     danh sách: Notebook 12, QuickNote 11, Project 12).

     Năm token dưới đây đặt tên theo VAI TRÒ. Quy ước bắt buộc:
       --fs-title    tiêu đề thẻ / tiêu đề mục          (16)
       --fs-body     chữ đọc chính: hàng danh sách,
                     preview ghi chú, nội dung thẻ      (14)  ← chữ nền
       --fs-body-sm  bí danh của --fs-body (bậc 13 đã gộp) (14)
       --fs-body-lg  chữ nội dung đọc: Notebook, AntiNote  (16)
       --fs-caption  meta: ngày giờ, số đếm, dòng phụ   (12)
       --fs-micro    CHỈ nhãn viết hoa + badge          (10)
     Google Keep lấy 14 làm chữ nền và 16 cho tiêu đề — đây là cùng thang.

     --content-scale là trục thứ hai, settingsPanel.js suy ra từ chính ô
     "Cỡ chữ công việc" (taskFontSize / 15, kẹp trong [0.9, 1.4]). Nhờ vậy
     kéo cỡ chữ việc lên 18 thì thẻ sự kiện, thẻ ghi chú và hàng danh sách
     to lên theo cùng nhịp — trước đây chỉ hàng việc to lên còn thẻ bên
     cạnh đứng yên ở 11px, chênh 1,64 lần trong cùng một cột.

     --fs-micro CỐ TÌNH không nhân --content-scale: nhãn viết hoa và badge
     là chrome, phóng theo cỡ nội dung sẽ đội các chiều cao cố định.

     Overline — MỘT spec cho mọi eyebrow / kicker / tiêu đề mục viết hoa
     (Today rail, section title QuickNote, nhãn nhóm danh sách, topbar…).
     Trước đây rải rác --fs-2xs/--fs-xs/--fs-micro + weight 700/800 + tracking
     .09/.12em → mỗi màn một kiểu, và đóng băng nên khi phóng chữ đọc thì nhãn
     đứng yên. Mô hình Material 3 `label` / Apple footnote: nhãn NẰM trong ramp,
     nở cùng --content-scale, cách chữ nền đúng một bậc (11 vs 14) + weight
     semibold + tracking vừa (.06em) để đọc ra "cùng hệ, nhạt hơn". --fs-micro
     giữ nguyên đóng băng CHỈ cho badge/pill có chiều cao cố định. */
  /* --content-scale ĐÃ NGHỈ HƯU (30/08/2026): nó là trục cỡ chữ THỨ HAI, suy từ
     ô "Cỡ chữ ghi chú & công việc". Hai trục cùng phóng toàn app là dư thừa và
     không hệ nào ngoài kia làm vậy — Apple Dynamic Type, Material, Fluent đều
     đúng MỘT trục. Ô thứ hai đã gỡ khỏi Cài đặt, giá trị cũ được quy đổi một
     lần sang uiTextScale lúc nạp hồ sơ (xem index.js). Giữ token ở đây bằng 1
     để mọi calc() cũ còn tham chiếu nó không vỡ. */
  --content-scale: 1;
  /* AT-UI 2026: px lấy thẳng từ DTCG (typography.fontSize.*). Mức Lớn không
     nhân ở đây nữa — generator sinh sẵn bộ px của mức Lớn dưới
     :root[data-ui-scale="large"], nên chữ và hình học phóng CÙNG một hệ số,
     ra số nguyên (bỏ damping 0.5 từng làm chữ ×1.125 trong khung ×1.0). */
  --fs-hero:       var(--dt-typography-font-size-hero);
  --fs-display-lg: var(--dt-typography-font-size-display-large);
  --fs-display:    var(--dt-typography-font-size-display);
  --fs-headline:   var(--dt-typography-font-size-headline);
  --fs-title-lg:   var(--dt-typography-font-size-title-large);
  --fs-title:      var(--dt-typography-font-size-title);
  --fs-body-lg:    var(--dt-typography-font-size-body-large);
  --fs-body:       var(--dt-typography-font-size-body);
  --fs-body-sm:    var(--dt-typography-font-size-body-small);
  --fs-caption:    var(--dt-typography-font-size-caption);
  --fs-overline:   var(--dt-typography-font-size-overline);
  --fs-micro:      var(--dt-typography-font-size-micro);

  /* ---------------------------------------------------------------
     BỘ BA KHOÁ THEO VAI (size + weight + line-height đi CÙNG NHAU).

     Trước đây token chỉ khoá mỗi CỠ, nên hai chỗ cùng --fs-body vẫn
     nhìn ra hai cỡ khác nhau: tên dự án 14/600/1.2 cạnh nội dung thẻ
     14/400/1.45. Các hệ quốc tế (Material `label`/`body`, Apple Text
     Style, Carbon type set) luôn phát hành cả ba trục cùng một lúc —
     đó là thứ khiến hai vùng đọc ra "cùng một hệ chữ".

     Quy ước: component chọn MỘT vai rồi lấy đủ ba token của vai đó,
     không trộn cỡ của vai này với độ đậm của vai kia.
     --------------------------------------------------------------- */
  --fw-title:    var(--fw-semibold);
  --fw-body:     var(--fw-normal);
  --fw-overline: var(--fw-semibold);
  --lh-title:    var(--lh-tight);
  --lh-body:     var(--lh-normal);
  --lh-body-sm:  var(--lh-snug);
  --lh-caption:  var(--lh-snug);
  --lh-overline: var(--lh-tight);
  --ls-overline: normal;   /* nhãn overline viết thường đầu câu — không giãn chữ (Thoáng–Gọn, BA 10/10/2026) */

  /* ---------------------------------------------------------------
     HÀNG DANH SÁCH — MỘT spec cho cả năm cột trái.

     Notebook (cây dự án + chip hạng mục), QuickNote (nav-cards), AntiPaint /
     AntiScreenshot (ws-list) và Project (project-list) trước đây mỗi chỗ tự
     chọn: 3 cỡ tiêu đề (11/12), 2 cỡ dòng phụ (10/11) và 5 padding khác nhau
     (3 / 7 / 0 10 / 10 12 / 7 8) — nhìn ra là năm ứng dụng khác nhau.

     Markup và logic kéo-thả của từng module giữ nguyên; chỉ lớp trình bày
     trỏ chung vào bốn biến này. Sửa một chỗ là cả năm cột đổi theo.
     --------------------------------------------------------------- */
  --list-title-fs: var(--fs-body);
  --list-sub-fs:   var(--fs-caption);
  --list-pad-x: 12px;
  --list-pad-y: 7px;

  /* Thang CSS chuẩn 300–900. Các giá trị lệch thang đang dùng trong file
     (450/540/550/650/680/720/750) được snap về bậc gần nhất — lệch tối đa
     50, dưới ngưỡng nhận biết ở cỡ chữ UI 10–13px. */
  --fw-light:    300;
  --fw-normal:   400;
  --fw-medium:   500;
  --fw-semibold: 600;
  --fw-bold:     700;
  --fw-heavy:    800;
  --fw-black:    900;

  /* Mọi giá trị line-height đang dùng đều snap được vào thang này trong
     sai số ±0.05 (≈0.65px ở 13px), nên không hàng nào bị cắt hay giãn thêm
     một dòng sau khi chuyển. */
  --lh-none:    1;
  --lh-flat:    1.1;
  --lh-tight:   1.2;
  --lh-snug:    1.35;
  --lh-normal:  1.45;
  --lh-relaxed: 1.55;
  --lh-loose:   1.7;

  /* Chỉ phủ letter-spacing hệ thống (đơn vị em — nhãn viết hoa, tiêu đề
     hiển thị). Các giá trị px rời rạc còn lại là chỉnh quang học cho từng
     phần tử cụ thể, không phải một thang, nên giữ nguyên. */
  --ls-tighter: -.03em;
  --ls-tight:   -.01em;
  --ls-normal:  0;
  --ls-wide:    .02em;
  --ls-caps:    .06em;
  --ls-caps-lg: .09em;
  --ls-caps-xl: .12em;
}

/* Appearance settings from the left menu. The defaults here are the values the
   layout was designed around, so an unset/legacy profile looks unchanged. */
:root {
  --app-font: "Segoe UI", system-ui, -apple-system, Roboto, Arial, sans-serif;
  /* Cách B: tiêu đề ngày không còn là trục người dùng chỉnh riêng — nó là bậc
     --fs-md (13px) của ramp, phóng theo "Cỡ chữ giao diện". */
  --font-title: var(--fs-body);
  /* Fallback cho frame đầu trước khi settingsPanel.js ghi giá trị thật (đã nhân
     --font-scale). */
  --font-task: 14px;
  /* Chữ trong hộp thoại/biểu mẫu (ô nhập, thẻ nháp, nhãn ưu tiên…). */
  /* AT-UI 2026: chữ form = chữ giao diện (body 14, Lớn 18). Công thức cũ
     --font-task × .86 ra 12,04px — chữ ô nhập nhỏ hơn cả nhãn bên cạnh. */
  --font-form: var(--fs-body);
  /* Popup title và content đồng bộ Design Tokens */
  --popup-title: var(--fs-body);
  --popup-content: var(--font-form);
  --popup-editor-line-height: var(--lh-normal);
  --task-row-height: 44px;
  --motion-standard: var(--dt-motion-easing-enter);
  --motion-accelerate: var(--dt-motion-easing-exit);
  --modal-scrim: rgba(var(--ui-scrim-rgb), .48);
  --modal-blur: 0px;
  --modal-enter-duration: .16s;
  --layer-header: var(--ui-layer-header);
  --layer-popover: var(--ui-layer-popover);
  --layer-notification: var(--ui-layer-notification);
  --layer-modal: var(--ui-layer-modal);
  --layer-alert: var(--ui-layer-alert);
  --layer-system: var(--ui-layer-system);
  --layer-toast: var(--ui-layer-toast);
  --ux-border-hover: var(--dt-semantic-color-dark-border-hover);
  --ui-border-hover: var(--ux-border-hover);
  --ux-control-border-hover: var(--dt-semantic-color-light-border-control-hover);
  --ux-control-border-active: var(--dt-semantic-color-light-border-focus);
  /* Fallback material lúc first paint + toàn bộ MATERIAL block (4 bậc + chỉnh
     scrim cho dark) → ĐÃ CHUYỂN sang src/renderer/styles/ui-theme-core.css để
     AntiNote dùng chung. Nạp trước styles.css nên thứ tự ghi đè giữ nguyên. */
}
html[data-mode="dark"] {
  color-scheme: dark;
  --modal-scrim: rgba(var(--ui-black-rgb), .72);
  --ux-control-border-hover: var(--dt-semantic-color-dark-border-control-hover);
  --ux-control-border-active: var(--dt-semantic-color-dark-border-focus);
}
html[data-mode="light"] {
  color-scheme: light;
  --ux-control-border-hover: var(--dt-semantic-color-light-border-control-hover);
  --ux-control-border-active: var(--dt-semantic-color-light-border-focus);
}

/* Motion policy — 3 mức chọn ở Settings > Giao diện > Chuyển động, mặc định
   "minimal". "off" khớp với hành vi Windows "Reduce motion" (cũng tự ép về
   "off" lúc chạy, xem utils/motion.js) nên dùng chung 1 rule kill-all thay vì
   nhân đôi logic prefers-reduced-motion. Các khối
   `@media (prefers-reduced-motion: reduce)` sẵn có trong file này giữ nguyên,
   không xung đột — chỉ là một lưới an toàn OS-level độc lập. */
html[data-motion="minimal"] :is(.widget-menu-panel, .picker-panel, .priority-picker-panel):not(.hidden),
html[data-motion="off"] :is(.widget-menu-panel, .picker-panel, .priority-picker-panel):not(.hidden) {
  transform: none;}
/* Menu trái (#navRail) có 3 bộ rule .nav-rail-item trùng lặp trong file này
   (thiết kế qua nhiều đợt), vài bộ tự đặt !important trên transform icon khi
   hover/active (scale 1.04–1.16, lift -1px). ID selector để chắc chắn thắng
   toàn bộ mà không cần dò từng bộ. Chỉ chạm icon/svg — không đụng
   .nav-rail-item vì nó còn nhận transform inline lúc kéo-thả sắp xếp rail
   (navRail.js: item.style.transform khi .is-dragging), đụng vào sẽ gãy kéo thả. */
html[data-motion="minimal"] #navRail .nav-rail-icon,
html[data-motion="off"] #navRail .nav-rail-icon,
html[data-motion="minimal"] #navRail .nav-rail-icon svg,
html[data-motion="off"] #navRail .nav-rail-icon svg,
html[data-motion="minimal"] #navRail .nav-icon-outline,
html[data-motion="off"] #navRail .nav-icon-outline,
html[data-motion="minimal"] #navRail .nav-icon-fill,
html[data-motion="off"] #navRail .nav-icon-fill {
  transform: none !important;
}
html[data-motion="minimal"] .nav-rail-item:active:not(:disabled):not(.is-dragging),
html[data-motion="off"] .nav-rail-item:active:not(:disabled):not(.is-dragging),
html[data-motion="minimal"] .nav-rail-toggle:active:not(:disabled),
html[data-motion="off"] .nav-rail-toggle:active:not(:disabled) {
  transform: none !important;
}

body {
  background: transparent;
  font-family: var(--app-font);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow: hidden;
  user-select: none;
}
a { color: var(--ui-accent); text-decoration: none; }
::selection { background: rgba(var(--ui-accent-rgb), .28); color: inherit; }
textarea, button, input, select, option { font-family: inherit; }
button { font: inherit; }

/* Native <select> menus are rendered outside the control's own box.  Without
   explicit option colours Chromium keeps its white popup while the select
   inherits Dark Mode's light text, making every unselected item unreadable.
   Keep both layers on the active design tokens so every shared form control
   remains legible in Light and Dark mode. */
select,
select option {
  color: var(--ui-text-primary);
  background-color: rgb(var(--ui-surface-raised-rgb));
}

/* =====================================================================
   DESIGN SYSTEM TOKENS + Mode-only tokens (--ink, tone palette)
   → ĐÃ CHUYỂN sang src/renderer/styles/ui-theme-core.css (cắt nguyên xi,
     không đổi giá trị) để AntiNote dùng chung mà không phải nạp file này.
     ui-theme-core.css được nạp TRƯỚC styles.css nên thứ tự ghi đè giữ
     nguyên. Khối "Unified shell" bên dưới (cũng đã chuyển) vẫn đứng SAU và
     ghi đè các block (system × mode) như cũ.
   ===================================================================== */
/* =====================================================================
   MATERIAL — trục thứ ba (4 bậc solid/focus/acrylic/glass + chỉnh scrim
   cho dark) → ĐÃ CHUYỂN sang src/renderer/styles/ui-theme-core.css (cắt
   nguyên xi). Hợp đồng khả đọc (--a-content ≥ .78 đi kèm --scrim-a) và
   toàn bộ chú thích nằm ở file đó. Khối `html { --shade-k / --stroke /
   --t-content }` ngay dưới vẫn ở lại đây vì nó dựng từ các token trên.
   ===================================================================== */
html {
  /* Text only needs a readability shadow once the surface under it actually
     gets thin, so this tracks --t-content (what the surfaces really do) rather
     than the material step. Driving it from the raw step made the shadow ramp
     to full strength while the surface behind was still nearly opaque, which
     is what read as fuzzy text rather than as help. */
  --shade-k: clamp(0, calc((var(--t-content) - 0.15) / 0.55), 1);
  --stroke: rgba(var(--ink), calc(var(--ui-stroke-alpha) + var(--ui-stroke-extra) * var(--t)));
}

/* --t-content TỪNG được khai hai lần với hai công thức khác nhau; bản ở `html`
   thua bản ở `:root` về specificity nên chưa bao giờ chạy. Đã xóa bản chết, và
   sau khi mọi bề mặt chuyển sang thang --ux-* thì bản còn lại được trả về đúng
   nghĩa nghịch đảo --a-content (xem chú thích tại chỗ khai, :root ~4470). */

/* =====================================================================
   CALENDAR SURFACE — window shell, titlebar, nav
   ===================================================================== */
/* The window keeps a surface at every material step, never dissolving to
   nothing. A hairline stroke at 7–17% ink with nothing behind it disappears
   against a wallpaper, so a fully transparent shell loses its outer frame.
   The veil is also what makes the window read as one panel rather than a
   scatter of floating cards.

   No backdrop-filter here on purpose: it would turn .app into a backdrop root
   and trap every child's blur. When the wallpaper is on, .app-background sits
   inside this element and every child's backdrop-filter samples it directly;
   when it is off, DWM draws the acrylic behind the whole window instead
   (see backgroundMaterial in windowManager.js). */
.app {
  position: relative;
  height: 100vh; display: flex; flex-direction: column; overflow: hidden;
  font-family: var(--app-font);
  /* Native window là opaque (transparent:false trong windowManager.js), nên
     bốn góc thừa ngoài đường bo để lộ đúng backgroundColor của BrowserWindow.
     Giá trị đó PHẢI khớp --sf-chrome cho từng cặp (system, mode) — xem
     CHROME_BY_MODE trong windowManager.js, sửa một bên phải sửa bên kia. */
  border-radius: var(--ui-radius-window);
  border: var(--ui-stroke-thin) solid transparent;
  color: var(--ui-text-primary);
}
/* AntiTask and AntiNote form one docked surface. Flatten only the touching
   edge so the opaque native BrowserWindow background cannot show through the
   rounded top-right/bottom-right corner. Standalone AntiTask remains rounded. */
html.antinote-docked .app {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}
html:not([data-material="glass"]) .app { clip-path: none; }
html[data-material="glass"] .app { clip-path: none; }
/* Glass specular highlights on the window shell — design: inset 0 1px 0 rgba(white, ...) */
/* Bóng khung cửa sổ trên kính theo chế độ (độ sâu ngoài + highlight inset theo --t). */
:root { --app-glass-shadow: 0 26px 72px rgba(var(--ui-shadow-rgb), .30), inset 0 1px 0 rgba(var(--ui-white-rgb),.60); } /* audit-keep: viền/vạch trong dựng bằng bóng inset, độ dày là hình học của viền */
html[data-mode="dark"] { --app-glass-shadow: var(--ui-shadow-geometry) rgba(var(--ui-shadow-rgb), var(--ui-shadow-alpha)), inset 0 1px 0 rgba(var(--ui-white-rgb), calc(0.14 + 0.16 * var(--t))); } /* 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 */

/* ---------- Top bar ---------- */
/* position/z-index are load-bearing: backdrop-filter makes the titlebar a
   stacking context, so without them the week picker's z-index is trapped
   inside it and the grid — later in the DOM — paints over the open panel. */
.topbar {
  -webkit-app-region: drag;
  position: relative; z-index: var(--ui-layer-header);
  flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between;
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
}
/* Bảng thả xuống từ ô tìm kiếm (lọc Task ở Lịch, phạm vi ở Notebook) đang mở:
   tạm tắt vùng kéo cửa sổ. Trên Windows cú bấm vào khoảng trống drag bị hệ
   điều hành nuốt, DOM không nhận pointerdown nên bấm-ra-ngoài không đóng bảng. */
html.topbar-popover-open .topbar { -webkit-app-region: no-drag; }
.topbar-left {
  min-width: 0;
  max-width: calc(50% - var(--dt-dimension-layout-104));
  -webkit-app-region: no-drag;
}
.topbar-section {
  display: inline-flex;
  align-items: center;
  gap: var(--ui-space-1-5);
  min-width: 0;
  flex: 0 1 auto;
}


.topbar-center {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  z-index: var(--ui-layer-pane);
  width: max-content;
  max-width: calc(100% - var(--dt-dimension-layout-256));
}
.topbar-center > * {
  pointer-events: auto;
  -webkit-app-region: no-drag;
}

.topbar-search-wrap {
  position: relative;
  display: flex;
  align-items: center;
  /* Trần hạ 420 → 320px. Ô rỗng 420px giữa thanh tiêu đề chiếm gần một phần
     tư bề ngang cửa sổ mà không chứa gì; 320px vẫn đủ đọc một câu tìm kiếm
     dài và trả lại chỗ cho tiêu đề ngày bên trái. */
  width: clamp(var(--dt-dimension-layout-208), 22vw, var(--dt-dimension-layout-320));
  gap: var(--ui-space-1-5);
  height: var(--ui-header-control-size);
  min-height: var(--ui-header-control-size);
  max-height: var(--ui-header-control-size);
  background: rgba(var(--ui-surface-raised-rgb), 0.96);
  border: var(--ui-stroke-thin) solid var(--ux-border, var(--stroke));
  border-radius: var(--dt-dimension-radius-full);
  transition: border-color var(--ui-duration-fast) var(--ui-ease), box-shadow var(--ui-duration-fast) var(--ui-ease), background var(--ui-duration-fast) var(--ui-ease);
  box-shadow: none;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  box-sizing: border-box;
  padding: 0 var(--ui-space-1-5) 0 var(--ui-space-2-5);
}
.topbar-search-wrap:hover {
  border-color: var(--ux-control-border-hover);
  box-shadow: none;
}
.topbar-search-wrap:focus-within {
  border-color: var(--ux-control-border-active);
  box-shadow: var(--ui-control-ring);
  background: rgb(var(--ui-surface-raised-rgb));
}
/* Kính lúp hiện lại. Luật cũ `display: none !important` khiến ô tìm kiếm
   không còn dấu hiệu nhận dạng nào — cộng với placeholder cũng bị ẩn (xem
   bên dưới), thứ người dùng nhìn thấy chỉ là một viên bo tròn trắng rỗng. */
.topbar-search-icon {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  color: var(--ui-text-muted);
  pointer-events: none;
}
.topbar-search-icon svg {
  width: var(--ui-header-icon-size);
  height: var(--ui-header-icon-size);
}
.topbar-search-input,
.topbar-search-input:focus,
.topbar-search-input:focus-visible {
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;
  height: 100%;
  /* Ô tìm cao = control header 24 (size small) → chữ Caption 12 như mọi control
     header khác (Hôm nay, Tuần/Tháng…), theo Fluent 2: small 24 = Caption, medium
     32 = Body. Trước 14 + line-height 24px số cứng → trông to, lệch token (BA 10/10/2026). */
  font-size: var(--fs-caption);
  font-family: inherit;
  color: var(--ui-text-primary);
  line-height: var(--lh-none);}
/* Chữ mờ hiện lại — xem lý do ở .topbar-search-icon ngay trên. */
.topbar-search-input::placeholder {
  color: var(--ui-text-muted);
  opacity: 1;
}
.topbar-project-filter-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--ui-space-1);
  min-height: var(--ui-size-sm);
  height: var(--ui-size-sm);
  padding: 0 var(--ui-space-2);
  margin-right: var(--ui-space-0-5);
  border-radius: var(--dt-dimension-radius-full);
  border: var(--ui-stroke-thin) solid var(--stroke);
  background: rgba(var(--ink), 0.05);
  color: var(--ui-text-secondary);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold, 600);
  cursor: pointer;
  white-space: nowrap;
  max-width: var(--dt-dimension-layout-120);
  transition: all var(--ui-duration-fast) var(--ui-ease);
  flex: 0 0 auto;
}

.topbar-project-filter-btn:hover {
  background: rgba(var(--ui-accent-rgb), 0.12);
  border-color: rgba(var(--ui-accent-rgb), 0.35);
  color: var(--ui-accent);
}
.topbar-project-filter-btn.is-active {
  background: var(--ui-accent-solid);
  border-color: var(--ui-accent);
  color: var(--ui-text-on-accent);
}
.topbar-project-filter-btn.is-active svg {
  stroke: var(--ui-text-on-accent);
}
html:not([data-view="calendar"]) #calendarProjectFilterBtn {
  display: none !important;
}

.topbar-search-clear {
  position: relative;
  width: var(--ui-size-sm);
  height: var(--ui-size-sm);
  border-radius: var(--ui-radius-circle);
  border: none;
  background: rgba(var(--ink), 0.08);
  color: var(--ui-text-secondary);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-body);
  line-height: 1;
  transition: all var(--ui-duration-fast) var(--ui-ease);
  padding: 0;
  flex: 0 0 auto;
  margin-left: var(--ui-space-0-5);
}
.topbar-search-clear[hidden],
.topbar-search-clear.hidden {
  display: none !important;
}
.topbar-search-clear:hover {
  background: rgba(var(--ui-accent-rgb), 0.2);
  color: var(--ui-accent);
}

.topbar-tag-filter-panel {
  position: absolute;
  top: calc(100% + var(--ui-space-1));
  left: 50%;
  transform: translateX(-50%);
  width: var(--dt-component-popover-wide-width);
  max-height: var(--dt-dimension-layout-440);
  z-index: var(--ui-layer-dropdown);
  box-shadow: var(--elev-4);
}

.topbar-project-tabs,
.topbar-dashboard-tabs {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  white-space: nowrap;
  /* Khung/cỡ: "SEGMENTED CHUẨN" (@layer components) — GĐ3 lát 5. */
  box-sizing: border-box;
}


.topbar-right {
  display: flex;
  justify-content: flex-end;
  flex: 1 1 0;
  margin-left: auto;
  min-width: 0;
  -webkit-app-region: no-drag;
}
.topbar-actions {
  display: inline-flex;
  align-items: center;
  gap: var(--ui-space-1-5);
  flex: 0 0 auto;
}


/* ==========================================================================
   TOPBAR CONTROLS & BUTTONS (FLAT WITH SUBTLE BORDER)
   Tắt toàn bộ đổ bóng, giữ viền nhẹ tinh tế cho toàn bộ các box/button trên header.
   ========================================================================== */

:is(
  .topbar-section > .notics-header-toggle,
  .topbar-section > .notics-icon-btn,
  .notics-project-filter-btn,
  .notics-open-project-btn,
  .antiscreenshot-zoom button,
  .antiscreenshot-capture-btn:not(.is-primary),
  .view-mode-wrap .glass-icon-btn
) {
  color: var(--ui-text-primary);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  transition: border-color var(--ui-duration-fast) var(--ui-ease), background var(--ui-duration-fast) var(--ui-ease), color var(--ui-duration-fast) var(--ui-ease);
  box-sizing: border-box;}



:is(
  .topbar-section > .notics-header-toggle,
  .topbar-section > .notics-icon-btn,
  .notics-open-project-btn,
  .view-mode-wrap .glass-icon-btn
) {
  min-width: var(--ui-header-control-size);
  max-width: var(--ui-header-control-size);}






:is(
  .topbar-actions .antiscreenshot-capture-btn.is-primary
):hover:not(:disabled) {
  filter: brightness(1.08);}
.nav-icon { display: block; fill: currentColor; flex: 0 0 auto; width: var(--dt-dimension-icon-header); height: var(--dt-dimension-icon-header); }
/* The Liquid Glass set is stroked outline. CSS beats an SVG
   presentation attribute, so without this `fill: currentColor` above would
   flood them and every icon would render as a solid blob. */
.nav-icon[fill="none"] { fill: none; }
.sys-icon { display: none; }
html:not([data-material="glass"]) .sys-icon.icon-fluent,
html[data-material="glass"] .sys-icon.icon-glass { display: block; }

.icon-btn,
.picker-btn {
  -webkit-app-region: no-drag;
  border: var(--ui-stroke-thin) solid var(--stroke);
  color: var(--ui-text-secondary); font-family: inherit;
  font-size: var(--fs-body); font-weight: var(--fw-semibold); letter-spacing: var(--ui-letter-spacing);
  white-space: nowrap;
}
.week-nav-cluster {
  -webkit-app-region: no-drag;
  max-height: var(--ui-header-control-size);
  transition: border-color var(--ui-duration-fast) var(--ui-ease), box-shadow var(--ui-duration-fast) var(--ui-ease);
  box-sizing: border-box;}
.week-nav-cluster:hover {
  border-color: var(--ux-control-border-hover);
}
.week-nav-cluster:has([aria-expanded="true"]),
.week-nav-cluster:focus-within {
  border-color: var(--ux-control-border-active);}
.week-nav-cluster .icon-btn,
.week-nav-cluster .picker-btn {
  max-height: calc(var(--ui-header-control-size) - var(--ui-space-1-5));
  transition: background var(--ui-duration-fast), transform var(--ui-duration-fast);}
.week-nav-cluster .picker-wrap {
  display: inline-flex;
  align-items: center;
  height: 100%;
}
.week-nav-cluster .icon-btn {
  min-width: calc(var(--ui-header-control-size) - var(--ui-space-1-5));
  max-width: calc(var(--ui-header-control-size) - var(--ui-space-1-5));}
.week-nav-cluster .icon-btn:hover,
.week-nav-cluster .picker-btn:hover {
  transform: none;}

.icon-btn {
  min-width: var(--ui-size-sm); min-height: var(--ui-size-sm); display: grid; place-items: center;
  cursor: pointer;
  transition: color var(--ui-duration-fast), background-color var(--ui-duration-fast), border-color var(--ui-duration-fast),
    box-shadow var(--ui-duration-standard) var(--motion-standard), transform var(--ui-duration-standard) var(--motion-standard);
}
.icon-btn .nav-icon { width: var(--ui-icon-xs); height: var(--ui-icon-xs); }
.icon-btn:active {
  box-shadow: var(--elev-1);
}
.icon-btn:focus-visible, .picker-btn:focus-visible {
  outline: var(--ui-stroke-thick) solid var(--ui-accent); outline-offset: var(--ui-stroke-thin);
}
.picker-wrap { position: relative; display: inline-flex; align-items: center; }
.picker-btn {
  /* Vô hiệu trong thực tế cùng lý do với bản .picker-btn ở dòng ~3768: nút
     "Tuần này" thật luôn khớp .topbar .week-nav-cluster .picker-btn (đặc
     trưng cao hơn, ở responsive-layout.css). Vẫn nhân --font-scale để nhất
     quán và để test quét toàn bộ file không bị vướng một bản quên nhân. */
  min-height: var(--ui-size-sm);
  max-height: var(--ui-size-sm);
  padding: 0 var(--ui-space-1);
  display: flex;
  align-items: center;
  gap: var(--ui-space-1);
  cursor: pointer;
  transition: color var(--ui-duration-fast), background-color var(--ui-duration-fast), border-color var(--ui-duration-fast),
    box-shadow var(--ui-duration-standard) var(--motion-standard), transform var(--ui-duration-standard) var(--motion-standard);
}
.picker-btn:active {
  box-shadow: var(--elev-1);
}
.picker-icon-wrap {
  width: var(--ui-icon-sm); height: var(--ui-icon-sm); flex: 0 0 var(--ui-icon-sm); display: grid; place-items: center;
  border-radius: var(--ui-radius-sm);
  color: var(--ui-accent);
}
.picker-icon-wrap .nav-icon { width: var(--ui-icon-xs); height: var(--ui-icon-xs); }
.picker-label { text-shadow: var(--shade-shadow); }
.picker-chevron {
  width: var(--ui-icon-xs); height: var(--ui-icon-xs); flex: 0 0 var(--ui-icon-xs); color: var(--ui-text-muted); opacity: .8;
  align-self: center;
  transition: transform var(--ui-duration-standard) var(--motion-standard), color var(--ui-duration-fast) var(--motion-standard);
}
.picker-btn:hover .picker-chevron,
.picker-btn[aria-expanded="true"] .picker-chevron { color: var(--ui-accent); opacity: 1; }
.picker-btn[aria-expanded="true"] .picker-chevron { transform: rotate(180deg); }

.picker-panel {
  -webkit-app-region: no-drag;
  position: absolute; top: calc(100% + var(--ui-space-1)); right: calc(-1 * var(--ui-space-10));
  width: var(--dt-component-popover-compact-width); max-width: calc(100vw - var(--ui-space-3));
  overflow: hidden;
  padding: var(--ui-space-1-5);
  border: var(--ui-stroke-thin) solid var(--stroke);
  transform-origin: top center;
  animation: month-picker-enter var(--ui-duration-standard) var(--ui-ease-enter) both;
}

.month-picker-header {
  display: grid; grid-template-columns: var(--ui-control-h-compact) minmax(0, 1fr) var(--ui-control-h-compact);
  align-items: center; gap: var(--ui-space-1); margin-bottom: var(--ui-space-1);
}
.month-picker-label {
  min-width: 0; text-align: center; color: var(--ui-text-primary);
  font-size: var(--fs-caption); font-weight: var(--fw-semibold); letter-spacing: var(--ui-letter-spacing);
  font-variant-numeric: tabular-nums;
}

.month-weekday-row,
.month-week-row {
  display: grid;
  grid-template-columns: 30px repeat(7, minmax(0, 1fr));
  align-items: center;
}
.month-weekday-row {
  min-height: var(--ui-space-4-5); margin-bottom: var(--ui-space-0-5);
  color: var(--ui-text-muted); font-size: var(--fs-micro); font-weight: var(--fw-semibold);
  letter-spacing: .15px; text-align: center;
}
.month-weekday-row span { display: grid; place-items: center; }
.month-weekday-row .month-week-heading { font-size: var(--fs-micro); letter-spacing: 0; }

.month-week-list { display: flex; flex-direction: column; gap: var(--ui-resizer-line); }

.month-picker-footer {
  display: flex; justify-content: flex-end;
  margin-top: var(--ui-space-1-5); padding-top: var(--ui-space-1-5); border-top: var(--ui-resizer-line) solid var(--ux-divider);
}
.month-today-btn {
  min-height: var(--ui-control-h-standard); border-radius: var(--ui-radius-control); cursor: pointer;
  font-size: var(--fs-micro); font-weight: var(--fw-semibold); letter-spacing: var(--ui-letter-spacing);
  transition: filter var(--ui-duration-fast) var(--ui-ease), transform var(--ui-duration-fast) var(--ui-ease), background-color var(--ui-duration-fast) var(--ui-ease);
  padding: 0 var(--ui-space-3); border: 0;
  background: var(--tone-blue-bar); color: var(--ui-text-on-accent);
}
.month-today-btn:hover { filter: brightness(1.1); }
.month-today-btn:active { transform: none; }
.month-today-btn:focus-visible { outline: var(--ui-focus-ring-width) solid var(--tone-blue-bar); outline-offset: var(--ui-focus-ring-offset); }

@keyframes month-picker-enter {
  from { transform: translateY(calc(-1 * var(--ui-motion-distance-subtle))) scale(var(--ui-motion-scale-popover)); opacity: 0; }
  to { transform: translateY(0) scale(1); opacity: 1; }
}


@media (max-width: 960px) {
  .topbar { gap: var(--ui-space-3-5); }
  .topbar-right { gap: var(--ui-space-1-5); }
}

@media (max-width: 760px) {
  .topbar { margin-inline: 0; }
}
/* ---------- Multi-week matrix ----------
   One single grid: column 1 is the week rail, columns 2..n are the days.
   The header row and every week row are subgrids of it, so the weekday
   labels line up with the day cards no matter how many weeks are shown. */
.grid.multi-week {
  /* 88px rail and 10px gutters are the design's own grid metrics
     (gridTemplateColumns: '88px repeat(5, 1fr)', gap 10px, padding 10px);
     narrowed to give each day column more width for task content. */
  --rail-w: 36px;
  --cell-gap: 7px;
  --head-h: 34px;
  --week-row-min: 0px;
  display: grid;
  grid-template-columns: var(--rail-w) repeat(var(--day-count, 7), minmax(0, 1fr));
  overflow-x: hidden; scroll-behavior: smooth;
  /* Any single click that re-renders the grid (toggling a task, reordering
     done items to the bottom, a badge count changing) can shift this
     container's total content height by a few px. Without this, that alone
     flips its vertical scrollbar on/off, which changes its content-box
     width — every column in every row (not just the clicked card) shrinks
     or grows by the scrollbar's width and reflows, which is what reads as
     "other cards get jostled". Reserving the gutter unconditionally means
     the scrollbar toggling never changes available width. */
  scrollbar-gutter: stable;
}
.multi-week-corner,
.shared-day-label {
  display: flex; align-items: center; min-width: 0;
  text-shadow: var(--shade-shadow); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.multi-week-corner { text-transform: uppercase; }
.shared-day-label { text-transform: none; }

/* ---------- Task rows & events (the design's "plate" component) ---------- */
html:not([data-material="glass"]) .task-item { border: 0; }
/* Glass specular on task plates — design: inset 0 1px 0, light vs dark formulas */
html[data-material="glass"] .task-item { box-shadow: inset 0 1px 0 light-dark(rgba(var(--ui-white-rgb), calc(0.35 + 0.3 * var(--t))), rgba(var(--ui-white-rgb), calc(0.06 + 0.10 * var(--t)))); } /* 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 */
.monochrome-task-rows .task-item:not(.done) .task-text,
.monochrome-task-rows .task-item:not(.done) .task-prefix {
  color: var(--ui-text-primary);
  font-weight: var(--fw-medium);
}
.monochrome-task-rows .priority-edge { opacity: .88; }
.task-item::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; transition: background var(--ui-duration-fast), box-shadow var(--ui-duration-fast);
}
.task-item:not(.dragging):hover {
  z-index: var(--ui-layer-raised);
}
.task-item:focus-within { z-index: var(--ui-layer-raised); }
.task-item.drop-before { box-shadow: inset 0 calc(var(--ui-focus-ring-width) * 1.5) 0 var(--ui-accent); }
.task-item.drop-after { box-shadow: inset 0 calc(var(--ui-focus-ring-width) * -1.5) 0 var(--ui-accent); }
.task-item.dragging { cursor: grabbing; }
/* "Done" is carried by the muted colour alone — no strikethrough. Dimming the
   whole row with opacity also thins its background, so over a wallpaper the
   finished tasks dropped out of sight entirely.

   --done-ink walks from the design's mute colour toward the stronger `sub` one
   as transparency rises. Mute is the weakest text on the palette and measured
   only 2.8:1 against a thin plate over a dark wallpaper — under the 3:1 floor,
   and the reason finished tasks read as washed out. Walking it to `sub` lifts
   the worst case to 5.3:1 without making any surface more opaque. */
html { --done-ink: color-mix(in srgb, var(--ui-text-muted), var(--ui-text-secondary) calc(var(--t) * 100%)); }
@keyframes task-gravity-complete {
  0% { transform: translateY(0) scale(1); }
  24% { transform: translateY(1px) scale(.985); }
  72% { transform: translateY(7px) scale(.985); }
  100% { transform: translateY(11px) scale(.98); opacity: .84; }
}
@keyframes task-lift-restore {
  0% { transform: translateY(0) scale(1); }
  35% { transform: translateY(-11px) scale(1.015); }
  68% { transform: translateY(-7px) scale(1.005); }
  100% { transform: translateY(-10px) scale(.99); opacity: .86; }
}
@keyframes task-land-complete {
  0% { transform: translateY(-10px) scale(.985); opacity: .72; }
  72% { transform: translateY(2px) scale(1.005); opacity: 1; }
  100% { transform: translateY(0) scale(1); opacity: 1; }
}
@keyframes task-rise-restore {
  0% { transform: translateY(12px) scale(.98); opacity: .72; }
  65% { transform: translateY(-3px) scale(1.01); opacity: 1; }
  100% { transform: translateY(0) scale(1); opacity: 1; }
}
.task-box:focus-visible { outline: var(--ui-stroke-thick) solid var(--ui-accent); outline-offset: var(--ui-stroke-thick); }

/* ---------- Priority colors (p1-p4 token) ---------- */
/* Shared color modifiers — applied to both the picker menu's preview dots
   (.priority-dot) and the task row's edge marker (.priority-edge), each of
   which supplies its own size/shape/position. */
.priority-color-urgent { background: var(--ui-danger); }
.priority-color-important { background: var(--ui-warning); }
.priority-color-normal { background: var(--ui-success); }
.priority-color-personal { background: var(--ui-accent); }

.priority-dot {
  display: inline-block; width: var(--ui-space-2-5); height: var(--ui-space-2-5); border-radius: var(--ui-radius-circle); flex-shrink: 0;
}
/* Chấm đứng trước chữ trong menu/gợi ý (thay emoji 🔴🟠🟢🔵, BA 12/10/2026). */
.priority-dot.is-inline { margin-inline-end: var(--ui-space-2); vertical-align: middle; }

/* Attached-note modal. Header/shell chrome comes from the shared overlay-*
   classes in the UNIFIED OVERLAY SYSTEM; only content-specific bits stay. */
.linked-note-meta-row { display: flex; align-items: center; flex-wrap: wrap; gap: var(--ui-space-1-5) var(--ui-space-2); }
.linked-note-master { display: inline-flex; align-items: center; flex-wrap: wrap; gap: var(--ui-space-1) var(--ui-space-1-5); }
.linked-note-source {
  border-radius: var(--dt-dimension-radius-full); padding: var(--ui-space-0-5) var(--ui-space-2); font-size: var(--fs-caption); font-weight: var(--fw-semibold);
  color: var(--ui-accent); background: rgba(var(--ui-accent-rgb), 0.12);
  border: var(--ui-stroke-thin) solid rgba(var(--ui-accent-rgb), 0.22);
}
.linked-note-source-outlook { color: var(--ui-brand-outlook); background: var(--ui-category-blue-bg); border-color: var(--ui-brand-outlook); }
.linked-note-source-google { color: var(--ui-accent); background: rgba(var(--ui-brand-google-rgb),0.12); border-color: rgba(var(--ui-brand-google-rgb),0.25); }
.linked-note-master-meta-item {
  display: inline-flex; align-items: center; gap: var(--ui-space-1); color: var(--ui-text-secondary);
  font-size: var(--fs-caption); font-weight: var(--fw-medium);
}
.linked-note-master-meta-item svg { width: var(--ui-icon-xs); height: var(--ui-icon-xs); opacity: 0.85; }

/* The Quill editor fills remaining modal height via flex:1, which needs a
   flex-column parent — .overlay-body alone is not one (other dialogs stack
   plain block content), so this adds just that on top. */
.linked-note-body { display: flex; flex-direction: column; }
.linked-note-editor-wrapper {
  flex: 1; min-height: var(--dt-component-editor-frame-min-height); display: flex; flex-direction: column;
  background: light-dark(rgb(var(--ui-surface-raised-rgb)), var(--ux-input-bg)); border: var(--ui-stroke-thin) solid light-dark(var(--stroke), var(--ux-border));
  border-radius: var(--ui-radius-panel); overflow: hidden;
  transition: border-color var(--ui-duration-fast) var(--ui-ease), box-shadow var(--ui-duration-fast) var(--ui-ease);
}
.linked-note-editor-wrapper:focus-within {
  border-color: var(--ux-control-border-active);
  box-shadow: var(--ui-control-ring);
}

.linked-note-editor-toolbar {
  display: flex; align-items: center; gap: var(--ui-space-1); padding: var(--ui-space-1-5) var(--ui-space-2-5);
  background: light-dark(rgba(var(--ui-surface-fill-rgb), 0.5), var(--ux-row)); border-bottom: var(--ui-stroke-thin) solid light-dark(var(--stroke), var(--ux-border));
}
.linked-note-editor-toolbar .ql-formats {
  display: inline-flex; align-items: center; gap: var(--ui-space-0-5); padding-right: var(--ui-space-1-5); margin-right: var(--ui-space-1);
  border-right: var(--ui-stroke-thin) solid var(--stroke);
}
.linked-note-editor-toolbar .ql-formats:last-child {
  padding-right: 0; margin-right: 0; border-right: 0;
}
.linked-note-editor-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;
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  transition-property: var(--tr-ui); transition-timing-function: var(--ui-ease); transition-duration: var(--ui-duration-fast);
}
.linked-note-editor-toolbar button svg { width: var(--ui-editor-toolbar-icon); height: var(--ui-editor-toolbar-icon); display: block; }
.linked-note-editor-toolbar button:hover,
.linked-note-editor-toolbar button.ql-active {
  color: var(--ui-accent); border-color: rgba(var(--ui-accent-rgb), 0.35);
  background: rgba(var(--ui-accent-rgb), 0.12);
}

.linked-note-editor {
  flex: 1; width: 100%; min-height: var(--dt-component-editor-content-min-height); color: var(--ui-text-primary);
  background: transparent; outline: none; overflow-y: auto;
  overscroll-behavior-y: contain;
  scrollbar-gutter: stable;
}
.linked-note-editor .ql-editor {
  position: relative; min-height: var(--dt-component-editor-rich-text-min-height); padding: var(--ui-space-3) var(--ui-space-3-5);
  color: var(--ui-text-primary); font-weight: var(--fw-medium); line-height: var(--popup-editor-line-height); outline: none;
  white-space: pre-wrap; overflow-wrap: anywhere; user-select: text;
  counter-reset: list-0 list-1 list-2 list-3;
}
.linked-note-editor .ql-editor.ql-blank::before {
  content: attr(data-placeholder); position: absolute; left: var(--ui-space-3-5); right: var(--ui-space-3-5);
  color: var(--ui-text-muted); font-style: normal; pointer-events: none; opacity: 0.85;
}
.linked-note-editor .ql-editor :is(p, ol, ul) { margin: 0 0 .12em; padding: 0; }
.linked-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;
}
.linked-note-editor .ql-editor ol { padding-left: 1.5em; counter-reset: list-0 list-1 list-2 list-3; }
.linked-note-editor .ql-editor li { position: relative; padding-left: 1.5em; list-style: none; }
.linked-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;
}
.linked-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. */
.linked-note-editor .ql-editor li[data-list]:not([class*="ql-indent-"]) { counter-set: list-1 0 list-2 0 list-3 0; }
.linked-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; }
.linked-note-editor .ql-editor li[data-list].ql-indent-1 { counter-set: list-2 0 list-3 0; }
.linked-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; }
.linked-note-editor .ql-editor li[data-list].ql-indent-2 { counter-set: list-3 0; }
.linked-note-editor .ql-editor li[data-list]:not([data-list="ordered"]).ql-indent-2 { counter-set: list-2 0 list-3 0; }
.linked-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; }
.linked-note-editor .ql-editor li[data-list="ordered"] { counter-increment: list-0; }
.linked-note-editor .ql-editor li[data-list="ordered"] > .ql-ui::before { content: counter(list-0, decimal) ". "; }
.linked-note-editor .ql-editor li[data-list="ordered"].ql-indent-1 { counter-increment: list-1; }
.linked-note-editor .ql-editor li[data-list="ordered"].ql-indent-1 > .ql-ui::before { content: counter(list-1, lower-alpha) ". "; }
.linked-note-editor .ql-editor li[data-list="ordered"].ql-indent-2 { counter-increment: list-2; }
.linked-note-editor .ql-editor li[data-list="ordered"].ql-indent-2 > .ql-ui::before { content: counter(list-2, lower-roman) ". "; }
.linked-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; }
.linked-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) ". "; }
.linked-note-editor .ql-editor .ql-indent-1:not(.ql-direction-rtl) { padding-left: 3em; }
.linked-note-editor .ql-editor li.ql-indent-1:not(.ql-direction-rtl) { padding-left: 4.5em; }
.linked-note-editor .ql-editor .ql-indent-2:not(.ql-direction-rtl) { padding-left: 6em; }
.linked-note-editor .ql-editor li.ql-indent-2:not(.ql-direction-rtl) { padding-left: 7.5em; }

.linked-note-kbd {
  display: inline-block; padding: var(--ui-space-0-5) var(--ui-space-1-5); font-size: var(--fs-caption); font-weight: var(--fw-semibold);
  color: light-dark(var(--ui-text-secondary), var(--ui-text-muted)); background: light-dark(rgba(var(--ink), 0.05), rgba(var(--ui-white-rgb), 0.08));
  border: 1px solid light-dark(rgba(var(--ink), 0.12), rgba(var(--ui-white-rgb), 0.14)); border-radius: var(--ui-radius-control); box-shadow: 0 1px 0 light-dark(rgba(var(--ink), 0.08), rgba(var(--ui-shadow-rgb), 0.3)); /* audit-keep: bóng riêng của thành phần, không thuộc bậc elevation chuẩn */
}


/* ---------- Delete-a-recurring-task scope picker ---------- */
.delete-scope-list { display: flex; flex-direction: column; gap: var(--ui-space-2); margin-top: var(--ui-space-3-5); }
.delete-scope-option {
  display: flex; align-items: flex-start; gap: var(--ui-space-2-5); padding: var(--ui-space-2-5) var(--ui-space-3-5); cursor: pointer;
  border: var(--ui-stroke-thick) solid var(--stroke); border-radius: var(--ui-radius-control);
  background: rgba(var(--ui-surface-fill-rgb), .5); transition: border-color var(--ui-duration-fast), background-color var(--ui-duration-fast);
}
.delete-scope-option:hover { border-color: var(--ui-accent); background: rgba(var(--ui-surface-fill-rgb), .85); }
.delete-scope-option:has(input:checked) { border-color: var(--ui-accent); background: rgba(var(--ui-surface-fill-rgb), .95); }
.delete-scope-option input { margin: var(--ui-space-0-5) 0 0; accent-color: var(--ui-accent); flex: 0 0 auto; }
.delete-scope-body { display: flex; flex-direction: column; gap: var(--ui-space-0-5); min-width: 0; }
.delete-scope-title { font-size: var(--fs-body); font-weight: var(--fw-semibold); color: var(--ui-text-primary); }
.delete-scope-desc { font-size: var(--fs-caption); line-height: var(--lh-normal); color: var(--ui-text-muted); }
#deleteSeriesTaskName { margin-top: var(--ui-space-0-5); font-size: var(--fs-body); color: var(--ui-text-secondary); overflow-wrap: anywhere; }
#deleteSeriesConfirmBtn:hover { box-shadow: 0 8px 18px rgba(var(--ui-danger-rgb), .25); } /* audit-keep: quầng sáng màu trạng thái (glow), không phải bậc độ nổi */

.priority-picker-panel {
  position: fixed;
  border: var(--ui-stroke-thin) solid rgba(var(--ui-neutral-rgb), 0.2);
  flex-direction: column;
  transition: opacity var(--ui-duration-standard) var(--ui-ease), transform var(--ui-duration-standard) var(--ui-ease), visibility 0s; /* audit-keep: nhịp riêng của hiệu ứng, không thuộc nhịp giao diện chuẩn */
}
.priority-picker-option {
  display: flex; align-items: center;
  background: transparent; cursor: pointer;
  font-weight: var(--fw-semibold); color: var(--ui-text-primary);
  text-align: left; width: 100%; font-family: inherit;
}
.priority-picker-option:hover, .priority-picker-option:focus-visible { background: rgba(var(--ui-surface-fill-rgb), 0.8); outline: none; }
.priority-picker-divider { height: var(--ui-resizer-line); margin: var(--ui-space-1) var(--ui-space-0-5); }

.grid.multi-week .progress-track { height: var(--ui-space-1); border-radius: 0 0 var(--ui-radius-panel) var(--ui-radius-panel); overflow: hidden; }
.gcal-event-title { font-weight: var(--fw-semibold); width: 100%; }
.outlook-event-title { font-weight: var(--fw-semibold); width: 100%; }
/* Event completion and past styles */
/* Quá khứ / đã xong chỉ hạ nổi bật bằng độ mờ + màu chữ "done"; GIỮ NGUYÊN
   sắc nền pastel riêng của từng thẻ (item-tone-*). grayscale() cũ nuốt sạch
   màu nên mọi thẻ lịch đồng bộ (gần như luôn ở quá khứ) trông xám như nhau. */
/* ARS-1: không hạ opacity cả thẻ (kéo chữ dưới 4.5:1) — lùi bằng màu chữ. */
.gcal-event-item.is-past-event :is(.gcal-event-title, .outlook-event-title),
.outlook-event-item.is-past-event :is(.gcal-event-title, .outlook-event-title) {
  color: var(--ui-text-secondary);
}
.gcal-event-item.event-done .gcal-event-title,
.outlook-event-item.event-done .outlook-event-title {
  color: var(--done-ink);
  text-decoration: line-through;
  text-decoration-color: var(--done-ink);
}

/* ---------- Meeting Alert SVG Snake Border Animation ---------- */
/* .task-item shares this with .outlook-event-item: a task whose text carries
   a recognized time gets the same approaching-meeting glow. */
.outlook-event-item.alert-warning,
.outlook-event-item.alert-urgent,
.task-item.alert-warning,
.task-item.alert-urgent {
  position: relative;
  z-index: 1;
}


@keyframes snakeMove {
  0% { stroke-dashoffset: 100; }
  100% { stroke-dashoffset: 0; }
}

@keyframes bellRingShake {
  0% { transform: rotate(0); }
  4% { transform: rotate(15deg); }
  8% { transform: rotate(-13deg); }
  12% { transform: rotate(11deg); }
  16% { transform: rotate(-9deg); }
  20% { transform: rotate(6deg); }
  24% { transform: rotate(-3deg); }
  28% { transform: rotate(0); }
  100% { transform: rotate(0); }
}

@media (prefers-reduced-motion: reduce) {
  .day-col, .task-item, .task-box, .task-prefix, .progress-fill, .icon-btn, .picker-btn, .picker-chevron { transition: none; }
  .day-col:hover, .task-item:hover, .icon-btn:hover, .picker-btn:hover { transform: none; }
      }

/* =====================================================================
   SETTINGS / EDIT / CONFIG DIALOGS
   Các màn cấu hình dùng cùng surface ladder, status, focus và component
   recipe với toàn ứng dụng. Màu thương hiệu chỉ đi qua token --ui-brand-*.
   ===================================================================== */

/* ---------- Overlays ---------- */
.overlay { position: fixed; inset: 0; }

#menuOverlay {
  align-items: center; justify-content: center; padding: var(--ui-space-4-5); display: flex;
  background: light-dark(var(--modal-scrim), rgba(var(--ui-black-rgb), .5)); backdrop-filter: blur(var(--modal-blur)); -webkit-backdrop-filter: blur(var(--modal-blur));
}
.checkbox-row {
  display: flex; align-items: center; gap: var(--ui-space-2-5); font-size: var(--fs-body); color: var(--ui-text-secondary);
  cursor: pointer; padding: var(--ui-space-2-5) var(--ui-space-3); border: var(--ui-stroke-thin) solid var(--stroke); border-radius: var(--ui-radius-panel);
}
.checkbox-row + .checkbox-row { margin-top: var(--ui-space-2); }
.checkbox-row:hover { border-color: var(--ui-accent); color: var(--ui-accent); }
.checkbox-box {
  width: var(--ui-icon-sm); height: var(--ui-icon-sm); border-radius: var(--ui-radius-control); display: grid; place-items: center;
  font-size: var(--fs-caption); color: var(--ui-text-on-accent); border: var(--ui-stroke-thick) solid var(--ui-divider); background: rgb(var(--ui-surface-raised-rgb)); flex: 0 0 auto;
}
.checkbox-box.checked { border-color: var(--ui-accent); background: var(--ui-accent); }
.sync-checkbox-row { align-items: flex-start; }
.sync-checkbox-row .checkbox-box { margin-top: var(--ui-space-0-5); }
.sync-menu-copy { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: var(--ui-space-0-5); }
.sync-menu-title { color: inherit; font-weight: var(--fw-semibold); line-height: var(--lh-tight); }
.sync-menu-status { color: var(--ui-text-muted); font-size: var(--fs-caption); line-height: var(--lh-snug); }
.sync-status-dot {
  flex: 0 0 auto; width: var(--ui-space-2); height: var(--ui-space-2); margin-top: var(--ui-space-1-5); border-radius: var(--ui-radius-circle);
  background: var(--ui-text-muted); box-shadow: 0 0 0 calc(var(--ui-focus-ring-width) * 1.5) light-dark(color-mix(in srgb, var(--ui-text-muted) 20%, transparent), rgba(var(--ui-module-settings-rgb), .16)); /* audit-keep: quầng sáng màu trạng thái (glow), không phải bậc độ nổi */
}
.sync-checkbox-row[data-phase="synced"] .sync-status-dot { background: var(--ui-success); box-shadow: 0 0 0 calc(var(--ui-focus-ring-width) * 1.5) color-mix(in srgb, var(--ui-success) 14%, transparent); }
.sync-checkbox-row[data-phase="syncing"] .sync-status-dot,
.sync-checkbox-row[data-phase="starting"] .sync-status-dot {
  background: var(--ui-accent); box-shadow: 0 0 0 calc(var(--ui-focus-ring-width) * 1.5) color-mix(in srgb, var(--ui-accent) 14%, transparent); animation: sync-pulse 1.25s ease-in-out infinite; /* audit-keep: chuyển động biên đạo riêng (keyframes), không thuộc nhịp giao diện chuẩn */
}
.sync-checkbox-row[data-phase="offline"] .sync-status-dot,
.sync-checkbox-row[data-phase="needs-auth"] .sync-status-dot { background: var(--ui-warning); box-shadow: 0 0 0 calc(var(--ui-focus-ring-width) * 1.5) color-mix(in srgb, var(--ui-warning) 16%, transparent); }
.sync-checkbox-row[data-phase="error"] .sync-status-dot { background: var(--ui-danger); box-shadow: 0 0 0 calc(var(--ui-focus-ring-width) * 1.5) color-mix(in srgb, var(--ui-danger) 14%, transparent); }
.sync-checkbox-row[data-phase="pending"] .sync-status-dot { background: var(--ui-warning); box-shadow: 0 0 0 calc(var(--ui-focus-ring-width) * 1.5) color-mix(in srgb, var(--ui-warning) 16%, transparent); }
@keyframes sync-pulse { 50% { transform: scale(.68); opacity: .55; } }
@media (prefers-reduced-motion: reduce) {  }
/* Người dùng chỉ cần trạng thái tổng quát. Chi tiết từng kênh vẫn sẵn sàng
   cho trường hợp cần chẩn đoán, và tự mở khi có lỗi thật. */
.sync-overview-status {
  margin: var(--ui-space-0-5) var(--ui-space-2-5) var(--ui-space-1); font-size: var(--fs-caption); line-height: var(--lh-snug); color: var(--ui-text-muted);
}
.sync-overview-status[data-state="success"] { color: var(--ui-success); }
.sync-overview-status[data-state="progress"] { color: var(--ui-accent); }
.sync-overview-status[data-state="attention"] { color: var(--ui-danger); font-weight: var(--fw-semibold); }
.sync-details { margin: 0 var(--ui-space-2-5); border-top: var(--ui-stroke-thin) solid light-dark(rgba(var(--ui-module-settings-rgb), .16), rgba(var(--ui-module-settings-rgb), .18)); }
.sync-details > summary {
  padding: var(--ui-space-2) 0; color: var(--ui-text-muted); font-size: var(--fs-caption); font-weight: var(--fw-semibold);
  cursor: pointer; user-select: none;
}
.sync-details > summary:hover { color: var(--ui-accent); }
.sync-details[open] > summary { color: var(--ui-text-secondary); }
/* Bảng trạng thái từng kênh. Dùng lại đúng bảng màu của chấm trạng
   thái chung ở trên để "xanh = xong / đỏ = hỏng" chỉ có một nghĩa duy nhất
   trong toàn bộ panel. */
.sync-channel-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--ui-space-0-5); }
.sync-channel-item {
  display: flex; align-items: flex-start; gap: var(--ui-space-2-5);
  padding: var(--ui-space-2) var(--ui-space-3-5); border-radius: var(--ui-radius-control);
}
.sync-channel-item + .sync-channel-item { border-top: var(--ui-stroke-thin) solid light-dark(rgba(var(--ui-module-settings-rgb), .12), rgba(var(--ui-module-settings-rgb), .18)); }
.sync-channel-dot {
  flex: 0 0 auto; width: var(--ui-space-2); height: var(--ui-space-2); margin-top: var(--ui-space-1); border-radius: var(--ui-radius-circle);
  background: var(--ui-text-muted); box-shadow: 0 0 0 calc(var(--ui-focus-ring-width) * 1.5) light-dark(color-mix(in srgb, var(--ui-text-muted) 20%, transparent), rgba(var(--ui-module-settings-rgb), .16)); /* audit-keep: quầng sáng màu trạng thái (glow), không phải bậc độ nổi */
}
.sync-channel-item.is-synced .sync-channel-dot { background: var(--ui-success); box-shadow: 0 0 0 calc(var(--ui-focus-ring-width) * 1.5) color-mix(in srgb, var(--ui-success) 14%, transparent); }
.sync-channel-item.is-syncing .sync-channel-dot {
  background: var(--ui-accent); box-shadow: 0 0 0 calc(var(--ui-focus-ring-width) * 1.5) color-mix(in srgb, var(--ui-accent) 14%, transparent); animation: sync-pulse 1.25s ease-in-out infinite; /* audit-keep: chuyển động biên đạo riêng (keyframes), không thuộc nhịp giao diện chuẩn */
}
.sync-channel-item.is-error .sync-channel-dot { background: var(--ui-danger); box-shadow: 0 0 0 calc(var(--ui-focus-ring-width) * 1.5) color-mix(in srgb, var(--ui-danger) 14%, transparent); }
.sync-channel-item.is-off .sync-channel-dot { background: var(--ui-text-muted); }
.sync-channel-copy { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: var(--ui-space-px); }
.sync-channel-copy strong { font-size: var(--fs-caption); font-weight: var(--fw-semibold); line-height: var(--lh-snug); color: inherit; }
.sync-channel-copy small { font-size: var(--fs-caption); line-height: var(--lh-snug); color: var(--ui-text-muted); overflow-wrap: anywhere; }
.sync-channel-item.is-error .sync-channel-copy small { color: var(--ui-danger); }
@media (prefers-reduced-motion: reduce) {  }
.sync-schedule-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--ui-space-4);
  padding: var(--ui-space-3) var(--ui-space-3-5); border-radius: var(--ui-radius-panel); background: var(--ux-fill);
}
.fluent-icon { display: block; fill: currentColor; flex: 0 0 auto; }
.menu-action-arrow { flex: 0 0 auto; font-size: var(--fs-title-lg); line-height: var(--lh-none); color: var(--ui-text-muted); }

/* [MODULARIZED] Settings styles moved to src/renderer/styles/settings.css */

/* ---------- Event Detail Modal ---------- */
.event-source-badge {
  padding: var(--ui-space-1) var(--ui-space-3); border-radius: var(--dt-dimension-radius-full); font-size: var(--fs-caption); font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide); display: inline-flex; align-items: center; gap: var(--ui-space-1); align-self: flex-start;
}
.event-source-badge.google {
  background: light-dark(rgba(var(--ui-brand-google-rgb), 0.12), var(--ui-category-blue-bg)); color: light-dark(var(--ui-accent), var(--ui-brand-google));
  border: var(--ui-stroke-thin) solid light-dark(rgba(var(--ui-brand-google-rgb), 0.25), var(--ui-brand-google));
}
.event-source-badge.outlook {
  background: light-dark(rgba(var(--ui-accent-rgb), 0.12), var(--ui-category-blue-bg)); color: light-dark(var(--ui-accent), var(--ui-brand-outlook));
  border: var(--ui-stroke-thin) solid light-dark(rgba(var(--ui-accent-rgb), 0.25), var(--ui-brand-outlook));
}
.event-info-list { display: flex; flex-direction: column; }
.event-info-item {
  display: flex; align-items: flex-start; gap: var(--ui-space-3); padding: var(--ui-space-2) var(--ui-space-3);
}
.event-info-item .info-icon {
  font-size: var(--fs-title); width: var(--ui-size-md); height: var(--ui-size-md); border-radius: var(--ui-radius-control);
  display: flex; align-items: center; justify-content: center;
  background: light-dark(rgb(var(--ui-surface-raised-rgb)), rgba(var(--ui-white-rgb), 0.06)); border: var(--ui-stroke-thin) solid light-dark(rgba(var(--ui-neutral-rgb), 0.15), rgba(var(--ui-white-rgb), 0.1));
  flex-shrink: 0; box-shadow: var(--elev-1);
}
.event-info-item .info-body { min-width: 0; flex: 1; }
.event-info-item .info-caption {
  font-size: var(--fs-caption); font-weight: var(--fw-overline); line-height: var(--lh-overline);
  color: var(--ui-text-secondary); margin-bottom: var(--ui-space-1); opacity: 0.9;
}
.event-info-item .info-text {
  font-size: var(--fs-body); font-weight: var(--fw-semibold); color: var(--ui-text-primary);
  word-break: break-word; line-height: var(--lh-snug);
}
.event-info-item .info-subtext { font-size: var(--fs-body); font-weight: var(--fw-medium); color: var(--ui-text-secondary); margin-top: var(--ui-space-0-5); }
#eventModalDoneBtn {
  padding: var(--ui-space-2) var(--ui-space-5); border-radius: var(--dt-dimension-radius-full);
  border: var(--ui-stroke-thin) solid light-dark(rgba(var(--ui-neutral-rgb), 0.25), var(--ux-border)); background: var(--ux-raised);
  color: var(--ui-text-primary); font-size: var(--fs-body); font-weight: var(--fw-semibold); cursor: pointer;
  transition-property: var(--tr-ui); transition-timing-function: var(--ui-ease); transition-duration: var(--ui-duration-standard);
}
#eventModalDoneBtn:hover {
  background: rgba(var(--ui-neutral-rgb), 0.12); border-color: light-dark(rgba(var(--ui-neutral-rgb), 0.4), var(--ux-border));
}
.btn-join-meeting {
  display: inline-flex; align-items: center; gap: var(--ui-space-2);
  min-height: var(--ui-control-h-standard); height: var(--ui-control-h-standard);
  background: var(--ui-accent-solid); color: var(--ui-text-on-accent); font-weight: var(--fw-semibold);
  font-size: var(--fs-body); padding: 0 var(--ui-space-3); border-radius: var(--ui-radius-control);
  border: 0; cursor: pointer; box-shadow: var(--join-meeting-shadow);
  transition-property: var(--tr-ui); transition-timing-function: var(--ui-ease); transition-duration: var(--ui-duration-standard);
}
.btn-join-meeting:hover {
  filter: var(--join-meeting-hover-filter); transform: none;
  box-shadow: var(--join-meeting-hover-shadow);
}
/* Token độ nổi nút Tham gia theo chế độ: Tối dùng quầng accent thay bóng xám. */
:root {
  --join-meeting-shadow: var(--elev-2);
  --join-meeting-hover-shadow: var(--elev-3);
  --join-meeting-hover-filter: brightness(1.1);
}
html[data-mode="dark"] {
  --join-meeting-shadow: var(--ui-shadow-accent);
  --join-meeting-hover-shadow: var(--ui-shadow-popover);
  --join-meeting-hover-filter: brightness(1.08);
}


/* The day-manager UI (quick-add, draft cards, drawer, repeat editor) now
   builds its colors from the shared --sf-* tokens (see the base rules
   above), which already vary correctly per mode AND per design system —
   so it no longer needs a separate hardcoded dark-mode block here. That
   block used to win by selector specificity over the token-based light
   rules, silently overriding them back to fixed hex in dark mode and
   undoing the whole point of switching to tokens. */

/* =====================================================================
   QUICK ADD WINDOW (renderer/quickAdd.html)
   The global-hotkey popup is a second BrowserWindow that loads THIS
   stylesheet, so it inherits every design-system token and skins itself
   the same way as the widget. Nothing below hardcodes a palette colour
   except the toast, which is a fixed success/error signal.
   Two layouts share one document; body.layout-mini / .layout-full pick
   which one is live.
   ===================================================================== */
.qa-body { height: 100%; overflow: hidden; background: rgb(var(--ui-surface-raised-rgb)); color: var(--ui-text-primary); }
.qa-shell { position: relative; display: flex; flex-direction: column; min-height: 0; }
body.layout-mini, body.layout-mini .qa-shell { height: 100%; }
body.layout-full, body.layout-full .qa-shell { height: 100%; }
body.layout-mini #qaFull { display: none; }
body.layout-full #qaMini { display: none; }

/* ---- mini: one-line spotlight entry ---- */
.qa-mini {
  height: 100%;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-2);
  padding: var(--ui-space-3-5) var(--ui-space-4) var(--ui-space-3);
}
.qa-mini-row { display: flex; align-items: center; gap: var(--ui-space-2-5); }
.qa-tag-input-wrap { position: relative; flex: 1 1 auto; min-width: 0; }
.qa-tag-input-wrap .quick-task-input { width: 100%; }
.qa-popup-tag-suggestions {
  z-index: var(--ui-layer-dropdown);
  width: min(var(--dt-dimension-layout-360), calc(100vw - var(--ui-space-12)));
  max-height: var(--dt-dimension-layout-240);
  overflow-y: auto;
  box-shadow: var(--elev-4);
}
.qa-day-chip {
  flex: 0 0 auto; height: max(var(--ui-size-md), var(--task-row-height)); padding: 0 var(--ui-space-3);
  display: inline-flex; align-items: center; white-space: nowrap;
  border-radius: var(--ui-radius-control); background: rgba(var(--ui-surface-fill-rgb), .85);
  border: var(--ui-stroke-thin) solid var(--ui-divider); color: var(--ui-text-secondary); font-size: var(--fs-body); font-weight: var(--fw-semibold);
}
.qa-mini-meta { display: flex; align-items: center; gap: var(--ui-space-2); min-height: var(--ui-size-sm); }
.qa-badges { display: flex; flex-wrap: wrap; gap: var(--ui-space-1-5); flex: 1; min-width: 0; }
/* Dải badge xem trước của layout full nằm trong khối dọc, không phải hàng ngang
   như bản mini — bỏ flex:1 để nó không giành hết chiều cao còn lại. */
.qa-full-badges { flex: 0 0 auto; padding-top: var(--ui-space-2); }
.qa-full-badges:empty { display: none; }
.qa-link-btn {
  margin-left: auto; flex: 0 0 auto; padding: var(--ui-space-1) var(--ui-space-2); border: 0; border-radius: var(--ui-radius-control);
  background: none; color: var(--ui-accent); font-size: var(--fs-body); font-weight: var(--fw-semibold); cursor: pointer;
}
.qa-link-btn:hover { background: var(--ui-hover); }
.qa-mini-detail { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: var(--ui-space-2-5); align-items: start; }
.qa-mini-detail .form-group { display: flex; flex-direction: column; gap: var(--ui-space-1); min-width: 0; }
.qa-mini-detail .form-label {
  font-size: var(--fs-caption);
  font-weight: var(--fw-overline);
  line-height: var(--lh-overline);
  color: var(--ui-text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.qa-mini-detail .form-input, .qa-mini-detail .form-select {
  width: 100%; min-height: var(--ui-size-lg); height: var(--ui-size-lg); box-sizing: border-box; padding: 0 var(--ui-space-2-5);
  border: var(--ui-stroke-thin) solid var(--ui-divider); border-radius: var(--ui-radius-control);
  background: rgb(var(--ui-surface-raised-rgb)); color: var(--ui-text-primary);
  font: var(--fw-medium) var(--fs-body)/var(--lh-none) var(--app-font);
  cursor: pointer; outline: none;
  transition: border-color var(--ui-duration-fast) var(--ui-ease), box-shadow var(--ui-duration-fast) var(--ui-ease);
}
.qa-mini-detail .form-input:hover, .qa-mini-detail .form-select:hover {
  border-color: var(--ux-border); background: var(--ui-hover);
}
.qa-mini-detail .form-input:focus-visible, .qa-mini-detail .form-select:focus-visible {
  outline: var(--ui-focus-ring-width) solid var(--ui-focus-ring); outline-offset: var(--ui-focus-ring-offset);
}
.qa-dropdown-wrap { position: relative; width: 100%; }
.qa-select-btn {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%; min-height: var(--ui-control-h-standard); height: var(--ui-control-h-standard); padding: 0 var(--ui-space-2-5);
  border: var(--ui-stroke-thin) solid var(--ui-divider); border-radius: var(--ui-radius-control);
  background: rgb(var(--ui-surface-raised-rgb)); color: var(--ui-text-primary);
  font: var(--fw-medium) var(--fs-body)/var(--lh-none) var(--app-font); cursor: pointer; outline: none;
  text-align: left; user-select: none;
  transition: border-color var(--ui-duration-fast) var(--ui-ease), box-shadow var(--ui-duration-fast) var(--ui-ease);
}
.qa-select-btn:hover { border-color: var(--ux-border); background: var(--ui-hover); }
.qa-select-btn:focus-visible { outline: var(--ui-focus-ring-width) solid var(--ui-focus-ring); outline-offset: var(--ui-focus-ring-offset); }
.qa-select-text { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qa-select-arrow { flex: 0 0 auto; margin-left: var(--ui-space-1-5); font-size: var(--fs-micro); opacity: 0.65; transition: transform var(--ui-duration-fast) var(--ui-ease); }
.qa-select-btn[aria-expanded="true"] .qa-select-arrow { transform: rotate(180deg); }
.qa-dropdown-menu {
  position: absolute; top: calc(100% + var(--ui-space-1)); left: 0; min-width: 100%; width: max(100%, var(--dt-dimension-layout-208));
  z-index: var(--ui-layer-dropdown); padding: var(--ui-space-1); background: rgb(var(--ui-surface-raised-rgb));
  border: var(--ui-stroke-thin) solid var(--ui-divider); border-radius: var(--ui-radius-panel);
  box-shadow: var(--elev-4);
  display: flex; flex-direction: column; gap: var(--ui-space-0-5);
}
.qa-dropdown-group { display: flex; flex-direction: column; gap: var(--ui-space-0-5); }
.qa-dropdown-item {
  display: flex; align-items: center; width: 100%; padding: var(--ui-space-2) var(--ui-space-2-5);
  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; transition: background var(--ui-duration-fast) var(--ui-ease), color var(--ui-duration-fast) var(--ui-ease); white-space: nowrap;
}
.qa-dropdown-item:hover, .qa-dropdown-item:focus-visible {
  background: rgba(var(--ui-accent-rgb), 0.14); color: var(--ui-accent); outline: none;
}
.qa-dropdown-item.selected {
  background: rgba(var(--ui-accent-rgb), 0.18); color: var(--ui-accent); font-weight: var(--fw-semibold);
}
.qa-dropdown-divider { height: var(--ui-resizer-line); background: var(--ui-divider); margin: var(--ui-space-1) 0; }
.qa-date-custom-row { display: flex; align-items: center; gap: var(--ui-space-1-5); padding: var(--ui-space-1) var(--ui-space-1-5); }
.qa-date-custom-label { font: var(--fw-semibold) var(--fs-caption)/var(--lh-none) var(--app-font); color: var(--ui-text-secondary); white-space: nowrap; }
.qa-date-input { flex: 1 1 auto; height: var(--ui-size-md); min-height: var(--ui-size-md); padding: 0 var(--ui-space-1-5); font-size: var(--fs-body); }
.qa-hint { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ui-space-2); font-size: var(--fs-caption); color: var(--ui-text-secondary); opacity: .85; }
.qa-hint b { font-weight: var(--fw-bold); }
.qa-hint-sep { opacity: .45; }

/* ---- full: same panel as the day editor, but filling the window ---- */
body.layout-full .qa-full {
  width: 100%; max-width: none; height: 100%; max-height: none;
  border-radius: 0; box-shadow: none;
  display: flex; flex-direction: column;
}
.qa-full .edit-body {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.qa-full .card-list-container {
  flex: 1 1 auto;
  min-height: var(--dt-dimension-layout-104);
  display: flex;
  flex-direction: column;
}
.qa-full .draft-task-list {
  flex: 1 1 auto;
  min-height: 100%;
  display: flex;
  flex-direction: column;
}
.edit-subtitle {
  font-size: var(--fs-caption);
  color: var(--ui-text-secondary);
  line-height: var(--lh-normal);
}
.qa-empty-hint {
  margin: auto var(--ui-space-3-5);
  padding: 28px var(--ui-space-4); text-align: center; color: var(--ui-text-secondary); /* 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) */
  font-size: var(--fs-body); font-weight: var(--fw-medium);
  border: var(--ui-stroke-thick) dashed var(--ui-divider); border-radius: var(--ui-radius-panel);
}

/* ---- feedback ---- */
.qa-toast {
  position: fixed; left: 50%; bottom: var(--ui-space-3-5); transform: translateX(-50%);
}

/* Pressing the hotkey while a task form is already open nudges that form
   instead of opening a second one or toggling it shut mid-typing. Used by the
   popup itself (.qa-shake) and by the widget's day editor (.qa-nudge).
   Both animate `translate`, never `transform`: the day editor's panel and
   drawer are draggable and carry an inline transform, which a transform
   animation would override — snapping a dragged panel back to origin for the
   length of the shake. */
@keyframes qa-nudge {
  10%, 90% { translate: -2px 0; }
  20%, 80% { translate: 4px 0; }
  30%, 50%, 70% { translate: -6px 0; }
  40%, 60% { translate: 6px 0; }
}
.qa-shake, .qa-nudge { animation: qa-nudge .45s cubic-bezier(.36,.07,.19,.97) both; } /* audit-keep: chuyển động biên đạo riêng (keyframes), không thuộc nhịp giao diện chuẩn */
@keyframes input-shake-anim {
  0%, 100% { transform: translateX(0); }
  20%, 60% { transform: translateX(-4px); }
  40%, 80% { transform: translateX(4px); }
}
.input-shake {
  animation: input-shake-anim 0.4s ease both; /* audit-keep: nhịp riêng của hiệu ứng, không thuộc nhịp giao diện chuẩn */
  box-shadow: 0 0 0 var(--ui-focus-ring-width) color-mix(in srgb, var(--ui-danger) 25%, transparent);}

/* ---- settings: layout picker illustrations (widget window) ---- */
.quickadd-mode-picker { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--ui-space-2); margin-bottom: var(--ui-space-2-5); }
.pinmode-mock { font-size: var(--fs-title-lg); line-height: var(--lh-none); }

/* ---------- Widget menu (topbar "▾" — Ẩn / Cài đặt / ...) ---------- */
/* Mirrors .picker-wrap/.picker-panel's positioning/visual style exactly —
   same as that panel, no dedicated dark-mode override exists (established
   precedent in this file), so none is added here either. */
.view-mode-wrap { position: relative; -webkit-app-region: no-drag; display: flex; align-items: center; }

:root {
  /* Fluent's "page transition" band (200-300ms) rather than the 500ms this
     used to be — long enough to read as a directional slide, short enough
     that it doesn't leave a wide window for other work to visibly interrupt
     it mid-flight. Matches --modal-enter-duration's spirit (popups: .16s)
     scaled up for a full-viewport distance instead of a small panel. */
  --motion-duration-slide: 0.26s;
}

/* Dropdown menu (reuses .widget-menu-panel's positioning/background/open
   transition — same trigger-button-to-vertical-menu pattern as the "•••"
   widget menu right next to it, instead of a bespoke horizontal reveal). */
.widget-menu-item.view-mode-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-space-2);
}
.view-mode-option .view-mode-glyph {
  font-size: var(--fs-title);
  line-height: var(--lh-none);
}
.view-mode-option.is-active {
  background: var(--ui-selected);
  font-weight: var(--fw-semibold);
  color: var(--ui-accent);
}

.widget-menu-panel {
  position: absolute; top: var(--ui-space-10); right: 0; width: var(--dt-component-popover-standard-width);
  border: var(--ui-stroke-thin) solid var(--ux-border);
  padding: var(--ui-space-1);
  display: flex; flex-direction: column; gap: var(--ui-space-0-5);
}

/* Chế độ Che mờ Bảo vệ Riêng tư khi trình chiếu (Screen Share Privacy Blur) */
html.privacy-blur-active .task-title,
html.privacy-blur-active .task-text,
html.privacy-blur-active .task-desc,
html.privacy-blur-active .task-row-title,
html.privacy-blur-active .backlog-item-title,
html.privacy-blur-active .today-event-brief strong,
html.privacy-blur-active .today-event-title,
html.privacy-blur-active .today-next-text,
html.privacy-blur-active .today-note-editor,
html.privacy-blur-active .today-note-box .ql-editor,
html.privacy-blur-active .calendar-day-preview-text,
html.privacy-blur-active .project-task-text,
html.privacy-blur-active .project-note-card-title,
html.privacy-blur-active .notespeed-all-card-title,
html.privacy-blur-active .notespeed-all-card-snippet,
html.privacy-blur-active .notespeed-row-title,
html.privacy-blur-active .notespeed-col-project-label,
html.privacy-blur-active .notics-content,
html.privacy-blur-active .gcal-event-title,
html.privacy-blur-active .gcal-event-body,
html.privacy-blur-active .outlook-event-title,
html.privacy-blur-active .outlook-event-body,
html.privacy-blur-active .task-tag,
html.privacy-blur-active .task-tags,
html.privacy-blur-active .task-tag-more,
html.privacy-blur-active .calendar-item-footer-tags,
html.privacy-blur-active .event-tag,
html.privacy-blur-active .task-span-mirror .task-text,
html.privacy-blur-active .event-title,
html.privacy-blur-active .gcal-event-item.is-holiday,
html.privacy-blur-active .gcal-event-item.is-birthday {
  filter: blur(var(--dt-component-privacy-blur-radius, 6px));
  user-select: none;
  transition: filter var(--ui-duration-fast) var(--ui-ease);
}

.glass-icon-btn.is-active {
  color: var(--ui-accent);
  background: var(--ui-selected);
}

/* =====================================================================
   UNIFIED OVERLAY SYSTEM
   One semantic layer scale and one visual shell for popovers, dialogs,
   alerts and system prompts. JavaScript guarantees that only the top layer
   is interactive; these rules keep all design systems visually coherent.
   ===================================================================== */
.overlay { z-index: var(--layer-modal); isolation: isolate; }
.overlay[data-overlay-kind="modal"] { z-index: var(--layer-modal); }
.overlay[data-overlay-kind="alert"] { z-index: var(--layer-alert); }
.overlay[data-overlay-kind="system"] { z-index: var(--layer-system); }
.overlay[data-overlay-kind="modal"],
.overlay[data-overlay-kind="alert"],
.overlay[data-overlay-kind="system"] {
  display: flex; align-items: center; justify-content: center; padding: var(--ui-space-5);
  background: var(--modal-scrim);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.overlay.is-overlay-underlay {
  pointer-events: none;}
.overlay-panel,
.overlay-panel--sm,
.overlay-panel--md,
.overlay-panel--lg,
.overlay-panel--xl {
  color: var(--ui-text-primary);
  font-family: var(--app-font);
  font-size: var(--popup-content);
  line-height: var(--lh-normal);
  border: var(--ui-stroke-thin) solid var(--stroke);
  border-radius: var(--ui-radius-panel);
  background: var(--ux-overlay);
  box-shadow: var(--ui-shadow-geometry) rgba(var(--ui-shadow-rgb), var(--ui-shadow-alpha)); /* 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: overlay-enter var(--modal-enter-duration) var(--motion-standard) both;
  will-change: transform, opacity;
  transform: translateZ(0);
  contain: layout style;
}
@keyframes overlay-enter {
  from { opacity: 0; transform: translateY(6px) scale(.985); }
  to { opacity: 1; transform: none; }
}

/* Shared dialog shell: size presets (--sm/md/lg/xl) + header/body/footer
   scaffold, layered on top of .overlay-panel above. Content-specific popups
   (Quill editor chrome, form fields...) keep their own classes for what's
   unique to them; these classes standardize the header/body/footer internals
   so new popups reuse markup instead of hand-rolling it again. */
.overlay-panel--sm { width: min(var(--dt-component-dialog-small-max-width), 100%); }
.overlay-panel--md { width: min(var(--dt-component-dialog-medium-max-width), 100%); }
.overlay-panel--lg { width: min(var(--dt-component-dialog-large-max-width), 100%); }
.overlay-panel--xl { width: min(var(--dt-component-dialog-extra-large-max-width), 100%); }
.overlay-panel--sm, .overlay-panel--md, .overlay-panel--lg, .overlay-panel--xl {
  max-height: min(80vh, var(--dt-dimension-layout-800)); display: flex; flex-direction: column; overflow: hidden;
}

.overlay-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--ui-space-4);
  padding: var(--ui-space-5) var(--ui-space-6) var(--ui-space-4); border-bottom: var(--ui-stroke-thin) solid var(--stroke);
}
.overlay-head-main { min-width: 0; flex: 1; display: flex; align-items: flex-start; gap: var(--ui-space-3); }
.overlay-icon {
  width: var(--ui-size-lg); height: var(--ui-size-lg); flex: 0 0 auto; border-radius: var(--ui-radius-control);
  display: flex; align-items: center; justify-content: center; font-size: var(--fs-title); line-height: var(--lh-none);
  color: var(--ui-accent); background: rgba(var(--ui-accent-rgb), .12);
  border: var(--ui-stroke-thin) solid rgba(var(--ui-accent-rgb), .2);
}
.overlay-icon svg { width: var(--dt-dimension-icon-header); height: var(--dt-dimension-icon-header); display: block; }
.overlay-icon--danger { color: var(--ui-danger); background: rgba(var(--ui-danger-rgb), .14); border-color: rgba(var(--ui-danger-rgb), .2); }
.overlay-icon--warning { color: var(--ui-warning); background: var(--ui-warning-bg); border-color: var(--ui-warning-line); }
.overlay-icon--success { color: var(--ui-success); background: rgba(var(--ui-success-rgb), .14); border-color: rgba(var(--ui-success-rgb), .2); }

.overlay-head-body { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: var(--ui-space-1); }
.overlay-eyebrow {
  color: var(--ui-text-muted); font-size: var(--fs-caption); font-weight: var(--fw-overline); }
.overlay-title {
  margin: 0; color: var(--ui-text-primary); font-size: var(--popup-title); font-weight: var(--fw-semibold); line-height: var(--lh-snug);
  overflow-wrap: anywhere; word-break: break-word;
}
.overlay-desc { margin: 0; color: var(--ui-text-secondary); font-size: var(--fs-body); line-height: var(--lh-normal); }
/* Ghi chú làm rõ phạm vi thật của một tính năng bảo mật (vd. Mật khẩu Master
   Notics chỉ ẩn hiển thị, không mã hóa tệp) — dùng tông cảnh báo nhẹ để người
   dùng không lướt qua như một câu mô tả bình thường, nhưng không đỏ gắt như lỗi. */
.notics-security-caveat {
  margin-top: var(--ui-space-2); padding: var(--ui-space-2) var(--ui-space-2-5); border-radius: var(--ui-radius-control);
  background: var(--ui-warning-bg); border: var(--ui-stroke-thin) solid var(--ui-warning-line);
  color: var(--ui-warning);
}

/* .overlay-close: chỉ còn là móc JS cho nút đóng dialog — dáng theo .ui-btn
   .ui-btn--subtle .ui-btn--icon (ui-components.css), cùng kiểu nút đóng Notebook/task. */

.overlay-body { flex: 1; min-height: 0; overflow-y: auto; padding: var(--ui-space-4-5) var(--ui-space-6); }

.overlay-foot {
  display: flex; align-items: center; gap: var(--ui-space-3);
  padding: var(--ui-space-3) var(--ui-space-6) var(--ui-space-4); border-top: var(--ui-stroke-thin) solid var(--stroke);
  background: var(--ux-fill);
}
.overlay-hint { display: inline-flex; align-items: center; gap: var(--ui-space-1); color: var(--ui-text-muted); font-size: var(--fs-caption); }
.overlay-foot-actions { display: flex; align-items: center; gap: var(--ui-space-2); margin-left: auto; }
@media (max-width: 520px) {
  .overlay-head { padding: var(--ui-space-3-5) var(--ui-space-4) var(--ui-space-3); }
  .overlay-body { padding: var(--ui-space-3) var(--ui-space-4); }
  .overlay-foot { padding: var(--ui-space-2-5) var(--ui-space-4) var(--ui-space-3); }
  .overlay-hint { display: none; }
}
.overlay-foot-actions :is(.ui-btn) {
  min-height: var(--ui-control-h-standard);
  height: var(--ui-control-h-standard);
  padding: 0 var(--ui-space-3);
  font-size: var(--fs-body);
  border-radius: var(--ui-radius-control);
  font-weight: var(--fw-semibold);
  box-sizing: border-box;
}

/* Reusable single-choice list inside the shared overlay shell. It deliberately
   inherits the same card, row, accent, radius and focus tokens as every other
   AntiTask dialog instead of introducing a feature-specific popup palette. */
.choice-dialog-options { display: grid; gap: var(--ui-density-gap); }
.choice-dialog-option {
  width: 100%; min-height: var(--ui-size-lg); padding: var(--ui-density-pad-row) var(--ui-density-pad-card);
  display: flex; align-items: center; gap: var(--ui-density-pad-row); text-align: left;
  color: var(--ui-text-primary); font: inherit; font-size: var(--fs-body); font-weight: var(--fw-semibold);
  border: var(--ui-stroke-thin) solid var(--stroke); border-radius: var(--ui-radius-control);
  background: var(--ux-fill); cursor: pointer;
  transition: border-color var(--ui-duration-fast) var(--ui-ease), background var(--ui-duration-fast) var(--ui-ease), color var(--ui-duration-fast) var(--ui-ease);
}
.choice-dialog-option:hover { background: var(--ux-fill); color: var(--ui-accent); }
.choice-dialog-option.is-selected {
  color: var(--ui-text-primary); border-color: color-mix(in srgb, var(--ui-accent) 72%, var(--stroke));
  background: color-mix(in srgb, var(--ui-accent) 13%, rgb(var(--ui-surface-raised-rgb)));
}
.choice-dialog-mark {
  width: var(--ui-icon-sm); height: var(--ui-icon-sm); flex: 0 0 auto; box-sizing: border-box;
  border: var(--ui-stroke-thin) solid rgba(var(--ink), .28); border-radius: var(--dt-dimension-radius-full);
  background: var(--ux-overlay);
}
.choice-dialog-option.is-selected .choice-dialog-mark {
  border: var(--ui-stroke-thickest) solid var(--ui-accent); background: var(--ux-overlay);
}
.choice-dialog-option:focus-visible { outline: var(--ui-stroke-thick) solid var(--ui-accent); outline-offset: var(--ui-stroke-thick); }

/* Reminders are modeless notifications. They wait while a blocking dialog is
   open, then appear at the lower-right without disabling the calendar. */
.overlay[data-overlay-kind="notification"] {
  z-index: var(--layer-notification);
  display: flex; align-items: flex-end; justify-content: flex-end;
  padding: var(--ui-space-5); pointer-events: none;
  background: transparent; backdrop-filter: none; -webkit-backdrop-filter: none;
}
.overlay[data-overlay-kind="notification"] :is(.overlay-panel, .overlay-panel--sm, .overlay-panel--md, .overlay-panel--lg, .overlay-panel--xl) {
  width: min(var(--dt-dimension-layout-400), calc(100vw - var(--ui-space-10))); pointer-events: auto;
  box-shadow: var(--elev-4);
}

/* The settings workspace consumes modern Fluent/Liquid Glass tokens. */
#menuOverlay :is(.settings-option-copy strong, .help-grid strong, .profile-name, .profile-hero-name) { color: var(--ui-text-primary); }
#menuOverlay :is(.settings-card-head p, .settings-option-copy small, .help-grid p, .settings-sidebar-label, .profile-state, .profile-hero-email) { color: var(--ui-text-secondary); }


/* Dialog chrome and actions share the same geometry across every popup. */
.overlay :is(.edit-header, .event-modal-header, .drawer-header) { border-color: var(--stroke); }
.overlay :is(.edit-footer, .event-modal-footer, .drawer-footer) {
  border-color: var(--stroke); background: var(--ux-fill);
}
#deleteSeriesConfirmBtn { background: var(--ui-danger); color: rgb(var(--ui-surface-raised-rgb)); box-shadow: 0 5px 14px rgba(var(--ui-danger-rgb), .22); } /* audit-keep: quầng sáng màu trạng thái (glow), không phải bậc độ nổi */
#deleteSeriesConfirmBtn:hover { background: color-mix(in srgb, var(--ui-danger) 86%, var(--ui-mix-shade)); }

/* Item details are a local side sheet inside the day editor. The parent's
   header/footer remain visible for context but are dimmed and non-interactive. */
.edit-body { position: static; }
.edit-panel.detail-sheet-open::after {
  display: none;
}
.edit-panel.detail-sheet-open .edit-body {
  overflow: hidden;
}
.item-detail-drawer {
  position: absolute; inset: 0;
  width: 100%; max-width: 100%; height: 100%; max-height: 100%;
  border-width: 0; border-radius: var(--ui-radius-panel);
  box-shadow: none;
  z-index: var(--ui-layer-pane);
  background: var(--ux-overlay);
  display: flex; flex-direction: column; overflow: hidden;
  will-change: opacity;
  transform: none;
}
.item-detail-drawer .drawer-header { cursor: default; }

/* When the calendar opens "Chỉnh sửa chi tiết", this same form is a
   first-class task dialog. Hide the day-level quick-add/list UI so it cannot
   be mistaken for task creation; the detail form remains the modal's focus
   target and its Save action closes back to the calendar. */
.edit-panel.standalone-task-edit {
  width: min(var(--dt-dimension-layout-880), calc(100vw - var(--ui-space-8)));
  height: min(82vh, var(--dt-dimension-layout-720));
}
.edit-panel.standalone-task-edit > :not(.edit-body) { display: none; }
.edit-panel.standalone-task-edit .edit-body { display: block; padding: 0; overflow: visible; }
.edit-panel.standalone-task-edit .edit-body > :not(.item-detail-drawer) { display: none; }
.edit-panel.standalone-task-edit::after { display: none; }
.edit-panel.standalone-task-edit .item-detail-drawer {
  position: static; width: 100%; max-width: none; height: 100%; max-height: none;
  border: 0; border-radius: var(--ui-radius-panel); box-shadow: none;
}
@keyframes side-sheet-enter {
  from { opacity: .7; transform: translateX(28px); }
  to { opacity: 1; transform: none; }
}

/* Liquid Glass needs a larger luminance gap between work-in-progress and
   completed rows. The generic 8% tint was too close to the muted done plate. */
html[data-material="glass"] .draft-card-item.editing {
  background: color-mix(in srgb, var(--ui-accent) 12%, var(--ux-fill));
  border-color: var(--ui-accent);
}

.picker-panel, .widget-menu-panel, .priority-picker-panel { z-index: var(--layer-popover); }
.picker-panel, .widget-menu-panel, .priority-picker-panel {
  color: var(--ui-text-primary); background: var(--ux-overlay);
  border-radius: var(--ui-radius-panel);
}
.widget-menu-divider, .priority-picker-divider { background: var(--stroke); }
.qa-toast { z-index: var(--layer-toast); }

@media (max-width: 900px) {
  .item-detail-drawer { left: auto; width: 100%; border-left: 0; border-radius: var(--ui-radius-panel); }
}
@media (prefers-reduced-motion: reduce) {
  }
.widget-menu-item {
  display: flex; align-items: center; gap: var(--ui-space-1-5);
  border: none; background: transparent; text-align: left;
  font-size: var(--fs-body); font-weight: var(--fw-semibold);
  padding: var(--ui-space-1) var(--ui-space-1-5); min-height: var(--ui-size-sm); cursor: pointer;
}
.widget-menu-item:hover { background: var(--ui-action-hover); }
.widget-menu-item.is-disabled { cursor: default; }
.widget-menu-item.is-disabled:hover { background: transparent; }
.widget-menu-item small { display: none; }
#widgetMenuPanel .widget-menu-item > span:not(.widget-menu-icon) { margin-left: auto; }
.widget-menu-icon {
  display: flex; align-items: center; justify-content: center;
  flex: 0 0 auto; width: var(--ui-icon-md); height: var(--ui-icon-md); color: var(--ui-text-secondary); font-size: var(--fs-body); line-height: var(--lh-none);
}
.widget-menu-icon svg { width: var(--ui-icon-xs); height: var(--ui-icon-xs); }
.widget-menu-item.is-disabled .widget-menu-icon { opacity: .6; }
.widget-menu-divider { height: var(--ui-resizer-line); margin: var(--ui-space-1) var(--ui-space-0-5); }


@media (prefers-reduced-motion: reduce) {
  .qa-shake, .qa-nudge { animation: none; }
}

/* Kept last because the widget-menu item rules live below the shared overlay
   block for historical reasons. These token overrides must win in every mode. */
.widget-menu-panel { color: var(--ui-text-primary); background: var(--ux-overlay); border-radius: var(--ui-radius-panel); }
.widget-menu-item { color: var(--ui-text-primary); border-radius: var(--ui-radius-control); }
.widget-menu-item:hover:not(:disabled) { background: rgba(var(--ui-surface-fill-rgb), .86); }
.widget-menu-item.is-disabled, .widget-menu-item small { color: var(--ui-text-secondary); }
.widget-menu-divider { background: var(--stroke); }

/* =====================================================================
   MAIN CALENDAR OVERHAUL
   A single calm work surface replaces the former stack of day cards. The
   three design systems share layout, hierarchy and interaction timing; only
   their surface, shape and depth tokens differ.
   ===================================================================== */
:root {
  --ui-focus-ring: color-mix(in srgb, var(--ui-accent) 58%, transparent);
  --ui-divider: rgba(var(--ink), .12);
  --ui-hover: var(--ui-action-hover);
  --ui-selected: color-mix(in srgb, var(--ui-accent) 12%, transparent);
  --ui-success-soft: rgba(var(--ui-success-rgb), .08);
  --ui-event-fill: rgba(var(--ui-accent-rgb), .11);
  --ui-event-hover: rgba(var(--ui-accent-rgb), .17);
  --ui-event-text: var(--ui-brand-outlook);
  --ui-birthday-fill: var(--ui-category-pink-bg);
  --ui-birthday-text: var(--ui-category-pink-fg);
  --ui-row-height: max(34px, calc(var(--task-row-height) - 8px));
}

html:not([data-material="glass"]) {
  --ui-divider: rgba(var(--ink), .12);
  --ui-hover: var(--ui-action-hover);
}
html[data-material="glass"] {
  --ui-divider: rgba(var(--ink), .14);
  --ui-hover: var(--ui-action-hover);
  --ui-success-soft: rgba(var(--ui-success-rgb), .08);
  --ui-event-fill: rgba(var(--ui-accent-rgb), .11);
  --ui-event-hover: rgba(var(--ui-accent-rgb), .17);
  --ui-event-text: var(--ui-brand-outlook);
  --ui-birthday-fill: var(--ui-category-pink-bg);
  --ui-birthday-text: var(--ui-category-pink-fg);
}
html[data-mode="dark"] {
  --ui-divider: rgba(var(--ui-white-rgb), .11);
  --ui-hover: var(--ui-action-hover);
  --ui-success-soft: rgba(var(--ui-success-rgb), .10);
  --ui-event-fill: rgba(var(--ui-accent-rgb), .16);
  --ui-event-hover: rgba(var(--ui-accent-rgb), .24);
  --ui-event-text: var(--ui-brand-outlook);
  --ui-birthday-fill: var(--ui-category-pink-bg);
  --ui-birthday-text: var(--ui-category-pink-fg);
}

.app {
  background: rgba(var(--ui-surface-shell-rgb), calc(1 + (0.22 - 1) * var(--t)));
  border-color: transparent;
  box-shadow: 0 18px 52px rgba(var(--ui-shadow-rgb), calc(var(--ui-shadow-alpha) * .78)); /* audit-keep: bóng riêng của thành phần, không thuộc bậc elevation chuẩn */
}
html[data-material="glass"] .app {
  border-radius: var(--sf-radius-win);
}

/* Header: one information group and one compact command dock. */
.topbar {
  height: var(--app-header-height);
  min-height: var(--app-header-height);
  max-height: var(--app-header-height);
  box-sizing: border-box;
  gap: var(--ui-space-2);
  padding: 0 var(--ui-space-3);
  border-bottom: var(--ui-resizer-line) solid var(--ux-divider);
  background: var(--ux-header);
  box-shadow: none;
}
.topbar-left { flex: 0 1 auto; display: flex; align-items: center; gap: var(--ui-space-2); }
.icon-btn,
.picker-btn {
  border-color: transparent;
  background: transparent;
  box-shadow: none;
  text-shadow: none;
}
html[data-material="glass"] .week-nav-cluster {
  background: transparent;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
 /* 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 */
.icon-btn { width: var(--ui-size-sm); height: var(--ui-size-sm); border-radius: var(--ui-radius-sm); }
/* Vô hiệu trong thực tế: nút "Tuần này" duy nhất dùng class này luôn nằm
   trong .week-nav-cluster, và selector .week-nav-cluster .picker-btn (đặc
   trưng 0,2,0) thắng bare .picker-btn ở đây (0,1,0) bất kể ai khai báo sau.
   Cỡ nút thật sự do khối đó quyết định — xem comment ở .week-nav-cluster
   .picker-btn phía dưới file. Vẫn giữ nhân --font-scale ở đây cho nhất quán,
   phòng khi có nơi khác dùng bare .picker-btn ngoài .week-nav-cluster sau này. */
.picker-btn { width: var(--dt-dimension-layout-112); min-width: var(--dt-dimension-layout-112); max-width: var(--dt-dimension-layout-112); box-sizing: border-box; height: var(--ui-size-sm); border-radius: var(--ui-radius-sm); }
.picker-icon-wrap { background: var(--ui-selected); }
.icon-btn:hover,
.picker-btn:hover,
.picker-btn[aria-expanded="true"],
.icon-btn[aria-expanded="true"] {
  color: var(--ui-text-primary);
  background: var(--ui-hover);
  border-color: transparent;
  box-shadow: none;
  transform: none;
}
.icon-btn:active,
.picker-btn:active { transform: none !important; }
.grid.multi-week {
  --rail-w: 52px;
  --cell-gap: 0px;
  --head-h: 36px;
}
.multi-week-corner,
.shared-day-label {
  justify-content: flex-start;
  padding: 0 var(--ui-space-2-5);
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-caps-lg);
}

/* Events retain a restrained tint; tasks become flat interactive rows. */
.gcal-event-item:active,
.outlook-event-item:active { transform: none !important; }
/* Chuẩn Flat Surface (calendar.css MỤC D/E): dòng Tháng, Tuần/Ngày/Danh sách phẳng đã
   không nền lúc nghỉ qua --task-row-bg, nên luật đơn sắc KHÔNG áp cho chúng —
   nếu áp, `transparent !important` của nó nuốt luôn nền hover. Khi đó nguồn nền
   duy nhất là luật .item-tone-* ngay dưới, đọc --task-row-bg. */
.monochrome-task-rows .task-item:not(:is(#grid.multi-week, html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"])) .task-item),
html:root.monochrome-task-rows .task-item:not(.done):not(:is(#grid.multi-week, html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"])) .task-item),
html:root.monochrome-task-rows .task-item.done:not(:is(#grid.multi-week, html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"])) .task-item),
html[data-material="glass"]:root.monochrome-task-rows .task-item:not(.done):not(:is(#grid.multi-week, html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"])) .task-item),
html[data-material="glass"]:root.monochrome-task-rows .task-item.done:not(:is(#grid.multi-week, html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"])) .task-item) {
  box-shadow: none;}
/* One background source for every rendered task/event. This sits after the
   legacy monochrome compatibility rules so the current per-item assignment
   cannot be overwritten by a view or appearance setting. */
.task-item:not(.dragging):hover,
.task-item:focus-within {
  padding-right: 34px; /* audit-keep: chừa chỗ cho icon/nút cuối ô nhập, rộng theo nút */
  /* Nền thẻ GIỮ NGUYÊN màu pastel lúc nghỉ khi hover (xem rule .item-tone-*
     !important ở trên). Trước đây dòng `background: var(--ui-hover) !important`
     ở đây ép thẻ thành vệt xám phẳng — chính là cái "đổi độ đục/sáng" cần bỏ. */
}
.task-item:not(.dragging):hover::before { box-shadow: none; }
.task-item.dragging {
  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 */
  opacity: .76;
  transform: translateY(-3px) scale(1.008);
  box-shadow: var(--elev-3);}
.task-item.mode-number .task-text,
.task-item.mode-bullet .task-text { margin-left: 0; }
.task-item.mode-text:hover .task-text,
.task-item.mode-text:focus-within .task-text,
.task-item.mode-number:hover .task-text,
.task-item.mode-number:focus-within .task-text,
.task-item.mode-bullet:hover .task-text,
.task-item.mode-bullet:focus-within .task-text { transform: none; }
.task-item.done { color: var(--ui-text-muted); }
.task-item.done .task-text { color: var(--done-ink); }

/* Week and Multi-week share the same bright day-card primitive. The white
   workspace remains neutral; border + elevation distinguish cards without a
   grey gutter or grey fill. */
.grid[data-view-mode="week"] {
  gap: var(--ui-space-2-5);
  padding: var(--ui-space-2-5);
  background: var(--ux-base);
}

.grid.multi-week {
  --cell-gap: var(--ui-density-gap);
  --head-h: calc(var(--fs-body) + var(--ui-density-pad-card) * 2);
  background: var(--ux-base);
  grid-template-rows: var(--head-h) repeat(var(--multi-week-count), minmax(0, 1fr));
  overflow-y: hidden;
}

/* Popovers, drawers and dialogs use the same state language as the calendar. */
.picker-panel,
.widget-menu-panel,
.priority-picker-panel,
:is(.overlay-panel, .overlay-panel--sm, .overlay-panel--md, .overlay-panel--lg, .overlay-panel--xl) {
  border-color: var(--ui-divider);
  box-shadow: var(--elev-4);
}
html[data-material="glass"] :is(.picker-panel, .widget-menu-panel, .priority-picker-panel, .overlay-panel, .overlay-panel--sm, .overlay-panel--md, .overlay-panel--lg, .overlay-panel--xl) {
  background: var(--ux-overlay);
  backdrop-filter: blur(24px) saturate(1.32);
  -webkit-backdrop-filter: blur(24px) saturate(1.32);
  box-shadow: 0 18px 46px rgba(var(--ui-shadow-rgb), .24), inset 0 1px 0 rgba(var(--ui-white-rgb),.28); /* audit-keep: viền/vạch trong dựng bằng bóng inset, độ dày là hình học của viền */
}
:is(.icon-btn, .picker-btn, .completed-toggle, .task-box, .gcal-event-item, .outlook-event-item):focus-visible {
  outline: var(--ui-stroke-thick) solid var(--ui-focus-ring);
  outline-offset: var(--ui-stroke-thin);
}

@media (max-width: 960px) {
  .topbar { padding-inline: var(--ui-space-2-5); }
  .grid,
  .grid.multi-week { padding-inline: var(--ui-space-2); }
  .multi-week-corner,
  .shared-day-label { padding-inline: var(--ui-space-2); }
  .task-list { padding-inline: var(--ui-space-1); }
}
@media (max-width: 760px) {
  .topbar { min-height: var(--app-header-height); }
  .grid.multi-week { --rail-w: 42px; }
  .shared-day-label { font-size: var(--fs-micro); }
}
@media (prefers-reduced-motion: reduce) {
    .grid.calendar-refreshing,
  .task-item.dragging,
  .gcal-event-item:active,
  .outlook-event-item:active,
  .icon-btn:active,
  .picker-btn:active { transform: none !important; }
}

/* =====================================================================
   DESIGN-SYSTEM REFINEMENT
   Keep the shared information architecture, but give Fluent and
   Liquid Glass separate surface, shape, depth and state signatures.
   ===================================================================== */
:root {
  /* At slider 100 the outer window may reveal the desktop, while the work
     surface still retains roughly 90% opacity. Text never sits directly on
     wallpaper, so maximum transparency remains usable. */
  /* Nay --t-content CHỈ còn một chỗ dùng: --shade-k, tức độ đậm của bóng chữ
     khi bề mặt mỏng đi. Toàn bộ bề mặt đã chuyển sang thang --ux-* nên công
     thức này không còn quyết định màu nền của thứ gì.
     Vì thế trả nó về đúng nghĩa mà chú thích gốc mô tả — nghịch đảo của
     --a-content (0 · .02 · .12 · .22) — thay cho `--t × .07` (0 · .018 · .039
     · .056) vốn gần như bằng 0 ở mọi bậc, khiến bóng chữ không bao giờ bật
     lên dù bề mặt đã trong hẳn. */
  --t-content: calc(1 - var(--a-content));
  /* Focus ô nhập = viền 1px đổi sang mực trung tính đậm
     (--ux-control-border-active = border.focus), không quầng sáng/đổ bóng và
     không tô xanh — theo shadcn/ui, Vercel Geist, Notion, Claude.ai.
     Ring giữ dạng lớp bóng trong suốt (không phải `none`) để các consumer
     ghép danh sách `var(--x-shadow), var(--ui-control-ring)` vẫn hợp lệ.
     Khối không có viền riêng (ô ghi chú trong ngày dạng phẳng) dùng
     --ui-surface-focus-line: đúng 1px inset cùng màu. */
  --ui-control-ring: 0 0 0 0 transparent;
  --ui-surface-focus-line: inset 0 0 0 var(--ui-space-px) var(--ux-control-border-active);
}

/* Long work items grow naturally instead of being irreversibly ellipsized. */
.gcal-event-title,
.outlook-event-title {
  display: -webkit-box;
  overflow: hidden;
  white-space: normal;
  text-overflow: ellipsis;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  line-height: var(--lh-snug);
  overflow-wrap: anywhere;
}

@keyframes nowDotPulse {
  0%, 100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.35;
    transform: scale(0.85);
  }
}
/* Ngày thường mà trống thì co vừa phải (.78) — vẫn phải đủ rộng để kéo-thả một
   việc vào và để đọc được tên thứ. Cuối tuần trống co mạnh hơn (.58) vì nó ít
   khi là đích của thao tác. */
/* Hai luật co bề ngang ngày trống (.day-col.is-quiet { flex: .78/.58 }) đã bị
   gỡ: .grid là CSS Grid nên `flex` trên ô ngày không có tác dụng — tính năng
   này chưa từng chạy dù có đủ class trong JS lẫn chú thích giải trình. BA chốt
   2026-09-11 giữ bảy cột bằng nhau, nên gỡ hẳn thay vì dựng lại bằng grid. */

/* Nhãn hai dòng trong nút chọn kỳ: dòng trên là kỳ ("Tuần này"), dòng dưới
   là số việc/lịch của đúng kỳ đó. Đặt sau mọi khối .picker-* phía trên vì
   nút này đã bị ghi đè qua nhiều đợt thiết kế; khai ở cuối là chắc thắng
   mà không phải gỡ từng khối cũ ra. */
.picker-btn { overflow: hidden; }
.picker-label-stack {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
}
.picker-label-stack .picker-label,
.picker-label {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: center;
  /* lh bằng cỡ chữ + overflow:hidden cắt dấu và chân chữ tiếng Việt ("Tuần này"). */
  line-height: var(--lh-caption);
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  color: var(--ui-text-primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* =====================================================================
   CỠ CHỮ HÀNG VIỆC THEO TỪNG DẠNG XEM — VÀ CẢ HỌ SỐ ĐO ĐI KÈM

   MÔ HÌNH QUỐC TẾ (Material density · Apple Dynamic Type · Carbon type set):
   MỘT ramp duy nhất (--fs-title/body/body-sm/caption ở đầu file), mỗi dạng
   xem CHỌN MỘT BẬC — không nhân hệ số tự do như bản cũ (.68/.74/.86 khiến
   chữ việc dạng Tháng còn ~10px, nhỏ hơn cả dòng ngày-giờ 12px của thẻ ghi
   chú ngay cạnh).

     Ngày / Agenda → --fs-body     (14px — BẰNG nội dung thẻ ghi chú)
     Tuần          → --fs-body-sm  (13px — tụt đúng một bậc)
     Tháng         → --fs-caption  (12px — SÀN, tụt hai bậc; dừng ở đây,
                                    ô chật thì "+N nữa" lo phần tràn)

   Cả ba bậc đã gồm × --font-scale × --content-scale, nên kéo ô "Cỡ chữ
   công việc" là task LẪN ghi chú nở cùng nhịp — một nguồn sự thật.

   Khối thứ hai bên dưới: mọi số đo còn lại của hàng việc (giờ giấc, icon,
   khe hở, làn số, ô tick) vẫn suy ra từ --task-effective-font của CHÍNH
   dạng xem, nên tự co theo bậc đã chọn. Phải khai lại trên .grid chứ không
   chỉ ở :root — custom property giải ngay tại phần tử khai báo.
   ===================================================================== */
:root { --task-effective-font: var(--fs-body); }
.grid[data-view-mode="week"] { --task-effective-font: var(--fs-body); }
.grid.multi-week { --task-effective-font: var(--fs-caption); }

:root,
.grid {
  /* Giờ giấc đứng CÙNG DÒNG tên việc → cùng cỡ, cùng baseline; phân biệt
     bằng màu (--tone-orange-fg) + độ đậm, không bằng cỡ chữ. */
  --task-meta-font: var(--task-effective-font);
  --task-meeting-font: var(--task-effective-font);
  --task-icon-size: calc(var(--task-effective-font) * 1.05);
  --task-icon-svg-size: calc(var(--task-effective-font) * .92);
  /* Khe hở trong một hàng đo bằng cỡ chữ của chính hàng đó. Bản cũ chốt
     cứng 8px, ở dạng Tuần (chữ ~11px) thành ra rộng bằng ba ký tự. */
  --task-icon-gap: calc(var(--task-effective-font) * .3);
  --task-inline-gap: calc(var(--task-effective-font) * .45);
  --task-prefix-lane: calc(var(--task-effective-font) * 1.5);
  --task-control-size: calc(var(--task-effective-font) * 1.45);
  --task-control-font: calc(var(--task-effective-font) * .92);
}

/* =====================================================================
   DẠNG THÁNG — MA TRẬN PHẲNG (DESIGN TOKENS)

   Mỗi ô ngày là một card sáng, dùng đúng surface/elevation của bộ chọn tuần.
   Khoảng cách nhỏ giữ được mật độ cao; task chip vẫn là lớp màu ngữ nghĩa
   nằm trên card ngày trắng.
   ===================================================================== */
.grid.multi-week {
  /* Làn số tuần và hàng tên thứ là hai "trục" của ma trận: dùng CHUNG một cỡ
     để góc trên-trái vuông và hai trục cân nhau, đồng thời thu nhỏ để nhường
     chỗ cho ô ngày. Cỡ bám --fs-xs nên vẫn co giãn theo trục chữ. */
  --month-axis-size: calc(var(--fs-caption) * 2 + var(--ui-space-1));
  --rail-w: var(--month-axis-size);
  --cell-gap: 6px;
  --head-h: var(--month-axis-size);
  gap: var(--cell-gap);
  padding: 0 var(--ui-space-2-5) var(--ui-space-2-5);
}
/* Ngày thuộc tháng liền kề hiện việc của nó Ở ĐỘ RÕ BÌNH THƯỜNG.

   Bản đầu của L9 làm nhạt các thẻ việc (opacity .55) để phân biệt với ngày
   trong tháng. Trên nền kính trong suốt phủ hình nền, giảm alpha một thẻ vốn
   đã bán trong suốt khiến nó trông như lỗi vẽ chứ không như một dấu hiệu cố ý.

   Dấu hiệu "ngày của tháng khác" đã đủ và đúng chuẩn: SỐ NGÀY được làm mờ
   (quy tắc ngay bên trên). Google Calendar cũng vậy — chỉ số ngày xám đi, còn
   sự kiện giữ nguyên độ rõ. */

/* Task Item & Event Item dải pastel chuẩn Token (Không border, màu nền pastel rõ ràng) */
.grid.multi-week .task-item,
.grid.multi-week :is(.gcal-event-item, .outlook-event-item),
.monochrome-task-rows .grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item),
html[data-material="glass"].monochrome-task-rows .grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item),
html:root.monochrome-task-rows .grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item) {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: calc(var(--ui-space-1) * 1.25);
  min-height: 0;
  height: calc((var(--fs-caption) - var(--ui-resizer-line)) * var(--lh-tight) + var(--ui-space-1-5));
  padding: var(--ui-space-0-5) var(--ui-density-pad-card) var(--ui-space-0-5) calc(var(--ui-space-1) * 1.25);
  border-radius: var(--ui-radius-sm);
  margin: 0;
  box-shadow: none;
  cursor: pointer;
  overflow: hidden;
  position: relative;}

/* Đồng bộ kích thước và padding của slot icon cho cả task và event (gần nhau hơn) */
.grid.multi-week :is(.task-prefix-slot, .event-prefix-slot) {
  position: static;
  flex: 0 0 var(--month-lead-lane, var(--ui-space-1));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: center;
  padding: 0;
  margin: 0;
  line-height: 1;}

/* Priority remains a small semantic marker. It must never recolour the row. */




/* One compact, stable title line; the native tooltip exposes the full text.
   line-height 1.4 (không phải 1.2): dấu ngã chồng dấu mũ trên chữ hoa tiếng
   Việt (Ẫ/Ễ/Ẩ…) cần hộp dòng cao hơn cỡ chữ ~1.33 lần mới đủ chỗ cho mực chữ
   thật — dưới ngưỡng đó `.task-item { overflow: hidden }` cắt mất phần dấu
   cao nhất, chữ hoa nhìn như mất dấu (ví dụ "MẪU" còn "MÂU"). */
.grid.multi-week :is(.task-text, .gcal-event-title, .outlook-event-title) {
  align-self: center;
  font-size: var(--task-effective-font);
  font-weight: var(--fw-normal);
  color: var(--ui-text-primary);
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;}

/* Cạnh ưu tiên: một thanh bo tròn thụt vào, thống nhất ở cả ba dạng xem.
   Bản cũ là dải vuông chạy hết chiều cao hàng, mỗi dạng xem lại đặt một
   kiểu (4 khối .priority-edge chồng nhau trong file này). Khai ở đây,
   sau cả 4 khối đó, để một định nghĩa duy nhất thắng ở mọi dạng xem. */
.monochrome-task-rows .priority-edge { width: var(--dt-component-calendar-item-priority-edge-width); }

/* =====================================================================
   MẬT ĐỘ HÀNG VIỆC — DẠNG TUẦN & DẠNG NGÀY
   .task-item là MỘT component dùng chung cho cả 4 dạng xem, với sàn
   min-height: var(--ui-row-height) = max(34px, --task-row-height − 8).
   Sàn đó sinh ra cho dạng Ngày (hàng thưa, dễ bấm) rồi bị áp luôn cho
   dạng Tuần, nơi cột chỉ rộng ~200px — hàng cao 34px+ mà chữ 15px thì
   mỗi việc chiếm 2 dòng và một cột chỉ chứa nổi 4–5 việc.
   Thiết kế mẫu dùng ba đặc tả riêng: ~32px cho Tuần, ~36px cho Ngày,
   ~19px cho Tháng. Khối này đặt lại cho Tuần và Ngày (Tháng đã có khối
   riêng ở trên).
   ===================================================================== */
/* Tỉ lệ hoàn tất nay chỉ nói MỘT lần, ở chân cột cạnh thanh tiến độ (chip
   done/total ở đầu cột đã gỡ). Trước đây cùng một sự thật được in ba lần
   trong một cột: chip "4/4" đầu cột, dòng "Đã hoàn tất 4", và thanh xanh
   đầy ở đáy — mà con số dưới đáy lại bị ẩn nên thanh đó thành một vệt màu
   không có chú giải. Xem hợp đồng chân cột ở styles/calendar.css MỤC C. */

/* Cụm 4 nút dạng xem (.view-segment) đã bỏ khỏi topbar (BA 10/10/2026): mọi khổ dùng
   một nút "Tuần ▾" (#viewModeBtn + menu). */

/* =====================================================================
   PANEL TÌM KIẾM + LỌC DỰ ÁN
   Kế thừa nền/viền/bóng/hiệu ứng mở của .picker-panel, chỉ ghi đè neo và
   bề rộng. Các thuộc tính này trước đây nằm trong style="" ngay trên thẻ
   ở index.html nên không theo token nào — chuyển hết vào đây.
   ===================================================================== */
.tag-filter-panel {
  top: calc(100% + var(--ui-space-1));
  right: auto;
  left: 0;
  display: flex;
  flex-direction: column;
  gap: var(--ui-density-gap);
  width: var(--dt-component-popover-filter-width);
  max-height: 60vh;
  overflow-y: auto;
  padding: var(--ui-density-pad-card);
}
/* Ô nhập giờ là một hàng bình thường trong panel. Bản cũ cho nó nở ngang
   0 → 160px ngay trên topbar; ở đây bề rộng do panel quyết định nên xoá
   hẳn phần hoạt ảnh bề rộng, tránh nó co lại thành 0 khi class
   .collapsed còn sót lại từ lần đóng trước. */
.tag-filter-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-density-gap);
  padding: var(--ui-space-0-5) var(--ui-space-1);
}
#tagFilterLabel {
  color: var(--ui-text-muted);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-caps-lg);
}
#clearTagFilterBtn {
  border: none;
  background: none;
  color: var(--ui-accent);
  font-family: inherit;
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  padding: var(--ui-space-0-5) var(--ui-space-1);
  border-radius: var(--ui-radius-control);
}
#clearTagFilterBtn:hover { background: var(--ui-hover); }
#tagFilterList {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--ui-space-1-5);
  padding: var(--ui-space-0-5) var(--ui-space-1);
}

.tag-filter-legend {
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-1);
  padding: var(--ui-density-pad-row) var(--ui-space-1) var(--ui-space-0-5);
  border-top: var(--ui-stroke-thin) solid var(--stroke);
}
.tag-filter-legend-title {
  color: var(--ui-text-muted);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-caps-lg);
}
.legend-row {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  color: var(--ui-text-secondary);
  font-size: var(--fs-caption);
  line-height: var(--lh-tight);
}
.legend-row svg {
  flex: 0 0 auto;
  width: var(--ui-icon-xs);
  height: var(--ui-icon-xs);
  color: var(--ui-text-muted);
}
/* Mẫu hai kênh màu: sọc dọc là cạnh ưu tiên của hàng việc, chấm tròn là
   màu dự án trên nhãn — đúng hai thứ mà dòng chữ bên cạnh đang mô tả. */
.legend-swatch {
  position: relative;
  flex: 0 0 auto;
  width: var(--ui-icon-xs);
  height: var(--ui-icon-xs);
}
.legend-swatch::before {
  content: '';
  position: absolute;
  left: var(--ui-space-px);
  top: var(--ui-space-px);
  bottom: var(--ui-space-px);
  width: var(--ui-space-1);
  border-radius: var(--ui-radius-xs);
  background: var(--tone-orange-fg, var(--ui-accent));
}
.legend-swatch::after {
  content: '';
  position: absolute;
  right: 0;
  top: 50%;
  width: var(--ui-space-1);
  height: var(--ui-space-1);
  margin-top: calc(-1 * var(--ui-space-0-5));
  border-radius: var(--ui-radius-circle);
  background: var(--ui-accent);
}

.tag-filter-actions {
  display: flex;
  flex-direction: column;
  gap: var(--ui-density-gap);
  padding: var(--ui-density-pad-row) var(--ui-space-1) var(--ui-space-0-5);
  border-top: var(--ui-stroke-thin) solid var(--stroke);
}
.tag-filter-action-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--ui-space-2);
  width: 100%;
  padding: var(--ui-space-1-5) var(--ui-space-3);
  border: var(--ui-stroke-thin) solid var(--stroke);
  border-radius: var(--ui-radius-control);
  background: var(--ux-raised);
  color: var(--ui-text-primary);
  font-family: inherit;
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  cursor: pointer;
  transition: background var(--ui-duration-fast) var(--ui-ease), border-color var(--ui-duration-fast) var(--ui-ease), color var(--ui-duration-fast) var(--ui-ease);
}
.tag-filter-action-btn:hover {
  background: var(--ui-hover);
  border-color: var(--ux-border-hover);
  color: var(--ui-text-primary);
}
.tag-filter-action-btn svg {
  flex: 0 0 auto;
  width: var(--ui-icon-dense);
  height: var(--ui-icon-dense);
  color: currentColor;
}

/* Shared UX language for editors, dialogs, popovers and Quick Add. */
:is(.quick-task-input, .draft-input, .form-input, .form-select, .text-input) {
  color: var(--ui-text-primary);
  border-color: var(--ui-divider);
  background: var(--ux-input-bg);
  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);
}
:is(.quick-task-input, .draft-input, .form-input, .form-select, .text-input):focus {
  color: var(--ui-text-primary);
  border-color: var(--ux-control-border-active);
  background: var(--ux-input-bg);
  box-shadow: var(--ui-control-ring);
  caret-color: var(--ui-accent);
  outline: none;
}
:is(.btn-join-meeting) {
  border-color: transparent;
  background: var(--ui-accent-solid);
  color: var(--ui-text-on-accent);
}
:is(.btn-join-meeting):hover {
  filter: brightness(1.06);
  transform: none;
}
:is(.draft-card-item, .event-info-item, .repeat-editor) {
  border-color: var(--ui-divider);
}
.draft-card-item {
  height: auto;
  border: 0;
  border-bottom: var(--ui-stroke-thin) solid var(--ui-divider);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}
.draft-task-list { gap: 0; border-top: var(--ui-stroke-thin) solid var(--ui-divider); }
.draft-card-item:last-child { border-bottom: 0; }
.draft-card-item:hover { border-color: var(--ui-divider); background: var(--ui-hover); box-shadow: none; }
.draft-card-text { white-space: normal; overflow-wrap: anywhere; }
.event-info-list { gap: 0; }
.event-info-item {
  padding-inline: var(--ui-space-1);
  border: 0;
  border-bottom: var(--ui-stroke-thin) solid light-dark(var(--ui-divider), rgba(var(--ui-white-rgb), 0.06));
  border-radius: 0;
  background: light-dark(transparent, rgba(var(--ui-white-rgb), 0.04));
}
.event-info-item:last-child { border-bottom: 0; }

.badge-day { color: light-dark(var(--ui-accent), var(--ui-category-purple-fg)); background: light-dark(var(--ui-selected), var(--ui-category-purple-bg)); }

/* Fluent: neutral acrylic, compact rectangular controls and hairline depth. */
/* Bo góc cửa sổ chỉ có MỘT nguồn là --ui-radius-window (ui-tokens.css) — nếu
   khai báo lại ở đây thì selector này (specificity cao hơn .app) sẽ âm thầm
   đè token và Fluent lệch khỏi hệ. */
html:not([data-material="glass"]) .app { border-radius: var(--ui-radius-window); }
html:not([data-material="glass"]) .topbar {
  height: var(--app-header-height);
  min-height: var(--app-header-height);
  max-height: var(--app-header-height);
  box-sizing: border-box;
  background: var(--ux-header);
  border-bottom-color: rgba(var(--ink), calc(var(--ui-stroke-alpha) * .7));
  box-shadow: none;
}
html:not([data-material="glass"]) .week-nav-cluster {
  border: var(--ui-stroke-thin) solid transparent;
  border-radius: var(--dt-dimension-radius-full);
  background: transparent;
  box-shadow: none;
}
html:not([data-material="glass"]) :is(.icon-btn, .picker-btn) { border-radius: var(--ui-radius-control); }
html:not([data-material="glass"]) .grid {
  background: var(--ux-base);
}
html:not([data-material="glass"]) :is(
  .edit-panel.expanded-edit-panel, .event-modal-panel, .settings-page, .overlay-panel, .overlay-panel--sm,
  .overlay-panel--md, .overlay-panel--lg, .overlay-panel--xl
) {
  border: var(--ui-stroke-thin) solid var(--ui-divider);
  border-radius: var(--ui-radius-control);
  background: rgb(var(--ui-surface-raised-rgb));
  box-shadow: var(--elev-3);
}
/* Ba hộp thả xuống tách ra khỏi danh sách trên, đối xứng với khối Glass bên
   dưới. Lý do là ĐỘ ƯU TIÊN chứ không phải màu: :is() lấy specificity của
   nhánh NẶNG NHẤT, mà .edit-panel.expanded-edit-panel là hai class — nên cả
   khối trên nặng (0,3,1) và đè mất khối "BO GÓC LỚP NỔI" (0,2,1) trong
   ui-components.css. Tách ra thì bo góc của dropdown chỉ còn một nguồn.
   Chỉ giữ lại độ dày/kiểu viền: nền, màu viền và đổ bóng của ba hộp này đã do
   khối popup trong ui-components.css quy định (và ép ưu tiên), khai lại ở đây
   là code chết. */
html:not([data-material="glass"]) :is(.picker-panel, .widget-menu-panel, .priority-picker-panel) {
  border: var(--ui-stroke-thin) solid var(--ui-divider);
}
html:not([data-material="glass"]) :is(.edit-header, .drawer-header, .event-modal-footer) {
  background: var(--ux-fill);
}
html:not([data-material="glass"]) .qa-body { background: rgb(var(--ui-surface-raised-rgb)); }
html:not([data-material="glass"]) .qa-mini {
  height: 100%;
  box-sizing: border-box;
  border: var(--ui-stroke-thin) solid var(--ui-divider);
  border-radius: var(--ui-radius-control);
  background: rgb(var(--ui-surface-raised-rgb));
  box-shadow: inset 0 1px 0 light-dark(rgba(var(--ui-white-rgb),.55), 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 */
}

/* Liquid Glass: layered translucency, specular edges and blur, with a safe
   content-opacity floor so wallpaper never competes with work text. */
html[data-material="glass"] .app {
  background:
    radial-gradient(circle at 82% -8%, rgba(var(--ui-module-art-rgb),.21), transparent 34%),
    radial-gradient(circle at 7% 110%, rgba(var(--ui-module-paint-rgb),.13), transparent 40%),
    rgba(var(--ui-surface-shell-rgb), calc(1 + (.34 - 1) * var(--t)));
  border-color: transparent;
  box-shadow: var(--app-glass-shadow);
}
html[data-material="glass"] .topbar {
  height: var(--app-header-height);
  min-height: var(--app-header-height);
  max-height: var(--app-header-height);
  box-sizing: border-box;
  margin: var(--ui-space-2) var(--ui-space-2) 0;
  border: var(--ui-stroke-thin) solid rgba(var(--ui-white-rgb),.44);
  border-radius: 0;
  background: rgba(var(--ui-surface-raised-rgb), .88);
  backdrop-filter: blur(28px) saturate(1.35);
  -webkit-backdrop-filter: blur(28px) saturate(1.35);
}
html[data-material="glass"] .grid {
  min-height: 0;
  margin: var(--ui-space-1-5) var(--ui-space-2) var(--ui-space-2);
  padding: 0 var(--ui-space-2) var(--ui-space-2);
  border: var(--ui-stroke-thin) solid rgba(var(--ui-white-rgb),.30);
  border-radius: var(--ui-radius-panel);
  background: rgba(var(--ui-surface-raised-rgb), .96);
  box-shadow: inset 0 1px 0 rgba(var(--ui-white-rgb),.30); /* 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 */
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
/* Notics/Project chưa từng có style riêng cho hệ Glass nên rơi về viền/bo góc/
   margin/shadow mặc định (dùng chung cho mọi hệ) — viền mờ hơn (alpha .196 so
   với .30) và box-shadow là drop-shadow mờ thay vì inset highlight kiểu kính
   như .grid. Lặp lại y hệt style .grid ở trên để 3 tab đồng bộ dưới hệ Glass. */
html[data-material="glass"] :is(.notics-page, .project-page) {
  margin: var(--ui-space-1-5) var(--ui-space-2) var(--ui-space-2);
  border: var(--ui-stroke-thin) solid rgba(var(--ui-white-rgb),.30);
  border-radius: var(--ui-radius-panel);
  background: rgba(var(--ui-surface-raised-rgb), .96);
  box-shadow: inset 0 1px 0 rgba(var(--ui-white-rgb),.30); /* 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 */
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
/* The system-specific `.grid` rules above (fluent/glass) all
   repaint the grid surface with --sf-card. Week/multi-week's day cards and
   the today/agenda workspace panels (.today-main, .today-backlog-rail,
   .today-rail-card, .agenda-day — all painted with --view-panel-bg, itself
   built from --sf-card) sit directly on that same surface, so at the default
   opaque setting box and page resolve to the literal same rgb() value: zero
   contrast in every system and mode. Those system rules outrank a plain
   view-mode selector on specificity, so the recessed --sf-chrome tone has to
   be restored here, after them, for every alternate view alike. */
html :is(.grid[data-view-mode="week"], .grid.multi-week, .grid.today-view, .grid.agenda-view) {
  /* --a-shell, not the content formula: this paints the gutters between day
     cards, and gutters carry no text. Holding it to the content floor was what
     made the glass step barely visible with the wallpaper off — the grid veil
     sat on top of the shell veil and the two composited back to nearly opaque
     across the whole calendar area. */
  background: rgba(var(--ui-surface-shell-rgb), var(--a-shell));
}
/* Day, Week and Month all sit on the product's white Light canvas. Their
   shared day-card shadow supplies separation, so no grey recessed gutter is
   needed behind them. */
html :is(.grid[data-view-mode="week"], .grid.multi-week, .grid.today-view) {
  background: var(--ux-base);
}


html[data-material="glass"] :is(
  .edit-panel.expanded-edit-panel, .event-modal-panel, .settings-page, .overlay-panel, .overlay-panel--sm,
  .overlay-panel--md, .overlay-panel--lg, .overlay-panel--xl
) {
  border: var(--ui-stroke-thin) solid rgba(var(--ui-white-rgb),.38);
  border-radius: var(--ui-radius-panel);
  background: rgba(var(--ui-surface-raised-rgb), .94);
  box-shadow: 0 22px 62px rgba(var(--ui-shadow-rgb), .28), inset 0 1px 0 rgba(var(--ui-white-rgb),.50); /* audit-keep: viền/vạch trong dựng bằng bóng inset, độ dày là hình học của viền */
  backdrop-filter: blur(30px) saturate(1.36);
  -webkit-backdrop-filter: blur(30px) saturate(1.36);
}
/* Trang Cài đặt là trang làm việc toàn khung (như Notics/Project), không phải
   lớp nổi: blur phủ cả tấm buộc vẽ lại mỗi lần cuộn — đo 30–66ms/khung khi
   không có GPU compositing, menu cuộn giật (BA 28/09/2026). Hình nền đã được
   làm mờ sẵn ở .app-bg-image. `.app >` cho cùng độ ưu tiên với khối trên. */
html[data-material="glass"] .app > .settings-page {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
/* Ba hộp thả xuống tách khỏi danh sách trên (xem lý do ở khối Fluent tương
   ứng). Riêng ở Glass còn một lỗi thật: khối kia bo theo --sf-radius-win —
   token khung CỬA SỔ, = 0px ở cả bốn theme — nên menu avatar, panel lọc dự án
   và priority picker ra hình VUÔNG. Bo góc nay đến từ khối "BO GÓC LỚP NỔI"
   trong ui-components.css, một nguồn cho cả 20 dropdown.
   Giữ lại đúng hai thứ chưa có ai khai hộ: viền kính và lớp blur. */
html[data-material="glass"] :is(.picker-panel, .widget-menu-panel, .priority-picker-panel) {
  border: var(--ui-stroke-thin) solid rgba(var(--ui-white-rgb),.38);
  backdrop-filter: blur(30px) saturate(1.36);
  -webkit-backdrop-filter: blur(30px) saturate(1.36);
}
/* Popup "Quản lý công việc ngày" tách khỏi hai khối :is() ở trên vì cùng lỗi:
   khối Glass bo theo --sf-radius-win (= 0px, token khung cửa sổ) nên popup ra
   hình VUÔNG, còn khối Fluent bám --sf-radius-row lệch bậc với modal/drawer.
   Kéo về --ui-radius-panel — đúng token lớp nổi mà .overlay-panel--* và mọi
   dropdown đang dùng. Specificity (0,3,1) hòa với hai khối kia, thắng nhờ đứng
   sau trong file. */
html[data-material="glass"] .edit-panel.expanded-edit-panel,
html:not([data-material="glass"]) .edit-panel.expanded-edit-panel {
  border-radius: var(--ui-radius-panel);
}
html[data-material="glass"] :is(.edit-header, .drawer-header, .event-modal-footer) {
  background: var(--ux-fill);
  box-shadow: inset 0 1px 0 rgba(var(--ui-white-rgb),.34); /* 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 */
}
html[data-material="glass"] .qa-body {
  background:
    radial-gradient(circle at 84% 0%, rgba(var(--ui-module-art-rgb),.16), transparent 42%),
    rgb(var(--ui-surface-raised-rgb));
}
html[data-material="glass"] .qa-mini {
  height: 100%;
  box-sizing: border-box;
  border: var(--ui-stroke-thin) solid rgba(var(--ui-white-rgb),.42);
  border-radius: var(--ui-radius-panel);
  background: rgba(var(--ui-surface-raised-rgb), .94);
  box-shadow: var(--qa-mini-glass-shadow);
  backdrop-filter: blur(24px) saturate(1.30);
  -webkit-backdrop-filter: blur(24px) saturate(1.30);
}

/* Kính: highlight + độ sâu của khung Quick Add theo chế độ (Tối chỉ còn highlight mảnh). */
:root { --qa-mini-glass-shadow: inset 0 1px 0 rgba(var(--ui-white-rgb),.62), 0 12px 36px rgba(var(--ui-shadow-rgb), .18); } /* 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 */
html[data-mode="dark"] { --qa-mini-glass-shadow: inset 0 1px 0 rgba(var(--ui-white-rgb),.12); } /* 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 */
html[data-mode="dark"] :is(.quick-task-input, .draft-input, .form-input, .form-select, .text-input) {
  background: var(--ux-input-bg);
  border-color: var(--ui-divider);
}

@media (prefers-reduced-motion: reduce) {
  }

/* Maximum slider transparency ---------------------------------------------
   Calendar cards collapse onto one shared surface at this setting. The final
   override below keeps that shared surface 10% opaque (90% transparent), so
   the desktop remains visible without placing text directly on the wallpaper. */

/* =====================================================================
   DASHBOARD
   A full in-window view: the calendar remains mounted so returning is instant,
   while the dashboard owns the scroll area below the shared title bar.
   ===================================================================== */
#dashboardBtn[aria-pressed="true"] {
  color: var(--ui-accent);
  background: color-mix(in srgb, var(--ui-accent) 15%, transparent);
}
/* Chỉ hiển thị tìm kiếm, chọn tuần và chọn dạng xem ở màn hình TASK (calendar).
   Ở các module khác (Notics, Project, Settings, Dashboard...), ẩn hết và chỉ để lại nút "..." */
html:not([data-view="calendar"]) :is(.tag-filter-wrap, .week-nav-cluster, .view-mode-wrap, .view-segment) {
  display: none !important;
}

/* Strict full-page view isolation: guarantee that only the active view renders */
html[data-view="calendar"] :is(#noticsPage, #dashboardPage, #projectPage, #settingsPage) { display: none !important; }
html[data-view="notics"] :is(#grid, #dashboardPage, #projectPage, #settingsPage) { display: none !important; }
html[data-view="dashboard"] :is(#grid, #noticsPage, #projectPage, #settingsPage) { display: none !important; }
html[data-view="project"] :is(#grid, #noticsPage, #dashboardPage, #settingsPage) { display: none !important; }
html[data-view="settings"] :is(#grid, #noticsPage, #dashboardPage, #projectPage) { display: none !important; }
html[data-view="feedbackAdmin"] :is(#grid, #noticsPage, #dashboardPage, #projectPage, #settingsPage, #premiumPage) { display: none !important; }

/* [MODULARIZED] Dashboard styles moved to src/renderer/styles/dashboard.css */

/* =====================================================================
   TODAY HIGHLIGHT OVERRIDES (For all systems: Fluent, Glass)
   ===================================================================== */
:root { --today-highlight-border: transparent; }

@keyframes gravityDrop {
  0% {
    transform: translateY(-100px) scale(1.02);
    opacity: 0;
  }
  30% {
    opacity: 1;
  }
  80% {
    transform: translateY(5px) scale(0.98);
  }
  90% {
    transform: translateY(-2px) scale(1);
  }
  100% {
    transform: translateY(0) scale(1);
  }
}

@keyframes antiGravityRise {
  0% {
    transform: translateY(30px) scale(0.95);
    opacity: 0;
  }
  100% {
    transform: translateY(0) scale(1);
    opacity: 1;
  }
}
/* Chữ căn TRÁI ở mọi dạng xem lịch.
   Bản cũ căn đều hai bên ("nhịp đọc như đoạn văn Word"). Nhịp đó chỉ đúng với
   cột văn bản rộng. Làn chữ của một thẻ việc dạng Tuần chỉ ~160px, cắt còn 2
   dòng: căn đều buộc trình duyệt giãn khoảng trắng của dòng 1 để chạm mép
   phải, sinh ra "sông chữ" — mỗi thẻ giãn một kiểu khác nhau, và đó là phần
   lớn cảm giác lộn xộn của lưới tuần. */
.task-text,
.gcal-event-title,
.outlook-event-title {
  text-align: left;
  text-align-last: auto;
  text-justify: auto;
}

/* Today and Agenda are reading views; Week and Multi-week stay denser. */
.grid.agenda-view .agenda-day :is(.task-item, .gcal-event-item, .outlook-event-item),
html.monochrome-task-rows .grid.agenda-view .agenda-day .task-item {
  /* Mẫu dùng hàng ~36px cho dạng Ngày (đệm 6px + nội dung). Sàn 46px cũ
     cao hơn hẳn và là thứ khiến dạng Ngày nhìn "to quá". */
  min-height: 0;
  padding-top: var(--ui-space-1-5);
  padding-right: 44px; /* audit-keep: chừa chỗ cho icon/nút cuối ô nhập, rộng theo nút */
  padding-bottom: var(--ui-space-1-5);
}
/* Week and Month views only (the Day view's own layout below is untouched):
   the checkbox and the "..." action are taken out of the row's flex flow
   and float over the text instead of reserving fixed space for it, so the
   task text gets the row's full width at rest. Both stay invisible/inert
   until the row is hovered or focused, at which point they fade in at
   their normal tap-friendly size — briefly overlapping the text at the two
   edges, which only happens while the user is already pointing at that
   row. The per-task background pill is also dropped (transparent by
   default, a faint tint only on hover) since it no longer needs to frame
   a permanently-visible checkbox lane. */

/* The prefix slot stays in normal flow so the number/bullet remains visible
   at rest. Only the checkbox (task-box) inside it is hidden, then revealed
   on hover to overlay the prefix mark. This keeps the numbered list readable
   while still offering the completion target on hover. */
:is(.grid[data-view-mode="week"], .grid.multi-week) .task-prefix-slot {
  position: relative;
  width: var(--ui-size-dense);
  min-width: var(--ui-size-dense);
  flex-basis: var(--ui-size-dense);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: var(--ui-layer-sticky);
}
/* Keep text indent for number/bullet modes so the prefix lane has room.
   The hover transform that used to shift text is disabled since the prefix
   slot now stays in flow and the checkbox floats on top. */
:is(.grid[data-view-mode="week"], .grid.multi-week) .task-item.mode-text:hover .task-text,
:is(.grid[data-view-mode="week"], .grid.multi-week) .task-item.mode-text:focus-within .task-text,
:is(.grid[data-view-mode="week"], .grid.multi-week) .task-item.mode-number:hover .task-text,
:is(.grid[data-view-mode="week"], .grid.multi-week) .task-item.mode-number:focus-within .task-text,
:is(.grid[data-view-mode="week"], .grid.multi-week) .task-item.mode-bullet:hover .task-text,
:is(.grid[data-view-mode="week"], .grid.multi-week) .task-item.mode-bullet:focus-within .task-text {
  transform: none;
}

/* Priority is a persistent three-pixel edge. Time and repeat stay inline;
   the note icon is status-only and the bell appears only for an alert.
   Flush to the row's full height, square-cornered, so it reads as one
   straight line instead of a short rounded pill. Left stays inset by
   default — .today-backlog-rail (the "Trễ hạn" list) clips its content to
   its own large rounded corner (overflow + border-radius), and the last
   row has no bottom padding, so a flush marker on the bottom item would
   get clipped into a curve there. Task/event rows override to a true
   flush left below, since those rows are squared off themselves. */
.calendar-priority-choice.is-normal .calendar-priority-dot { background: var(--tone-blue-bar); }
.calendar-priority-choice.is-important .calendar-priority-dot { background: var(--tone-orange-bar); }
.calendar-priority-choice.is-urgent .calendar-priority-dot { background: var(--ui-danger); }
.calendar-priority-choice.is-urgent:focus-visible,
.calendar-priority-choice.is-urgent.is-selected { border-color: color-mix(in srgb, var(--ui-danger) 55%, var(--ui-divider)); box-shadow: 0 0 0 var(--ui-focus-ring-width) color-mix(in srgb, var(--ui-danger) 25%, transparent); }
.task-tags-compact { gap: var(--ui-space-0-5); margin-left: var(--ui-space-1); }

/* Priority selection uses the same compact card language as the action menu. */
.priority-picker-panel {
  z-index: calc(var(--layer-popover, 1200) + 2);
  min-width: var(--dt-component-popover-priority-min-width);
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--ui-space-1-5);
  padding: var(--ui-space-3);
  border-radius: var(--ui-radius-panel);
}
.priority-picker-panel::before {
  content: 'ĐỘ ƯU TIÊN';
  grid-column: 1 / -1;
  color: var(--ui-text-muted);
  font: var(--fw-semibold) var(--fs-micro)/var(--lh-tight) var(--app-font);
  letter-spacing: var(--ls-caps);
}
.priority-picker-option {
  flex-direction: column;
  justify-content: center;
  gap: var(--ui-space-1);
  border: var(--ui-stroke-thin) solid var(--ui-divider);
  border-radius: var(--ui-radius-panel);
  font-size: var(--fs-caption);
}
.priority-picker-option span:not(.priority-dot) { flex: 0; font-size: var(--fs-caption); text-align: center; }
.priority-picker-option .priority-dot { width: var(--ui-space-2-5); height: var(--ui-space-2-5); }
.priority-picker-divider { display: none; }
.priority-picker-clear { grid-column: 1 / -1; min-height: var(--ui-size-md); flex-direction: row; border: 0; color: var(--ui-text-secondary); }
.priority-picker-option {
  min-height: var(--ui-size-lg);
  padding: var(--ui-space-2) var(--ui-space-3);
}

/* =====================================================================
   TOPBAR VIEW ACTIONS
   The view switcher, Dashboard and overflow menu are deliberately one
   control family: equal 36px targets, clear gaps and semantic colour.
   ===================================================================== */
.topbar-right {
  gap: var(--ui-space-1-5);
  /* Cao = control header (24), KHÔNG phải size.lg 40 còn sót từ topbar 48: khối 40
     trong topbar 32 làm hàng lưới nở 40, cả hàng tiêu đề Notebook/Project/Art
     Editor/Cài đặt trôi xuống ~4.8px so với tâm (BA báo lệch 10/10/2026). */
  height: var(--ui-header-control-size);
  align-items: center;
}
.week-nav-cluster {
  height: var(--ui-size-md);
  gap: var(--ui-space-0-5);
  padding: var(--ui-space-0-5);
  border-radius: var(--dt-dimension-radius-full);
  border: var(--ui-stroke-thin) solid transparent;
  background: transparent;
  box-shadow: none;
  display: flex;
  align-items: center;
}
.week-nav-cluster .icon-btn,
.week-nav-cluster .picker-btn {
  height: var(--ui-size-sm);
}
.week-nav-cluster .icon-btn {
  width: var(--ui-size-dense);
  border-radius: var(--ui-radius-circle);
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.week-nav-cluster .icon-btn svg {
  width: var(--ui-icon-sm);
  height: var(--ui-icon-sm);
}
.week-nav-cluster .picker-btn {
  /* Selector này (đặc trưng 0,2,0) thắng bare .picker-btn ở đầu file, nên đây
     mới là chỗ thật sự quyết định độ rộng nút "Tuần này". Icon/chevron bên
     trong giữ nguyên cỡ cố định (đúng token riêng cho icon), chỉ nới BOX ngoài
     theo --font-scale để .picker-label — vốn dùng --fs-xs, có nhân hệ số —
     có đủ chỗ. Không nới thì ở 200% chữ "Tuần này" bị cắt cả hai đầu vì
     white-space: nowrap không có ellipsis. */
  width: var(--dt-dimension-layout-128);
  min-width: var(--dt-dimension-layout-128);
  max-width: var(--dt-dimension-layout-128);
  box-sizing: border-box;
  padding: 0 var(--ui-space-1-5);
  border-radius: var(--dt-dimension-radius-full);
  gap: var(--ui-space-1);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.week-nav-cluster .picker-btn .picker-icon-wrap {
  flex: 0 0 var(--ui-icon-md);
  width: var(--ui-icon-md);
  height: var(--ui-icon-md);
  border-radius: var(--ui-radius-sm);
  display: grid;
  place-items: center;
  align-self: center;
}
.week-nav-cluster .picker-btn .nav-icon {
  width: var(--ui-icon-sm);
  height: var(--ui-icon-sm);
}
.week-nav-cluster .picker-btn .picker-chevron {
  flex: 0 0 var(--ui-icon-xs);
  width: var(--ui-icon-xs);
  height: var(--ui-icon-xs);
  align-self: center;
}

.view-mode-wrap { flex: 0 0 auto; }


/* View choices retain their colour in the menu, making the four layouts
   recognisable before the user reads their labels. */
.view-mode-option[data-calendar-view] {
  min-height: var(--ui-size-lg);
  gap: var(--ui-space-2-5);
}
.view-mode-option[data-calendar-view] .view-mode-glyph {
  display: grid;
  width: var(--ui-icon-lg);
  height: var(--ui-icon-lg);
  flex: 0 0 var(--ui-icon-lg);
  place-items: center;
  border-radius: var(--ui-radius-control);
}
.view-mode-option[data-calendar-view] .view-mode-glyph svg {
  width: var(--ui-icon-sm);
  height: var(--ui-icon-sm);
}
.view-mode-option[data-calendar-view="today"] .view-mode-glyph { color: var(--tone-blue-fg); background: var(--tone-blue-bg); }
.view-mode-option[data-calendar-view="week"] .view-mode-glyph { color: var(--tone-purple-fg); background: var(--tone-purple-bg); }
.view-mode-option[data-calendar-view="agenda"] .view-mode-glyph { color: var(--tone-green-fg); background: var(--tone-green-bg); }
.view-mode-option[data-calendar-view="multiWeek"] .view-mode-glyph { color: var(--tone-orange-fg); background: var(--tone-orange-bg); }

@media (max-width: 820px) {
  .topbar-right { gap: var(--ui-space-1-5); }
  .week-nav-cluster .picker-btn { width: var(--dt-dimension-layout-120); min-width: var(--dt-dimension-layout-120); max-width: var(--dt-dimension-layout-120); padding: 0 var(--ui-space-1); }
}


.glass-icon-btn {
  width: var(--ui-size-md);
  height: var(--ui-size-md);
  box-shadow: var(--elev-1);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: var(--ui-text-secondary);
  transition: transform var(--ui-duration-fast), background var(--ui-duration-fast), border-color var(--ui-duration-fast);
  -webkit-app-region: no-drag;}
.glass-icon-btn svg {
  width: var(--ui-icon-sm);
  height: var(--ui-icon-sm);
}
.glass-icon-btn:hover {
  transform: none;}

#tagFilterToggle {
  overflow: hidden;}
/* #tagFilterToggle.hidden-icon đã bỏ: nút kính lúp giờ là điểm neo của
   panel tìm kiếm nên phải luôn thấy. Thu nó về width 0 chính là nguồn
   của cú dịch topbar mà panel này sinh ra để loại bỏ. */

/* Directional slide transition for view-mode switches, dashboard/notics open/close,
   and week/day navigation. #grid, #dashboardPage, and #noticsPage are mutually exclusive full-page
   views, so sharing one view-transition-name morphs cleanly between them. */
#dashboardPage, #noticsPage { view-transition-name: main-content; }

/* The transition overlay covers the whole viewport as a fixed layer while
   active; without this it swallows pointer events (hover, mousemove) meant
   for real chrome sitting elsewhere on the page — e.g. the topbar's
   view-mode hover menu — for the entire animation duration, reading as a
   spurious mouseleave that closes menus mid-hover. */
::view-transition,
::view-transition-group(*),
::view-transition-image-pair(*),
::view-transition-old(*),
::view-transition-new(*) {
  pointer-events: none;
}

::view-transition-group(main-content) {
  animation-duration: var(--motion-duration-slide);
  /* The group's own box is sized/positioned to exactly match #grid's
     on-screen rect (right below the header) — but the sliding old/new
     images inside it are otherwise free to paint outside that box while
     animating, which is exactly what let the vertical slide visually
     bleed up into the header instead of staying confined below it. */
  overflow: hidden;
}
::view-transition-image-pair(main-content) {
  overflow: hidden;
}
::view-transition-old(main-content),
::view-transition-new(main-content) {
  mix-blend-mode: normal;
}
/* Each of old/new keeps exactly one curve for its whole run — same
   no-mid-animation-stitching rule as before (a curve switch partway through
   a single element's animation is a velocity discontinuity, which reads as a
   hitch). old and new are two separate elements animating concurrently
   though, not one continuous timeline, so giving each its own curve isn't
   that stitch: it's Fluent's standard decelerate-in/accelerate-out pairing,
   the same pairing .overlay-panel's --motion-standard already uses for
   popups — the outgoing view speeds away instead of lingering, the incoming
   one settles into place instead of snapping to speed immediately. */
::view-transition-old(main-content) { animation-timing-function: var(--motion-accelerate); }
::view-transition-new(main-content) { animation-timing-function: var(--motion-standard); }

/* Vertical, direction-aware: forward slides the new content up from below
   (old content continues up and out the top); backward mirrors it downward. */
html[data-transition-dir="forward"]::view-transition-old(main-content) { animation-name: vt-out-up; }
html[data-transition-dir="forward"]::view-transition-new(main-content) { animation-name: vt-in-up; }
html[data-transition-dir="backward"]::view-transition-old(main-content) { animation-name: vt-out-down; }
html[data-transition-dir="backward"]::view-transition-new(main-content) { animation-name: vt-in-down; }

@keyframes vt-out-up   { to   { transform: translateY(-30%); opacity: 0; } }
@keyframes vt-out-down { to   { transform: translateY(30%);  opacity: 0; } }
@keyframes vt-in-up    { from { transform: translateY(30%);  opacity: 0; } to { transform: translateY(0); opacity: 1; } }
@keyframes vt-in-down  { from { transform: translateY(-30%); opacity: 0; } to { transform: translateY(0); opacity: 1; } }

/* Same policy as .overlay-panel (see the prefers-reduced-motion block near
   its definition): views should swap instantly, no slide, when the user has
   asked the OS for reduced motion. */
@media (prefers-reduced-motion: reduce) {
  }

/* [MODULARIZED] Notics & Premium styles moved to notics.css and premium.css */

/* =====================================================================
   APP WALLPAPER & FROSTED GLASS BACKGROUND
   ===================================================================== */
.app-background {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 0;
  border-radius: inherit;
}

.app-bg-image {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  transition: background var(--ui-duration-standard) var(--ui-ease);
}

/* MICA: làm mờ CHÍNH lớp hình nền một lần theo bậc vật liệu (--glass-blur 0 ở
   Đục → không đổi gì). Nhờ vậy các thẻ bán trong suốt phía trên chỉ nhận màu
   nền đã dịu, không nhận chi tiết ảnh lấm tấm — rẻ hơn nhiều so với
   backdrop-filter trên từng thẻ. Tràn ra ngoài đúng hai lần bán kính mờ để mép
   ảnh không bị nhạt; .app-background đã overflow:hidden. Chế độ xem ảnh
   (.is-image-canvas) phải thấy ảnh gốc nên không áp. */
html:not(.is-image-canvas) .app-bg-image {
  inset: calc(var(--glass-blur) * -2);
  filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
}

/* The scrim. This is the half of the readability contract that lives on the
   wallpaper rather than on the surfaces: it raises the floor of what can ever
   sit behind a card, so --a-content is composited against a bounded backdrop
   instead of against whatever the user happened to pick. A photo with a black
   region is what pushed secondary text under WCAG AA before this existed.

   Tinted toward the theme's own paper colour, not neutral grey, so a light
   theme over a dark photo still reads as a light theme. */
.app-bg-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: rgba(var(--ui-surface-shell-rgb), var(--scrim-a));
}

/* "Ngắm hình nền" (components/wallpaperPeek.js, BA 04/10/2026): xem ảnh nền nét
   100% phủ kín cửa sổ — bỏ lớp che và độ mờ. Đưa CHÍNH lớp nền lên trên giao diện
   thay vì ẩn từng phần: thân trang có hiệu ứng chuyển màn (viewCrossFade) mà giá trị
   của hiệu ứng luôn thắng opacity tĩnh, nên cách ẩn từng phần để lộ thẻ Lịch. */
@keyframes wallpaper-peek-in { from { opacity: 0; } to { opacity: 1; } }
html.is-wallpaper-peek #appBackground {
  position: fixed;
  inset: 0;
  z-index: var(--ui-layer-system);
  border-radius: 0;
  animation: wallpaper-peek-in var(--ui-duration-standard) var(--ui-ease) both;
}
html.is-wallpaper-peek .app-bg-overlay { opacity: 0; }
html.is-wallpaper-peek:not(.is-image-canvas) .app-bg-image { inset: 0; filter: none; }
/* Góc trái dưới (BA 04/10/2026): không che phần giữa ảnh. */
.wallpaper-peek-exit {
  position: fixed;
  left: var(--ui-space-6);
  bottom: var(--ui-space-6);
  z-index: var(--ui-layer-toast);
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  /* Cụm gọn (BA 12/10/2026): nút .ui-btn--sm, chữ chú thích cùng cỡ caption. */
  padding: var(--ui-space-1) var(--ui-space-1) var(--ui-space-1) var(--ui-space-3);
  border-radius: var(--ui-radius-full);
  background: var(--ux-overlay);
  color: var(--ui-text-primary);
  box-shadow: var(--ui-elevation-2);
  font-size: var(--fs-caption);
}
.wallpaper-peek-caption { max-width: var(--dt-dimension-layout-320); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ui-text-secondary); }

/* Wallpaper Settings Controls */
/* Chọn chất liệu nền = SEGMENTED CHUẨN (.ui-segmented, role=radiogroup + aria-checked;
   GĐ F 01/10/2026); ô chia đều bề ngang. */
.source-picker { display: flex; }
.source-choice { flex: 1; }

.setting-note-static {
  margin: var(--ui-space-1) var(--ui-space-2) 0;
  font-size: var(--fs-micro);
  line-height: var(--lh-normal);
  color: var(--ui-text-muted);
}

/* Ghi chú cần được ĐỌC chứ không chỉ hiện ra (sắp hết hạn Premium). Màu chữ mờ
   mặc định là màu của thứ có thể bỏ qua — đúng cho mọi ghi chú khác, sai cho
   dòng này. */
.setting-note-static.is-warning {
  color: var(--ui-warning);
  font-weight: 650;
}













/* [MODULARIZED] Project & Rail styles moved to src/renderer/styles/project-nav.css */

/* =====================================================================
   IMAGE CANVAS — a calm, data-free view of the configured application
   wallpaper.  The image itself remains owned by wallpaper.js/settings; this
   mode merely removes the readability layers needed by normal work screens.
   ===================================================================== */
/* Avatar tài khoản (đầu mối duy nhất còn hiện trong chế độ này) đã chuyển
   sang #navRail — topbar không còn nội dung nào cần giữ lại, ẩn hẳn. */
.project-portfolio-plan-btn:hover { background: var(--ux-hover); }
.project-portfolio-plan-btn.is-active { border-left-color: var(--ui-accent); background: var(--ux-active); }
.project-portfolio-plan-btn:focus-visible { outline: none; box-shadow: 0 0 0 var(--ui-focus-ring-width) color-mix(in srgb, var(--ui-accent) 20%, transparent); }
.project-portfolio-plan-icon { width: var(--ui-icon-lg); height: var(--ui-icon-lg); display: inline-flex; align-items: center; justify-content: center; flex: none; }
.project-portfolio-plan-copy { min-width: 0; display: flex; flex-direction: column; gap: var(--ui-space-px); }
.project-portfolio-plan-copy strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-body); font-weight: var(--fw-medium); }
.project-portfolio-plan-copy small { color: var(--ui-text-muted); font-size: var(--list-sub-fs); font-weight: var(--fw-normal); }
/* Danh sách dự án dùng ĐÚNG khuôn hàng phẳng của cây dự án bên Notebook
   (.notics-tree-project) và cột lọc QuickNote/Painting: không viền, không nền,
   không bóng — vạch màu bên trái chỉ bật khi đang chọn, nền chỉ hiện khi
   hover/active. Một ngôn ngữ chung cho mọi cột liệt kê dự án. */
.project-list-item {
  position: relative;
  display: flex; align-items: center; gap: var(--ui-space-2);
  width: 100%; min-height: var(--ui-list-row-min); margin-bottom: var(--ui-space-px);
  padding: var(--ui-space-1) var(--ui-space-2-5);
  border: none;
  border-left: var(--ui-stroke-thick) solid transparent;
  border-radius: 0;
  background: transparent; color: var(--ui-text-primary);
  text-align: left; cursor: pointer;
  transition-property: var(--tr-ui); transition-timing-function: var(--ui-ease); transition-duration: var(--ui-duration-fast);
}
.project-list-item:hover {
  background: var(--ux-hover);
}
.project-list-item.is-active {
  border-left-color: var(--ui-accent);
  background: var(--ux-active);
}
.project-list-dot { flex: none; width: var(--ui-space-2-5); height: var(--ui-space-2-5); border-radius: var(--ui-radius-circle); background: var(--project-color, var(--ui-accent)); }
.project-list-body { display: flex; flex-direction: column; gap: var(--ui-space-px); min-width: 0; flex: 1; }
.project-list-name { font: var(--fw-medium) var(--fs-body)/var(--lh-snug) var(--app-font); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.project-list-meta { font-size: var(--list-sub-fs); color: var(--ui-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.project-list-lock { font-size: var(--list-sub-fs); }

/* "Dự án cũ" = mục điều hướng 1 dòng cuối danh sách (MỤC ĐIỀU HƯỚNG CỘT CON);
   vạch ngăn phía trên vẽ ở project-nav.css vì hợp đồng đặt border: 0. */
.project-archive-link {
  flex: none;
  display: flex; align-items: center; gap: var(--ui-space-1-5);
  margin: var(--ui-space-2) var(--ui-nav-item-inset) var(--ui-space-2);
  color: var(--ui-text-secondary);
  font: var(--fw-semibold) var(--fs-caption)/var(--lh-none) var(--app-font); cursor: pointer;
}

.project-tab-panel { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
#projectTabOverview, #projectTabTasks, #projectTabNotes {
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-gutter: stable;
  padding: var(--ui-space-4-5) var(--ui-space-5);
}
.project-tab-empty { margin: 0; padding: var(--ui-space-5) var(--ui-space-1); color: var(--ui-text-muted); font-size: var(--fs-body); line-height: var(--lh-relaxed); }
.project-tab-empty code {
  padding: var(--ui-space-px) var(--ui-space-1-5); border-radius: var(--ui-radius-control);
  background: color-mix(in srgb, var(--ui-accent) 12%, transparent); color: var(--ui-accent);
}

/* --- Tab Tổng quan ------------------------------------------------------- */
.project-overview { display: flex; flex-direction: column; gap: var(--ui-space-4-5); max-width: var(--dt-dimension-layout-720); width: 100%; align-self: center; }
.project-overview-head { display: flex; align-items: center; gap: var(--ui-space-3); }
.project-overview-title { min-width: 0; }
.project-overview-dot { flex: none; width: var(--ui-icon-dense); height: var(--ui-icon-dense); border-radius: var(--ui-radius-circle); background: var(--project-color, var(--ui-accent)); }
.project-overview-head h2 { margin: 0; font-size: var(--fs-title); font-weight: var(--fw-semibold); }
.project-overview-head p { margin: var(--ui-space-0-5) 0 0; font-size: var(--fs-caption); color: var(--ui-text-muted); }

.project-progress { display: flex; flex-direction: column; gap: var(--ui-space-1-5); }
.project-progress-bar {
  height: var(--ui-space-2); border-radius: var(--dt-dimension-radius-full); overflow: hidden;
  background: color-mix(in srgb, var(--ui-text-muted) 22%, transparent);
}
.project-progress-bar i {
  display: block; height: 100%; border-radius: var(--dt-dimension-radius-full);
  background: var(--project-color, var(--ui-accent));
  transition: width var(--ui-duration-standard) var(--ui-ease);
}
.project-progress-text { font-size: var(--fs-caption); color: var(--ui-text-secondary); }

.project-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--ui-space-2-5); }
.project-stat {
  display: flex; flex-direction: column; gap: var(--ui-space-0-5);
  padding: var(--ui-space-3) var(--ui-space-3-5);
  border: var(--ui-stroke-thin) solid var(--stroke); border-radius: var(--ui-radius-panel);
  background: rgba(var(--ui-surface-raised-rgb), .45);
}
.project-stat.is-clickable { cursor: pointer; transition: border-color var(--ui-duration-fast) var(--ui-ease), background var(--ui-duration-fast) var(--ui-ease); }
.project-stat.is-clickable:hover { border-color: var(--ui-accent); background: color-mix(in srgb, var(--ui-accent) 7%, transparent); }
.project-stat-value { font: var(--fw-semibold) var(--fs-title-lg)/var(--lh-flat) var(--app-font); }
.project-stat-label { font: var(--fw-semibold) var(--fs-body)/var(--lh-none) var(--app-font); color: var(--ui-text-primary); }
.project-stat-hint { font-size: var(--fs-caption); color: var(--ui-text-muted); }
/* Khối "cần để ý" của Tổng quan: không khung/viền, chỉ tiêu đề nhóm + hàng việc của tab
   Công việc (báo cáo UX 10/10/2026 §4.2). */
.project-focus { display: flex; flex-direction: column; gap: var(--ui-space-4); }
.project-focus-block { display: flex; flex-direction: column; gap: var(--ui-space-1-5); align-items: stretch; }
.project-focus-block > .ui-btn { align-self: flex-start; }
.project-focus-title {
  display: flex; align-items: baseline; gap: var(--ui-space-2); margin: 0;
  font-size: var(--fs-caption); font-weight: var(--fw-semibold); color: var(--ui-text-secondary);
}
.project-focus-title small { font-size: var(--fs-caption); font-weight: var(--fw-normal); color: var(--ui-text-muted); font-variant-numeric: tabular-nums; }
.project-focus-milestone {
  display: flex; align-items: baseline; gap: var(--ui-space-2); width: 100%;
  padding: var(--ui-space-1-5) var(--ui-space-2); border: 0; border-radius: var(--ui-radius-control);
  background: transparent; color: var(--ui-text-primary); font: inherit; text-align: left; cursor: pointer;
}
.project-focus-milestone:hover { background: color-mix(in srgb, var(--ui-accent) 8%, transparent); }
.project-focus-milestone:focus-visible { outline: var(--ui-stroke-thick) solid var(--ui-accent); outline-offset: calc(-1 * var(--ui-stroke-thick)); }
.project-focus-milestone-name { flex: 1 1 auto; min-width: 0; font-size: var(--fs-body); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.project-overview-actions { display: flex; gap: var(--ui-space-2); flex: none; margin-left: auto; }

/* --- Tab Công việc ------------------------------------------------------- */
/* Thanh công cụ: dùng lại vỏ .project-notes-toolbar / .project-notes-search của
   tab Ghi chú (khai báo ở khối "Tab Ghi chú" bên dưới), thêm hàng lọc riêng. */
.project-task-toolbar { flex-wrap: wrap; gap: var(--ui-space-2-5); }
.project-task-filters {
  width: 100%; display: flex; align-items: center; justify-content: center;
  gap: var(--ui-space-3-5); flex-wrap: wrap;
}
.project-task-segbar {
  display: inline-flex; padding: var(--ui-space-0-5); gap: var(--ui-space-0-5);
  border: var(--ui-stroke-thin) solid var(--stroke); border-radius: var(--ui-radius-control);
  background: rgb(var(--ui-surface-raised-rgb));
}
.project-task-seg {
  padding: var(--ui-space-1) var(--ui-space-3); border: 0; border-radius: calc(var(--ui-radius-control) - 2px); /* 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: transparent; color: var(--ui-text-muted); cursor: pointer;
  font: var(--fs-caption)/var(--lh-none) var(--app-font);
  transition: background var(--ui-duration-fast) var(--ui-ease), color var(--ui-duration-fast) var(--ui-ease);
}
.project-task-seg:hover { color: var(--ui-text-primary); }
.project-task-seg.is-active {
  background: color-mix(in srgb, var(--ui-accent) 14%, transparent);
  color: var(--ui-accent); font-weight: var(--fw-semibold);
}
.project-task-hidedone {
  display: inline-flex; align-items: center; gap: var(--ui-space-1-5);
  font-size: var(--fs-caption); color: var(--ui-text-secondary); cursor: pointer;
}
.project-task-hidedone input { margin: 0; cursor: pointer; }

/* Nhóm việc không khung viền (một lớp phân tách: tiêu đề nhóm + vạch tiến độ là đủ) và
   cùng trục giữa với ô tìm/bộ lọc phía trên, cùng khổ với Tổng quan (báo cáo UX 10/10/2026). */
.project-task-groups {
  display: flex; flex-direction: column; gap: var(--ui-space-5);
  width: 100%; max-width: var(--dt-dimension-layout-720); margin-inline: auto;
}
.project-task-group { padding: 0 var(--ui-space-1); }
.project-task-group-head { display: flex; align-items: baseline; gap: var(--ui-space-2); }
.project-task-group-head h3 { margin: 0; font-size: var(--fs-body); font-weight: var(--fw-semibold); color: var(--ui-text-primary); }
.project-task-due {
  font-size: var(--fs-micro); color: var(--ui-text-muted);
  padding: var(--ui-space-0-5) var(--ui-space-2); border-radius: var(--dt-dimension-radius-full);
  background: rgba(var(--ink), .06);
}
.project-task-due.is-overdue {
  color: var(--ui-danger);
  background: color-mix(in srgb, var(--ui-danger) 14%, transparent);
}
.project-task-group-head small { margin-left: auto; font-size: var(--fs-caption); color: var(--ui-text-muted); font-variant-numeric: tabular-nums; }
.project-task-progress {
  height: var(--ui-space-1); margin: var(--ui-space-2) 0 var(--ui-space-2-5); border-radius: var(--dt-dimension-radius-full);
  background: rgba(var(--ink), .08); overflow: hidden;
}
.project-task-progress > span { display: block; height: 100%; background: var(--ui-accent); border-radius: inherit; }
.project-task-rows { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--ui-space-0-5); }
.project-task-row {
  display: flex; align-items: flex-start; gap: var(--ui-space-2-5);
  padding: var(--ui-space-1-5) var(--ui-space-2); border-radius: var(--ui-radius-control);
  cursor: pointer; transition: background var(--ui-duration-fast) var(--ui-ease);
}
.project-task-row:hover { background: color-mix(in srgb, var(--ui-accent) 8%, transparent); }
.project-task-row:focus-visible { outline: var(--ui-stroke-thick) solid var(--ui-accent); outline-offset: calc(-1 * var(--ui-stroke-thick)); }
.project-task-check {
  flex: none; width: var(--ui-icon-sm); height: var(--ui-icon-sm); margin-top: var(--ui-space-px);
  display: inline-flex; align-items: center; justify-content: center;
  border: var(--ui-stroke-thick) solid var(--stroke); border-radius: var(--ui-radius-sm); color: transparent;
}
.project-task-row.is-done .project-task-check {
  border-color: var(--ui-accent); background: var(--ui-accent-solid); color: var(--ui-text-on-accent);
}
.project-task-body { min-width: 0; display: flex; flex-direction: column; gap: var(--ui-space-0-5); }
.project-task-text {
  font-size: var(--fs-body); line-height: var(--lh-snug); color: var(--ui-text-primary);
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.project-task-row.is-done .project-task-text { color: var(--ui-text-muted); }
.project-task-date { font-size: var(--fs-micro); color: var(--ui-text-muted); font-variant-numeric: tabular-nums; }
.project-task-date.is-overdue { color: var(--ui-danger); }
/* Chưa có dự án nào: 6 tab trỏ vào khoảng trống → ẩn nhưng giữ chỗ (topbar không nhảy). */
.topbar-project-tabs.is-empty-workspace { visibility: hidden; }

/* --- Tab Ghi chú — lưới thẻ kiểu Google Keep -------------------------------- */
/* Lưới thẻ dùng chung khuôn .notespeed-all-masonry/.km-col với QuickNote &
   Notebook — keepMasonry.js (cardSelector '.project-note-card') chia cột: căn
   giữa khung, tối đa 5 cột, mỗi thẻ cao theo nội dung. `.project-note-grid` cũ
   (CSS columns) không còn dùng. */
.project-notes-gridhost .notespeed-all-masonry > .project-note-card { flex: 0 1 var(--ui-note-card-w, var(--dt-dimension-layout-256)); }
.project-note-card {
  break-inside: avoid; -webkit-column-break-inside: avoid;
  display: flex; flex-direction: column; gap: var(--ui-space-2);
  width: 100%; margin: 0; padding: var(--ui-space-3) var(--ui-space-3-5);
  border: var(--ui-stroke-thin) solid var(--ux-border); border-radius: var(--ui-radius-panel);
  /* L3 raised — cùng khuôn với .notespeed-all-card. */
  background: var(--ux-raised);
  cursor: pointer; text-align: left;
  transition: border-color var(--ui-duration-fast) var(--ui-ease), box-shadow var(--ui-duration-fast) var(--ui-ease), transform var(--ui-duration-fast) var(--ui-ease);
}
.project-note-card:hover {
  border-color: var(--ux-border-hover);
  box-shadow: var(--ui-elevation-2);
}
.project-note-card:focus-visible { outline: var(--ui-stroke-thick) solid var(--ui-accent); outline-offset: var(--ui-stroke-thick); }
.project-note-card-title {
  font: var(--fw-title) var(--fs-title)/var(--lh-title) var(--app-font); color: var(--ui-text-primary);
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  padding-right: var(--ui-space-6);
}
.project-note-card-preview {
  font-size: var(--fs-body); font-weight: var(--fw-body);
  line-height: var(--lh-body); color: var(--ui-text-secondary);
  white-space: pre-wrap; overflow: hidden; text-overflow: ellipsis;
  display: -webkit-box; -webkit-line-clamp: 7; -webkit-box-orient: vertical;
}
.project-note-card-preview.is-untitled { color: var(--ui-text-primary); -webkit-line-clamp: 8; }
.project-note-card-preview.is-empty { font-style: italic; color: var(--ui-text-muted); }
.project-note-card-lock { display: inline-flex; color: var(--ui-text-muted); }
.project-note-card-date { margin-left: auto; }

/* Màu nền thẻ — dùng lại đúng bảng màu của trình soạn Notics (styles.css ~10035)
   để một note tô vàng trông giống nhau ở hai chỗ, và vẫn đọc được ở dark mode. */
/* GĐ4: 19 dòng mã màu viết thẳng ở đây đã bỏ. Bảng màu nền ghi chú kiểu Keep
   giờ khai MỘT LẦN qua biến --ns-note-* (khối .notespeed-all-card[data-bg] bên
   dưới, selector đã mở rộng để nhận cả .project-note-card) — trước đây cùng
   một bảng 8 màu × 2 chế độ bị chép ở hai chỗ, sửa một màu phải nhớ sửa cả hai. */
.project-note-card[data-bg] { background: var(--ns-note-bg, var(--ux-raised)); }
.project-note-card[data-bg] .project-note-card-title,
.project-note-card[data-bg] .project-note-card-preview { color: var(--ns-note-fg, inherit); }

/* Tab "Ghi chú" — thanh tìm kiếm căn giữa, trên cùng, kiểu Google Keep. */
.project-notes-toolbar {
  position: relative;
  display: flex; justify-content: center; align-items: center;
  padding: var(--ui-space-0-5) 0 var(--ui-space-4);
}
/* Tab Ghi chú: lưới 3 cột — ô tìm kiếm giữa, nút đổi dạng xem cột phải. Hai cột
   bên chia đều nên ô tìm kiếm vẫn đứng giữa khi đủ chỗ; cột hẹp thì cột phải
   giữ đúng bề rộng nút, ô tìm kiếm co lại. Trước đây nút nằm absolute nên ở cột
   hẹp nó đè lên phần phải ô tìm kiếm (che cả nút × xóa từ khóa). */
.project-notes-toolbar:not(.project-task-toolbar) {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 520px) minmax(max-content, 1fr);
  gap: var(--ui-space-2);
}
.project-notes-toolbar:not(.project-task-toolbar) > .project-notes-search { grid-column: 2; }
.project-notes-viewtoggle { grid-column: 3; justify-self: end; }
.project-notes-gridhost.is-list-view { overflow-x: auto; }
.project-notes-search {
  position: relative;
  display: flex; align-items: center; gap: var(--ui-space-2);
  width: 100%; max-width: var(--dt-dimension-layout-520);
  padding: var(--ui-space-2) var(--ui-space-3);
  border: var(--ui-stroke-thin) solid var(--stroke); border-radius: var(--ui-radius-control);
  background: rgb(var(--ui-surface-raised-rgb));
  transition: border-color var(--ui-duration-fast) var(--ui-ease), box-shadow var(--ui-duration-fast) var(--ui-ease);
}
.project-notes-search:focus-within {
  border-color: var(--ui-accent);
  box-shadow: var(--ui-control-ring);
}
.project-notes-search-icon { display: inline-flex; color: var(--ui-text-muted); flex: 0 0 auto; }
.project-notes-search-input {
  flex: 1; min-width: 0;
  border: 0; background: transparent; outline: none;
  color: var(--ui-text-primary); font: var(--fs-body)/var(--lh-normal) var(--app-font);
}
.project-notes-search-input::placeholder { color: var(--ui-text-muted); }
.project-notes-search-input::-webkit-search-cancel-button { display: none; }
.project-notes-search-clear {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto; width: var(--ui-icon-md); height: var(--ui-icon-md); padding: 0;
  border: 0; border-radius: var(--ui-radius-circle);
  background: transparent; color: var(--ui-text-muted); cursor: pointer;
}
.project-notes-search-clear:hover { background: rgba(var(--ink), .08); color: var(--ui-text-primary); }
.project-notes-search-clear.hidden { display: none; }

/* Nút ghim hiện khi hover thẻ (hoặc luôn hiện nếu đã ghim).
   Nền/màu dùng token KHÔNG lệ thuộc màu nền riêng của từng ghi chú (nút này
   nổi trên mọi data-bg, kể cả thẻ tô đen) — bug từng gặp: hover đổi sang nền
   rgba(--ink, .1) (gần trong suốt) + icon màu --sf-text (tối trong light mode)
   → trên thẻ nền đen, icon tối trên nền gần-trong-suốt lộ nền đen = biến mất.
   Nay nền luôn đặc (rgb(--sf-card)) + viền, hover đổi màu icon sang accent
   (xanh, tương phản tốt trên mọi nền) thay vì đổi theo --sf-text. */
.project-note-card { position: relative; }
.project-note-card-pin-toggle {
  position: absolute; top: var(--ui-space-1-5); right: var(--ui-space-1-5);
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--ui-size-sm); height: var(--ui-size-sm); padding: 0;
  border: var(--ui-stroke-thin) solid var(--stroke); border-radius: var(--ui-radius-circle);
  /* Nút ghim nổi trên thẻ: phải ĐỤC. Thẻ có thể mang màu người dùng chọn (kể
     cả đen), nền mờ theo vật liệu sẽ ăn màu thẻ và icon biến mất. */
  background: rgb(var(--ux-raised-rgb));
  color: var(--ui-text-muted); cursor: pointer;
  box-shadow: var(--ui-elevation-1);
  opacity: 0; transition: opacity var(--ui-duration-fast) var(--ui-ease), border-color var(--ui-duration-fast) var(--ui-ease), color var(--ui-duration-fast) var(--ui-ease);
}
.project-note-card:hover .project-note-card-pin-toggle,
.project-note-card:focus-within .project-note-card-pin-toggle,
.project-note-card-pin-toggle.is-pinned { opacity: 1; }
.project-note-card-pin-toggle:hover { border-color: var(--ux-border-hover); color: var(--ui-text-primary); }
.project-note-card-pin-toggle.is-pinned { color: var(--ui-accent); border-color: color-mix(in srgb, var(--ui-accent) 45%, var(--stroke)); }

/* ---- Popup chỉnh sửa ghi chú (projectNotePopup.js) ----
   Lấy đúng layout workspace của Notebook: cùng edge-gap token và dùng toàn bộ
   phần còn lại của viewport.
   Vì overlayManager gắn thêm class .overlay-panel nên popup này dính các rule
   ghi đè theo theme (fluent bẻ về --sf-radius-row, glass đổi nền/bóng) mà
   popup Notebook — vốn KHÔNG chạy qua overlayManager — không bị. Do đó phải
   khóa cỡ + bo góc bằng selector có #id để luôn thắng cascade. */
#projectNotePopup.overlay[data-overlay-kind="modal"] {
  /* Kích thước panel tự chừa edge-gap token; overlay không cộng padding lần hai. */
  padding: 0;
}
.pnp-card,
#projectNotePopup .pnp-card {
  width: calc(100% - var(--ui-dialog-edge-gap) - var(--ui-dialog-edge-gap));
  height: calc(100% - var(--ui-dialog-edge-gap) - var(--ui-dialog-edge-gap));
  max-width: none;
  max-height: none;
  display: flex; flex-direction: column; overflow: hidden;
  padding: 0;
  border: var(--ui-stroke-thin) solid var(--stroke);
  border-radius: var(--ui-radius-panel);
  box-shadow: var(--elev-4);
}
#projectNotePopup.is-expanded .pnp-card {
  width: 100%;
  height: 100%;
  border: 0;
  border-radius: 0;
}
/* Thanh đầu = khuôn Notebook (.notics-doc-header/.note-doc-header, notics.css +
   note-editor-shell.css; BA 12/10/2026 dùng chung 1 form). Ở đây chỉ còn chữ vị trí:
   tên dự án đang chứa ghi chú, nằm trong .notics-doc-location. */
.pnp-head { flex: 0 0 auto; }
.pnp-head-context {
  min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--ui-text-secondary); font-size: var(--fs-body); font-weight: var(--fw-medium);
}

.pnp-editor-wrap { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.pnp-editor-wrap.hidden { display: none; }
.pnp-card .notics-editor-stage { flex: 1; min-height: 0; overflow: hidden; padding: 0; }
.pnp-card #pnpLockScreen { flex: 1; display: flex; align-items: center; justify-content: center; padding: var(--ui-space-6); }
.pnp-card #pnpLockScreen.hidden { display: none; }

/* Panel Gantt bên trong tab Milestone — cùng khung với các panel khác. */
#projectTabMilestones { display: flex; flex-direction: column; }
#projectTabMilestones.hidden { display: none; }


/* [MODULARIZED] Notics tree (Phase 5) moved to src/renderer/styles/notics.css */

/* =========================================================================
   LÀN DẪN & MẬT ĐỘ HÀNG — CHẾ ĐỘ TUẦN / NHIỀU TUẦN
   ========================================================================= */

/* ---------- Gói A: một nhịp lề trái duy nhất ----------
   Trước đây mỗi loại hàng tự tính lề trái riêng, đo trên cột ngày ~259px:
     · task          padding-left 10 + làn 26 + gap 8            = 44px
     · Google/Outlook padding-left 10 + body margin-left 37       = 47px
     · việc dài ngày  padding-left 10 + vạch 3+3 + gap 8          = 24px
   Ba nhịp khác nhau trong cùng một cột nên mép trái bị răng cưa. Riêng làn
   26px rộng hơn gấp đôi thứ nó chứa: glyph "1." chỉ ~11px mà lại canh giữa,
   nên chết 8px mỗi bên rồi còn cộng thêm gap 8px — tổng 16px trắng giữa số
   và chữ, 18px trước số.

   Làn 26px vốn là để chứa vùng bấm của ô tích, nhưng ô tích là
   position:absolute nên nó không cần làn rộng — nó tự tràn ra được. Nghĩa là
   ta trả diện tích 100% thời gian cho một control chỉ xuất hiện lúc hover.

   Giờ cả ba loại hàng dùng chung một token --cal-lead-lane, canh trái, + gap
   4px. Giá trị 20px ở đây chỉ là mức dự phòng; mỗi cột ngày tự ghi đè lên
   .task-list theo nội dung thật của nó (18px, 23px khi số từ 10 việc trở
   lên) — xem renderWeekDays trong calendarGrid.js. Sàn 18px chừa đủ chỗ cho
   vòng tròn ô tích/icon lịch ngoài (~16px) nên chúng không bị chật. Vùng bấm
   của ô tích neo theo padding-left thật của hàng (xem rule .task-box riêng
   bên dưới), không phụ thuộc làn, nên không bao giờ lấn sang vùng chữ: bấm
   vào chữ vẫn mở trình soạn thảo như cũ. */
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid.multi-week) {
  /* Làn số & khe hở đo theo cỡ chữ việc của CHÍNH dạng xem (co đúng ở 125%
     OS scale / khi tăng "Cỡ chữ công việc"), không ghim px. Sàn max() chừa
     đủ vòng tròn ô tích. renderWeekDays vẫn ghi đè --cal-lead-lane lên
     .task-list theo số chữ số thật của cột (1 hay 2 chữ số). */
  --cal-lead-lane: max(15px, calc(var(--task-effective-font) * 1.4));
  /* SÀN 4px là bắt buộc, không phải cho đẹp. Hệ số thuần (0.22) từng cho ra
     2.6px ở dạng Tháng và 2.9px ở dạng Tuần — HẸP HƠN mức 4px cố định của bản
     cũ, nên icon lịch ngoài dính sát vào tiêu đề. Khe hở giữa hai khối khác
     vai có ngưỡng đọc tối thiểu không co theo cỡ chữ được. */
  --cal-lead-gap: max(4px, calc(var(--task-effective-font) * 0.34));
  /* Icon nguồn lịch phải NHỎ HƠN làn dẫn đủ để còn lề thở hai bên: 1.05 khiến
     icon 12.6px lấp gần kín làn 16.8px của dạng Tháng, nhìn ra là "dính". */
  --task-icon-size: calc(var(--task-effective-font) * 0.95);
}
/* .task-prefix-slot BẮT BUỘC giữ position:relative — nó là khung quy chiếu
   của HAI phần tử absolute chồng lên nhau: .task-prefix (dòng ~4083:
   position:absolute; left:50%; top:50%; translate(-50%,-50%)) và .task-box.
   Cả hai cùng canh giữa làn nên vốn đã đồng tâm sẵn, hover chỉ đổi opacity
   giữa hai lớp. Từng thử đổi làn sang position:static để ô tích neo thẳng
   vào hàng — hỏng ngay: mất khung quy chiếu, số thứ tự văng ra giữa hàng và
   đè lên chữ. Chỉ thu bề rộng làn, tuyệt đối không đụng vào position. */
:is(.grid[data-view-mode="today"], .grid[data-view-mode="week"], .grid.multi-week) .task-prefix-slot {
  width: var(--cal-lead-lane);
  min-width: var(--cal-lead-lane);
  flex-basis: var(--cal-lead-lane);
}

/* ---------- Gói B: ĐÃ QUAY LẠI mặc định sau phản hồi thực tế ----------
   Bản nén dọc (min-height = 0.6× / 0.52× chiều cao hàng) làm hàng một dòng
   thấp hơn hẳn cỡ chạm quen tay. Người dùng cần dễ bấm hơn là cần nhồi thêm
   việc mỗi ô — quay lại đúng công thức mặc định dùng chung với ngày/tuần
   (--ui-row-height, 40px ở cỡ hàng mặc định 48px) thay vì override riêng.
   measureMultiWeekItemCap() trong calendarGrid.js đã đổi theo cùng công
   thức, nên hạn mức số việc/ô vẫn tính đúng theo chiều cao hàng thật — chỉ
   là với hàng cao hơn, hạn mức tính ra thường về sát mức sàn 6 (bằng đúng
   hằng số cũ) thay vì 9–12 như bản nén trước đó. */

/* Ô ngày ít việc để trống một khoảng lớn bên dưới là ĐÚNG Ý ĐỒ, không phải
   lỗi cần bù: mọi ô trong cùng hàng-tuần luôn cao bằng nhau (grid.multi-week
   chia đều 1fr theo TUẦN, không theo nội dung từng ngày), nên chỗ trống đó
   là phần dự phòng của chính ngày ấy. Từng thử trải các hàng ra cho "cân đối"
   (space-evenly, rồi safe center) — cả hai đều làm việc nằm lơ lửng giữa ô,
   mắt phải dò tìm thay vì luôn biết trước việc đầu tiên ở đâu. Danh sách
   công việc bám mép trên, giống mọi ô ngày khác. Giữ nguyên flex-start mặc
   định; đừng thêm justify-content ở đây nữa. */

/* ---------- Gói C: chuẩn hoá khối thông tin ----------
   Tiêu đề event vốn đã bị kẹp 2 dòng, còn tiêu đề task thì wrap không giới
   hạn — một việc dài đủ sức đẩy các việc khác ra ngoài hạn mức hiển thị của ô
   ngày. Cho cả hai cùng một luật; phần bị cắt nằm trong tooltip của hàng. */
:is(.grid[data-view-mode="week"], .grid.multi-week) .task-text {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}


/* [MODULARIZED] AntiPaint & NoteSpeed moved to src/renderer/styles/paint-speed.css (shared workspaceListPane retained below) */

/* ==========================================================================
   workspaceListPane — cột danh sách dùng chung (Notics / NoteSpeed / AntiPaint
   / AntiScreenshot). JS: src/renderer/src/components/workspaceListPane.js
   ========================================================================== */

/* --- Cột danh sách khi thu gọn: ẩn hoàn toàn --- */
.notics-col.is-ws-collapsed { display: none !important; }

/* --- Header cột (component tự dựng) --- */
.ws-pane-head .ws-pane-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* --- Item danh sách --- */
.ws-list { padding: 0; }
.ws-list-empty {
  margin: var(--ui-space-3-5) var(--ui-space-3);
  color: var(--ui-text-muted);
  font-size: var(--fs-body);
  line-height: var(--lh-normal);
}
.ws-list-group {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-space-2);
  padding: var(--ui-space-2-5) var(--ui-space-3) var(--ui-space-1);
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-weight: var(--fw-overline);
}
.ws-list-more { padding: var(--ui-space-1-5) var(--ui-space-3) var(--ui-space-2-5); color: var(--ui-text-muted); font-size: var(--fs-caption); }
button.ws-list-more,
.ws-list-more-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--ui-space-1-5);
  width: 100%;
  min-height: var(--ui-size-lg);
  padding: var(--ui-space-2) var(--ui-space-3);
  border: var(--ui-stroke-thin) dashed var(--stroke);
  border-radius: var(--ui-radius-panel);
  background: transparent;
  color: var(--ui-accent);
  font-family: var(--app-font);
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  cursor: pointer;
  box-sizing: border-box;
  text-align: center;
  user-select: none;
  transition: background var(--ui-duration-fast) var(--ui-ease), border-color var(--ui-duration-fast) var(--ui-ease), color var(--ui-duration-fast) var(--ui-ease);
}
button.ws-list-more:hover,
.ws-list-more-btn:hover {
  background: var(--ux-hover);
  border-color: var(--ui-accent);
  color: var(--ui-accent);
}
button.ws-list-more:active,
.ws-list-more-btn:active {
  background: var(--ux-active);
}

.ws-item {
  display: flex;
  align-items: flex-start;
  gap: var(--ui-space-2-5);
  width: 100%;
  padding: var(--list-pad-y) var(--list-pad-x) var(--list-pad-y) calc(var(--list-pad-x) - var(--ui-space-0-5));
  border: none;
  border-left: var(--ui-stroke-thicker) solid transparent;
  border-bottom: var(--ui-stroke-thin) solid var(--stroke);
  background: transparent;
  color: var(--ui-text-primary);
  text-align: left;
  cursor: pointer;
  transition: background var(--ui-duration-fast) var(--ui-ease), border-color var(--ui-duration-fast) var(--ui-ease);
}
.ws-item:hover { background: var(--ux-hover); }
.ws-item.is-active {
  background: var(--ux-active);
  border-left-color: var(--ui-accent);
}
.ws-item.is-active .ws-item-title { color: var(--ui-accent); }
.ws-item.drop-target-before { box-shadow: inset 0 var(--ui-focus-ring-width) 0 var(--ui-accent); }
.ws-item.drop-target-after { box-shadow: inset 0 calc(var(--ui-focus-ring-width) * -1) 0 var(--ui-accent); }
.ws-item.is-dragging { opacity: 0.4; }

.ws-item-dot {
  flex: 0 0 var(--ui-space-2);
  width: var(--ui-space-2);
  height: var(--ui-space-2);
  margin-top: var(--ui-space-1);
  border-radius: var(--ui-radius-circle);
  background: var(--ws-dot, var(--stroke));
}
.ws-item-thumb {
  flex: 0 0 var(--ui-size-touch);
  width: var(--ui-size-touch);
  height: var(--ui-size-touch);
  border-radius: var(--ui-radius-control);
  border: var(--ui-stroke-thin) solid var(--stroke);
  background: rgba(var(--ink), 0.04) center / cover no-repeat;
}
.ws-item-thumb.is-empty { background-image: none; }

.ws-item-body { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; gap: var(--ui-space-1); }
.ws-item-title {
  /* Vai TITLE ở cỡ body — lấy đủ bộ ba của vai, không trộn tay. */
  font-size: var(--list-title-fs);
  font-weight: var(--fw-title);
  line-height: var(--lh-title);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ws-item-meta {
  display: flex;
  align-items: center;
  gap: var(--ui-space-1);
  font-size: var(--list-sub-fs);
  color: var(--ui-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ws-item-badge { display: inline-flex; align-items: center; }
.ws-item-badge.is-pin { color: var(--ui-warning); }
/* Huy hiệu phân loại Dự án/Nhóm trên hàng bộ lọc QuickNote/Painting — cùng
   công thức color-mix + pill với .project-type-badge (Cài đặt → Dự án) và
   cùng ý nghĩa màu: accent = Dự án (liên kết Công việc), trung tính = Nhóm. */
.ws-item-badge.is-type-linked {
  background: color-mix(in srgb, var(--ui-accent) 18%, transparent);
  color: var(--ui-accent);
}
.ws-item-badge.is-type-notebook {
  background: color-mix(in srgb, var(--ui-text-muted) 16%, transparent);
  color: var(--ui-text-secondary);
}
.ws-item-sub { min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* --- Cards layout (AntiScreenshot: lưới thumbnail tự co giãn 1-3 cột theo độ rộng kéo thả) --- */
.ws-list--cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(calc(130px * var(--font-scale, 1)), 1fr));
  align-content: start;
  gap: var(--ui-space-1-5);
  padding: var(--ui-space-1-5) var(--ui-space-2);
}
.ws-list--cards .ws-list-group {
  grid-column: 1 / -1;
  padding: var(--ui-space-1-5) var(--ui-space-0-5) var(--ui-space-0-5);
}
.ws-list--cards .ws-list-more {
  grid-column: 1 / -1;
}
.ws-list--cards .ws-item {
  /* Art Editor cards are a two-row unit: thumbnail then metadata.
     Cố định chiều cao toàn bộ card và thumbnail theo --font-scale để hiển thị
     đều đặn, không co rúm khi cuộn nhiều item. */
  display: grid;
  grid-template-rows: calc(84px * var(--font-scale, 1)) calc(36px * var(--font-scale, 1));
  align-content: start;
  gap: var(--ui-space-1-5);
  padding: var(--ui-space-1-5);
  border: var(--ui-stroke-thin) solid var(--stroke);
  border-radius: var(--ui-radius-panel);
  margin-bottom: 0;
  width: 100%;
  height: var(--dt-dimension-layout-144);
  min-height: var(--dt-dimension-layout-144);
  max-height: var(--dt-dimension-layout-144);
  box-sizing: border-box;
  overflow: hidden;
  flex-shrink: 0;
}
.ws-list--cards .ws-item.is-active { border-color: var(--ui-accent); }
.ws-list--cards .ws-item-thumb {
  width: 100%;
  height: var(--dt-dimension-layout-88);
  min-height: var(--dt-dimension-layout-88);
  max-height: var(--dt-dimension-layout-88);
  flex-shrink: 0;
}
.ws-list--cards .ws-item-body {
  width: 100%;
  min-width: 0;
  max-width: 100%;
  height: var(--ui-size-lg);
  flex: 0 0 auto;
  overflow: hidden;
}
.ws-list--cards :is(.ws-item-title, .ws-item-meta) { max-width: 100%; }

/* --- Nav-cards layout (QuickNote/AntiPaint: nhãn lọc "Tất cả/Đã ghim/theo dự án")
   Danh sách 1 cột PHẲNG kiểu sidebar (Notion/Todoist/Keep): không viền, không
   nền từng hàng — nền chỉ hiện khi hover/đang chọn. Tên 1 dòng + "…", số đếm
   căn phải cùng dòng, mờ. Mục dự án rỗng (.is-zero) làm nhạt số đếm. Danh sách
   dọc = điều hướng; khung có viền để dành cho NỘI DUNG (thẻ ghi chú/ảnh). --- */
.ws-list--navcards {
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-px);
  padding: var(--ui-space-0-5) var(--ui-space-1) var(--ui-space-1-5);
}
.ws-list--navcards .ws-list-group {
  padding: var(--ui-space-2-5) var(--ui-space-2-5) var(--ui-space-1);
}
.ws-list--navcards .ws-list-more { padding: var(--ui-space-1) var(--ui-space-2-5) var(--ui-space-2); }
.ws-list--navcards .ws-item {
  flex-direction: row;
  align-items: center;
  gap: var(--ui-space-2);
  width: 100%;
  padding: var(--ui-space-1-5) var(--ui-space-2-5);
  border: none;
  border-left: var(--ui-stroke-thick) solid transparent;
  border-radius: 0;
  background: transparent;
}
.ws-list--navcards .ws-item:hover {
  background: var(--ux-hover);
  border-left-color: transparent;
}
.ws-list--navcards .ws-item.is-active {
  background: var(--ux-active);
  border-left-color: var(--ui-accent);
}
.ws-list--navcards .ws-item-dot {
  flex: 0 0 var(--ui-space-1-5);
  width: var(--ui-space-1-5);
  height: var(--ui-space-1-5);
  margin: 0;
  align-self: center;
  /* Nhích 1px: chữ có dấu (VŨ, ĐỪNG…) dồn khối lên trên nên tâm hình học của
     dòng nằm hơi cao so với tâm mắt đọc — chấm canh theo hình học sẽ trông cao. */
  position: relative;
  top: var(--ui-space-px);
}
.ws-list--navcards .ws-item-body {
  /* Hàng ngang: [tên co giãn][số đếm]. min-width:0 để ellipsis của tên bám
     được vào bề rộng còn lại sau khi trừ chấm màu + số đếm. */
  flex-direction: row;
  align-items: center;
  gap: var(--ui-space-2);
  min-width: 0;
  flex: 1 1 auto;
}
.ws-list--navcards .ws-item-title {
  min-width: 0;
  flex: 1 1 auto;
  /* Điều hướng cấp 3 → tụt một bậc so với chữ đọc chính (body-sm), medium là đủ. */
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  line-height: var(--lh-body-sm);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ws-list--navcards .ws-item-meta {
  flex: 0 0 auto;
  color: var(--ui-text-muted);
  font-size: var(--list-sub-fs);
}
.ws-list--navcards .ws-item-badge.is-zero { opacity: 0.45; }

@media (max-width: 780px) {
  .antiscreenshot-page.is-list-collapsed .notics-body { grid-template-columns: 1fr; }
}


/* --- TokenSelect Custom Dropdown ---------------------------------------- */
.token-select-hidden-native {
  position: absolute !important;
  pointer-events: none !important;}

.token-select-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
  max-width: 100%;
}

.token-select-wrap.is-block,
.quick-add-field .token-select-wrap,
.form-group .token-select-wrap,
.form-row .token-select-wrap {
  display: flex;
  width: 100%;
}

/* Trong hàng Cài đặt (flex space-between: nhãn co giãn | control cố định),
   token-select phải giữ vai trò control cố định như .setting-select gốc —
   không được width:100% nếu không nó nuốt hết chỗ và bóp nhãn về mép trái. */
.settings-field-row .token-select-wrap {
  flex: 0 0 auto;
  width: auto;
  max-width: min(var(--dt-dimension-layout-240), 45%);
}

.token-select-trigger {
  height: var(--ui-size-md);
  min-height: var(--ui-size-md);
  min-width: var(--dt-dimension-layout-120);
  max-width: min(var(--dt-dimension-layout-240), 25vw);
  display: inline-flex;
  align-items: center;
  gap: var(--ui-space-1-5);
  padding: 0 var(--ui-space-2-5);
  border: var(--ui-stroke-thin) solid var(--stroke);
  border-radius: var(--ui-radius-control);
  background-color: rgb(var(--ui-surface-raised-rgb));
  color: var(--ui-text-primary);
  font-family: var(--app-font);
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  cursor: pointer;
  box-shadow: var(--ui-elevation-1);
  transition: border-color var(--ui-duration-fast) var(--ui-ease), box-shadow var(--ui-duration-fast) var(--ui-ease), background-color var(--ui-duration-fast) var(--ui-ease);
  text-align: left;
}

.token-select-wrap.is-block .token-select-trigger,
.quick-add-field .token-select-trigger,
.form-group .token-select-trigger,
.form-row .token-select-trigger,
.item-detail-drawer .token-select-trigger {
  width: 100%;
  max-width: 100%;
  min-height: var(--ui-field-h);
  font-size: var(--fs-body);
  font-weight: var(--fw-normal);
}

/* Toolbar Context (Notics, NoteSpeed, PNP, Kế hoạch) */
.notics-toolbar .token-select-wrap,
.ql-formats .token-select-wrap {
  display: inline-flex;
}

.notics-toolbar .token-select-trigger,
.ql-formats .token-select-trigger {
  height: var(--ui-size-sm);
  min-height: var(--ui-size-sm);
  max-width: none;
  padding: 0 var(--ui-space-1-5);
  gap: var(--ui-space-1);
  font-size: var(--fs-caption);
  border-radius: var(--ui-radius-control);
  background-color: color-mix(in srgb, var(--ui-text-primary) 5%, transparent);
  border: var(--ui-stroke-thin) solid transparent;
  box-shadow: none;
}
.notics-toolbar .token-select-trigger:hover,
.ql-formats .token-select-trigger:hover {
  background-color: var(--ui-hover);
  border-color: transparent;
  color: var(--ui-text-primary);
}

/* Giữ trọn nhãn ("Đoạn văn"…) khi thanh công cụ còn chỗ; hết chỗ thì cả nhóm
   tự xuống dòng nhờ flex-wrap của .notics-toolbar, KHÔNG co nhãn còn mỗi mũi
   tên. Selector đủ đặc hiệu để thắng khối .token-select-wrap.is-compact bên
   dưới (cùng độ đặc hiệu, đứng sau trong file). */
.notics-toolbar .token-select-wrap.is-compact .token-select-trigger,
.ql-formats .token-select-wrap.is-compact .token-select-trigger {
  min-width: max-content;
  flex: 0 0 auto;
}

.notics-toolbar .token-select-label,
.ql-formats .token-select-label {
  font-size: var(--fs-caption);
  overflow: visible;
  text-overflow: clip;
}

/* Cố định chiều rộng dropdown định dạng trong toolbar để không bị giật khi chọn.
   em phải tính theo cỡ chữ CỦA Ô (--fs-caption, xem editorToolbarStandard trong
   ui-components.css) — trước đây kế thừa cỡ chữ nội dung (--font-task) nên ô
   phình gần gấp đôi nhãn. Bề rộng = nhãn dài nhất ("Times New Roman",
   "Cỡ cực lớn") + đệm + mũi tên. */
.notics-toolbar .token-select-wrap.is-ql-header,
.ql-formats .token-select-wrap.is-ql-header,
.notics-toolbar .token-select-wrap:has(select.ql-header),
.ql-formats .token-select-wrap:has(select.ql-header) {
  font-size: var(--fs-caption);
  width: 10em;
  flex: 0 0 auto;
}

.notics-toolbar .token-select-wrap.is-ql-font,
.ql-formats .token-select-wrap.is-ql-font,
.notics-toolbar .token-select-wrap:has(select.ql-font),
.ql-formats .token-select-wrap:has(select.ql-font) {
  font-size: var(--fs-caption);
  width: 11.5em;
  flex: 0 0 auto;
}

.notics-toolbar .token-select-wrap.is-ql-size,
.ql-formats .token-select-wrap.is-ql-size,
.notics-toolbar .token-select-wrap:has(select.ql-size),
.ql-formats .token-select-wrap:has(select.ql-size) {
  font-size: var(--fs-caption);
  width: 8em;
  flex: 0 0 auto;
}

.notics-toolbar .token-select-wrap.is-ql-header .token-select-trigger,
.notics-toolbar .token-select-wrap.is-ql-font .token-select-trigger,
.notics-toolbar .token-select-wrap.is-ql-size .token-select-trigger,
.ql-formats .token-select-wrap.is-ql-header .token-select-trigger,
.ql-formats .token-select-wrap.is-ql-font .token-select-trigger,
.ql-formats .token-select-wrap.is-ql-size .token-select-trigger,
.notics-toolbar .token-select-wrap:has(select.ql-header) .token-select-trigger,
.notics-toolbar .token-select-wrap:has(select.ql-font) .token-select-trigger,
.notics-toolbar .token-select-wrap:has(select.ql-size) .token-select-trigger,
.ql-formats .token-select-wrap:has(select.ql-header) .token-select-trigger,
.ql-formats .token-select-wrap:has(select.ql-font) .token-select-trigger,
.ql-formats .token-select-wrap:has(select.ql-size) .token-select-trigger {
  width: 100%;
  min-width: 0;
  justify-content: space-between;
}

.notics-toolbar .token-select-wrap.is-ql-header .token-select-label,
.notics-toolbar .token-select-wrap.is-ql-font .token-select-label,
.notics-toolbar .token-select-wrap.is-ql-size .token-select-label,
.ql-formats .token-select-wrap.is-ql-header .token-select-label,
.ql-formats .token-select-wrap.is-ql-font .token-select-label,
.ql-formats .token-select-wrap.is-ql-size .token-select-label,
.notics-toolbar .token-select-wrap:has(select.ql-header) .token-select-label,
.notics-toolbar .token-select-wrap:has(select.ql-font) .token-select-label,
.notics-toolbar .token-select-wrap:has(select.ql-size) .token-select-label,
.ql-formats .token-select-wrap:has(select.ql-header) .token-select-label,
.ql-formats .token-select-wrap:has(select.ql-font) .token-select-label,
.ql-formats .token-select-wrap:has(select.ql-size) .token-select-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Compact / Inline Selects */
.token-select-wrap.is-compact .token-select-trigger,
.compact-select + .token-select-trigger {
  height: var(--ui-size-sm);
  min-height: var(--ui-size-sm);
  min-width: auto;
  max-width: none;
  padding: 0 var(--ui-space-1-5);
  gap: var(--ui-space-1);
  font-size: var(--fs-caption);
  border-radius: var(--ui-radius-control);
}

.token-select-trigger:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  pointer-events: none;
}

.token-select-trigger:hover {
  background-color: rgb(var(--ui-surface-fill-rgb));
  border-color: rgba(var(--ui-accent-rgb), 0.4);
  color: var(--ui-accent);
}

.token-select-trigger:focus-visible,
.token-select-trigger.is-open {
  /* Như ô nhập và .token-date-trigger: chỉ viền đậm mực trung tính, không tô nền/chữ xanh. */
  outline: none;
  border-color: var(--ux-control-border-active);
  box-shadow: var(--ui-control-ring);
}

.token-select-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.token-select-swatch {
  width: var(--ui-space-2);
  height: var(--ui-space-2);
  flex: 0 0 var(--ui-space-2);
  border-radius: var(--ui-radius-circle);
}

.token-select-caret {
  flex: 0 0 auto;
  color: var(--ui-text-secondary);
  transition: transform var(--ui-duration-standard) var(--ui-ease);
  margin-left: var(--ui-space-0-5);
}

.token-select-trigger.is-open .token-select-caret {
  transform: rotate(180deg);
}

.token-select-popover[hidden] {
  display: none !important;
}

.token-select-popover {
  position: fixed;
  /* Bọc trên body và luôn là tương tác vừa mở → phải nổi trên MỌI lớp modal/
     drawer. --layer-popover (100) thấp hơn .item-detail-drawer (z 200) và
     .overlay kind=modal (--layer-modal 1000), nên dropdown "Lịch lặp" trong
     hộp Chỉnh sửa công việc bị đẩy xuống dưới hộp và không bấm được. Đặt trên
     --layer-modal, vẫn dưới --layer-alert (1200) để hộp xác nhận vẫn che được. */
  z-index: calc(var(--layer-modal, 1000) + 100);
  padding: var(--ui-space-1-5);
  border: var(--ui-stroke-thin) solid var(--stroke);
  border-radius: var(--ui-radius-panel);
  background: var(--ux-overlay);
  box-shadow: var(--elev-4);
  font-family: var(--app-font);
  display: flex;
  flex-direction: column;
  gap: 0;
  animation: tokenSelectFadeIn var(--ui-duration-fast) var(--ui-ease);
}

@keyframes tokenSelectFadeIn {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}

.token-select-popover.is-placement-top {
  animation-name: tokenSelectFadeInTop;
}

@keyframes tokenSelectFadeInTop {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}

.token-select-popover-title {
  padding: var(--ui-space-1) var(--ui-space-2) var(--ui-space-1-5);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--ui-text-muted);
  border-bottom: var(--ui-stroke-thin) solid var(--ux-border);
  margin-bottom: var(--ui-space-1);
  user-select: none;
}

.token-select-search-wrap {
  position: relative;
  display: flex;
  align-items: center;
  color: var(--ui-text-muted);
  padding: 0;
  margin-bottom: var(--ui-space-1-5);
  border-bottom: none;
}

.token-select-search-wrap svg {
  position: absolute;
  left: var(--ui-space-2-5);
  pointer-events: none;
  color: var(--ui-text-muted);
}

.token-select-search {
  width: 100%;
  height: var(--ui-size-md);
  padding: 0 var(--ui-space-2-5) 0 var(--ui-space-8);
  border: var(--ui-stroke-thin) solid var(--stroke);
  border-radius: var(--ui-radius-control);
  background: rgba(var(--ink), 0.035);
  color: var(--ui-text-primary);
  font: var(--fs-body) var(--app-font);
  outline: none;
  transition: border-color var(--ui-duration-fast) var(--ui-ease), box-shadow var(--ui-duration-fast) var(--ui-ease);
}

.token-select-search:focus {
  border-color: var(--ui-accent);
  box-shadow: var(--ui-control-ring);
}

.token-select-options {
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-0-5);
  max-height: min(var(--dt-dimension-layout-304), calc(100vh - var(--dt-dimension-layout-152)));
  overflow-y: auto;
  overflow-x: hidden;
}

.token-select-option {
  width: 100%;
  min-height: var(--ui-size-md);
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  padding: var(--ui-space-1) var(--ui-space-2);
  border: 0;
  border-radius: var(--ui-radius-control);
  background: transparent;
  color: var(--ui-text-primary);
  font-family: var(--app-font);
  text-align: left;
  cursor: pointer;
  transition: background-color var(--ui-duration-fast) var(--ui-ease), color var(--ui-duration-fast) var(--ui-ease);
}

.token-select-option.has-hint {
  min-height: var(--ui-size-lg);
}

.token-select-option:hover,
.token-select-option:focus-visible {
  outline: none;
  background: color-mix(in srgb, var(--ui-accent) 9%, transparent);
}

.token-select-option.is-selected {
  background: color-mix(in srgb, var(--ui-accent) 13%, transparent);
  color: var(--ui-text-primary);
}

.token-select-option-swatch {
  width: var(--ui-space-2);
  height: var(--ui-icon-md);
  flex: 0 0 auto;
  border-radius: var(--dt-dimension-radius-full);
}

.token-select-option-text {
  min-width: 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-px);
}

/* Danh sách chọn luôn hiện đủ chữ: popover tự nới theo nhãn dài nhất (tokenSelect.js),
   khi chạm mép cửa sổ thì nhãn xuống dòng — không cắt bằng "…". */
.token-select-option-text strong {
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
  overflow-wrap: anywhere;
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
}

.token-select-option.is-selected .token-select-option-text strong {
  font-weight: var(--dt-typography-weight-semibold);
}

.token-select-option-text small {
  color: var(--ui-text-muted);
  font-size: var(--fs-micro);
  font-weight: var(--fw-normal);
}

.token-select-check {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--ui-accent);
}

.token-select-empty {
  padding: var(--ui-space-2-5) var(--ui-space-2);
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  text-align: center;
}

/* --- TokenDatePicker In-DOM Component ----------------------------------- */
.token-date-hidden-native {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  pointer-events: none;
  border: 0;
  padding: 0;
  margin: 0;
  z-index: -1;
}

.token-date-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
  width: 100%;
  max-width: 100%;
}

.token-date-trigger {
  width: 100%;
  min-height: var(--ui-field-h);
  padding: 0 var(--ui-field-pad-inline);
  border: var(--ui-stroke-thin) solid var(--stroke);
  border-radius: var(--ui-radius-control);
  background: rgb(var(--ui-surface-raised-rgb));
  color: var(--ui-text-primary);
  font-family: var(--app-font);
  font-size: var(--fs-body);
  font-weight: var(--fw-normal);
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-space-2);
  cursor: pointer;
  text-align: left;
  user-select: none;
  box-sizing: border-box;
  box-shadow: var(--ui-elevation-1);
  transition: border-color var(--ui-duration-fast) var(--ui-ease),
              box-shadow var(--ui-duration-fast) var(--ui-ease),
              background-color var(--ui-duration-fast) var(--ui-ease);
}

.token-date-trigger:hover {
  border-color: var(--ui-accent);
}

.token-date-trigger:focus-visible,
.token-date-trigger.is-open {
  outline: none;
  border-color: var(--ux-control-border-active);
  box-shadow: var(--ui-control-ring);
}

.token-date-trigger:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  pointer-events: none;
}

.token-date-display {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.token-date-display.is-placeholder {
  color: var(--ui-text-muted);
}

.token-date-icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ui-text-secondary);
}

.token-date-popover {
  position: fixed;
  z-index: calc(var(--layer-modal, 1000) + 100);
  width: min(var(--dt-dimension-layout-288), calc(100vw - var(--ui-space-6)));
  background: var(--ux-overlay);
  backdrop-filter: var(--glass-panel, blur(16px));
  -webkit-backdrop-filter: var(--glass-panel, blur(16px));
  border: var(--ui-stroke-thin) solid var(--ux-border);
  border-radius: var(--ui-radius-panel);
  box-shadow: var(--elev-4);
  padding: var(--ui-space-3);
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-2);
  user-select: none;
  font-family: var(--app-font);
  font-size: var(--fs-body);
  color: var(--ui-text-primary);
}

.token-date-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-space-1);
}

.token-date-title {
  flex: 1 1 auto;
  text-align: center;
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  color: var(--ui-text-primary);
}

.token-date-nav-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--ui-size-sm);
  height: var(--ui-size-sm);
  padding: 0;
  border: var(--ui-stroke-thin) solid transparent;
  border-radius: var(--ui-radius-control);
  background: transparent;
  color: var(--ui-text-secondary);
  cursor: pointer;
  transition: background-color var(--ui-duration-fast) var(--ui-ease),
              color var(--ui-duration-fast) var(--ui-ease);
}

.token-date-nav-btn:hover {
  background: rgba(var(--ink), 0.08);
  color: var(--ui-text-primary);
}

.token-date-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: var(--ui-space-0-5);
  text-align: center;
  padding: var(--ui-space-1) 0;
  border-bottom: var(--ui-stroke-thin) solid var(--ui-divider);
}

.token-date-weekday {
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  color: var(--ui-text-muted);
}

.token-date-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: var(--ui-space-0-5);
}

.token-date-cell {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--ui-size-md);
  padding: 0;
  border: var(--ui-stroke-thin) solid transparent;
  border-radius: var(--ui-radius-control);
  background: transparent;
  color: var(--ui-text-primary);
  font-size: var(--fs-body);
  font-family: var(--app-font);
  cursor: pointer;
  transition: background-color var(--ui-duration-fast) var(--ui-ease),
              border-color var(--ui-duration-fast) var(--ui-ease);
}

.token-date-cell:hover:not(.is-selected) {
  background: rgba(var(--ink), 0.08);
}

.token-date-cell.is-other-month {
  color: var(--ui-text-muted);
  opacity: 0.45;
}

.token-date-cell.is-today:not(.is-selected) {
  border-color: var(--ui-accent);
  font-weight: var(--fw-semibold);
  color: var(--ui-accent);
}

.token-date-cell.is-selected {
  background: var(--ui-accent-solid);
  color: var(--ui-text-on-accent);
  font-weight: var(--fw-semibold);
}

.token-date-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: var(--ui-space-1-5);
  border-top: var(--ui-stroke-thin) solid var(--ui-divider);
}

.token-date-action-btn {
  border: 0;
  background: transparent;
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  font-family: var(--app-font);
  padding: var(--ui-space-1) var(--ui-space-2);
  border-radius: var(--ui-radius-control);
  cursor: pointer;
  transition: background-color var(--ui-duration-fast) var(--ui-ease),
              color var(--ui-duration-fast) var(--ui-ease);
}

.token-date-action-btn.is-clear {
  color: var(--ui-text-secondary);
}

.token-date-action-btn.is-clear:hover {
  background: rgba(var(--ink), 0.08);
  color: var(--ui-text-primary);
}

.token-date-action-btn.is-today {
  color: var(--ui-accent);
}

.token-date-action-btn.is-today:hover {
  background: rgba(var(--ui-accent-rgb), 0.12);
}

/* Time range input styling đồng bộ Segoe UI */
.time-range-field .form-input,
.time-range-field .form-input::-webkit-datetime-edit,
.time-range-field .form-input::-webkit-datetime-edit-fields-wrapper,
.time-range-field .form-input::-webkit-datetime-edit-text,
.time-range-field .form-input::-webkit-datetime-edit-hour-field,
.time-range-field .form-input::-webkit-datetime-edit-minute-field,
.time-range-field .form-input::-webkit-datetime-edit-ampm-field {
  font-family: var(--app-font);
  font-size: var(--fs-body);
  font-weight: var(--fw-normal);
  color: var(--ui-text-primary);
}


/* Header 1 hàng kiểu Google Keep: TRÁI chỉ có tiêu đề + thẻ dự án (không bị
   co lại khi cửa sổ hẹp — title dùng min-width:0 để tự nhường chỗ), PHẢI gom
   toàn bộ icon thao tác. Thay cho khuôn 2 hàng cũ (.notics-editor-title-row
   + .notics-editor-meta-row) mà Notics vẫn giữ nguyên — đây là biến thể
   riêng của NoteSpeed nên không đụng tới base dùng chung. */
/* Icon nào cũng cần đứng cạnh nhau đều tăm tắp — is-icon-only đã lo kích
   thước (32x32), ở đây chỉ bớt khoảng đệm ngoài cho khít cụm. */

/* "Thẻ dự án": trigger của tokenSelect thu gọn thành dạng pill nhỏ đứng cạnh
   tiêu đề, thay vì một ô dropdown to như trước. */

/* Màu icon theo trạng thái, đúng chuẩn token đang dùng cho Khóa/Ghim ở nơi
   khác trong app (amber cho khóa/ghim, accent cho hành động đang bật, đỏ
   cho hành động phá hủy) — không hard-code màu riêng cho NoteSpeed. */

/* Nút "Nền" (chấm màu) + popover màu nền: styles/note-editor-shell.css (dùng chung AntiNote). */

/* ── Nút chỉ-icon trong khu Ghi chú (bỏ nhãn chữ: Bảo mật / Khóa / Nền) ──
   Gọn về ô vuông cạnh bằng chiều cao control, icon canh giữa. */
:is(.notics-btn-lock-toggle).is-icon-only {
  width: var(--ui-size-md);
  min-width: var(--ui-size-md);
  justify-content: center;}
.notespeed-bg-btn.is-icon-only .notespeed-bg-btn-dot { width: var(--dt-dimension-icon-header); height: var(--dt-dimension-icon-header); }










/* "Tất cả" — overlay phủ toàn trang module, không phải modal ứng dụng (không
   dùng registerOverlay của overlayManager): nó chỉ che nội dung của riêng
   module đó, đóng bằng Esc tự bắt trong file JS tương ứng.
   NAY CHỈ CÒN AntiPaint (#antiPaintAllOverlay) và Art Editor
   (#antiScreenshotAllOverlay) dùng — QuickNote đã bỏ popup này, lưới thẻ của
   nó là màn hình chính (xem khối bên dưới). */
.notespeed-all-overlay {
  position: absolute;
  inset: 0;
  z-index: var(--ui-layer-control);
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(var(--ui-shadow-rgb), 0.35);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.notespeed-all-panel {
  width: min(var(--dt-dimension-layout-960), 92%);
  height: min(var(--dt-dimension-layout-640), 86%);
  display: flex;
  flex-direction: column;
  /* L4 overlay — hộp "Tất cả" phủ lên trang nên phải đục và nổi hơn thẻ. */
  background: var(--ux-overlay);
  border: var(--ui-stroke-thin) solid var(--stroke);
  border-radius: var(--ui-radius-panel);
  box-shadow: var(--elev-4);
  overflow: hidden;
}

.notespeed-all-header {
  flex: 0 0 auto;
  height: var(--dt-dimension-layout-56);
  padding: 0 var(--ui-space-4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: var(--ui-resizer-line) solid var(--ux-divider);
}


/* [MODULARIZED] QuickNote & AntiPaint details moved to src/renderer/styles/paint-speed.css */

/* ========================================================================== */
/* 2026-08 — Unified Fluent/Liquid Glass product shell                       */
/* Khối token --sf-* / --ux-* (light + dark) → ĐÃ CHUYỂN sang               */
/* src/renderer/styles/ui-theme-core.css (cắt nguyên xi). Vẫn nạp SAU khối   */
/* "Design system tokens" nên vẫn ghi đè như cũ. Các rule .topbar / .grid    */
/* bên dưới giữ nguyên tại đây.                                              */
/* ========================================================================== */

html:not(.is-image-canvas) .topbar {
  box-sizing: border-box;
  backdrop-filter: blur(22px) saturate(1.16);
  -webkit-backdrop-filter: blur(22px) saturate(1.16);}

/* Header và rail KHÔNG được ép #ffffff ở chế độ Sáng: chúng là hai bề mặt
   chrome duy nhất còn lại mà hiệu ứng kính đọc ra được, và --ux-header đã nhân
   sẵn --a-header (Đục 1 · Đậm .92 · Acrylic .78 · Kính trong .64). Ép trắng đục
   ở đây là lý do bốn bậc độ đục nhìn như nhau ở chế độ Sáng.
   Các panel nổi (menu, picker) thì vẫn giữ nền đục — chúng che nội dung bên
   dưới trong lúc thao tác nên cần tương phản tuyệt đối. Nhưng chúng KHÔNG còn
   rule riêng ở đây nữa: nền của mọi lớp nổi giờ do một token duy nhất
   --surface-raised quyết định, cho cả Sáng lẫn Tối (xem khối "B. Bề mặt nổi"
   bên dưới). Trước đây chỉ có bản Sáng ép #ffffff mà không có bản Tối, nên ở
   chế độ Tối các popup rơi về một màu khác hẳn phần còn lại của app. */


html:not(.is-image-canvas) :is(
  .grid,
  .notics-page,
  .feedback-admin-page,
  .project-page,
  .dashboard-page,
  .settings-page,
  .premium-page,
  .premium-admin-page,
  .antiscreenshot-page,
  .guide-page
) {
  /* Vòng viền 1px phải nằm trên nền như viền của .topbar ngay phía trên. Khi có
     hình nền, các trang có pane bên trong bỏ veil (--surface-page: transparent,
     xem "HỢP ĐỒNG HÌNH NỀN") nên viền rơi thẳng lên ảnh, còn pane chỉ tô từ
     trong viền: thân trang trông hụt 1px so với header. Lớp ảnh dưới đây chỉ
     tô đúng vùng viền (border-area), không chồng thêm veil dưới pane.
     --ux-page-frame-fill mặc định trong suốt nên các trang có veil không đổi.
     Lớp `none` thứ hai là bắt buộc: background-color lấy clip của lớp DƯỚI
     CÙNG; chỉ có một lớp ảnh thì giá trị `border-box` thừa bị bỏ, màu nền bị cắt
     theo border-area và trang có veil (lưới lịch Tháng) mất luôn nền, lộ ảnh. */
  background-image: linear-gradient(var(--ux-page-frame-fill), var(--ux-page-frame-fill)), none;
  background-clip: border-area, border-box;}

/* ==========================================================================
   CHẾ ĐỘ LIỀN MẠCH (SEAMLESS SHELL FRAME) — kiểu TickTick (17/09/2026)
   - Menu trái + header là MỘT dải khung liền màu (--ui-chrome-surface), bọc
     tiếp xuống cạnh phải và cạnh dưới bằng một khe --ui-seamless-inset.
   - Thân trang là một tấm bo đủ 4 góc (--ui-seamless-canvas-radius) nằm lọt
     trong khung. KHÔNG có đường viền ngang/dọc nào ở góc giao.
   - Màu khung theo Cài đặt > Khung viền > Màu khung (html[data-shell-chrome]):
       neutral           — nền trung tính theo Sáng/Tối, chữ giữ nguyên;
       blue … graphite   — nền màu, chữ/icon trên khung dùng bộ mực sáng;
       yellow, white     — nền sáng, chữ/icon trên khung dùng bộ mực tối.
     Khung sáng (neutral, white) gần màu thân trang nên tấm thân trang có một
     đường viền KHÉP KÍN.
   - Cột con (cây dự án, danh sách dự án, menu Cài đặt) nằm TRONG tấm thân
     trang với nền trầm + đường chia dọc của chính nó (như TickTick/Slack/Teams).
   - Chỉ áp dụng khi data-shell-frame="seamless" và KHÔNG ở chế độ ảnh nền
     (.is-image-canvas có vỏ trong suốt riêng); chế độ Thẻ nổi giữ nguyên.
   ========================================================================== */

html[data-shell-frame="seamless"] {
  --ui-chrome-surface: var(--ui-chrome-neutral-surface);
}

html[data-shell-frame="seamless"]:is(
  [data-shell-chrome="blue"],
  [data-shell-chrome="green"],
  [data-shell-chrome="purple"],
  [data-shell-chrome="pink"],
  [data-shell-chrome="orange"],
  [data-shell-chrome="graphite"]
) {
  --ui-chrome-fg: var(--ui-chrome-ink-light-fg);
  --ui-chrome-fg-muted: var(--ui-chrome-ink-light-fg-muted);
  --ui-chrome-hover: var(--ui-chrome-ink-light-hover);
  --ui-chrome-active: var(--ui-chrome-ink-light-active);
  --ui-chrome-line: var(--ui-chrome-ink-light-line);
  --ui-chrome-field: var(--ui-chrome-ink-light-field);
  /* Kênh RGB cho công thức rgba(var(--ink|--ui-accent-rgb), a) trên khung. */
  --ui-chrome-ink-rgb: var(--ui-white-rgb);
  --ui-chrome-accent-rgb: var(--ui-white-rgb);
}

html[data-shell-frame="seamless"]:is([data-shell-chrome="yellow"], [data-shell-chrome="white"]) {
  --ui-chrome-fg: var(--ui-chrome-ink-dark-fg);
  --ui-chrome-fg-muted: var(--ui-chrome-ink-dark-fg-muted);
  --ui-chrome-hover: var(--ui-chrome-ink-dark-hover);
  --ui-chrome-active: var(--ui-chrome-ink-dark-active);
  --ui-chrome-line: var(--ui-chrome-ink-dark-line);
  --ui-chrome-field: var(--ui-chrome-ink-dark-field);
  --ui-chrome-ink-rgb: var(--ink);
  --ui-chrome-accent-rgb: var(--ui-accent-rgb);
}

html[data-shell-frame="seamless"][data-shell-chrome="blue"] { --ui-chrome-surface: var(--ui-chrome-palette-blue); }
html[data-shell-frame="seamless"][data-shell-chrome="green"] { --ui-chrome-surface: var(--ui-chrome-palette-green); }
html[data-shell-frame="seamless"][data-shell-chrome="purple"] { --ui-chrome-surface: var(--ui-chrome-palette-purple); }
html[data-shell-frame="seamless"][data-shell-chrome="pink"] { --ui-chrome-surface: var(--ui-chrome-palette-pink); }
html[data-shell-frame="seamless"][data-shell-chrome="orange"] { --ui-chrome-surface: var(--ui-chrome-palette-orange); }
html[data-shell-frame="seamless"][data-shell-chrome="yellow"] { --ui-chrome-surface: var(--ui-chrome-palette-yellow); }
html[data-shell-frame="seamless"][data-shell-chrome="graphite"] { --ui-chrome-surface: var(--ui-chrome-palette-graphite); }
html[data-shell-frame="seamless"][data-shell-chrome="white"] { --ui-chrome-surface: var(--ui-chrome-palette-white); }

/* Khung có màu (mọi lựa chọn trừ neutral): chụp lại token GỐC ở cấp html trước
   khi khung ghi đè chúng. Popup nằm trong DOM của header/rail đọc lại bản gốc
   này, nếu không sẽ thừa hưởng màu chữ của khung trên nền popup. */
html[data-shell-frame="seamless"]:not([data-shell-chrome="neutral"]):not(.is-image-canvas) {
  --ui-chrome-keep-text-primary: var(--ui-text-primary);
  --ui-chrome-keep-text-secondary: var(--ui-text-secondary);
  --ui-chrome-keep-text-muted: var(--ui-text-muted);
  --ui-chrome-keep-text-on-accent: var(--ui-text-on-accent);
  --ui-chrome-keep-accent: var(--ui-accent);
  --ui-chrome-keep-accent-rgb: var(--ui-accent-rgb);
  --ui-chrome-keep-accent-solid: var(--ui-accent-solid);
  --ui-chrome-keep-ink: var(--ink);
  --ui-chrome-keep-border: var(--ux-border);
  --ui-chrome-keep-divider: var(--ux-divider);
  --ui-chrome-keep-ui-divider: var(--ui-divider);
  --ui-chrome-keep-stroke: var(--stroke);
  --ui-chrome-keep-hover: var(--ui-hover);
  --ui-chrome-keep-ux-hover: var(--ux-hover);
  --ui-chrome-keep-control-border-hover: var(--ux-control-border-hover);
  --ui-chrome-keep-control-border-active: var(--ux-control-border-active);
  --ui-chrome-keep-surface-panel: var(--ui-surface-panel);
  --ui-chrome-keep-raised: var(--ux-raised);
}

html[data-shell-frame="seamless"]:not([data-shell-chrome="neutral"]):not(.is-image-canvas) :is(.nav-rail, .topbar) {
  --ui-text-primary: var(--ui-chrome-fg);
  --ui-text-secondary: var(--ui-chrome-fg-muted);
  --ui-text-muted: var(--ui-chrome-fg-muted);
  --ui-text-on-accent: var(--ui-chrome-surface);
  --ui-accent: var(--ui-chrome-fg);
  --ui-accent-solid: var(--ui-chrome-fg);
  --ui-accent-rgb: var(--ui-chrome-accent-rgb);
  --ink: var(--ui-chrome-ink-rgb);
  --ux-border: var(--ui-chrome-line);
  --ux-divider: var(--ui-chrome-line);
  --ui-divider: var(--ui-chrome-line);
  --stroke: var(--ui-chrome-line);
  --ui-hover: var(--ui-chrome-hover);
  --ux-hover: var(--ui-chrome-hover);
  --ux-control-border-hover: var(--ui-chrome-line);
  --ux-control-border-active: var(--ui-chrome-fg);
  --ui-surface-panel: var(--ui-chrome-field);
  --ux-raised: var(--ui-chrome-field);
  color: var(--ui-chrome-fg);
}

html[data-shell-frame="seamless"]:not([data-shell-chrome="neutral"]):not(.is-image-canvas) :is(.nav-rail, .topbar) :is(
  .widget-menu-panel,
  .picker-panel,
  .notics-project-filter-panel,
  .notics-create-menu,
  [role="menu"],
  [role="listbox"],
  [role="dialog"]
) {
  --ui-text-primary: var(--ui-chrome-keep-text-primary);
  --ui-text-secondary: var(--ui-chrome-keep-text-secondary);
  --ui-text-muted: var(--ui-chrome-keep-text-muted);
  --ui-text-on-accent: var(--ui-chrome-keep-text-on-accent);
  --ui-accent: var(--ui-chrome-keep-accent);
  --ui-accent-rgb: var(--ui-chrome-keep-accent-rgb);
  --ui-accent-solid: var(--ui-chrome-keep-accent-solid);
  --ink: var(--ui-chrome-keep-ink);
  --ux-border: var(--ui-chrome-keep-border);
  --ux-divider: var(--ui-chrome-keep-divider);
  --ui-divider: var(--ui-chrome-keep-ui-divider);
  --stroke: var(--ui-chrome-keep-stroke);
  --ui-hover: var(--ui-chrome-keep-hover);
  --ux-hover: var(--ui-chrome-keep-ux-hover);
  --ux-control-border-hover: var(--ui-chrome-keep-control-border-hover);
  --ux-control-border-active: var(--ui-chrome-keep-control-border-active);
  --ui-surface-panel: var(--ui-chrome-keep-surface-panel);
  --ux-raised: var(--ui-chrome-keep-raised);
  color: var(--ui-chrome-keep-text-primary);
}


/* Hình nền chỉ hiện TRONG tấm thân trang; khe khung phải cùng màu với rail
   và header, không được lộ ảnh ra. */
html[data-shell-frame="seamless"]:not(.is-image-canvas) .app-background {
  inset: var(--ui-header-h) var(--ui-seamless-inset) var(--ui-seamless-inset) var(--rail-w);
  border-radius: var(--ui-seamless-canvas-radius);
}

/* Hình học rail áp cả ở màn Ảnh (Ctrl+6): chỉ NỀN khung mới loại trừ
   .is-image-canvas. Trước đây cả khối bị loại trừ nên vào màn Ảnh rail lấy lại
   padding của Thẻ nổi — avatar và các mục tụt 9px, hẹp 2px (giật menu). */

html[data-shell-frame="seamless"]:not(.is-image-canvas) .nav-rail {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;}

html[data-shell-frame="seamless"] .nav-rail-avatar-btn,
html[data-shell-frame="seamless"] .nav-rail-avatar-btn:hover,
html[data-shell-frame="seamless"] .nav-rail-avatar-btn.is-active {
  display: flex !important;}

html[data-shell-frame="seamless"] .nav-rail-avatar-btn .nav-rail-icon {
  width: var(--ui-size-md);}

html[data-shell-frame="seamless"] .nav-rail-avatar-btn .menu-avatar-wrap,
html[data-shell-frame="seamless"] .nav-rail-avatar-btn .menu-avatar {
  width: var(--ui-size-md);}

/* Icon rail trên khung có màu: nghỉ = chữ mờ, chọn = chữ đặc + nền pill.
   --item-accent (màu module) đặt inline trên .nav-rail-item nên ghi đè ở
   phần tử con để icon/nhãn đọc giá trị của khung. */
html[data-shell-frame="seamless"]:not([data-shell-chrome="neutral"]):not(.is-image-canvas) .nav-rail-item :is(.nav-rail-icon, .nav-rail-label) {
  --item-accent: var(--ui-chrome-fg);
}

html[data-shell-frame="seamless"]:not([data-shell-chrome="neutral"]):not(.is-image-canvas) .nav-rail-item:not(.nav-rail-avatar-btn):hover .nav-rail-icon {
  background: var(--ui-chrome-hover);
}

html[data-shell-frame="seamless"]:not([data-shell-chrome="neutral"]):not(.is-image-canvas) .nav-rail-item.is-active:not(.nav-rail-avatar-btn) .nav-rail-icon {
  color: var(--ui-chrome-fg);
  background: var(--ui-chrome-active);
}

html[data-shell-frame="seamless"]:not(.is-image-canvas) .topbar {
  position: relative;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;}

/* Nút viền trên header có nền đặc (surface-raised) nên trên khung màu phải
   chuyển sang nền mờ của khung, nếu không là chữ sáng trên nền sáng. */
html[data-shell-frame="seamless"]:not([data-shell-chrome="neutral"]):not(.is-image-canvas) .topbar .notics-open-project-btn {
  background: var(--ui-chrome-field);
}

/* Cụm chọn tuần mang cùng nền pill với cụm chọn dạng xem đứng cạnh nó. */

html[data-shell-frame="seamless"]:not(.is-image-canvas) :is(
  .grid,
  .notics-page,
  .feedback-admin-page,
  .project-page,
  .dashboard-page,
  .settings-page,
  .premium-page,
  .premium-admin-page,
  .antiscreenshot-page,
  .guide-page
) {
  /* Lớp tô vòng viền của chế độ Thẻ nổi không dùng ở đây: tấm cắt theo
     padding-box nên lớp đó sẽ phủ cả thân trang. */
  background-image: none;
  overflow: hidden;
  --ui-seamless-inner-radius: calc(var(--ui-seamless-canvas-radius) - var(--ui-seamless-card-border, 0px));}

/* Premium không có thân cuộn bên trong như các trang trên: chính tấm là vùng
   cuộn. `auto` vẫn cắt nội dung theo bo góc như `hidden`, chỉ không khóa cuộn. */
html[data-shell-frame="seamless"]:not(.is-image-canvas) .premium-page {
  overflow: auto;
}

/* Lịch dạng Danh sách cũng vậy: #grid chính là vùng cuộn (calendar.css,
   `html .grid.agenda-view`). Luật tấm ở trên (0,3,1) đè `overflow-y: auto`
   của nó (0,2,1) nên ở Liền mạch Danh sách bị cắt đáy, không cuộn được. */
html[data-shell-frame="seamless"]:not(.is-image-canvas) .grid.agenda-view {
  overflow-x: hidden;
  overflow-y: auto;
}

/* Header ghim ở đỉnh tấm có backdrop-filter: khi chạy GPU, lớp hợp thành đó
   không bị overflow + border-radius của tấm cắt, nên góc trên thò ra vuông
   (Cài đặt, Premium, Quản trị…). Bo chính header theo bán kính TRONG của tấm. */
html[data-shell-frame="seamless"]:not(.is-image-canvas) :is(
  .premium-admin-header-bar,
  .notics-page-header) {
  border-start-start-radius: var(--ui-seamless-inner-radius);
  border-start-end-radius: var(--ui-seamless-inner-radius);
}

/* Khung sáng (neutral, white): nền khung và thân trang gần màu nhau nên tấm
   thân trang cần một đường viền KHÉP KÍN (không phải hai nét cắt nhau).
   Viền bán trong suốt và nền tấm cắt theo padding-box, mà .app-background nằm
   đúng khung tấm → có hình nền thì nét 1px lộ ảnh, loang màu (05/10/2026). Vùng
   viền được tô lót màu khung (--ux-page-frame-fill = --ui-chrome-surface, clip
   border-area) ở khối overrides cuối file: viền ra đúng màu như khi không có ảnh. */
html[data-shell-frame="seamless"]:is([data-shell-chrome="neutral"], [data-shell-chrome="white"]):not(.is-image-canvas) :is(
  .grid,
  .notics-page,
  .feedback-admin-page,
  .project-page,
  .dashboard-page,
  .settings-page,
  .premium-page,
  .premium-admin-page,
  .antiscreenshot-page,
  .guide-page
) {
  --ui-seamless-card-border: var(--ui-resizer-line);}

/* Lớp lót viền chỉ che được đoạn thẳng: ở cung bo góc, mép ảnh nền và mép lớp
   lót cùng khử răng cưa trên một đường cong nên ảnh lọt qua, góc trên như bị
   đè ~2px (06/10/2026). Thu ảnh nền vào đúng mép trong của viền, bo theo bán
   kính trong — dưới vùng viền chỉ còn màu khung. Thụt 2 nét (BA 11/10/2026: bo 16 ở màn 125%
   thì khử răng cưa của cung rộng hơn 1px, góc trên-phải lọt ảnh), vẫn đồng tâm với cung bo. */
html[data-shell-frame="seamless"]:is([data-shell-chrome="neutral"], [data-shell-chrome="white"]):not(.is-image-canvas) .app-background {
  inset: calc(var(--ui-header-h) + var(--ui-stroke-thick))
    calc(var(--ui-seamless-inset) + var(--ui-stroke-thick))
    calc(var(--ui-seamless-inset) + var(--ui-stroke-thick))
    calc(var(--rail-w) + var(--ui-stroke-thick));
  border-radius: calc(var(--ui-seamless-canvas-radius) - var(--ui-stroke-thick));
}

/* Lịch dạng danh sách: thanh tuần là đoạn TRÊN của cùng tấm thân trang.
   - Nền = đúng nền canvas của lưới (--ux-base), không phải bậc popup
     --ux-overlay, để hai đoạn đọc ra một mặt.
   - Viền khép kín (nếu có) chia đôi: thanh tuần giữ cạnh trên + hai bên, lưới
     giữ cạnh dưới + hai bên, và chỉ còn MỘT đường chia giữa hai đoạn. */
html[data-shell-frame="seamless"]:not(.is-image-canvas) .agenda-week-bar:not(.hidden) {
  margin: 0 var(--ui-seamless-inset) 0 0;
  border: 0;
  border-bottom: var(--ui-resizer-line) solid var(--ux-divider);
  border-radius: var(--ui-seamless-canvas-radius) var(--ui-seamless-canvas-radius) 0 0;
  background: var(--ux-base);
  /* Cùng quy tắc với tấm thân trang (padding-box): nền không lan dưới nét viền.
     Để mặc định border-box thì viền thanh tuần vẽ đè lên nền mờ của chính nó
     (xám), còn viền lưới bên dưới vẽ trên hình nền/khung (ánh màu) — hai đoạn
     của cùng một viền lệch màu, nhảy màu khi đổi Hôm nay ↔ Danh sách. */
  background-clip: padding-box;
}

html[data-shell-frame="seamless"]:is([data-shell-chrome="neutral"], [data-shell-chrome="white"]):not(.is-image-canvas) .agenda-week-bar:not(.hidden) {
  border: var(--ui-resizer-line) solid var(--ux-border);
  border-bottom-color: var(--ux-divider);
  /* Cùng lớp lót viền màu khung với tấm lưới bên dưới (xem khối viền khép kín). */
  background-image: linear-gradient(var(--ui-chrome-surface), var(--ui-chrome-surface)), none;
  background-clip: border-area, padding-box;
}

/* Có hình nền: thanh tuần và lưới trong suốt, thẻ tuần/ngày nổi trên ảnh, nên
   đường chia giữa hai đoạn thành một nét kẻ ngang cắt qua ảnh (06/10/2026).
   Bỏ nét chia; viền ngoài khép kín của tấm giữ nguyên. */
html.has-wallpaper[data-shell-frame="seamless"]:not(.is-image-canvas) .agenda-week-bar:not(.hidden) {
  border-bottom-width: 0;
}


/* Triệt tiêu khoảng cách padding-top đẩy lùi sidebar ở chế độ liền mạch */

/* Các cột điều hướng con tiếp giáp phẳng 100% không khoét lẹm góc */

/* Chuẩn hóa header body (pane toolbars) ở chế độ liền mạch:
   Trong suốt (background: transparent) để hòa làm một bề mặt liên tục với cột,
   loại bỏ hiện tượng "Double Header" kẹp màu và chém ngang cột sidebar.
   .antiscreenshot-toolbar KHÔNG thuộc danh sách: thanh công cụ Art Editor (ảnh + video)
   là mặt phẳng đặc theo token sáng/tối, không lộ hình nền (BA 2026-09-27). */

/* MỘT SỐ TRANG TỰ LÀ CANVAS CỦA CHÍNH NÓ (06/09/2026).

   HỢP ĐỒNG HÌNH NỀN ở khối token phía dưới cho --surface-page về `transparent`
   khi có hình nền, với GIẢ ĐỊNH: lớp chắn hình nền là .ux-pane / .ux-canvas
   nằm BÊN TRONG vỏ trang. Giả định đó đúng với sáu trang có cột mang class vai
   trò: Notebook, Dự án, Cài đặt, QuickNote, Painting, Art Editor.

   Năm trang dưới đây KHÔNG có class vai trò nào bên trong:
     .grid                 lịch vẽ thẳng .day-col mà .day-col nền TRONG SUỐT
                           (chủ ý — "Calendar matrix: one surface, separators
                           instead of cards and gutters", ~L4285);
     .dashboard-page       .premium-page      .premium-admin-page
     .feedback-admin-page  chỉ có thẻ/panel rời nằm trên nền trang.
   Với chúng, VỎ TRANG CHÍNH LÀ canvas L2. Xoá veil là xoá luôn bậc L2, không
   còn lớp nào chắn hình nền: trang Lịch trơ hình nền trong khi mọi trang khác
   vẫn có nền xám nhẹ — đúng triệu chứng người dùng báo 06/09/2026.

   Trả --surface-page về đúng bậc L2 ngay tại chỗ: KHÔNG thêm !important, vẫn đi
   qua MỘT điểm ép ưu tiên duy nhất là rule ngay trên. Khi TẮT hình nền,
   --surface-page vốn đã là --ux-base nên khối này là no-op — chỉ đổi đúng
   trường hợp đang sai. Alpha đi theo --a-content-light y như .ux-canvas của sáu
   trang kia, nên độ trong suốt đồng bộ đủ 11 trang. */
html:not(.is-image-canvas) :is(
  .grid,
  .dashboard-page,
  .premium-page,
  .premium-admin-page,
  .feedback-admin-page
) {
  --surface-page: var(--ux-base);
  --ux-page-frame-fill: transparent;
}

/* Rail là cột điều hướng → bậc L1 sunken, cùng token với cây dự án và các cột
   danh sách. Trước GĐ1 nó dùng --ux-header, mà --ux-header nhân --a-header
   (Acrylic .78 · Kính trong .64) — mỏng hơn hẳn thân trang, lại nằm sát mép
   cửa sổ nên 22–36% xuyên thẳng xuống desktop. Kết quả ở chế độ Tối: rail
   không còn là một bề mặt, nó chỉ là chỗ desktop lọt qua. Header vẫn giữ
   --ux-header — nó là dải ngang nằm TRÊN thân app nên phần xuyên qua là nội
   dung của chính app, đọc ra hiệu ứng kính chứ không thành lỗ thủng. */
.nav-rail {
  backdrop-filter: blur(22px) saturate(1.14);
  -webkit-backdrop-filter: blur(22px) saturate(1.14);}

.nav-rail-item {
  transition: color var(--ui-duration-fast) var(--ui-ease), background-color 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), transform var(--ui-duration-fast) var(--ui-ease);
}

/* Ba block "spec bộ design cũ" (hover + is-active + is-active riêng Dark) —
   gradient/màu theo --item-accent bằng color-mix() — đã bị đè hoàn toàn bởi
   khối "Canonical terminal block for the rail" (~dòng 16200): selector list ở
   đó liệt kê tường minh .nav-rail-item:hover/.is-active/dark .is-active, đặt
   border:0 (đè cả border-color), background/background-color:transparent,
   box-shadow:none, color:var(--ui-text-secondary) — phủ hết mọi property ba block này
   từng khai báo. Đúng như banner "selection belongs to the icon itself,
   never to a row/card" mô tả: nền/viền màu theo icon ở hàng đã bị bỏ, xóa hẳn
   ba block chết ở đây. */


.nav-rail-item:hover .nav-rail-icon svg {
  transform: none !important;}

.nav-rail-item.is-active .nav-rail-icon svg {
  transform: none !important;}

/* Các header cấp module dùng cùng chiều cao và cùng một surface. */
/* GĐ4: min-height / border-bottom / background từng khai ở đây đã xóa — cùng
   selector này được ui-foundation.css khai lại (nạp sau, cũng ép ưu tiên) nên
   ba dòng ở đây chưa bao giờ có tác dụng. Nền header nay là --ux-header của
   thang bề mặt, không phải --surface-panel. */
:is(.notics-page-header, .feedback-admin-header) {
  height: var(--app-header-height);
  color: var(--ui-text-primary);
  backdrop-filter: blur(16px) saturate(1.1);
  -webkit-backdrop-filter: blur(16px) saturate(1.1);
}


/* Hai block "Cột danh sách" từng đứng ở đây đã xóa từ đợt trước. GĐ2 đi tiếp
   một bước: nền cột không còn bám tên component nữa mà bám class vai trò
   .ux-pane / .ux-canvas khai ở ui-foundation.css. */

:is(.notics-editor-wrap, .settings-main) {
  /* background: transparent — vốn ép ưu tiên — đã bị đè bởi ui-foundation.css:89
     (cùng giá trị transparent, nạp sau) — xóa hẳn ở đây. */
  color: var(--ui-text-primary);
}

/* Settings: mỗi nhóm là một surface có chủ đích, thay vì chìm trong vùng trắng. */


/* Lớp override .settings-scroll / .settings-section / .settings-card* từng ở đây
   đã GỘP hết vào khối gốc (~dòng 2495–2545) — một-nguồn-một-khai-báo, hết
   !important cho thẻ Cài đặt. */

/* Khối cũ "nâng cỡ chữ nhỏ nhất" đã bị đè hoàn toàn bởi khối eyebrow phía dưới
   (.notics-eyebrow, .dashboard-page .notics-eyebrow, .dashboard-kicker — nay
   dùng spec overline dùng chung), cùng phủ đúng hai selector này và trùng cả
   letter-spacing. Xóa hẳn, không còn tác dụng gì ở đây. */

/* P0: nội dung dán từ Word/clipboard có màu inline tối phải đọc được ở Dark. */

/* Màu inline tương phản thấp (dán từ Word/email, hoặc chọn ở chế độ kia) do
   utils/inkAdaptation.js xử lý lúc hiển thị — chuỗi selector theo mã màu cũ ở
   đây không bao giờ khớp cách Quill ghi style ("color: rgb(…)") nên đã gỡ. */



/* Control system: cùng chiều cao, radius, focus ring và phản hồi tương tác.
   .settings-nav-item KHÔNG thuộc họ nút: nó là mục điều hướng, theo hợp đồng
   NavigationView ở ui-components.css (17/09/2026). */



/* Chỉ áp cho control không viền/nền riêng (button) và input dạng bật/tắt
   (checkbox/radio/range/file). Input/select/textarea văn bản dùng vòng sáng
   mềm --ui-control-ring ("Ô NHẬP CHUẨN" ui-components.css), không outline
   cứng này — theo đúng quy ước Fluent 2/Material 3/HIG (xem giải thích đầy
   đủ ở khối "Vòng focus hai lớp" phía dưới, đây là một bản gần trùng lặp
   của khối đó). */
:is(
  button:not(.token-date-trigger):not(.token-select-trigger):not(.antiscreenshot-stepper-btn),
  [role="button"],
  input[type="checkbox"],
  input[type="radio"],
  input[type="range"],
  input[type="file"]
):focus-visible {
  outline-offset: var(--ui-focus-ring-offset);}

:is(
  .premium-admin-search,
  input[type="text"]:not(.topbar-search-input):not(.notespeed-quick-input):not(.project-notes-search-input):not(.notics-find-input):not(.notics-cmdk-input):not(.notics-note-title):not(.notics-project-filter-search):not(.note-search-input):not(.antiscreenshot-inspector-input):not(.antiscreenshot-inspector-field input),
  input[type="search"]:not(.topbar-search-input):not(.notespeed-quick-input):not(.project-notes-search-input):not(.notics-find-input):not(.notics-cmdk-input):not(.notics-note-title):not(.notics-project-filter-search):not(.note-search-input):not(.antiscreenshot-inspector-input):not(.antiscreenshot-inspector-field input),
  input[type="date"],
  select
) {
  border-color: var(--ux-border);
  border-radius: var(--ui-radius-control);
  background-color: color-mix(in srgb, var(--ux-card) 90%, transparent);
  color: var(--ui-text-primary);
}


/* Tooltip ứng dụng thay native tooltip tối và lệch hệ thiết kế trong Light. */
.app-tooltip {
  position: fixed;
  z-index: var(--ui-layer-toast);
  max-width: min(var(--dt-dimension-layout-288), calc(100vw - var(--ui-space-4)));
  padding: var(--ui-space-1-5) var(--ui-space-2);
  border: var(--ui-stroke-thin) solid var(--ux-border);
  border-radius: var(--ui-radius-control);
  background: color-mix(in srgb, var(--ux-card) 96%, transparent);
  box-shadow: var(--ux-shadow);
  color: var(--ui-text-primary);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-snug);
  pointer-events: none;
  opacity: 0;
  transform: translateY(-2px) scale(.98);
  transition: opacity var(--ui-duration-fast) var(--ui-ease), transform var(--ui-duration-fast) var(--ui-ease);
  backdrop-filter: blur(18px) saturate(1.12);
  -webkit-backdrop-filter: blur(18px) saturate(1.12);
}

.app-tooltip.is-visible { opacity: 1; transform: translateY(0) scale(1); }

/* Khối "Image canvas vẫn là module của app" (padding-left, background,
   box-shadow trên html.is-image-canvas .app; background trên .app-bg-overlay)
   đã bị đè hoàn toàn bởi khối "Trang chỉ hiển thị nền" ở dòng ~14209 — đúng
   selector, khai báo sau, phủ hết cả ba property. Xóa hẳn hai block. */


@media (max-width: 760px) {
    :is(.notics-page-header) {
    height: auto;}
}

@media (prefers-reduced-motion: reduce) {
  }

/* ==========================================================================
   2026-08 — LỚP CHUẨN HOÁ SHELL & ĐIỀU KHIỂN (đợt 2)
   Sửa 5 điểm người dùng báo + các token mồ côi phát hiện khi audit.

   Nguyên tắc hình học của shell: mọi bề mặt cấp 1 (rail, header, thân trang)
   đều là "thẻ bo góc nổi trên nền shell", cách nhau đúng một --shell-gap.
   Trước đợt này header+thân đã là thẻ bo góc (margin 8px) nhưng rail vẫn là
   phiến vuông full-height dán sát mép — đó là lý do rail trông lệch hẳn.
   ========================================================================== */

:root {
  --shell-gap: var(--ui-space-2);
  --shell-radius: 0px;
  --app-header-height: var(--ui-header-h, 50px);
  --app-header-btn-size: var(--ui-header-control-size, 34px);
  --app-header-icon-size: var(--ui-header-icon-size, 18px);

  /* Rail rộng 72px thay vì 64px: sau khi trừ --shell-gap và padding 8px,
     lòng rail còn đúng 48px — bằng ô bấm 48x48 theo chuẩn Material 3
     Navigation Rail (target 56) / Fluent NavigationView (tối thiểu 32),
     và vượt ngưỡng 44x44 của WCAG 2.2 AAA. Ở 64px cũ ô bấm bị ép còn 44px
     nên vừa nhỏ vừa sát nhau. */
  --rail-w: 50px;
  --rail-item: 40px;
  --rail-icon: 22px;

  /* THANG --ts-* ĐÃ GỠ (30/08/2026). Nó là thang chữ thứ hai dựng ở đợt chuẩn
     hoá shell, trùng vai hoàn toàn với thang --fs-* ở đầu file: --ts-meta 11 =
     --fs-xs, --ts-body 12 = --fs-sm, --ts-strong 13 = --fs-md, --ts-title 16 =
     --fs-xl, --ts-page 22 = --fs-3xl, --ts-eyebrow = --fs-overline. Hai thang
     phủ cùng một dải px nên không có cách nào biết bậc nào thuộc thang nào —
     mỗi component chọn theo thói quen người viết nó. 27 call-site đã đổi sang
     token --fs-* tương đương, đúng từng pixel. ĐỪNG dựng lại thang thứ ba:
     bậc mới thuộc về thang vai trò ở đầu file. */

  /* Token bị dùng nhưng chưa bao giờ được định nghĩa. var() không hợp lệ mà
     không có fallback làm cả khai báo bị bỏ: border-radius rơi về 0 (menu
     thao tác task bị vuông góc), animation không chạy, nền mất hẳn. */
  --sf-ease: cubic-bezier(.2, .8, .2, 1);
  --sf-radius-control: 9px;
  --sf-card-rgb: var(--ui-surface-raised-rgb);
  --text-secondary: var(--ui-text-secondary);
  --bg-hover: rgba(var(--ink), .06);
}

html[data-rail="expanded"] { --rail-w: 200px; }

html[data-mode="light"] {
  --sf-bg: rgb(var(--ui-surface-shell-rgb));
  --sf-surface: rgb(var(--ui-surface-raised-rgb));
  --panel-bg: rgb(var(--ui-surface-raised-rgb));
  --ink-strong: var(--ui-text-primary);
}

html[data-mode="dark"] {
  --sf-bg: rgb(var(--ui-surface-shell-rgb));
  --sf-surface: rgb(var(--ui-surface-raised-rgb));
  --panel-bg: rgb(var(--ui-surface-raised-rgb));
  --ink-strong: var(--ui-text-primary);
}

/* --- 1. Rail thành thẻ bo góc, cùng nhịp với header + thân trang --------- */
/* Vị trí và bề rộng của rail do ui-foundation.css quyết định (một nguồn duy
   nhất). Ở đây chỉ còn viền và đổ bóng của thẻ.
   KHÔNG đặt lại border-radius: 0 ở đây — selector html[data-material="glass"]
   có specificity cao hơn .nav-rail của ui-foundation, nên chính hai dòng đó
   là thứ giữ rail vuông góc ở hệ Glass dù token đã đổi. */
/* GĐ4: cả hai dòng cũ (border + box-shadow) đều chết — ui-foundation.css khai
   "border" và "box-shadow: none" cho cùng .nav-rail và nạp sau. Viền rail nay
   do --ui-rail-divider quyết định theo bậc vật liệu. */

/* --- 2. Kích thước & giãn cách nút rail ---------------------------------- */
/* Nhóm icon chính canh lề trên sát dưới avatar theo flex thông thường.
   Không dùng ::before flex spacer để tránh đẩy nhóm icon xuống giữa rail. */
.nav-rail-body::before { content: none; }

.nav-rail-primary {
  position: static !important;
  inset: auto !important;
  transform: none !important;
}

.nav-rail-spacer { flex: 1 1 0; min-height: var(--ui-space-4-5); }

/* Nhóm dưới tách khỏi nhóm module bằng khoảng trống (.nav-rail-spacer), không thêm vạch
   (luật "một cách tách", BA 11/10/2026). */
.nav-rail-secondary {
  border-top: 0;
}
.nav-rail-icon svg { width: var(--rail-icon); height: var(--rail-icon); }

/* Chỉ báo mục đang chọn: pill nằm TRONG ô, kiểu Fluent 2. Bản cũ đặt
   left:-8px nên nó nằm đè lên mép rail — với rail bo góc thì đâm vào góc. */
.nav-rail-item.is-active::before {
  left: var(--ui-space-1) !important;
  top: 50%;
  height: var(--ui-icon-md);
  margin-top: calc(-1 * var(--ui-space-2-5));}

.nav-rail-toggle { height: var(--ui-size-lg); border-radius: var(--ui-radius-panel); }
.nav-rail-toggle svg { width: var(--ui-icon-sm); height: var(--ui-icon-sm); }

/* Nhóm tiện ích dưới cùng (Premium, Dashboard, Quản trị Premium) và avatar tài
   khoản LUÔN hiện ở đáy rail — ở mọi chiều cao cửa sổ và cả cỡ chữ 125%. Khi
   bảy icon module không đủ chỗ, chính cột module đó tự cuộn, thay vì các nút
   dưới trượt xuống dưới avatar hoặc cả rail biến thành một vùng cuộn làm mất
   hút chúng. Trước đây xử lý bằng @media (max-height:720px) cho rail cuộn cả
   khối — nhưng cuộn xong vẫn phải kéo mới thấy nhóm dưới, đúng thứ người dùng
   cần luôn thấy. */
.nav-rail-primary {
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none;
}
.nav-rail-primary::-webkit-scrollbar { width: 0; height: 0; }
.nav-rail-secondary,
.nav-rail-avatar-btn { flex: 0 0 auto; }

/* Nhãn khoá Premium: nền trước đây là var(--ui-surface-panel,#fff) — token không
   tồn tại nên luôn rơi về #fff, ra đốm trắng giữa rail tối. */
.nav-rail-item.is-locked::after {
  background-color: var(--ui-surface-panel);
  box-shadow: 0 0 0 1px var(--ux-border); /* audit-keep: bóng riêng của thành phần, không thuộc bậc elevation chuẩn */
}

/* --- 3. Trang "chỉ hiển thị nền": trả lại đúng mục đích ------------------ */
/* Đây là chế độ xem ảnh nền không kèm dữ liệu. Lớp trước phủ thêm veil 38%
   và ép hiện đủ rail + header, nên nó không còn là "xem ảnh nền" nữa. */




/* Chỉ chừa avatar làm lối mở menu. Rule cũ ép display:block lên #todayLabel,
   phá layout flex-column của nó nên "HÔM NAY" và ngày dính liền một dòng. */



/* --- 4. Nút Khóa / Xóa đứng cùng hệ với các nút header khác -------------- */
/* Trước: Khóa dùng .notics-btn-lock-toggle (padding 3px, chữ 11px, nền trong),
   Xóa dùng .notics-btn (cao 34px) — hai nút cạnh nhau lệch chiều cao, một bên
   có icon một bên không. */
/* GĐ4: .notics-btn đã thành .ui-btn, .notics-btn-lock-toggle đi cùng .ui-btn — bỏ khỏi khối ép cỡ chữ. */
.notics-icon-btn {
  height: var(--ui-size-md);
  min-height: var(--ui-size-md);
  padding: 0 var(--ui-space-3);
  font-weight: var(--fw-semibold);
  gap: var(--ui-space-2);}

.notics-btn-lock-toggle {
  display: inline-flex;
  align-items: center;}



.notics-icon-btn > svg { flex: none; }

/* Xóa là hành động phá huỷ: phải đọc ra ngay là "nguy hiểm", không chỉ đổi
   chữ sang đỏ nhạt như trước. */


/* Nút chỉ có icon phải vuông, không kéo dài theo padding chữ. */
:is(.notics-icon-btn, .notics-btn-note-menu) {
  width: var(--ui-size-md);
  justify-content: center;}

/* Phản hồi khi bấm — không giật (transform: none), chỉ fill nhẹ box */
:is(.notics-icon-btn, .notics-btn-lock-toggle,
    .nav-rail-toggle):active:not(:disabled) {
  transform: none;
  background-color: rgba(var(--ink), 0.10);
}

/* --- 5. Thang chữ dùng chung giữa các màn -------------------------------- */
.notics-eyebrow,
.dashboard-page .notics-eyebrow {
  color: var(--ui-text-primary);}


:is(.notics-page-header h1) {
  letter-spacing: var(--ls-overline);}

/* Tiêu đề trong trang Notebook (.notics-title-field) cỡ theo em của vùng soạn để
   ăn theo thu phóng — xem notics.css; rule ép cỡ ở đây chỉ còn cho tiêu đề header. */

/* Sàn cỡ chữ: tối thiểu 12px (Caption) cho văn bản đọc/nhãn, 13px (Body Small) cho tab/nút. */


/* Khu Quản trị Premium là chỗ duy nhất còn viền/nền hardcode đen-trắng,
   nên ở Dark mode đường kẻ tab gần như biến mất. */

@media (prefers-reduced-motion: reduce) {
  :is(.notics-icon-btn, .notics-btn-lock-toggle,
      .nav-rail-item, .nav-rail-toggle):active:not(:disabled) { transform: none; }
}

/* ==========================================================================
   2026-08 — SỬA RAIL Ở CHẾ ĐỘ XEM ẢNH NỀN (Ctrl+6)

   Hai lỗi cùng một gốc là cách ẩn rail bằng translateX:

   1) Viền trắng đè avatar. Rail ẩn bằng translateX(calc(-100% + 6px)) nên vẫn
      còn một dải ~14px nhô ra ở mép trái, mang theo border 1px sáng và góc bo
      16px — đúng chỗ avatar đang đứng.

   2) Hover bị giật. Rail rộng 64px đặt ở left:8px. Khi ẩn nó nằm ở x = -50..14;
      khi hover nó về x = 8..72. Con trỏ đang ở x≈4 (trong dải nhô ra) sau khi
      rail trượt vào thì nằm NGOÀI rail -> mất :hover -> trượt ra -> con trỏ lại
      nằm trong dải nhô ra -> trượt vào. Vòng dao động này là cái "giật" nhìn
      thấy, không phải máy yếu. backdrop-filter: blur(22px) làm nặng thêm vì
      mỗi khung hình của transform phải lấy mẫu lại toàn bộ ảnh nền phía sau.

   Cách sửa: bỏ hẳn transform. Rail đứng yên đúng vị trí thật và chỉ mờ/hiện.
   Vùng hover vì thế không bao giờ dịch chuyển -> hết dao động; opacity là
   thuộc tính rẻ nhất để animate -> hết giật; khi ẩn thì opacity 0 nên không
   còn viền sáng nào cạnh avatar.

   2026-08 cập nhật: avatar tài khoản chuyển từ topbar (.brand) vào rail
   (mục cuối cùng trong #navRail, đứng NGOÀI .nav-rail-body — xem index.html).
   Opacity của cha luôn nuốt opacity riêng của con nên không thể vừa ẩn
   #navRail vừa giữ avatar hiện — target ẩn/hiện phải là .nav-rail-body
   (bọc Task/Notics/.../nút thu-mở), không phải .nav-rail ngoài cùng nữa.
   #navRail giờ chỉ còn là khung chứa trong suốt, không tự mang nền/viền
   trong chế độ này. Yêu cầu: hover không tự bung — avatar nằm ngoài
   .nav-rail-body nên hover vào avatar không kích hoạt :hover của nó. */



/* Nền/viền của thẻ menu KHÔNG vẽ thẳng lên .nav-rail-body: khối này nằm trong
   padding 8px của #navRail nên chỉ rộng 46px, tô nền lên nó thì thẻ menu hụt
   16px so với màn thường (ở đó nền nằm trên chính .nav-rail, rộng đủ 64px).
   Vẽ bằng ::after tràn ra mép rail thì phần nhìn thấy đúng bằng thẻ rail ở
   màn thường mà layout bên trong không đổi.  ::after tràn xuống (-8px bottom)
   chứ không tràn lên, vì avatar nằm phía trên — tràn lên sẽ chồng hover. */

/* Nền thẻ menu nổi trong Image Canvas: vẽ bằng ::after tràn sang hai mép rail
   và tràn xuống đáy, top:0 nằm dưới avatar và gap nên không đè vào avatar.
   pointer-events:none triệt tiêu hoàn toàn hiện tượng chớp/giật màn hình khi hover. */



/* Avatar đứng một mình trên ảnh nền: bỏ luôn viên nền pill để không còn vòng
   sáng nào quanh nó. Đổ bóng nhẹ thay cho nền, đủ để avatar không chìm khi
   người dùng chọn ảnh nền sáng. */



/* ==========================================================================
   2026-08 — SỬA GIẬT KHI ĐỔI MODULE (rõ nhất khi rời màn Ảnh nền Ctrl+6)

   Bối cảnh quyết định: src/main.js:281 gọi app.disableHardwareAcceleration().
   App KHÔNG có compositor GPU. Vì vậy transform/opacity/backdrop-filter đều
   KHÔNG rẻ như trên web thường — mỗi khung hình đều rasterize bằng CPU.

   Khi rời .is-image-canvas có bốn thứ chạy transition cùng lúc, ngay đúng lúc
   trang mới đang layout lần đầu:
     .app            padding-left 0 -> 72px   (transition .18s)  <- RELAYOUT toàn cây
     .app-bg-overlay background transparent -> rgba(chrome, scrim)  (.3s)  <- repaint toàn màn
     .topbar         margin/radius/background + bật backdrop-filter blur(22px)
     .brand          transition: all var(--ui-duration-fast)  (nội suy cả padding/border/shadow)
   Cộng lại thành đúng cái giật người dùng thấy.
   ========================================================================== */

/* 1) Khoanh vùng đổi module: áp dụng cross-fade tinh tế var(--ui-duration-fast) trên vùng chứa nội dung của trang mới */
.app > main:not(.hidden),
.app > #grid:not(.hidden) {
  animation: viewCrossFade var(--ui-duration-fast) var(--ui-ease) forwards;
}

@keyframes viewCrossFade {
  0% { opacity: 0.88; }
  100% { opacity: 1; }
}

/* 2) Bỏ hẳn việc đổi padding-left ở màn Ảnh nền.
      Rail giờ không còn trượt ra ngoài nữa (chỉ mờ/hiện tại chỗ), nên không có
      lý do gì để thu padding về 0. Giữ nguyên --rail-w có hai cái lợi:
        - đổi vào/ra màn Ảnh nền không còn relayout toàn bộ cây;
        - avatar không còn nằm đè lên vùng hover vô hình của rail (x = 8..72),
          trước đây rê chuột tới avatar là rail tự hiện ra. */

/* 3) Lớp phủ ảnh nền: nội suy màu trên toàn màn hình bằng CPU là phép tô đắt
      nhất trong lúc chuyển màn. Rút ngắn để nó xong trước khi trang mới vẽ. */

/* 4) transition: all bắt trình duyệt nội suy MỌI thuộc tính đổi giá trị, kể cả
      padding/border-width vốn kéo theo relayout. Riêng .brand nằm trên topbar
      và đổi cả bộ khi vào/ra màn Ảnh nền nên phải khoanh lại. */

/* ==========================================================================
   2026-08 — SỬA TƯƠNG PHẢN CHỮ TRÊN NỀN ACCENT VÀ NÚT XÓA

   A) Nút nền accent + chữ trắng. Ở Dark mode --sf-accent là #4f9cf9 (xanh sáng,
      chọn sáng để link/icon nổi trên nền tối). Nhưng chữ trắng đặt lên chính
      màu đó chỉ đạt 2.82:1 — dưới hẳn ngưỡng AA 4.5:1. Đây là nút "Thêm công
      việc", "+ Ghi chú", "+ Bản vẽ", "+ Dự án" và mọi tab/tool đang active,
      tức là các nút nổi bật nhất màn hình.

      Không hạ độ sáng accent, vì cùng token đó còn dùng cho link và icon trên
      nền tối, hạ xuống là hỏng chỗ khác. Cách chuẩn (Material 3 "on-primary"):
      tách riêng màu chữ ĐẶT TRÊN accent thành token --on-accent.
        light: #ffffff trên #2563eb -> 5.17:1  PASS
        dark : #0b1220 trên #4f9cf9 -> 6.65:1  PASS

   B) Nút Xóa ở Light mode: --notics-danger #d9534f đặt trên nền đỏ 8% chỉ đạt
      3.53:1. #c0392b đạt 4.84:1, và trùng luôn giá trị --sf-danger đã khai báo
      ở lớp trước nên hệ màu nguy hiểm chỉ còn một giá trị duy nhất cho Light.
   ========================================================================== */

html[data-mode="light"] { --on-accent: var(--ui-text-on-accent); --notics-danger: var(--ui-danger); --notics-danger-rgb: var(--ui-danger-rgb); }
html[data-mode="dark"]  { --on-accent: var(--ux-shell); }


/* Các nút này đang dùng -webkit-text-stroke + text-shadow để "ép" chữ trắng nổi
   trên nền accent — một cách vá tương phản bằng cách làm dày nét chữ. Khi màu
   chữ đã đúng thì bỏ đi, không thì chữ trông nhoè. */

/* ==========================================================================
   2026-08 — ĐỢT 3: nút primary Dark, bề mặt nổi Dark, chốt guard chuyển màn
   ========================================================================== */

/* --- A. Nút primary ở Dark: quay lại chữ trắng, tối nền nút -------------- */
/* Bản trước dùng chữ tối trên nền xanh sáng (đúng 6.65:1) nhưng nhìn không
   thuận mắt — nút primary ở Dark mà chữ tối thì đọc ra như nút đang disabled.

   Cách đúng: tách màu NỀN NÚT khỏi màu accent. --sf-accent giữ nguyên độ sáng
   vì nó còn dùng cho link, icon và viền focus trên nền tối. Riêng nền nút đặc
   thì tối hơn một bậc:
     light #2563eb + chữ trắng -> 5.17:1
     dark  #2b74c4 + chữ trắng -> 4.77:1   (đạt AA)
   #2b74c4 là điểm cân bằng duy nhất tìm được: tối thêm nữa (#2668b0) thì chữ
   đạt 5.69:1 nhưng nút chìm vào nền tối (2.94:1, dưới ngưỡng 3:1 cho ranh
   giới thành phần); sáng hơn (#3179cf) thì chữ tụt xuống 4.41:1.
   Ở #2b74c4 nút so với nền đạt 3.50:1 — viền nút vẫn tách bạch. */

html[data-mode="light"] { --on-accent: var(--dt-semantic-color-light-action-on-accent); --accent-solid: var(--dt-semantic-color-light-action-accent-solid); --accent-solid-rgb: var(--dt-semantic-color-light-action-accent-solid-rgb); }
html[data-mode="dark"]  { --on-accent: var(--dt-semantic-color-dark-action-on-accent); --accent-solid: var(--dt-semantic-color-dark-action-accent-solid); --accent-solid-rgb: var(--dt-semantic-color-dark-action-accent-solid-rgb); }




/* --- B. Bề mặt nổi: MỘT token duy nhất cho mọi hộp thoại/popover -------- */
/* --surface-raised là màu nền DUY NHẤT của lớp nổi. Trước đây mỗi popup tự
   khai một màu (rgb(var(--ui-surface-raised-rgb)), #ffffff !important, hoặc không khai gì
   nên trong suốt), nên đổi bảng màu app xong vẫn còn một loạt hộp thoại giữ
   tông cũ. Giờ mọi thứ nổi lên trên nội dung đều lấy đúng token này.

   Fluent (Flyout) và Material (elevation overlay) cùng một luật ở nền tối:
   càng nổi càng sáng. Thang ở Dark là nền trang #202124 (L .0137) → thẻ
   #2a2b2e (L .0241) → hộp nổi #35363a (L .0357), mỗi bậc sáng hơn bậc dưới
   khoảng 1.5 lần nên hộp thoại tách hẳn khỏi trang mà vẫn cùng hệ xám trung
   tính của Google Keep. Giá trị cũ #1E2B40 là xám XANH, dựng cho bảng màu
   navy trước đây — chính nó là "màu xanh cũ" còn sót trong các popup.
   Chữ vẫn đạt AA trên nền này: --sf-text 9.9:1, --sf-mute 4.69:1.

   Light giữ trắng đặc trên canvas ivory — ở đó thẻ vốn đã sáng hơn nền rồi.

   GĐ1 (29/08/2026): hai dòng khai báo #ffffff/#35363a từng nằm ở đây đã dời
   vào thang bề mặt — --surface-raised giờ là alias của --ux-overlay (bậc L4),
   khai ở khối `html[data-mode]` bên dưới. Giá trị không đổi
   (255,255,255 và 53,54,58), chỉ khác chỗ đứng: mọi bậc nền nay nằm chung một
   bảng để không còn hai nguồn sự thật. */

html[data-mode="dark"] { --modal-scrim: rgba(var(--ui-black-rgb), .62); }

/* Danh sách này là HỢP ĐỒNG: thêm popup mới thì thêm class vào đây, đừng khai
   một màu nền riêng cho nó.
   .overlay-card (thẻ ghi chú dự án, hộp thoại NoteSpeed) trước đây KHÔNG có
   nền nào cả — trong suốt, để lộ scrim và trang phía sau, nên nó ăn theo màu
   nền cũ mà không có dòng CSS nào để sửa. */

/* Hàng và ô nhập bên trong hộp thoại phải nâng theo, không thì chúng tối hơn
   cả nền hộp và trông như lỗ thủng. */
html[data-mode="dark"] :is(
  .edit-panel.expanded-edit-panel,
  .event-modal-panel,
  .overlay-panel,
  .overlay-panel--sm,
  .overlay-panel--md,
  .overlay-panel--lg,
  .overlay-panel--xl
) :is(input[type="text"], input[type="time"], input[type="date"], select, textarea) {
  background: rgba(var(--ui-white-rgb), .05);
  border-color: rgba(var(--ui-white-rgb), .13);
  color: var(--ui-text-primary);
}

/* --- C. Chốt guard chuyển màn ------------------------------------------- */
/* Rule tắt transition dùng selector phổ quát (0,1,0) nên thua các rule riêng
   của rail (0,2,1) vẫn còn !important — opacity vì thế vẫn animate đúng lúc
   đang đổi module. Nâng specificity để guard thắng tuyệt đối. */

/* ==========================================================================
   2026-08 — ĐỢT 4: nối lại 4 bậc Material vào các bề mặt cấp 1  [P0]

   Lỗi cũ: bộ --ux-header/workspace/panel/card/row từng bị khoá theo hệ thiết
   kế, trong khi độ trong suốt của app thuộc trục `data-material`. Vì vậy lựa
   chọn hình học và lựa chọn vật liệu có thể ghi đè lẫn nhau.
   Kết quả: 4 bậc Material trong Cài đặt không đổi được topbar, thân trang hay
   card; 19 bề mặt bị ghim cứng trong khi 52 chỗ khác vẫn chạy theo --a-content
   thật, app tách làm hai nửa không đồng bộ.

   GĐ5 giữ hai trục giao diện độc lập:
     data-material quyết định ĐỘ TRONG và BLUR
     data-mode     quyết định sáng/tối; hình học dùng một thang token chung
   Bộ --ux-* từ nay chỉ giữ mã màu nền; phần alpha lấy thẳng từ --a-header và
   --a-content của khối MATERIAL (dòng ~178).

   Giữ nguyên bộ RGB cũ để ở bậc mặc định (Acrylic) diện mạo gần như không đổi;
   thứ thay đổi là hai đầu thang: Đục giờ đục thật, Kính trong giờ trong thật.

   Hợp đồng khả đọc vẫn nguyên vẹn: --a-content không bao giờ xuống dưới .78 và
   luôn đi kèm --scrim-a trên ảnh nền, nên chữ phụ không rơi dưới ngưỡng AA.
   ========================================================================== */

html[data-mode="light"] {
  /* THANG BỀ MẶT — 5 bậc theo ĐỘ NỔI (GĐ1, 29/08/2026).

     Quy ước quốc tế cho chế độ Sáng (Notion, VS Code, Gmail/Material 3,
     Fluent 2, Apple Mail): vùng CHROME — menu, cây dự án, danh sách — chìm
     hơn nền; vùng NỘI DUNG là chỗ sáng nhất, để mắt tự rơi vào nội dung chứ
     không vào khung. Thang chạy đơn điệu 245 → 250 → 255 nên thứ tự phân lớp
     GIỐNG HỆT chế độ Tối. Đây chính là thứ --ux-panel cũ không làm được: nó
     là bậc nổi nhất ở Sáng (255) nhưng lại là bậc nền ở Tối (39,40,43), nên
     cùng một dòng CSS cho ra hai kết quả ngược nhau.

       L0 shell    khung app: rail, header
       L1 sunken   cột menu, cây dự án, danh sách lọc
       L2 base     nền thân trang, vùng chứa lưới thẻ
       L3 raised   thẻ, card, editor
       L4 overlay  popup, modal (luôn đục, kèm bóng)

     --ux-fill KHÔNG phải một bậc bề mặt: nó là vệt tô nhẹ cho hover và hàng
     danh sách. Tách riêng vì --ux-row cũ gánh cả hai việc — dùng nó làm nền
     cột menu thì ở chế độ Tối cột menu SÁNG hơn nội dung, ngược hẳn L1. */
  --ux-shell-rgb:   var(--dt-semantic-color-light-surface-rgb-shell);
  /* Bậc chìm phải cách nền THẤY ĐƯỢC. Giá trị đầu (245,244,239) chỉ cách nền
     250,249,245 khoảng 2% — trên màn hình văn phòng gần như không phân biệt
     nổi, nên ở chế độ Sáng cột menu trông y hệt thân trang và cả thang bề mặt
     "như chưa áp dụng". VS Code dùng bước 5% (#f3f3f3 trên nền trắng), Notion
     3%; 240,239,233 cho bước ~4% mà vẫn nằm trong họ ivory ấm.
     KHÔNG dùng --ux-fill cho việc này: fill là vệt hover, phải NHẠT hơn. */
  --ux-sunken-rgb:  var(--dt-semantic-color-light-surface-rgb-sunken);
  --ux-base-rgb:    var(--dt-semantic-color-light-surface-rgb-base);
  --ux-raised-rgb:  var(--dt-semantic-color-light-surface-rgb-raised);
  --ux-overlay-rgb: var(--dt-semantic-color-light-surface-rgb-overlay);
  --ux-fill-rgb:    var(--dt-semantic-color-light-surface-rgb-fill);
  /* Bốn góc bo của cửa sổ native phải khớp --ux-workspace-rgb
     (CHROME_BY_MODE trong main/windowManager.js và main/antiNoteWindow.js).
     Test phân giải generated DTCG token để khóa hai phía mà không cần giữ một
     bộ ba RGB thứ hai trong consumer stylesheet. Giá trị = L0 shell. */
  --ux-workspace-rgb: var(--dt-semantic-color-light-surface-rgb-shell);
  --ux-header-rgb: var(--ux-shell-rgb);
  --ux-panel-rgb:  var(--ux-base-rgb);
  --ux-card-rgb:   var(--ux-raised-rgb);
  --ux-row-rgb:    var(--ux-fill-rgb);
  --ux-border:  var(--dt-semantic-color-light-border-default);
  --ux-divider: var(--dt-semantic-color-light-border-divider);
  /* Khung Thẻ nổi (BA 11/10/2026): thẻ trắng (rail, header, cột menu) đặt trên
     NỀN BÀN xám nhạt — tách nhau bằng khe, không bằng viền. */
  --ux-desk-rgb:  var(--ux-base-rgb);
  --ux-frame-rgb: var(--ux-raised-rgb);
}

html[data-mode="dark"] {
  /* Xám trung tính của Google Keep, cùng thang 5 bậc như khối Sáng ở trên.
     Ở chế độ Tối "nổi = sáng" là luật cứng của cả Material (elevation overlay)
     lẫn Fluent (flyout), nên thang chạy 32 → 39 → 42 → 53: cột menu nằm cùng
     mặt phẳng với khung app, nội dung nhấc lên một bậc, thẻ thêm một bậc, hộp
     nổi thêm bậc nữa. --ux-fill (48,49,52) đứng ngoài thang, chỉ dùng cho
     hover — đúng bậc hover của Keep.

     Cùng ràng buộc với khối Sáng: đổi --ux-workspace-rgb thì phải đổi
     CHROME_BY_MODE bên main. */
  --ux-shell-rgb:   var(--dt-semantic-color-dark-surface-rgb-shell);
  --ux-sunken-rgb:  var(--dt-semantic-color-dark-surface-rgb-sunken);
  --ux-base-rgb:    var(--dt-semantic-color-dark-surface-rgb-base);
  --ux-raised-rgb:  var(--dt-semantic-color-dark-surface-rgb-raised);
  --ux-overlay-rgb: var(--dt-semantic-color-dark-surface-rgb-overlay);
  --ux-fill-rgb:    var(--dt-semantic-color-dark-surface-rgb-fill);
  --ux-workspace-rgb: var(--dt-semantic-color-dark-surface-rgb-shell);
  --ux-header-rgb: var(--ux-shell-rgb);
  --ux-panel-rgb:  var(--ux-base-rgb);
  --ux-card-rgb:   var(--ux-raised-rgb);
  --ux-row-rgb:    var(--ux-fill-rgb);
  --ux-border:  var(--dt-semantic-color-dark-border-default);
  --ux-divider: var(--dt-semantic-color-dark-border-divider);
  /* Thẻ nổi: nền bàn = khung cửa sổ (trùng CHROME_BY_MODE), thẻ khung nhấc một bậc. */
  --ux-desk-rgb:  var(--ux-shell-rgb);
  --ux-frame-rgb: var(--ux-base-rgb);
}

/* Alpha lấy từ material, không còn số cố định.
   --a-header  : Đục 1 · Đậm .92 · Acrylic .78 · Kính trong .64
   --a-content : Đục 1 · Đậm .98 · Acrylic .88 · Kính trong .78
   Header mỏng hơn content là có chủ đích: header là khung, không mang thân chữ,
   và đó chính là chỗ hiệu ứng kính đọc ra rõ nhất. */
html[data-mode] {
  /* --- 5 bậc bề mặt: đây là bộ token DUY NHẤT component được phép đọc ------ */
  --ux-shell:   rgba(var(--ux-shell-rgb),   var(--a-shell));
  /* --a-*-override: móc cho bậc Kính trong + hình nền (thẻ đặc trên ảnh nét, 04/10/2026). */
  --ux-sunken:  rgba(var(--ux-sunken-rgb),  var(--a-text-override, var(--a-content)));
  --ux-base:    rgba(var(--ux-base-rgb),    var(--a-plate-override, var(--a-content)));
  --ux-raised:  rgba(var(--ux-raised-rgb),  var(--a-text-override, var(--a-content)));
  /* Lớp nổi luôn ĐỤC: nó che nội dung phía sau, và scrim đã lo phần tách lớp.
     Cho nó trong theo material thì chữ trong hộp thoại chồng lên chữ của trang. */
  --ux-overlay: rgb(var(--ux-overlay-rgb));
  --ux-fill:    rgba(var(--ux-fill-rgb),    var(--a-fill-override, calc(var(--a-content) * .94)));

  /* --- Trạng thái hàng/thẻ (GĐ3) — một cặp duy nhất cho MỌI danh sách -------
     Hover phải bám --ink chứ không bám một bậc bề mặt: hàng danh sách nằm trên
     nền chìm (245 ở Sáng), mà --ux-fill cũng đúng 245 — lấy bậc bề mặt làm
     hover thì ở chế độ Sáng hover vô hình. --ink tối dần ở Sáng và sáng dần ở
     Tối nên nổi trên bất kỳ bề mặt nào.
     Trước GĐ3 mỗi danh sách tự chọn một công thức: .ws-item hover rgba(ink,.05)
     + active accent 10%, .antiscreenshot-card hover accent 8% + active accent
     14% — ba con số cho cùng một trạng thái. */
  --ux-hover:  rgba(var(--ink), .06);
  /* Nền mục điều hướng đang chọn (NavigationView Windows 11): trung tính,
     màu nhấn chỉ nằm ở vạch chọn. */
  --ux-nav-selected: rgba(var(--ink), var(--ui-nav-selected-alpha));
  --ux-active: color-mix(in srgb, var(--ui-accent) 10%, transparent);

  /* --- Tên cũ, giữ làm alias để không phải sửa ~50 chỗ dùng trong GĐ1 ------
     Chỉ --ux-panel đổi NGHĨA: từ "bậc nổi nhất ở Sáng / bậc nền ở Tối" về
     đúng một nghĩa là L2 base. Sidebar là chỗ duy nhất từng dựa vào nghĩa cũ,
     và nó đã được chuyển sang --ux-sunken trong ui-foundation.css.
     Bốn popup còn tham chiếu --ux-panel/--ux-panel-rgb (.menu-panel,
     .config-panel, .event-modal-panel, .widget-menu-panel) đều nằm trong hợp
     đồng --surface-raised bên dưới nên nền của chúng không đọc token này. */
  --ux-header:    rgba(var(--ux-header-rgb),    var(--a-header));
  --ux-workspace: rgba(var(--ux-workspace-rgb), var(--a-plate-override, var(--a-content)));
  --ux-panel:     var(--ux-base);
  --ux-card:      var(--ux-raised);
  --ux-row:       var(--ux-fill);
  /* --surface-page là màu nền THẬT của 12 trang: rule ép-ưu-tiên ở
     `html:not(.is-image-canvas) :is(.grid, .notics-page, …)` đè lên mọi khai
     báo `background` của từng trang, nên đổi ở đây mới có tác dụng.
     GĐ1 chuyển nó từ --ux-workspace (bậc L0 shell) sang --ux-base (L2): trước
     đây thân trang trùng đúng màu khung app, nên ở chế độ Tối cột menu, thân
     trang và khung cửa sổ dính làm một mảng phẳng. */
  --surface-page: var(--ux-base);
  --ux-page-frame-fill: transparent;
  /* Khung Thẻ nổi: nền bàn (lộ ở khe), tấm thân trang chứa thẻ (plate), thẻ khung có
     chữ (header, cột menu) và rail (chỉ icon). Alpha theo thang độ trong khi có hình
     nền — khai ở styles/shell-layout.css (--a-plate/--a-chrome, mặc định 1). Rail dùng CHUNG
     --ux-frame với header (BA 11/10/2026, Phương án A: hai vùng khung một vật liệu). */
  --ux-desk:  rgb(var(--ux-desk-rgb));
  --ux-plate: rgba(var(--ux-desk-rgb), var(--a-plate, 1));
  --ux-frame: rgba(var(--ux-frame-rgb), var(--a-chrome, 1));
  --ux-rail:  var(--ux-frame);
  --surface-panel: var(--ux-base);
  --surface-card: var(--ux-raised);
  --surface-raised: var(--ux-overlay);
  /* KHÔNG khai --sf-surface ở đây. Nó đã có sẵn ở html[data-mode="light"/"dark"]
     (= rgb(var(--ui-surface-raised-rgb))) — khối này specificity cao hơn nên sẽ đè, và mọi
     thumbnail thư viện ảnh đổi màu theo mà không có lý do. Đưa --sf-surface về
     thang bề mặt là việc của GĐ3 (thẻ & danh sách). */
}
/* Chế độ Sáng có THANG RIÊNG cho nội dung, không khóa đục và cũng không dùng
   chung --a-content với chế độ Tối.

   Vì sao cần thang riêng: nền sáng + wallpaper sáng làm chữ đen mất tương phản
   nhanh hơn hẳn nền tối. Thang --a-content xuống tới .78 là an toàn ở Tối
   nhưng không an toàn ở Sáng. .90 là mức thấp nhất còn giữ 4.5:1 cho
   --sf-text trên wallpaper sáng nhất — không hạ thêm.

   Vì sao KHÔNG khóa rgb() đục như trước: khóa cứng làm cả bốn bậc độ đục ở
   chế độ Sáng trông y hệt nhau, đúng triệu chứng người dùng báo.

   Vì sao KHÔNG viết max(var(--a-content), .90): Acrylic (.88) và Kính trong
   (.78) sẽ cùng bị kẹp về .90 — mất khác biệt ở đúng hai bậc trong nhất.
   Phải liệt kê đủ bốn bậc để bậc nào cũng nhìn thấy được. */
html[data-mode="light"][data-material="solid"]   { --a-content-light: 1;   }
html[data-mode="light"][data-material="focus"]   { --a-content-light: .99; }
html[data-mode="light"][data-material="acrylic"] { --a-content-light: .96; }
html[data-mode="light"][data-material="glass"]   { --a-content-light: .90; }
/* 30/09/2026: Acrylic và Kính trong ở chế độ Sáng từng chỉ chênh 3% (.93 vs .90)
   nên nhìn như một. Sàn Kính trong (.90) bị chặn bởi tương phản nên KHÔNG hạ;
   kéo khoảng cách bằng cách nâng bậc trên (Tập trung .99 · Acrylic .96), giờ
   chênh 6% giữa Acrylic và Kính trong. Nâng alpha chỉ làm chữ an toàn hơn.
   Khi có hình nền: .97 · .92 · .84. */

/* PHƯƠNG ÁN C (30/08/2026) — chế độ Sáng + hình nền BẬT.

   Vấn đề: sàn --a-content-light .90 (Kính trong) làm thân trang / cột / thẻ ở
   chế độ Sáng đục 90% → hình nền chỉ lọt ~4%, coi như tắt. (Chế độ Tối .78 nên
   lọt ~14%, thấy được — chênh lệch này là thứ người dùng báo.)

   Cách xử lý: hạ --a-content-light để hình nền lộ ra, BÙ bằng --scrim-a dày hơn.
   Mấu chốt: ở chế độ Sáng, scrim là veil TRẮNG (--sf-chrome ≈ 250,249,245), nên
   tăng scrim làm DỊU hình nền VÀ nâng nền chữ sáng lên — chữ đen KHÔNG tụt tương
   phản, ngược lại còn an toàn hơn. Worst case (card trắng .35 trên wallpaper đen
   tuyền): nền chữ vẫn ≈ 92% trắng → --sf-text > 11:1, --sf-mute > 4.5:1.

   CHỈ áp khi có hình nền: không hình nền thì scrim vô nghĩa và .90/.93/.97 giữ
   nguyên. Bậc Đục không đổi (đã đục hoàn toàn, hình nền chỉ hiện ở viền). */
html.has-wallpaper[data-mode="light"][data-material="focus"]   { --a-content-light: .97; --scrim-a: .60; }
html.has-wallpaper[data-mode="light"][data-material="acrylic"] { --a-content-light: .92; --scrim-a: .46; }
html.has-wallpaper[data-mode="light"][data-material="glass"]   { --a-content-light: .84; --scrim-a: .40; --a-header: .76; }
/* ARS-1: header Sáng mang nút có chữ accent — .66 trên hình nền đen chỉ còn
   4.1:1, .76 giữ ≥4.5:1. Tấm nội dung .84 là mức lọt ~10% hình nền cao nhất
   mà chữ màu trạng thái còn đạt AA ở trường hợp xấu nhất. */

/* LỚP NỔI (hộp thoại, drawer sửa việc, popup, menu) đục ở MỌI chế độ, kể cả
   Sáng + hình nền. Bản nới .95 cũ (Phương án C) làm drawer "Chỉnh sửa công việc"
   lộ chữ của khung Quản lý công việc ngày nằm ngay dưới nó — scrim chỉ che
   trang, không che lớp cha của chính hộp thoại (BA 2026-09-28). */

/* Áp thang riêng của chế độ Sáng cho ĐỦ CẢ NĂM bậc. Trước đây khối này chỉ
   nhắc lại workspace/panel/card, bỏ sót --ux-row — nên ở chế độ Sáng cột danh
   sách chạy theo thang của chế độ Tối và trong hơn thẻ khoảng 10% mà không ai
   chủ ý. Giờ chỉ cần khai lại 4 bậc gốc; --ux-panel/--ux-card/--ux-row là alias
   nên tự đi theo.
   --ux-header cố tình KHÔNG có mặt ở đây: nó bám --a-header, là trục "header
   mỏng hơn thân trang" chứ không phải trục sáng/tối. */
html[data-mode="light"] {
  --ux-workspace: rgba(var(--ux-workspace-rgb), var(--a-plate-override, var(--a-content-light, 1)));
  --ux-sunken: rgba(var(--ux-sunken-rgb), var(--a-text-override, var(--a-content-light, 1)));
  --ux-base:   rgba(var(--ux-base-rgb),   var(--a-plate-override, var(--a-content-light, 1)));
  --ux-raised: rgba(var(--ux-raised-rgb), var(--a-text-override, var(--a-content-light, 1)));
  --ux-fill:   rgba(var(--ux-fill-rgb),   var(--a-fill-override, calc(var(--a-content-light, 1) * .94)));
}

/* LỚP THẺ TRÊN MICA (17/09/2026). Hình nền đã được làm mờ ở .app-bg-image;
   thẻ nổi (--ux-raised: thẻ ngày, panel, thẻ ghi chú) thì không được trong hơn
   --ui-raised-floor-wallpaper — như lớp Layer của Windows 11 trên Mica. Thân
   trang / cột (--ux-base, --ux-sunken) giữ nguyên độ trong của phương án C để
   hình nền vẫn lộ ở khoảng trống. max() chỉ kẹp ĐÁY của thẻ, không gộp các bậc
   vật liệu của thân trang. */
html.has-wallpaper[data-mode] {
  --ux-raised: rgba(var(--ux-raised-rgb), var(--a-text-override, max(var(--a-content), var(--ui-raised-floor-wallpaper))));
}
html.has-wallpaper[data-mode="light"] {
  --ux-raised: rgba(var(--ux-raised-rgb), var(--a-text-override, max(var(--a-content-light, 1), var(--ui-raised-floor-wallpaper))));
}

/* MỘT LỚP CHE (ARS-1, 17/09/2026). Thẻ nằm TRONG một tấm đã che hình nền
   (lưới lịch, pane, canvas) không che thêm lần nữa: tấm .86 + thẻ .94 cũ chỉ
   còn lọt ~0.5% hình nền, nên "Kính trong" nhìn như Đục. Thẻ trên tấm dùng
   --a-layer (Đục/Đậm 1 · Acrylic .6 · Kính .5) — vẫn đục hơn chính tấm nên
   chữ trên thẻ không tụt tương phản. Alias --ux-card/--surface-card tính ở
   :root nên phải khai lại tại đây. */
html.has-wallpaper:root:not(.is-image-canvas) :is(.grid, .ux-pane, .ux-canvas) {
  --ux-raised: rgba(var(--ux-raised-rgb), var(--a-layer, 1));
  --ux-card: var(--ux-raised);
  --surface-card: var(--ux-raised);
}

/* HỢP ĐỒNG HÌNH NỀN — MỘT nguồn cho cả 12 trang (30/08/2026).

   --surface-page là veil --ux-base (.78) của thân trang. Nhưng .ux-pane /
   .ux-canvas / thẻ con của MỖI trang CŨNG là bề mặt --a-content (.78). Hai lớp
   .78 chồng nhau ≈ 95% đục → chọn "Kính trong" mà menu Notebook/QuickNote/
   Painting, thân Notics/Project/Dashboard… vẫn không thấy hình nền. Trước đây
   vài trang tự vá bằng alpha ghim tay (Dashboard .52/.46…), mỗi trang một số,
   lệch nhau — đúng thứ người dùng báo "các menu không cùng độ trong suốt".

   Chuẩn hóa: khi CÓ hình nền, thân trang bỏ veil (transparent). Lớp chắn hình
   nền DUY NHẤT là pane/canvas/thẻ con — tất cả bám --a-content nên tự theo bậc
   vật liệu: Đục 1.0 → kín, Kính trong .78 → lộ ~22%. Đồng nhất 12 trang, đồng
   nhất Fluent = Liquid Glass. Tắt hình nền: --surface-page về --ux-base như cũ.
   Hợp đồng khả đọc nguyên vẹn: --a-content ≥ .78 (Tối) / .90 (Sáng) + scrim.

   NGOẠI LỆ (06/09/2026): năm trang KHÔNG có .ux-pane/.ux-canvas bên trong
   (Lịch #grid, Dashboard, Premium, Premium admin, Ghi nhận ý kiến) tự nhận lại
   --surface-page: var(--ux-base) ở khối ~L17090 — vỏ trang của chúng CHÍNH LÀ
   canvas, bỏ veil là không còn lớp chắn nào. */
html.has-wallpaper[data-mode] {
  --surface-page: transparent;
  --ux-page-frame-fill: var(--ux-base);
}

/* KÍNH TRONG + HÌNH NỀN = "THẺ ĐẶC TRÊN ẢNH NÉT" (BA duyệt 04/10/2026; báo cáo
   docs/BAO-CAO-CHUAN-GIAO-DIEN-DESKTOP-WEB-2026-10-04.md §12).
   Chuẩn quốc tế (Microsoft To Do, TickTick theme, tab mới Chrome/Edge, Windows 11):
   chữ luôn nằm trên mặt đặc, độ trong chỉ ở khe trống. Mô hình cũ (tấm kính .72–.84
   phủ ảnh mờ 30px + màn che .40–.46) thua cả hai phía: Sáng ra xám bùn (59% Notebook),
   Tối kéo chữ chính 14–17:1 xuống 10–11:1, mà ảnh vẫn không rõ.
   - Thân trang (--ux-base, tấm chứa thẻ) mỏng .14 → ảnh nét lộ ở khe.
   - Mọi bề mặt mang chữ đặc .94: cột/pane (sunken), thẻ (raised, --a-layer), ô (fill),
     rail/topbar. Ảnh không làm mờ, màn che rất mỏng.
   - Acrylic/Đậm/Đục giữ mô hình cũ. utils/adaptiveGlass.js bỏ qua bậc Kính trong
     (tấm thân trang không còn là nền của chữ). */
html.has-wallpaper[data-material="glass"][data-mode]:not(.is-image-canvas) {
  --a-text-surface: .94;
  --glass-blur: 0px;
  --glass-sat: 1;
  --a-layer: var(--a-text-surface);
  --a-shell: .92;
  --a-header: .92;
  --a-plate-override: .14;
  --a-text-override: var(--a-text-surface);
  --a-fill-override: calc(var(--a-text-surface) - .04);
  /* Viền 1px của thân trang (khung Nổi) nằm trên nền như header, không lộ vạch ảnh. */
  --ux-page-frame-fill: var(--ux-header);
}
html.has-wallpaper[data-material="glass"][data-mode="light"]:not(.is-image-canvas) { --scrim-a: .06; }
/* Tối: thẻ tối trên ảnh sáng lọt 6% đã thấy hoạ tiết sau chữ → .97. */
html.has-wallpaper[data-material="glass"][data-mode="dark"]:not(.is-image-canvas) { --scrim-a: .2; --a-text-surface: .97; }
/* Trang mà chính vỏ trang là bề mặt chữ (lưới Tuần/Tháng đặt chữ thẳng lên lưới;
   Dashboard/Premium/Quản trị không có thẻ riêng) → vỏ trang đặc như thẻ.
   Lịch Hôm nay và Agenda giữ tấm mỏng: chữ đã nằm trong thẻ ngày (--view-panel-bg)
   — gán đặc cho Agenda từng chia màn làm dải ảnh tối ở thanh tuần + lớp trắng đục
   bên dưới (BA 04/10/2026). */
html.has-wallpaper[data-material="glass"]:not(.is-image-canvas) :is(
  .grid:not([data-view-mode="today"]):not(.agenda-view),
  .dashboard-page,
  .premium-page,
  .premium-admin-page,
  .feedback-admin-page
) {
  --surface-page: var(--ux-raised);
}
/* Chữ đặt thẳng trên thân trang mỏng (trạng thái trống giữa canvas) cần thẻ riêng —
   như To Do/TickTick đặt khối chữ trên ảnh. */
html.has-wallpaper[data-material="glass"]:not(.is-image-canvas) .ux-canvas :is(.ux-empty-state, .project-tab-empty, .ws-list-empty, .trash-empty) {
  border-radius: var(--ui-radius-panel);
  background: var(--ux-raised);
  box-shadow: var(--ui-elevation-1);
}

/* Tắt hình nền ở chế độ Tối: giữ bề mặt đục 100% để ngăn ánh sáng và màu sắc
   từ desktop Windows lọt qua DWM acrylic làm nhạt/mờ nền đen của app. */
html:not(.has-wallpaper)[data-mode="dark"] {
  --a-shell: 1;
  --a-header: 1;
  --a-content: 1;
}

/* --- Blur cũng phải theo bậc vật liệu ------------------------------------ */
/* Trước đây blur ghim cứng 22px/16px, nên ở bậc Đục vẫn tốn một lượt blur CPU
   mà không để làm gì (app chạy không GPU — xem main.js:275). --glass-blur:
   Đục 0 · Đậm 8px · Acrylic 20px · Kính trong 30px. */

:is(.notics-page-header) {
  -webkit-backdrop-filter: blur(calc(var(--glass-blur) * .75)) saturate(var(--glass-sat));}

/* blur(0px) vẫn tạo backdrop root và vẫn tốn một lượt hợp thành. Ở bậc Đục thì
   gỡ hẳn thuộc tính — đây cũng là bậc nhẹ nhất cho máy yếu. */

/* Ở bậc Đục thì hình nền chỉ còn hiện ở khe hở quanh các thẻ, đúng như mô tả
   trong Cài đặt: "Bề mặt đặc hoàn toàn. Hình nền chỉ hiện ở viền cửa sổ." */
/* Đục chỉ ép chrome phẳng ở khung Thẻ nổi. Trong khung Liền mạch, .app,
   topbar và rail phải cùng dùng --ui-chrome-surface; nếu rule này chạy sau thì
   topbar/rail trở về --ux-header-rgb và tạo một vết khuyết màu ở mép trên. */

/* ==========================================================================
   2026-08 — ĐỢT 4b: Premium & Quản trị Premium về chung khuôn header

   Bảy module dùng thanh header ghim cao 56px (.notics-page-header và họ hàng).
   Riêng hai trang Premium dùng khuôn "tiêu đề nằm trong nội dung": h1 cỡ
   clamp(28px,3.3vw,43px) đặt thẳng trong vùng cuộn, nên vừa lệch thang chữ vừa
   cuộn mất tiêu đề — người dùng cuộn xuống là không còn biết đang ở trang nào.

   Không sửa DOM: giữ nguyên <header> hiện có, chỉ ghim nó lại và đưa về đúng
   thang chữ. Nền và đường kẻ dùng chung --ux-panel/--ux-divider nên nó tự động
   theo bậc Material như mọi header khác.
   ========================================================================== */

html { --premium-pad-x: clamp(22px, 5vw, 76px); }


/* .premium-page-header đã bỏ (BA 10/10/2026): topbar đã ghi "AntiTask Premium". */

/* ==========================================================================
   2026-08 — CHỐT CHẾ ĐỘ XEM ẢNH NỀN (Ctrl+6)

   Đây là lần thứ ba chế độ này bị một lớp đắp sau làm hỏng, luôn cùng một cơ
   chế: rule mới có specificity BẰNG rule của image canvas (0,2,1) nhưng nằm
   sau trong file nên thắng. Lần này là
   `html[data-material="solid"] :is(.topbar, .nav-rail)` của đợt Material — ở
   bậc Đục nó trả lại nền đặc cho topbar, thành dải đen trên ảnh nền.
   `!important` không cứu được vì specificity xử trước độ ưu tiên.

   Khối dưới đây dùng `html.is-image-canvas[data-material]` = (0,3,1), cao hơn
   hẳn mọi rule chrome khác trong file, và đặt cuối cùng. Từ đây thêm lớp mới
   ở cuối file cũng không rò vào chế độ này được nữa.

   Nguyên tắc của chế độ: chỉ còn ảnh nền và avatar. Rail vẫn nằm đúng chỗ
   nhưng trong suốt — hiện lại khi rê chuột vào đúng mép rail, hoặc khi bấm
   avatar (pin mở). Avatar KHÔNG tự bung rail chỉ vì rê chuột ngang qua nó —
   xem lý do tách .nav-rail-avatar-btn khỏi .nav-rail-body bên dưới.

   2026-08 cập nhật: avatar tài khoản chuyển từ topbar (.brand) sang mục cuối
   cùng của #navRail (đứng ngoài .nav-rail-body). Topbar không còn nội dung
   cần giữ lại nên ẩn hẳn; #navRail chỉ còn là khung chứa trong suốt, phần
   nền/viền/opacity ẩn-hiện chuyển sang .nav-rail-body — tách avatar ra khỏi
   subtree đó là bắt buộc vì opacity của cha luôn nuốt opacity riêng của con,
   không có cách nào "lộ" một phần tử con trong khi cha đang opacity:0. */







/* Nền/viền chuyển sang ::after tràn ra mép rail — lý do xem khối
   `html.is-image-canvas .nav-rail-body` phía trên: tô thẳng lên .nav-rail-body
   làm thẻ menu hụt 16px so với màn thường. Dùng ::after chứ không phải
   ::before vì ::before của .nav-rail-body đã là flex spacer canh giữa nhóm
   icon chính ("đợt 2" phía trên) — ghi đè nó làm icon dồn lên sát mép trên. */




/* Rail đang hiện (rê chuột vào rail HOẶC bấm avatar ghim mở): kéo mép trên
   của pill lên khỏi .nav-rail-body để bao trọn avatar phía trên, không để hở
   khoảng trống giữa avatar và pill — áp dụng cùng lúc với rule opacity/viền
   ngay phía trên (cùng bộ điều kiện :hover/:focus-within/.is-image-canvas-menu-open).
   audit-keep: 42px là chiều cao hàng avatar (flex: 0 0 42px của
   .nav-rail-avatar-btn, styles.css) — cộng với khoảng cách flex gap
   (--ui-space-1 trên .nav-rail) và margin-top của .nav-rail-body
   (--ui-space-3) ra đúng khoảng cách hình học thật giữa hai phần tử, không
   có token tổng hợp sẵn cho quãng này. */


/* ==========================================================================
   2026-08 — GĐ2: bộ màu ngữ nghĩa dùng chung

   Vùng Settings/dialogs đang có 6 sắc đỏ khác nhau cho cùng một nghĩa
   "nguy hiểm" (#e2231a #dc2626 #c62828 #d34a4a #d1292f #ff7a7a) và 5 sắc vàng
   cho "cảnh báo". Chuẩn trang Giới thiệu thì mỗi trạng thái luôn là một BỘ BA
   nền / viền / chữ cùng hue, theo công thức nền L≈96%, viền L≈88%, chữ L≈34%.
   Khai báo một lần ở đây để mọi nơi dùng lại, thay vì mỗi chỗ tự chọn một sắc.
   ========================================================================== */

html[data-mode="light"] {
  --sf-danger: var(--dt-semantic-color-light-status-danger); --sf-danger-rgb: var(--dt-semantic-color-light-status-danger-rgb);
  --sf-danger-bg: var(--dt-semantic-color-light-status-danger-bg); --sf-danger-line: var(--dt-semantic-color-light-status-danger-line);
  --sf-warning: var(--dt-semantic-color-light-status-warning); --sf-warning-rgb: var(--dt-semantic-color-light-status-warning-rgb);
  --sf-warning-bg: var(--dt-semantic-color-light-status-warning-bg); --sf-warning-line: var(--dt-semantic-color-light-status-warning-line);
  --sf-success: var(--dt-semantic-color-light-status-success); --sf-success-rgb: var(--dt-semantic-color-light-status-success-rgb);
  --sf-success-bg: var(--dt-semantic-color-light-status-success-bg); --sf-success-line: var(--dt-semantic-color-light-status-success-line);
}

html[data-mode="dark"] {
  --sf-danger: var(--dt-semantic-color-dark-status-danger); --sf-danger-rgb: var(--dt-semantic-color-dark-status-danger-rgb);
  --sf-danger-bg: var(--dt-semantic-color-dark-status-danger-bg); --sf-danger-line: var(--dt-semantic-color-dark-status-danger-line);
  --sf-warning: var(--dt-semantic-color-dark-status-warning); --sf-warning-rgb: var(--dt-semantic-color-dark-status-warning-rgb);
  --sf-warning-bg: var(--dt-semantic-color-dark-status-warning-bg); --sf-warning-line: var(--dt-semantic-color-dark-status-warning-line);
  --sf-success: var(--dt-semantic-color-dark-status-success); --sf-success-rgb: var(--dt-semantic-color-dark-status-success-rgb);
  --sf-success-bg: var(--dt-semantic-color-dark-status-success-bg); --sf-success-line: var(--dt-semantic-color-dark-status-success-line);
}

/* ==========================================================================
   2026-08 — GĐ3/1: thang chuyển động

   Trước: 27 giá trị thời lượng khác nhau (lẫn cả s và ms) và 43 khai báo
   `transition: all`. `all` bắt trình duyệt nội suy MỌI thuộc tính đổi giá trị,
   kể cả padding và border-width — hai thứ kéo theo relayout toàn cây. Với app
   chạy không GPU (main.js:275) thì đó là nguồn giật ẩn rải khắp giao diện.

   Fluent dùng thang 3 bậc. Giá trị dưới đây chọn sát với những gì đang chiếm
   đa số trong file (var(--ui-duration-fast) và .15–var(--ui-duration-standard)) nên cảm giác thao tác gần như không đổi,
   chỉ còn 3 con số thay vì 27.
   ========================================================================== */

html {
  /* Danh sách thuộc tính an toàn để animate: chỉ màu, bóng, biến hình và độ mờ.
     Không có thuộc tính nào gây relayout. */
  --tr-ui: background-color, border-color, color, box-shadow, transform, opacity, filter;
}

/* ==========================================================================
   2026-08 — GĐ3/3: token bo góc là nguồn sự thật duy nhất

   Trước: cùng --sf-radius-chip xuất hiện với BA fallback khác nhau
   (4px, 6px, 8px) và --sf-radius-card với ba giá trị (8px, 10px, 12px) —
   nghĩa là ba người viết code không thống nhất được "chip bo bao nhiêu".

   Fallback phải có trước khi JS áp mode/material đã lưu để khung hình đầu tiên
   không mất bo góc.
   Nên khai báo mặc định ngay trong `html` — specificity (0,0,1) nên luôn thua
   bốn khối html[data-mode], chỉ có tác dụng đúng lúc trước khi
   JS kịp chạy. Sau đó mới xoá được toàn bộ fallback trong var().
   ========================================================================== */

html {
  --sf-radius-win: 0px;
  --sf-radius-card: var(--dt-dimension-radius-panel);
  --sf-radius-row: var(--dt-dimension-radius-control);
  --sf-radius-chip: var(--dt-dimension-radius-control);
  --sf-radius-pill: var(--dt-dimension-radius-full);
}

/* ==========================================================================
   2026-08 — GĐ3/4: vòng focus vẽ đúng trên ô, không phải trên input bên trong

   Ô tìm kiếm trên topbar là một viên pill (.search-expand-bar, radius 20px,
   padding 4px 10px) bọc lấy một <input> cao 24px không viền, nền trong suốt.
   Rule focus chung nhắm vào `input:focus-visible` nên vòng xanh vẽ quanh cái
   input bên trong — nhỏ hơn viên pill và lệch bo góc, đúng như nhìn thấy.

   NHƯNG chỉ ô trên topbar theo khuôn đó. Bốn ô còn lại (.notics-search-wrap,
   .notics-project-filter-search-wrap, .notics-lock-input-wrap) ngược lại:
   wrapper chỉ là khung định vị rỗng — position:relative để đặt icon — còn hộp
   thật nằm trên chính <input> (border + border-radius: pill). Đặt outline lên
   wrapper ở những chỗ đó thì vẽ ra một khung VUÔNG bao ngoài viên pill.
   Chúng vốn đã có :focus ring đúng hình rồi, không cần đụng tới.

   Bài học: quy tắc này phải áp theo từng ca, căn cứ vào element nào mang hộp
   nhìn thấy được, không áp đồng loạt theo tên class.
   ========================================================================== */

html { --focus-ring: 2px solid rgba(var(--ui-accent-rgb), .85); }



/* .search-expand-bar có overflow:hidden để chạy hiệu ứng mở rộng chiều ngang.
   Outline của chính nó không bị cắt, nhưng để chắc chắn thì cho phép tràn khi
   đang mở — lúc đó chiều rộng đã cố định, không còn gì cần cắt nữa. */

/* ==========================================================================
   2026-08 — GĐ3/5: thang elevation

   Trước: 293 khai báo box-shadow với ~197 công thức khác nhau, chỉ 80 đi qua
   token, và 40 công thức dùng rgba(var(--ui-black-rgb),…) — đen thuần.

   Chuẩn trang Giới thiệu không bao giờ đổ bóng đen: luôn ngả navy
   (0 20px 40px rgba(66,91,168,.10)). Bóng đen trên nền sáng làm giao diện xỉn
   vì nó hút cả sắc lẫn độ sáng, trong khi bóng cùng hue với nền chỉ hút độ
   sáng. --sf-shadow-rgb đã có sẵn đúng giá trị đó cho từng hệ và từng mode
   (light 15,20,40 · dark 0,0,0 — nền tối thì bóng đen mới đúng), nên chỉ cần
   trỏ 40 công thức kia về nó.

   Bốn bậc dưới đây là hạ tầng cho phần còn lại: nghỉ / nổi / flyout / hộp
   thoại, theo đúng bốn mức Fluent phân biệt.
   ========================================================================== */

html {
  --elev-1: 0 1px 2px rgba(var(--ui-shadow-rgb), .14), 0 1px 3px rgba(var(--ui-shadow-rgb), .08);
  --elev-2: 0 4px 12px rgba(var(--ui-shadow-rgb), .09);
  --elev-3: 0 10px 28px rgba(var(--ui-shadow-rgb), .14);
  --elev-4: 0 22px 56px rgba(var(--ui-shadow-rgb), .22);
}

/* ==========================================================================
   2026-08 — GĐ4: ngôn ngữ icon

   1) Icon nằm cạnh chữ phải canh theo tâm chữ, không theo baseline. SVG mặc
      định là inline nên tụt xuống dưới đường baseline — đó là lý do emoji cũ
      và SVG mới trông "lệch tầng" khi đứng cùng hàng.
   2) Icon-tile: chuẩn trang Giới thiệu không bao giờ để icon đứng trần —
      luôn nằm trong ô bo góc nền nhạt CÙNG HUE, tỉ lệ radius/cạnh ≈ 0.29
      (.card-icon 38px/11px). Trong app đã có sẵn một chỗ làm đúng
      (.premium-card-heading > span: 32px/10px = 0.31), giờ nâng thành lớp
      dùng chung ba cỡ để mọi nơi lấy về dùng.
   3) Thang cỡ icon: 16 trong nút, 20 trong tile nhỏ, 24 ở rail.
   ========================================================================== */

:is(button, .badge-tag, .widget-menu-item, .premium-showcase-pills span) > svg {
  flex: none;
  vertical-align: -0.125em;
}

/* Dấu tích trạng thái nằm trên nền accent — cùng vấn đề tương phản với nút
   primary: chữ/nét trắng trên accent sáng ở Dark chỉ đạt 2.82:1. */

/* --- Icon-tile dùng chung ------------------------------------------------ */

/* Các ô icon đã tồn tại nhưng mỗi nơi một công thức — kéo về cùng một tỉ lệ. */

/* --- Thang cỡ icon ------------------------------------------------------- */
:is(.notics-icon-btn, .notics-btn-lock-toggle) > svg {
  width: var(--ui-icon-dense);
  height: var(--ui-icon-dense);
}

.widget-menu-icon > svg { width: var(--ui-icon-xs); height: var(--ui-icon-xs); }

/* ==========================================================================
   2026-08 — GĐ4/2: trạng thái tương tác đầy đủ + khuôn trạng thái rỗng

   Fluent quy định chuỗi trạng thái bắt buộc: nghỉ → hover → NHẤN → chọn,
   cộng disabled và focus. App đang có 274 rule :hover nhưng chỉ 25 :active và
   23 :disabled cho 257 <button>. Thiếu trạng thái nhấn là thiếu vòng phản hồi:
   người dùng bấm mà giao diện không nhúc nhích cho tới khi hành động xong —
   đó là một phần của cảm giác "app không ăn chuột".
   ========================================================================== */

/* --- Nhấn: Token chung cho toàn bộ nút — không giật (transform: none), chỉ fill nhẹ box ---
   Các danh sách dưới KHÔNG liệt kê móc của nút .ui-btn (notics-pin-btn, -today, btn-google…):
   rule legacy có cờ important từng đè trạng thái nhấn/vô hiệu chuẩn của .ui-btn (chuẩn hoá lát 6). */
:is(
  button,
  [role="button"],
  .glass-icon-btn, .icon-btn, .picker-btn, .month-today-btn,
  .widget-menu-item,
  .settings-nav-item, .source-choice, .notics-icon-btn,
  .notics-row-action, .notics-item-edit-btn,
  .project-portfolio-plan-btn,
  .premium-admin-tabs button, .nav-rail-item,
  .calendar-item-more
):active:not(:disabled) {
  transform: none !important;
}

/* Fill nhẹ box khi nhấn cho các họ nút thông thường / ghost / icon / outline.
   Trừ .ui-btn: nút chuẩn có trạng thái nhấn riêng từng kiểu (ui-components.css);
   trước đây rule !important này tô xám cả nút Chính khi nhấn. */

/* Fill nhẹ box khi nhấn cho các họ nút màu đậm / primary (làm đậm nhẹ nền) */
:is(
  .month-today-btn,
  #deleteSeriesConfirmBtn):active:not(:disabled) {
  filter: brightness(0.88);
}

/* --- Disabled: một luật cho mọi họ nút --------------------------------- */
/* Không dùng pointer-events:none — sẽ mất cả tooltip giải thích vì sao nút
   đang bị vô hiệu, mà đó chính là lúc người dùng cần lời giải thích nhất. */
:is(
  .glass-icon-btn, .icon-btn, .picker-btn, .widget-menu-item, .settings-nav-item, .source-choice, .notics-icon-btn):disabled {
  opacity: .45;
  cursor: not-allowed;
  transform: none;}

:is(.glass-icon-btn, .icon-btn, .notics-icon-btn):disabled:hover {
  background: inherit;
  border-color: var(--ux-border);
}

/* --- Vòng focus hai lớp ------------------------------------------------ */
/* Vòng một màu chìm khi phần tử focus đang nằm trên nền cùng tông accent —
   đúng cảnh nút đang ở trạng thái chọn. Fluent dùng vòng kép: nét trong theo
   màu nền, nét ngoài theo accent, nên đọc được trên mọi nền.
   Chỉ áp cho control không có viền/nền riêng để đánh dấu vị trí (button,
   custom control gắn [tabindex]) và input dạng bật/tắt (checkbox/radio/
   range/file). Input/select/textarea văn bản có viền riêng dùng vòng sáng
   mềm --ui-control-ring ("Ô NHẬP CHUẨN" ui-components.css), không vòng đôi
   này — theo đúng quy ước Fluent 2/Material 3/HIG. */

/* Ô nhập có wrapper mang hộp: vòng vẫn phải nằm trên wrapper. */

/* Vòng focus chỉ thuộc wrapper có hình dạng nhìn thấy được. Toàn bộ ô tìm kiếm
   và input nhúng dạng phẳng/trong suốt không nhận viền focus độc lập để tránh
   hiện tượng box vuông 90 độ đè lên khung bo tròn. */

/* --- Khuôn trạng thái rỗng dùng chung ---------------------------------- */
/* Bốn khuôn đang tồn tại song song: .notics-empty, .notics-empty-state,
   .notespeed-empty-list, .project-tab-empty. Gom về cùng một ngôn ngữ thị
   giác mà không cần sửa markup. Trạng thái rỗng là lúc người dùng cần chỉ dẫn
   nhất, nên nó phải nói rõ chỗ này chứa gì — không chỉ "không có dữ liệu". */
:is(.notics-empty, .notics-empty-state, .project-tab-empty) {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--ui-space-2);
  max-width: var(--dt-dimension-layout-320);
  margin: var(--ui-space-6) auto;
  padding: var(--ui-space-5) var(--ui-space-4);
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  line-height: var(--lh-relaxed);
  text-align: center;
}

:is(.notics-empty-state-icon) {
  display: grid;
  place-items: center;
  width: var(--ui-size-lg);
  height: var(--ui-size-lg);
  margin-bottom: var(--ui-space-0-5);
  border-radius: var(--ui-radius-panel);
  background: color-mix(in srgb, var(--ui-accent) 12%, transparent);
  color: var(--ui-accent);
}

:is(.notics-empty-state-icon) > svg { width: var(--ui-icon-lg); height: var(--ui-icon-lg); }

.notics-empty-state-title {
  color: var(--ui-text-primary);
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
}

.notics-empty-state-hint {
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
}

/* ==========================================================================
   2026-08 — GĐ5: một ngôn ngữ cho phản hồi hành động

   Đính chính so với bản rà soát: #mainToast đã dùng chung class .qa-toast với
   cửa sổ Quick Add từ trước, nên không phải 4 cơ chế mà là 3, và chúng thuộc
   HAI loại khác nhau về bản chất — gộp làm một là sai:

     • Nhất thời  (.qa-toast)        — việc vừa xảy ra, tự biến mất sau 2.5s
     • Liên tục   (.notics-save-status) — trạng thái đang diễn ra, nằm tại chỗ
     • Cần hành động (.update-card)     — chờ người dùng bấm, không tự biến mất

   Việc cần làm không phải gom về một cơ chế, mà cho ba cơ chế cùng một bảng
   màu và cùng một mức nổi. Trước đây mỗi cái tự chọn màu riêng: toast dùng
   rgba(var(--ui-success-rgb),.96) xanh đặc, save-status mượn --gantt-status-done của module
   Gantt, banner thì dựa vào hai token chưa từng được định nghĩa.
   ========================================================================== */

/* Toast: bộ ba nền/viền/chữ theo chuẩn, thay vì một mảng màu đặc.
   Nền đặc màu bão hòa cho MỌI thao tác là quá nặng tay — người dùng lưu ghi
   chú chứ không phải nhận cảnh báo hệ thống. */
.qa-toast {
  display: inline-flex;
  align-items: center;
  gap: var(--ui-space-2);
  padding: var(--ui-space-2) var(--ui-space-4);
  border: var(--ui-stroke-thin) solid var(--ui-success-line);
  border-radius: var(--dt-dimension-radius-full);
  background: var(--ui-success-bg);
  color: var(--ui-success);
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  box-shadow: var(--elev-3);
  backdrop-filter: blur(14px) saturate(1.1);
  -webkit-backdrop-filter: blur(14px) saturate(1.1);
}

.qa-toast.is-error {
  border-color: var(--ui-danger-line);
  background: var(--ui-danger-bg);
  color: var(--ui-danger);
}

/* Toast không đặt max-width nên tự co theo nội dung; message dài hơn một
   câu ngắn (vd nhắc thêm về Thùng rác) làm khối flex hẹp lại theo viewport,
   và nút Hoàn tác — vốn không có flex-shrink/white-space riêng — bị bóp
   chữ vỡ dòng ("Hoàn" / "tác") thay vì message tự xuống dòng. Message được
   phép co/xuống dòng, nút thì không bao giờ. */
.qa-toast-msg {
  min-width: 0;
  flex: 1 1 auto;
}

.qa-toast-action {
  flex: 0 0 auto;
  margin-left: var(--ui-space-1-5);
  padding: var(--ui-space-0-5) var(--ui-space-2);
  border-radius: var(--dt-dimension-radius-full);
  background: var(--ux-overlay);
  color: inherit;
  border: var(--ui-stroke-thin) solid currentColor;
  font: inherit;
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
  cursor: pointer;
  transition: transform var(--ui-duration-fast) var(--ui-ease), opacity var(--ui-duration-fast) var(--ui-ease);
}

.qa-toast-action:hover {
  opacity: 0.85;
}

.qa-toast-action:active {
  transform: scale(0.95);
}

/* Trạng thái lưu: cùng bảng màu ngữ nghĩa với toast, không mượn token của
   module khác nữa. */
.notics-save-status[data-tone="saved"] { color: var(--ui-success); }
.notics-save-status[data-tone="error"] { color: var(--ui-danger); }
.notics-save-status { font-size: var(--fs-caption); }

/* ==========================================================================
   2026-08 — GĐ5: một mẫu tab duy nhất cho cấp trong module

   Project dùng segmented control (.notics-segmented-control + .notics-tab):
   viên pill bọc ngoài, segment đang chọn nổi lên bằng nền + bóng.
   Quản trị Premium lại dùng tab gạch chân — hai mẫu cho cùng một việc.

   Fluent chỉ có hai mẫu điều hướng: NavigationView cho cấp module (rail) và
   Pivot/TabView cho cấp trong module. Chọn segmented control làm mẫu duy nhất
   vì nó đã phủ nhiều nơi hơn (Project, bộ lọc Dashboard) và vì trạng thái chọn
   của nó mạnh hơn — đổi cả nền lẫn độ nổi, không chỉ một nét gạch 2px.

   Không sửa markup: cùng là <button role="tab"> trong một container, chỉ khoác
   lại lớp áo bằng CSS. */

/* Tab quản trị Premium: SEGMENTED CHUẨN (ui-components.css). */

/* Quản trị Premium — bộ lọc gói và danh sách VIP vĩnh viễn (2026-08). */
.premium-admin-filters { display: flex; align-items: center; gap: var(--ui-space-2); flex: 0 0 auto; }
.premium-admin-filters .setting-select { width: auto; min-width: var(--dt-dimension-layout-136); }
.premium-admin-subhead { margin-top: var(--ui-space-5); padding-top: var(--ui-space-4); border-top: var(--ui-stroke-thin) solid var(--ux-divider); }
.premium-admin-vip-form { display: flex; align-items: center; gap: var(--ui-space-2); margin-bottom: var(--ui-space-2-5); flex-wrap: wrap; }
.premium-admin-vip-form .premium-admin-search { flex: 1 1 var(--dt-dimension-layout-176); min-width: 0; }

/* =====================================================================
   DAY EDITOR — refined hierarchy for the quick-add form
   The calendar uses compact row rhythm; the editor keeps that density while
   separating compose, view controls and saved draft with token-based surfaces.
   ===================================================================== */
.edit-panel.expanded-edit-panel {
  /* AT-UI Rhythm (BA 10/10/2026): hộp soạn nhanh 640 (mức Lớn 800) thay 880 — nội dung
     chỉ là ô nhập + danh sách việc, rộng hơn chỉ đẩy control ra xa nhau. */
  width: min(var(--ui-dialog-compose-w), calc(100vw - var(--ui-space-8)));
  height: min(82vh, var(--dt-dimension-layout-720));
  --task-row-height: 36px;
  border: var(--ui-stroke-thin) solid var(--ui-divider);
  background: rgb(var(--ui-surface-raised-rgb));
  box-shadow: var(--elev-4);
}
.edit-header {
  padding: var(--ui-space-3) var(--ui-space-4-5);
  background: color-mix(in srgb, rgb(var(--ui-surface-fill-rgb)) 62%, transparent);
}
.edit-accent { width: var(--ui-space-1); height: var(--ui-size-sm); }
.edit-title { font-size: var(--popup-title); letter-spacing: var(--ls-tight); }
.edit-body { padding: var(--ui-space-3) var(--ui-space-4-5) var(--ui-space-2-5); gap: var(--ui-space-2-5); }
.quick-add-composer {
  padding: var(--ui-space-2-5);
  border: var(--ui-stroke-thin) solid var(--ui-divider);
  border-radius: var(--ui-radius-panel);
  background: color-mix(in srgb, rgb(var(--ui-surface-fill-rgb)) 46%, transparent);
}
.edit-panel.expanded-edit-panel :is(.quick-task-input, .draft-input) {
  font-family: var(--app-font);
  font-size: var(--fs-body);
  font-weight: var(--fw-normal);
  line-height: var(--lh-body);
}
.edit-panel.expanded-edit-panel .quick-add-btn {
  font-family: var(--app-font);
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
}
.edit-panel.expanded-edit-panel .draft-card-text {
  font-family: var(--app-font);
  font-size: var(--fs-body);
  font-weight: var(--fw-normal);
  line-height: var(--lh-snug);
}
/* Dòng Ưu tiên/Giờ nhắc: token-select, form-input và form-select cao bằng nhau chuẩn 32px. */
:is(.edit-panel.expanded-edit-panel, .qa-full) .quick-add-field .token-select-trigger,
:is(.edit-panel.expanded-edit-panel, .qa-full) .quick-add-field :is(.form-input, .form-select) {
  font-family: var(--app-font);
  font-size: var(--fs-body);
  font-weight: var(--fw-normal);}
:is(.edit-panel.expanded-edit-panel, .qa-full) .edit-footer :is(button) {
  height: var(--ui-control-h-standard);
  min-height: var(--ui-control-h-standard);
  padding: 0 var(--ui-space-3-5);
}
.editor-controls-bar { padding: 0 var(--ui-space-0-5) var(--ui-space-2); }
.card-list-container,
.raw-text-container {
  min-height: var(--dt-dimension-layout-104);
  border: var(--ui-stroke-thin) solid var(--ui-divider);
  border-radius: var(--ui-radius-panel);
  background: rgba(var(--ui-surface-fill-rgb), .24);
  overflow: auto;
}
.draft-task-list { min-height: 100%; }
.empty-draft-hint {
  margin: var(--ui-space-3-5);
  padding: var(--ui-space-6) var(--ui-space-4);
  border: var(--ui-stroke-thin) dashed var(--ui-divider);
  border-radius: var(--ui-radius-control);
  color: var(--ui-text-secondary);
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  line-height: var(--lh-normal);
  text-align: center;
}
.draft-card-item { min-height: var(--task-row-height); padding-inline: var(--ui-space-2-5); }
.draft-card-btn { width: var(--ui-size-sm); height: var(--ui-size-sm); font-size: var(--fs-body); }
.raw-text-container .draft-input { height: 100%; min-height: var(--dt-dimension-layout-104); padding: var(--ui-space-2-5) var(--ui-space-3); }
.edit-footer {
  padding: var(--ui-space-2-5) var(--ui-space-4-5) var(--ui-space-3);
  background: color-mix(in srgb, rgb(var(--ui-surface-fill-rgb)) 36%, transparent);
}

/* The standalone task editor uses the same drawer as the day editor.  Its
   recurrence options can be taller than the dialog, so the middle section
   must be the flex item that shrinks and scrolls.  Without this explicit
   sizing, the content overflows underneath the fixed action footer and the
   recurrence summary/end controls look as if they have disappeared. */
.item-detail-drawer { min-height: 0; }
.item-detail-drawer .drawer-header,
.item-detail-drawer .drawer-footer { flex: 0 0 auto; }
.item-detail-drawer .drawer-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
}
/* .drawer-body is a column flex container.  The repeat card has
   overflow:hidden for its rounded corners; that makes its automatic flex
   minimum zero, so Flexbox was shrinking the card itself and clipping the
   Monthly/ending controls.  Keep the card at its content height and let the
   already-scrollable drawer body own any overflow. */
.item-detail-drawer .repeat-editor { flex: 0 0 auto; }

/* Đồng bộ hóa typography 100% cho mọi form controls trong Task Detail Drawer theo chuẩn Design Tokens */
.item-detail-drawer :is(.form-input, .form-select, .token-date-trigger, .token-select-trigger),
.edit-panel.expanded-edit-panel .item-detail-drawer :is(.form-input, .form-select, .token-date-trigger, .token-select-trigger) {
  font-family: var(--app-font);
  font-size: var(--fs-body);
  font-weight: var(--fw-normal);
  line-height: var(--lh-body);
  color: var(--ui-text-primary);
}

.item-detail-drawer :is(.token-date-display, .token-select-label) {
  font-family: var(--app-font);
  font-size: var(--fs-body);
  font-weight: var(--fw-normal);
  color: var(--ui-text-primary);
}

.item-detail-drawer input[type="time"],
.item-detail-drawer input[type="time"]::-webkit-datetime-edit,
.item-detail-drawer input[type="time"]::-webkit-datetime-edit-fields-wrapper,
.item-detail-drawer input[type="time"]::-webkit-datetime-edit-text,
.item-detail-drawer input[type="time"]::-webkit-datetime-edit-hour-field,
.item-detail-drawer input[type="time"]::-webkit-datetime-edit-minute-field,
.item-detail-drawer input[type="time"]::-webkit-datetime-edit-ampm-field {
  font-family: var(--app-font);
  font-size: var(--fs-body);
  font-weight: var(--fw-normal);
  color: var(--ui-text-primary);
}

.clear-all-btn {
  color: var(--ui-danger);
  border-color: var(--ui-danger-line);
  background: var(--ui-danger-bg);
}
.clear-all-btn:hover {
  color: var(--ui-danger);
  border-color: var(--ui-danger);
  background: color-mix(in srgb, var(--ui-danger) 16%, transparent);
}

/* [MODULARIZED] AntiScreenshot styles moved to src/renderer/styles/screenshot.css */

/* Text-only feedback: uses the shared overlay and semantic colour tokens so it
   remains legible in Fluent, Material and Liquid Glass modes. */
.feedback-panel { width: min(var(--dt-dimension-layout-560), calc(100vw - var(--ui-size-dense))); }
.feedback-body { display: grid; gap: var(--ui-space-2); }
.feedback-body > label { color: var(--ui-text-primary); font-weight: var(--fw-semibold); font-size: var(--fs-body); }
.feedback-body textarea {
  width: 100%; min-height: var(--dt-component-editor-feedback-min-height); resize: vertical; box-sizing: border-box;
  padding: var(--ui-space-2-5) var(--ui-space-3); border: var(--ui-stroke-thin) solid var(--ux-border); border-radius: var(--ui-radius-panel);
  background: rgb(var(--ui-surface-fill-rgb)); color: var(--ui-text-primary); font: inherit; line-height: var(--lh-normal);
}
.feedback-compose-meta { display: flex; justify-content: space-between; gap: var(--ui-space-3); color: var(--ui-text-muted); font-size: var(--fs-caption); }
.feedback-compose-meta small { font: inherit; }
.feedback-compose-meta .is-over { color: var(--ui-danger); font-weight: var(--fw-semibold); }
.feedback-admin-header, .feedback-admin-toolbar, .feedback-admin-row, .feedback-admin-meta, .feedback-admin-header-actions, .feedback-enabled-switch, .feedback-admin-actions { display: flex; align-items: center; }
.feedback-admin-header {
  flex: 0 0 auto;
  padding-inline: var(--ui-space-4-5);
}
.feedback-admin-header-title { min-width: 0; }
.feedback-admin-header h1 { margin: 0; color: var(--ui-text-primary); font-weight: var(--fw-semibold);}
.feedback-admin-header-actions { gap: var(--ui-space-2-5); flex-wrap: wrap; }
.feedback-enabled-switch { height: var(--ui-size-md); gap: var(--ui-space-1-5); color: var(--ui-text-primary); font-size: var(--fs-caption); font-weight: var(--fw-semibold); cursor: pointer; white-space: nowrap;}
.feedback-enabled-switch input { accent-color: var(--ui-accent); }
.feedback-admin-panel {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-height: 0;
  margin: 0;
  max-width: none;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  overflow: hidden;
}
.feedback-admin-toolbar { flex: 0 0 var(--dt-dimension-layout-56); justify-content: space-between; gap: var(--ui-space-3); padding: 0 var(--ui-space-5); border-bottom: var(--ui-stroke-thin) solid var(--ux-divider); color: var(--ui-text-secondary); background: color-mix(in srgb, var(--ux-panel) 86%, transparent); }
.feedback-admin-toolbar > div:last-child { display: flex; align-items: center; gap: var(--ui-space-2); }
.feedback-admin-summary { display: flex; align-items: baseline; gap: var(--ui-space-1); }
.feedback-admin-toolbar strong { color: var(--ui-accent); font-size: var(--fs-title); }
.feedback-selected-count { color: var(--ui-text-muted); font-size: var(--fs-caption); }
.feedback-admin-list { display: grid; min-height: 0; overflow: auto; align-content: start; scrollbar-gutter: stable; }
.feedback-admin-row { align-items: flex-start; gap: var(--ui-space-3); padding: var(--ui-space-3-5) var(--ui-space-5); border-bottom: var(--ui-stroke-thin) solid var(--ux-divider); transition: background-color var(--ui-duration-fast) var(--ui-ease); }
.feedback-admin-row:hover { background: color-mix(in srgb, var(--ui-accent) 5%, transparent); }
.feedback-admin-row:last-child { border-bottom: 0; }
.feedback-admin-row.is-completed { opacity: .72; }
.feedback-admin-row > input { margin-top: var(--ui-space-1); accent-color: var(--ui-accent); }
.feedback-admin-copy { min-width: 0; flex: 1; }
.feedback-admin-copy p { margin: var(--ui-space-1-5) 0 0; color: var(--ui-text-primary); font-size: var(--fs-body); line-height: var(--lh-relaxed); white-space: pre-wrap; overflow-wrap: anywhere; }
.feedback-admin-meta { gap: var(--ui-space-2); flex-wrap: wrap; color: var(--ui-text-muted); font-size: var(--fs-caption); }
.feedback-admin-meta strong { color: var(--ui-text-primary); font-size: inherit; }
.feedback-status { padding: var(--ui-space-0-5) var(--ui-space-2); border-radius: var(--dt-dimension-radius-full); background: color-mix(in srgb, var(--ui-accent) 12%, transparent); color: var(--ui-accent); font-weight: var(--fw-semibold); }
.feedback-admin-actions { gap: var(--ui-space-1-5); flex: 0 0 auto; }
.feedback-empty { flex: 1 1 auto; max-width: none; min-height: var(--dt-component-editor-empty-min-height); }
@media (max-width: 680px) {
  .feedback-admin-header { padding-block: var(--ui-space-1-5);}
  .feedback-admin-toolbar { flex-basis: auto; min-height: var(--dt-dimension-layout-56); padding: var(--ui-space-2-5) var(--ui-space-3-5); }
  .feedback-admin-header, .feedback-admin-toolbar { align-items: flex-start; flex-direction: column; }
  .feedback-admin-row { flex-wrap: wrap; }
  .feedback-admin-actions { width: 100%; justify-content: flex-end; margin-left: var(--ui-space-6); }
}

/* ========================================================================
   2026-08 — Navigation rail app tiles

   Canonical terminal block for the rail. Labels sit below compact rounded
   app icons; selection belongs to the icon itself, never to a row/card.
   ======================================================================== */
/* Tỉ lệ đệm lấy từ bộ design "Bộ icon 10 ứng dụng" (glyph 34 trong ô 58 → ~21%
   mỗi bên): ở đây glyph 20px trong ô 36px, đệm 8px mỗi bên. Chiều cao ô bấm 68px
   vượt ngưỡng 48dp của Material 3 và 44px của WCAG 2.2.

   --rail-item PHẢI đủ chứa: ô icon + khe 2px + nhãn 22px + padding dọc 6px của
   .nav-rail-item. Thiếu một hai px thôi là nhãn hai dòng ("Quản trị Premium")
   bị cắt mất dòng dưới. */
:root,
html[data-rail="expanded"] {
  --rail-w: var(--ui-navigation-rail-width, 66px);
  --rail-item: var(--ui-navigation-item-h, 68px);
  --rail-icon: 20px;
  --rail-tile: 36px;
  --rail-group-gap: 6px;
}

html[data-rail="collapsed"] {
  --rail-w: var(--ui-navigation-rail-width, 66px);
  --rail-item: var(--ui-navigation-item-h-collapsed);
  --rail-icon: var(--ui-icon-navigation);
  --rail-tile: calc(var(--ui-icon-navigation) + var(--ui-space-4));
  --rail-group-gap: var(--ui-navigation-item-gap);
}

/* Cửa sổ thấp thì 11 ô cao 68px cộng avatar sẽ vượt chiều cao rail và bị
   overflow:hidden cắt mất. Thu bớt thay vì để mục cuối biến mất. */
@media (max-height: 860px) {
  :root,
  html[data-rail="expanded"] {
    --rail-item: var(--ui-navigation-item-h-compact, 62px);
    --rail-icon: 18px;
    --rail-tile: 31px;
  }
}

/* GĐ4: padding rail khai ở đây là mã chết — ui-foundation.css đặt
   "padding: var(--ui-space-2) var(--ui-space-1)" cho cùng .nav-rail, nạp sau. */

.nav-rail-primary,
.nav-rail-secondary {
  gap: var(--rail-group-gap, var(--ui-space-1-5));
}

.nav-rail-secondary {
  padding-top: var(--ui-space-1-5);
}

.nav-rail-item,
.nav-rail-item:hover,
.nav-rail-item:active,
.nav-rail-item:focus,
.nav-rail-item:focus-visible,
.nav-rail-item.is-active {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: var(--ui-navigation-item-gap, var(--ui-space-0-5));
  height: var(--rail-item);
  min-height: var(--rail-item);
  padding: var(--ui-navigation-item-pad-block, var(--ui-space-0-5)) var(--ui-navigation-item-pad-inline, var(--ui-space-px));
  border-radius: var(--ui-navigation-item-radius, var(--ui-radius-control));
  transform: var(--ui-interaction-stable-transform);}


.nav-rail-item.is-active::before { display: none !important; }

/* Trạng thái nghỉ theo bộ design: không khung viền, không nền — chỉ còn nét
   glyph theo màu module. Nhờ vậy ô đang chọn (pill đặc màu) nổi bật hẳn thay
   vì chỉ đậm hơn ô thường một chút. */
.nav-rail-icon,
html[data-rail="expanded"] .nav-rail-icon {
  position: relative;
  isolation: isolate;
  width: var(--rail-tile);
  height: var(--rail-tile);
  border: var(--ui-stroke-thin) solid transparent;
  border-radius: var(--ui-radius-full);
  color: var(--ui-text-secondary);
  background: transparent;
  box-shadow: none;
  transition: color var(--ui-duration-fast) var(--ui-ease);
  transform: none;
}

.nav-rail-icon > svg {
  width: var(--rail-icon);
  height: var(--rail-icon);
  stroke-width: 1.5;
  filter: none;
  transform: none;
}

.nav-rail-item:hover .nav-rail-icon {
  transform: none;
  color: color-mix(in srgb, var(--item-accent, var(--ui-accent)) 80%, var(--ui-text-primary));
  background: transparent;
  border-color: transparent;
  box-shadow: none;
}

/* Đang chọn: icon chuyển sang glyph solid với màu module, TUYỆT ĐỐI KHÔNG nền và KHÔNG border */
.nav-rail-item.is-active .nav-rail-icon {
  color: var(--item-accent, var(--ui-accent));
  border-color: transparent;
  background: transparent;
  box-shadow: none;
  transform: none;
}

/* Bề rộng nhãn bám theo lòng rail (bề rộng card trừ 4px đệm mỗi bên đặt ở
   ui-foundation.css), nên "Ghi chú nhanh" và "Quản trị Premium" tự xuống dòng
   thành hai dòng thay vì bị ép một dòng rồi cắt cụt.
   KHÔNG ghi số cứng ở đây: giá trị 44px trước đây tính cho rail 66px, khi rail
   đổi sang 50px thì nhãn tràn 2px ra ngoài và bị cắt ở cả hai mép.
   max-height 22px = đúng 2 dòng ở 8.6px/1.22 và còn dư ~1px, không được hạ. */
.nav-rail-label,
html[data-rail="expanded"] .nav-rail-label {
  display: -webkit-box;
  width: calc(var(--rail-w) - var(--ui-space-1) * 2);
  height: var(--ui-navigation-label-h);
  max-height: var(--ui-navigation-label-h);
  opacity: 1;
  transform: none;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  white-space: normal;
  overflow-wrap: break-word;
  text-align: center;
  color: var(--ui-text-secondary);
  font: var(--fw-medium) var(--fs-caption)/var(--lh-tight) var(--app-font);
  letter-spacing: 0;
  pointer-events: auto;
  transition: color var(--ui-duration-fast) var(--ui-ease);
}

.nav-rail-item.is-active .nav-rail-label {
  color: var(--item-accent, var(--ui-accent));
  font-weight: var(--fw-semibold);
}
.nav-rail-item:hover .nav-rail-label {
  color: var(--ui-text-primary);
}
.nav-rail-kbd { display: none !important; }

/* Tắt tên ứng dụng chỉ được ẩn CHỮ, không được đổi bố cục: dùng visibility nên
   nhãn vẫn giữ nguyên chỗ, nhờ vậy icon không nhích lên hay đổi cỡ khi bật/tắt
   — display:none sẽ làm justify-content:center canh lại và cả cột icon trôi. */
html[data-rail="collapsed"] .nav-rail-label {
  visibility: hidden;
}

.nav-rail-avatar-btn,
.nav-rail-avatar-btn:hover,
.nav-rail-avatar-btn.is-active {
  flex: 0 0 var(--ui-size-touch);}

.nav-rail-avatar-btn .nav-rail-icon {
  width: var(--ui-size-lg);
  height: var(--ui-size-lg);
  border: 0;
  border-radius: var(--ui-radius-circle);
  background: transparent;
  box-shadow: none;
}

.nav-rail-toggle { display: none !important; }

.nav-avatar-menu {
  position: fixed;
  z-index: calc(var(--layer-popover) + 2);
  top: var(--ui-space-3);
  right: auto;
  bottom: auto;
  left: calc(var(--rail-w) + var(--ui-space-2));
  width: var(--dt-component-popover-avatar-menu-width);
  max-height: calc(100vh - var(--ui-space-6));
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--ui-space-1);
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-px);
  transform-origin: left top;
}

.nav-avatar-menu:not(.hidden) {
  animation: menuGravityDrop 0.2s cubic-bezier(0.16, 1, 0.3, 1) forwards; /* audit-keep: chuyển động biên đạo riêng (keyframes), không thuộc nhịp giao diện chuẩn */
  will-change: transform, opacity;
}

@keyframes menuGravityDrop {
  0% {
    transform: translateY(-8px) scale(0.98);
    opacity: 0;
  }
  100% {
    transform: translateY(0) scale(1);
    opacity: 1;
  }
}

.nav-avatar-summary {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  min-width: 0;
  padding: var(--ui-space-1) var(--ui-space-1-5) var(--ui-space-1-5);
}

.nav-avatar-menu-avatar {
  display: grid;
  place-items: center;
  flex: 0 0 var(--ui-size-md);
  width: var(--ui-size-md);
  height: var(--ui-size-md);
  overflow: hidden;
  border: var(--ui-stroke-thin) solid var(--ux-border);
  border-radius: var(--ui-radius-circle);
  color: var(--ui-text-secondary);
  background: color-mix(in srgb, var(--ui-accent) 8%, rgb(var(--ui-surface-fill-rgb)));
  box-shadow: var(--elev-1);
}

.nav-avatar-menu-avatar .menu-avatar { width: 100%; height: 100%; object-fit: cover; }
.nav-avatar-summary-copy { display: flex; flex: 1; min-width: 0; flex-direction: column; gap: var(--ui-space-px); }
.nav-avatar-summary-copy strong { overflow: hidden; color: var(--ui-text-primary); font-size: var(--fs-caption); font-weight: var(--fw-semibold); text-overflow: ellipsis; white-space: nowrap; }
.nav-avatar-summary-copy small { color: var(--ui-text-secondary); font-size: var(--fs-caption); font-weight: var(--fw-medium); }

.nav-avatar-menu .widget-menu-divider {
  height: var(--ui-resizer-line);
  margin: var(--ui-space-1) var(--ui-space-0-5);
  background: var(--stroke);
  opacity: 0.8;
}

.widget-menu-group-title {
  padding: var(--ui-space-1-5) var(--ui-space-2) var(--ui-space-0-5);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--ui-text-muted);
  user-select: none;
}

.nav-avatar-action {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--ui-space-2);
  width: 100%;
  min-height: var(--ui-size-sm);
  padding: var(--ui-space-0-5) var(--ui-space-1-5);
  border: none;
  background: transparent;
  border-radius: var(--ui-radius-control);
  color: var(--ui-text-primary);
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  cursor: pointer;
  text-align: left;
  transition: background var(--ui-duration-fast) var(--ui-ease);
}

.nav-avatar-action:hover:not(:disabled) {
  background: rgba(var(--ui-surface-fill-rgb), .86);
}

.nav-avatar-action-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: left;
}

.nav-avatar-action-hint,
.nav-avatar-action small {
  display: inline-flex !important;
  align-items: center;
  margin-left: auto;
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  color: var(--ui-text-secondary);
  white-space: nowrap;
}

.nav-avatar-action.is-selected {
  font-weight: var(--fw-semibold);
  color: var(--ui-accent);
}

.nav-avatar-action.is-selected .nav-avatar-action-hint {
  color: var(--ui-accent);
  font-weight: var(--fw-semibold);
}

.nav-avatar-action-icon {
  display: grid;
  place-items: center;
  flex: 0 0 var(--ui-icon-md);
  width: var(--ui-icon-md);
  height: var(--ui-icon-md);
  border-radius: var(--ui-radius-sm);
  color: var(--ui-accent);
  background: color-mix(in srgb, var(--ui-accent) 10%, transparent);
}

.nav-avatar-action-icon > svg {
  width: var(--ui-icon-xs);
  height: var(--ui-icon-xs);
  display: block;
}

/* Specific colored icon tiles for avatar menu actions */
.nav-avatar-action[data-avatar-action="settings"] .nav-avatar-action-icon {
  color: light-dark(var(--ui-accent), var(--ui-category-blue-fg));
  background: light-dark(rgba(var(--ui-module-task-rgb), 0.1), rgba(var(--ui-module-task-rgb), 0.16));
}

.nav-avatar-action[data-avatar-action="sync"] .nav-avatar-action-icon {
  color: var(--ui-accent);
  background: light-dark(rgba(var(--ui-module-art-rgb), 0.1), rgba(var(--ui-module-art-rgb), 0.16));
}

.nav-avatar-action[data-avatar-action="theme"] .nav-avatar-action-icon {
  color: light-dark(var(--ui-category-purple-fg), var(--ui-warning));
  background: light-dark(rgba(var(--ui-module-note-rgb), 0.1), rgba(var(--ui-warning-rgb), 0.18));
}

.nav-avatar-action[data-avatar-action="pin"] .nav-avatar-action-icon {
  color: light-dark(var(--ui-accent), var(--ui-category-purple-fg));
  background: light-dark(rgba(var(--ui-module-project-rgb), 0.1), rgba(var(--ui-module-project-rgb), 0.16));
}

.nav-avatar-action[data-avatar-action="image"] .nav-avatar-action-icon {
  color: var(--ui-success);
  background: light-dark(rgba(var(--ui-module-dashboard-rgb), 0.1), rgba(var(--ui-module-dashboard-rgb), 0.16));
}

.nav-avatar-action[data-avatar-action="antinote"] .nav-avatar-action-icon {
  color: var(--ui-warning);
  background: light-dark(rgba(var(--ui-warning-rgb), 0.1), rgba(var(--ui-warning-rgb), 0.16));
}

.nav-avatar-action[data-task-sort="timePriority"] .nav-avatar-action-icon {
  color: var(--ui-accent);
  background: light-dark(rgba(var(--ui-module-art-rgb), 0.1), rgba(var(--ui-module-art-rgb), 0.16));
}

.nav-avatar-action[data-task-sort="manual"] .nav-avatar-action-icon {
  color: var(--ui-success);
  background: light-dark(rgba(var(--ui-module-capture-rgb), 0.1), rgba(var(--ui-module-capture-rgb), 0.16));
}

.nav-avatar-action[data-avatar-action="feedback"] .nav-avatar-action-icon {
  color: var(--ui-brand-webex);
  background: light-dark(rgba(var(--ui-module-art-rgb), 0.1), rgba(var(--ui-module-art-rgb), 0.16));
}

.nav-avatar-action[data-avatar-action="feedback-admin"] .nav-avatar-action-icon {
  color: var(--ui-category-purple-fg);
  background: light-dark(rgba(var(--ui-module-note-rgb), 0.1), rgba(var(--ui-module-note-rgb), 0.16));
}

.nav-avatar-action[data-avatar-action="hide"] .nav-avatar-action-icon {
  color: var(--ui-danger);
  background: light-dark(rgba(var(--ui-danger-rgb), 0.1), rgba(var(--ui-danger-rgb), 0.16));
}

/* Context menu chuột phải trên icon rail */
.nav-rail-context-menu {
  position: fixed;
  z-index: calc(var(--layer-popover) + 2);
  top: auto;
  right: auto;
  left: calc(var(--rail-w) + var(--ui-space-2));
  width: var(--dt-component-popover-avatar-menu-width);
  max-height: calc(100vh - var(--ui-space-6));
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--ui-space-1);
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-px);
  transform-origin: left top;
}

.nav-context-menu-header {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  min-width: 0;
  padding: var(--ui-space-1) var(--ui-space-1-5) var(--ui-space-1-5);
}

.nav-context-menu-icon {
  display: grid;
  place-items: center;
  flex: 0 0 1.375rem;
  width: var(--ui-icon-lg);
  height: var(--ui-icon-lg);
  border-radius: var(--ui-radius-control);
  color: var(--ui-accent);
  background: color-mix(in srgb, var(--ui-accent) 10%, transparent);
}

.nav-context-menu-icon svg {
  width: var(--ui-icon-dense);
  height: var(--ui-icon-dense);
}

.nav-context-menu-title {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--ui-text-primary);
}

.nav-context-menu-kbd {
  flex: 0 0 auto;
  margin-left: auto;
  padding: var(--ui-space-0-5) var(--ui-space-1-5);
  border-radius: var(--ui-radius-control);
  background: var(--ux-hover);
  border: var(--ui-stroke-thin) solid var(--ux-border);
  color: var(--ui-text-muted);
  font: var(--fw-medium) var(--fs-micro)/var(--lh-none) var(--app-font);
  white-space: nowrap;
}

.nav-avatar-action[data-nav-action="hide"] .nav-avatar-action-icon {
  color: var(--ui-danger);
  background: color-mix(in srgb, var(--ui-danger) 12%, transparent);
}

.nav-avatar-action[data-nav-action="customize"] .nav-avatar-action-icon {
  color: var(--ui-accent);
  background: color-mix(in srgb, var(--ui-accent) 12%, transparent);
}

/* Panel tùy chỉnh danh sách menu trên Navigation Rail */
.nav-rail-customizer-panel {
  position: fixed;
  z-index: calc(var(--layer-popover) + 2);
  top: auto;
  right: auto;
  left: calc(var(--rail-w) + var(--ui-space-2));
  width: var(--dt-component-popover-quick-action-width);
  max-height: calc(100vh - var(--ui-space-6));
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--ui-space-2);
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-0-5);
  transform-origin: left center;
}

.nav-customizer-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--ui-space-2);
  padding: var(--ui-space-0-5) var(--ui-space-1) var(--ui-space-1);
}

.nav-customizer-title-wrap {
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-0-5);
  min-width: 0;
  flex: 1 1 auto;
}

.nav-customizer-title {
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--ui-text-primary);
  line-height: var(--lh-tight);
}

.nav-customizer-hint {
  font-size: var(--fs-caption);
  color: var(--ui-text-secondary);
  line-height: var(--lh-tight);
}

.nav-customizer-close-btn {
  display: grid;
  place-items: center;
  flex: 0 0 1.375rem;
  width: var(--ui-size-sm);
  height: var(--ui-size-sm);
  padding: 0;
  border: none;
  background: transparent;
  border-radius: var(--dt-dimension-radius-full);
  color: var(--ui-text-secondary);
  cursor: pointer;
  transition: background var(--ui-duration-fast) var(--ui-ease), color var(--ui-duration-fast) var(--ui-ease);
}

.nav-customizer-close-btn:hover {
  background: var(--ui-action-hover);
  color: var(--ui-text-primary);
}

.nav-customizer-close-btn svg {
  width: var(--ui-icon-dense);
  height: var(--ui-icon-dense);
}

.nav-customizer-list {
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-0-5);
  max-height: calc(100vh - var(--dt-dimension-layout-160));
  overflow-y: auto;
  overflow-x: hidden;
  padding-right: var(--ui-space-0-5);
}

.nav-customizer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-space-2);
  min-height: var(--ui-list-row-min);
  padding: var(--ui-space-0-5) var(--ui-space-1-5);
  border-radius: var(--ui-radius-control);
  transition: background var(--ui-duration-fast) var(--ui-ease);
}

.nav-customizer-row:hover {
  background: var(--ux-hover);
}

.nav-customizer-item-info {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  min-width: 0;
  flex: 1 1 auto;
}

.nav-customizer-item-icon {
  display: grid;
  place-items: center;
  flex: 0 0 1.375rem;
  width: var(--ui-icon-lg);
  height: var(--ui-icon-lg);
  border-radius: var(--ui-radius-control);
  color: var(--ui-accent);
  background: color-mix(in srgb, var(--ui-accent) 10%, transparent);
}

.nav-customizer-item-icon svg {
  width: var(--ui-icon-sm);
  height: var(--ui-icon-sm);
}

.nav-customizer-item-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  color: var(--ui-text-primary);
}

.nav-customizer-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--ui-space-1-5);
  padding: var(--ui-space-0-5) var(--ui-space-2);
  border: var(--ui-stroke-thin) solid var(--stroke);
  border-radius: var(--dt-dimension-radius-full);
  background: transparent;
  cursor: pointer;
  flex: 0 0 auto;
  transition: border-color var(--ui-duration-fast) var(--ui-ease), background var(--ui-duration-fast) var(--ui-ease);
}

.nav-customizer-toggle:hover {
  background: var(--ux-hover);
}

.nav-customizer-toggle-track {
  position: relative;
  display: inline-block;
  width: var(--ui-size-sm);
  height: var(--ui-space-3);
  border-radius: var(--dt-dimension-radius-full);
  background: var(--stroke);
  transition: background var(--ui-duration-fast) var(--ui-ease);
}

.nav-customizer-toggle-thumb {
  position: absolute;
  top: var(--ui-space-px);
  left: var(--ui-space-px);
  width: var(--ui-space-2-5);
  height: var(--ui-space-2-5);
  border-radius: var(--dt-dimension-radius-full);
  background: var(--ui-text-muted);
  transition: transform var(--ui-duration-fast) var(--ui-ease), background var(--ui-duration-fast) var(--ui-ease);
}

.nav-customizer-toggle.is-on .nav-customizer-toggle-track {
  background: var(--ui-accent);
}

.nav-customizer-toggle.is-on .nav-customizer-toggle-thumb {
  background: var(--ui-text-on-accent);
  transform: translateX(10px);
}

.nav-customizer-toggle.is-on {
  border-color: color-mix(in srgb, var(--ui-accent) 40%, var(--stroke));
  background: color-mix(in srgb, var(--ui-accent) 8%, transparent);
}

.nav-customizer-toggle-text {
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  min-width: var(--ui-space-5);
  text-align: center;
}

.nav-customizer-toggle.is-on .nav-customizer-toggle-text {
  color: var(--ui-accent);
}

.nav-customizer-toggle.is-off .nav-customizer-toggle-text {
  color: var(--ui-text-muted);
}

.nav-customizer-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-space-2);
  padding: var(--ui-space-1) var(--ui-space-0-5) 0;
}

.nav-customizer-footer-btn {
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  padding: var(--ui-space-0-5) var(--ui-space-2-5);
  min-height: var(--ui-control-h-compact);
  border-radius: var(--dt-dimension-radius-full);
  border: var(--ui-stroke-thin) solid var(--stroke);
  background: var(--ux-hover);
  color: var(--ui-text-secondary);
  cursor: pointer;
  transition: background var(--ui-duration-fast) var(--ui-ease), border-color var(--ui-duration-fast) var(--ui-ease), color var(--ui-duration-fast) var(--ui-ease);
}

.nav-customizer-footer-btn:hover {
  background: var(--ux-fill);
  border-color: var(--ui-accent);
  color: var(--ui-text-primary);
}

@media (max-height: 720px) {
  :root,
  html[data-rail="expanded"],
  html[data-rail="collapsed"] { --rail-item: 54px; }
  .nav-rail-label, html[data-rail="expanded"] .nav-rail-label { font-size: var(--fs-caption); }
}

/* Banner chế độ chỉ đọc của màn Dự án. Dùng sắc cảnh báo nhẹ chứ không phải đỏ
   lỗi: người dùng không làm gì sai, họ chỉ hết hạn — và thông điệp chính ở đây
   là trấn an rằng dữ liệu còn nguyên. */
.project-readonly-notice {
  display: flex; align-items: center; gap: var(--ui-space-3); flex-wrap: wrap;
  margin: var(--ui-space-2-5) var(--ui-space-4) 0; padding: var(--ui-space-2-5) var(--ui-space-4);
  border: var(--ui-stroke-thin) solid rgba(var(--ui-accent-rgb), .3); border-radius: var(--ui-radius-panel);
  background: rgba(var(--ui-accent-rgb), .08);
}
.project-readonly-notice strong { flex: 0 0 auto; color: var(--ui-text-primary); font-size: var(--fs-body); }
.project-readonly-notice p { flex: 1 1 var(--dt-dimension-layout-256); margin: 0; color: var(--ui-text-secondary); font-size: var(--fs-body); line-height: var(--lh-normal); }
.project-readonly-notice button {
  flex: 0 0 auto; height: var(--ui-size-sm); padding: 0 var(--ui-space-3-5); border: none;
  border-radius: var(--ui-radius-control); background: var(--ui-accent-solid); color: var(--ui-text-on-accent);
  font-size: var(--fs-body); font-weight: var(--fw-semibold); cursor: pointer;
}
.project-readonly-notice button:hover { filter: brightness(1.07); }
/* Ẩn hẳn các lối tạo mới khi chỉ đọc — để nút bấm được rồi mới báo lỗi là kiểu
   giao diện hứa suông. Thao tác ghi vẫn có chốt chặn riêng trong ganttChart.js
   cho những đường không đi qua nút (kéo thả, phím tắt). */
.project-page.is-readonly #noticsPlanNewMilestoneBtn { display: none; }

.project-archived-notice {
  display: flex; align-items: center; gap: var(--ui-space-3); flex-wrap: wrap;
  margin: var(--ui-space-2-5) var(--ui-space-4) 0; padding: var(--ui-space-2-5) var(--ui-space-4);
  border: var(--ui-stroke-thin) solid var(--ui-warning-line); border-radius: var(--ui-radius-panel);
  background: var(--ui-warning-bg);
}
.project-archived-notice-icon {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
  color: var(--ui-warning);
}
.project-archived-notice-content {
  flex: 1 1 var(--dt-dimension-layout-256); display: flex; flex-direction: column; gap: var(--ui-space-0-5);
}
.project-archived-notice strong { color: var(--ui-text-primary); font-size: var(--fs-body); }
.project-archived-notice p { margin: 0; color: var(--ui-text-secondary); font-size: var(--fs-body); line-height: var(--lh-normal); }
.project-archived-notice button {
  flex: 0 0 auto; height: var(--ui-size-sm); padding: 0 var(--ui-space-3-5); border: none;
  border-radius: var(--ui-radius-control); background: var(--ui-warning); color: var(--ui-text-on-accent);
  font-size: var(--fs-body); font-weight: var(--fw-semibold); cursor: pointer;
}
.project-archived-notice button:hover { filter: brightness(1.07); }
.project-page.is-archived #noticsPlanNewMilestoneBtn,
.project-page.is-archived #projectEditBtn,
.project-page.is-archived #projectQuickAdd,
.project-page.is-archived #projectNewNoteBtn,
.project-page.is-archived #projectNewTaskBtn { display: none; }

/* ── Trang Hướng dẫn sử dụng (view "guide") ──────────────────────────────────
   Vỏ trang mượn đúng khuôn .dashboard-page / .notics-page: một tấm bo góc nổi
   trên nền shell, tự cuộn bên trong. Hai cột: mục lục dính trái + nội dung
   cuộn phải; ở layout hẹp thì xếp chồng. Chỉ dùng token --ux-* / --fs-* /
   --ui-* — không màu Hex, không font-size px. */
.guide-page {
  position: relative;
  z-index: 1;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding: 0;
  margin: var(--ui-space-2-5);
  color: var(--ui-text-primary);
  background: var(--ux-base);
  border-radius: var(--ui-radius-panel);
  border: var(--ui-stroke-thin) solid var(--stroke);
  box-shadow: var(--elev-4);
  overflow: hidden;
}
.guide-layout {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
  gap: 0;
}
.guide-toc {
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--ui-space-4) var(--ui-space-3);
  border-right: var(--ui-stroke-thin) solid var(--ux-divider);
  background: var(--ux-sunken);
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-1);
}
/* Hàng mục lục = MỤC ĐIỀU HƯỚNG CỘT CON (cao, bo, đệm, nền rê — ui-components.css). */
.guide-toc-link {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  width: 100%;
  flex: 0 0 auto;
  color: var(--ui-text-secondary);
  font-size: var(--fs-body);
  text-align: left;
  cursor: pointer;
}
.guide-toc-link span { flex: 0 0 auto; }
.guide-toc-link:hover { color: var(--ui-text-primary); }
.guide-toc-link:focus-visible { outline: var(--ui-focus-ring-width) solid var(--ui-focus-ring); outline-offset: var(--ui-focus-ring-offset); }
.guide-toc-link.is-intro { font-weight: var(--fw-semibold); color: var(--ui-text-primary); }
.guide-toc-foot { margin-top: auto; padding-top: var(--ui-space-3); }

.guide-content {
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--ui-space-5) clamp(var(--ui-space-4), 4vw, var(--ui-space-10)) var(--ui-space-10);
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-4);
  background: var(--ux-base);
}
.guide-section {
  border: var(--ui-stroke-thin) solid var(--ux-border);
  border-radius: var(--ui-radius-panel);
  background: var(--ux-raised);
  padding: clamp(var(--ui-space-4), 3vw, var(--ui-space-6));
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-3);
  scroll-margin-top: 12px;
}
.guide-section.is-guide-focus { border-color: var(--ui-accent); box-shadow: 0 0 0 1px var(--ui-accent); } /* audit-keep: quầng sáng màu trạng thái (glow), không phải bậc độ nổi */
.guide-section-head { display: flex; align-items: flex-start; gap: var(--ui-space-3); }
.guide-section-icon {
  flex: 0 0 auto;
  width: var(--ui-size-lg);
  height: var(--ui-size-lg);
  display: grid;
  place-items: center;
  border-radius: var(--ui-radius-control);
  background: var(--ux-hover);
  font-size: var(--fs-body);
}
.guide-section-head h2 { margin: 0; font-size: var(--fs-title); font-weight: var(--fw-title); line-height: var(--lh-title); }
.guide-section-group {
  margin: 0 0 var(--ui-space-0-5);
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-weight: var(--fw-overline);
}
.guide-section-intro { margin: 0; color: var(--ui-text-secondary); font-size: var(--fs-body); line-height: var(--lh-body); }
.guide-tagline { color: var(--ui-text-primary); font-weight: var(--fw-semibold); }

/* Hộp phím tắt đứng đầu mỗi mục — đọc như "tra cứu nhanh". */
.guide-block--kbd {
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-1-5);
  padding: var(--ui-space-2-5) var(--ui-space-3);
  border: var(--ui-stroke-thin) solid var(--ux-border);
  border-radius: var(--ui-radius-control);
  background: var(--ux-base);
}
.guide-block--kbd h3 {
  margin: 0;
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
  font-weight: var(--fw-overline);
}
.guide-tips { margin: 0; padding-left: var(--ui-space-4-5); display: flex; flex-direction: column; gap: var(--ui-space-1); }
.guide-tips li { color: var(--ui-text-secondary); font-size: var(--fs-body); line-height: var(--lh-body-sm); }

.guide-kbd-list { display: flex; flex-direction: column; gap: var(--ui-space-1); }
.guide-kbd-row { display: flex; align-items: baseline; gap: var(--ui-space-2-5); font-size: var(--fs-body); color: var(--ui-text-secondary); }
.guide-kbd-row kbd {
  flex: 0 0 auto;
  min-width: var(--dt-dimension-layout-72);
  padding: var(--ui-space-0-5) var(--ui-space-1-5);
  border: var(--ui-stroke-thin) solid var(--ux-border);
  border-bottom-width: var(--ui-stroke-thick);
  border-radius: var(--ui-radius-control);
  background: var(--ux-base);
  color: var(--ui-text-primary);
  font-family: inherit;
  font-size: var(--fs-caption);
  text-align: center;
}

.guide-shots { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); gap: var(--ui-space-3); }
.guide-shot {
  margin: 0;
  border: var(--ui-stroke-thin) solid var(--ux-border);
  border-radius: var(--ui-radius-control);
  background: var(--ux-base);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.guide-shot img { display: block; width: 100%; height: auto; }
.guide-shot-fallback {
  display: none;
  padding: var(--ui-space-6) var(--ui-space-3);
  text-align: center;
  color: var(--ui-text-muted);
  font-size: var(--fs-caption);
}
.guide-shot.is-missing .guide-shot-fallback { display: block; }
.guide-shot figcaption { padding: var(--ui-space-1-5) var(--ui-space-2-5); color: var(--ui-text-muted); font-size: var(--fs-caption); line-height: var(--lh-caption); }

.guide-section-actions { display: flex; flex-wrap: wrap; gap: var(--ui-space-2); }

/* Hướng dẫn — BIẾN THỂ FLAT (GĐ5.4, docs/PLAN-FLAT-SURFACE-GD5.md): các mục
   liền nhau thành MỘT nhóm, đúng một vạch giữa hai mục, chỉ bo 4 góc ngoài;
   ô icon tiêu đề thành glyph trần; hộp "Phím tắt" bỏ khung (đã có tiêu đề
   overline). Ảnh minh hoạ (.guide-shot) là đối tượng nội dung nên GIỮ thẻ (BA
   Q3). Tiền tố html[data-surface] thắng các luật gốc cùng @layer legacy bằng
   độ đặc hiệu; chỉ đổi độ dày viền nên viền accent của mục đang focus vẫn giữ.
   Đầu/cuối chọn theo anh em cùng class — mục đầu là <section>, các mục sau là
   <article>, nên :first-of-type/:last-of-type chọn sai. */
html[data-surface="flat"] .guide-content { gap: var(--ui-flat-gap); }
html[data-surface="flat"] .guide-content > .guide-section {
  border-width: 0 var(--ui-flat-divider-w) var(--ui-flat-divider-w);
  border-radius: var(--ui-flat-radius-inner);
}
html[data-surface="flat"] .guide-content > .guide-section:not(.guide-section ~ .guide-section) {
  border-top-width: var(--ui-flat-divider-w);
  border-top-left-radius: var(--ui-flat-group-radius);
  border-top-right-radius: var(--ui-flat-group-radius);
}
html[data-surface="flat"] .guide-content > .guide-section:not(:has(~ .guide-section)) {
  border-bottom-left-radius: var(--ui-flat-group-radius);
  border-bottom-right-radius: var(--ui-flat-group-radius);
}
html[data-surface="flat"] .guide-section-icon { background: transparent; }
html[data-surface="flat"] .guide-block--kbd {
  padding-inline: 0;
  border-color: transparent;
  background: transparent;
}

/* Layout hẹp: mục lục thành dải cuộn ngang ở đầu, nội dung một cột. */
html[data-layout-mode="compact"] .guide-layout,
html[data-layout-mode="tight"] .guide-layout {
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr);
}
html[data-layout-mode="compact"] .guide-toc,
html[data-layout-mode="tight"] .guide-toc {
  border-right: none;
  border-bottom: var(--ui-stroke-thin) solid var(--ux-divider);
  flex-direction: row;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  gap: var(--ui-space-1-5);
  padding: var(--ui-space-2-5) var(--ui-space-3);
}
html[data-layout-mode="compact"] .guide-toc-link,
html[data-layout-mode="tight"] .guide-toc-link { width: auto; white-space: nowrap; border: var(--ui-resizer-line) solid var(--ux-border); }
html[data-layout-mode="compact"] .guide-toc-foot,
html[data-layout-mode="tight"] .guide-toc-foot { display: none; }

.settings-help-actions { display: flex; flex-direction: column; gap: var(--ui-space-2-5); }
.settings-help-actions p { margin: 0; color: var(--ui-text-secondary); font-size: var(--fs-body); line-height: var(--lh-body-sm); }
.settings-help-btn-row { display: flex; flex-wrap: wrap; gap: var(--ui-space-2); }
} /* @layer legacy */

@layer modules {
  /* Khung rail chuẩn (BA 10/10/2026): avatar tài khoản ở đỉnh thay logo, cách mép trên
     đúng bằng cách mép trái/phải ((rail − avatar) / 2) cho cân; menu tài khoản (khối gốc
     .nav-avatar-menu: top + menuGravityDrop) sổ từ trên xuống cạnh avatar. Phần ô ngoài nút vẫn kéo được cửa sổ; nút avatar thì không. */
  .nav-rail-brand {
    --rail-avatar-inset: calc((var(--rail-w) - var(--ui-size-md)) / 2);
    flex: 0 0 auto;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    /* rail đã có đệm trên --ui-space-2 (ui-foundation.css) → chỉ bù phần thiếu. */
    padding-top: max(0px, calc(var(--rail-avatar-inset) - var(--ui-space-2)));
    /* + khe rail 4 = 8 dưới avatar, bằng khe giữa các mục module. */
    padding-bottom: var(--ui-space-1);
    -webkit-app-region: drag;
  }
  /* Liền mạch: rail không có đệm trên (padding-top 0) → ô tự gánh trọn lề trên. */
  html[data-shell-frame="seamless"] .nav-rail-brand { padding-top: var(--rail-avatar-inset); }
  .nav-rail-brand .nav-rail-avatar-btn { -webkit-app-region: no-drag; }
  .nav-rail-body { margin-top: 0; }
  .nav-rail-avatar-btn .nav-rail-icon {
    width: var(--ui-size-md);
    height: var(--ui-size-md);
  }
  .menu-avatar-default { display: none; }
  .menu-avatar-wrap.is-default-avatar .menu-avatar { display: none; }
  .menu-avatar-wrap.is-default-avatar .menu-avatar-default {
    display: block;
    width: var(--ui-icon-md);
    height: var(--ui-icon-md);
    color: var(--ui-text-secondary);
  }
  /* Ô tìm kiếm gọn (BA 10/10/2026, kiểu Notion/Linear): ở Notebook ô nằm
     sát cụm thao tác bên phải thay vì một viên trống giữa header; lúc nghỉ nền
     chìm không viền, rộng 208; bấm vào hoặc đang có chữ thì nở 320. Khổ hẹp
     (medium/compact/tight) vẫn là nút kính lúp mở ô nổi — responsive-layout.css. */
  /* Hai khai báo dưới chuyển từ @layer overrides (ui-components.css) — giữ nguyên cho khổ hẹp. */
  .topbar-search-wrap { background: color-mix(in srgb, var(--ui-surface-panel) 94%, transparent); }
  .topbar-search-wrap:not(:hover, :focus-within) { border-color: var(--ui-divider); }
  html[data-layout-mode="wide"]:is([data-view="notics"], [data-view="noteSpeed"]) .topbar {
    grid-template-columns: minmax(0, 1fr) auto auto;
    column-gap: var(--ui-space-2);
  }
  html[data-layout-mode="wide"]:is([data-view="notics"], [data-view="noteSpeed"]) .topbar-center {
    justify-self: end;
    margin-inline: 0;
    max-width: none;
    transform: none;
  }
  html[data-layout-mode="wide"] .topbar .topbar-search-wrap {
    width: var(--dt-dimension-layout-208);
    min-width: 0;
    border-color: transparent;
    background: color-mix(in srgb, var(--ui-text-primary) 5%, transparent);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    transition: width var(--ui-duration-fast) var(--ui-ease), border-color var(--ui-duration-fast) var(--ui-ease), background var(--ui-duration-fast) var(--ui-ease);
  }
  html[data-layout-mode="wide"] .topbar .topbar-search-wrap:hover {
    border-color: var(--ux-control-border-hover);
  }
  html[data-layout-mode="wide"] .topbar .topbar-search-wrap:is(:focus-within, :has(.topbar-search-input:not(:placeholder-shown))) {
    width: var(--dt-dimension-layout-320);
  }
  html[data-layout-mode="wide"] .topbar .topbar-search-wrap:focus-within {
    border-color: var(--ux-control-border-active);
    background: rgb(var(--ui-surface-raised-rgb));
  }

  /* ==== Topbar Lịch kiểu Google Calendar/Outlook (BA 10/10/2026 lượt 3) ====
     Trái: Hôm nay ‹ › Tháng 10, 2026 ▾ (bộ chọn thay tiêu đề trang). Phải: 🔍 · Tuần ▾.
     Không nền/khung cụm — nút ghost, chỉ hiện nền khi rê/đang mở. Mọi khổ dùng chung
     bố cục: hai lớp vỏ (.topbar-right, .topbar-actions-calendar) thành display: contents
     để ba nhóm đứng thẳng trên lưới topbar. */
  html[data-view="calendar"] :is(.topbar-right, .topbar-actions-calendar) { display: contents; }
  html[data-view="calendar"] .topbar {
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    column-gap: var(--ui-space-1);
  }
  html[data-view="calendar"] .topbar .week-nav-cluster {
    grid-row: 1;
    grid-column: 1;
    justify-self: start;
    gap: var(--ui-space-0-5);
    min-width: 0;
  }
  html[data-view="calendar"] .topbar-center {
    grid-row: 1;
    grid-column: 3;
    justify-self: end;
    margin: 0;
    max-width: none;
    transform: none;
  }
  html[data-view="calendar"] .topbar .view-mode-wrap {
    grid-row: 1;
    grid-column: 4;
  }
  .calendar-today-btn { margin-right: var(--ui-space-1); }
  /* Nút chữ trên topbar dùng màu chữ chính: màu phụ của --subtle chỉ 3.78:1 trên khung
     Liền mạch + Kính Sáng (readabilityStandard.spec.js). */
  .topbar .view-mode-btn { color: var(--ui-text-primary); }
  /* "Hôm nay" (BA 13/10/2026, thay viên thuốc accent của 11/10 — "bó viền lạc lõng"): cùng họ
     với ‹ › và tiêu đề tháng bên cạnh — nút nhẹ không nền, bo control, chữ chính 500; nền chỉ
     hiện khi rê/nhấn (hover/active của .ui-btn--subtle). Chữ chính thay màu phụ của --subtle
     để đạt AA trên khung Liền mạch + Kính Sáng (readabilityStandard.spec.js). */
  .topbar .calendar-today-btn { color: var(--ui-text-primary); }
  /* Khung Liền mạch màu đậm: accent trên khung = mực trắng, nền trắng nhạt lúc nghỉ hạ chữ
     xuống 4.0–4.47:1 — chỉ giữ chữ đậm, nền dùng hover/active của khung. */
  html[data-shell-frame="seamless"]:is([data-shell-chrome="blue"], [data-shell-chrome="green"], [data-shell-chrome="purple"], [data-shell-chrome="pink"], [data-shell-chrome="orange"], [data-shell-chrome="graphite"]) .topbar .calendar-today-btn {
    background: transparent;
  }
  html[data-shell-frame="seamless"]:is([data-shell-chrome="blue"], [data-shell-chrome="green"], [data-shell-chrome="purple"], [data-shell-chrome="pink"], [data-shell-chrome="orange"], [data-shell-chrome="graphite"]) .topbar .calendar-today-btn:hover {
    background: var(--ui-chrome-hover);
  }
  html[data-shell-frame="seamless"]:is([data-shell-chrome="blue"], [data-shell-chrome="green"], [data-shell-chrome="purple"], [data-shell-chrome="pink"], [data-shell-chrome="orange"], [data-shell-chrome="graphite"]) .topbar .calendar-today-btn:active {
    background: var(--ui-chrome-active);
  }
  /* Bộ chọn = tiêu đề: rộng theo chữ ("Tháng 9 – 10, 2026"), chữ tiêu đề 14/500. */
  html[data-view="calendar"] .topbar .week-nav-cluster .picker-btn {
    width: auto;
    min-width: 0;
    max-width: none;
    padding-inline: var(--ui-space-2);
    gap: var(--ui-space-1);
  }
  html[data-view="calendar"] .topbar .picker-label {
    color: var(--ui-text-primary);
    font-size: var(--fs-body);
    font-weight: var(--fw-medium);
    white-space: nowrap;
  }
  /* Header 32 (BA 10/10/2026): mọi nút .ui-btn trên topbar (kể cả nút chính "+ Ghi chú")
     cao bằng control header 24, còn lề 4 trên/dưới. */
  .topbar .ui-btn {
    height: var(--ui-header-control-size);
    min-height: var(--ui-header-control-size);
  }
  .topbar .ui-btn.ui-btn--icon {
    width: var(--ui-header-control-size);
    min-width: var(--ui-header-control-size);
  }
  .topbar .ui-input {
    height: var(--ui-header-control-size);
    min-height: var(--ui-header-control-size);
  }
  /* Bộ chọn tuần nay ở bên trái → bảng thả xuống canh mép trái nút, mọi khổ (khổ hẹp
     trước đây ghim mép phải cửa sổ vì nút nằm bên phải). */
  html[data-view="calendar"] .topbar .picker-wrap { position: relative; }
  html[data-view="calendar"] #pickerPanel {
    position: absolute;
    top: calc(100% + var(--ui-space-1));
    left: 0;
    right: auto;
    width: min(var(--dt-component-popover-compact-width), calc(100dvw - var(--rail-w) - var(--ui-space-6)));
    transform-origin: top left;
  }
  /* Menu dạng xem: thả ngay dưới nút icon dạng xem, canh mép phải nút; chữ canh trái như menu chuẩn. */
  html[data-view="calendar"] .view-mode-wrap { position: relative; }
  html[data-view="calendar"] .widget-menu-panel.view-mode-panel {
    position: absolute;
    top: calc(100% + var(--ui-space-1));
    right: 0;
    left: auto;
    width: var(--dt-component-popover-small-width);
  }
  #viewModePanel .view-mode-option { justify-content: flex-start; }
  html[data-view="calendar"] .topbar .picker-chevron {
    width: var(--ui-icon-sm);
    height: var(--ui-icon-sm);
    color: var(--ui-text-secondary);
  }
  /* Tìm kiếm ở Lịch + Notebook (BA 10/10/2026) = kính lúp; bấm mới mở ô (khổ rộng: nở tại chỗ; khổ hẹp: ô nổi
     sẵn có ở responsive-layout.css). Đang có chữ hoặc đang lọc dự án thì ô luôn hiện
     để người dùng thấy bộ lọc đang bật. */
  html:is([data-view="calendar"], [data-view="notics"]) .topbar-search-toggle {
    align-items: center;
    justify-content: center;
    width: var(--ui-header-control-size);
    min-width: var(--ui-header-control-size);
    height: var(--ui-header-control-size);
    padding: 0;
    border: 0;
    border-radius: var(--ui-radius-control);
    background: transparent;
    color: var(--ui-text-secondary);
    cursor: pointer;
  }
  html:is([data-view="calendar"], [data-view="notics"]) .topbar-search-toggle:hover { background: var(--ui-hover); color: var(--ui-text-primary); }
  html:is([data-view="calendar"], [data-view="notics"]) .topbar-search-toggle svg { width: var(--ui-icon-sm); height: var(--ui-icon-sm); }
  html[data-view="calendar"][data-layout-mode="wide"] .topbar:is(.is-compact-search-open, :has(.topbar-search-input:not(:placeholder-shown)), :has(#calendarProjectFilterBtn.is-active)) .topbar-search-wrap,
  html[data-view="notics"][data-layout-mode="wide"] .topbar:is(.is-compact-search-open, :has(.topbar-search-input:not(:placeholder-shown))) .topbar-search-wrap {
    width: var(--dt-dimension-layout-320);
    min-width: 0;
  }
  /* Ẩn/hiện ô tìm, kính lúp, tiêu đề trái ở Lịch nằm trong @layer legacy (cuối
     responsive-layout.css) — layer chuẩn không đặt display cho class legacy ẩn theo khổ
     (tests/cssLayers.test.js). */

  /* Breadcrumb topbar cùng 14/500 với tiêu đề (BA 10/10/2026). Cấp cha KHÔNG hạ màu phụ:
     trên khung Liền mạch + Kính, chữ phụ còn 3.78:1 < AA (readabilityStandard.spec.js). */
  .topbar .notics-project-filter-btn { font-weight: var(--fw-medium); }

  /* Notebook: danh sách đang trống đã có lời mời tạo ghi chú → khung soạn không vẽ
     khối trống thứ hai ("Chưa chọn ghi chú") cạnh nó. Giữ #noticsEditorEmpty (luồng/test). */
  .notics-page:has(#noticsNoteList > .notics-empty-state) #noticsEditorEmpty .notics-empty-state {
    visibility: hidden;
  }

  /* Nút ‹ › tháng trong bộ chọn tuần: .ui-btn nhẹ, cỡ = ô ngày (control compact)
     để hàng đầu thẳng lưới ngày (calendarPickerTokens.spec.js). */
  .ui-btn.month-nav-btn {
    width: var(--ui-control-h-compact);
    min-width: var(--ui-control-h-compact);
    height: var(--ui-control-h-compact);
    min-height: var(--ui-control-h-compact);
  }
}

/* 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 {
  html[data-motion="off"] *, html[data-motion="off"] *::before, html[data-motion="off"] *::after { animation-duration: .001ms; /* audit-keep: nhịp riêng của hiệu ứng, không thuộc nhịp giao diện chuẩn */ animation-iteration-count: 1; transition-duration: .001ms; /* audit-keep: nhịp riêng của hiệu ứng, không thuộc nhịp giao diện chuẩn */ scroll-behavior: auto; }
  html[data-motion="minimal"] :is(.widget-menu-panel, .picker-panel, .priority-picker-panel):not(.hidden), html[data-motion="off"] :is(.widget-menu-panel, .picker-panel, .priority-picker-panel):not(.hidden) { animation: none; opacity: 1; }
  .topbar-search-input, .topbar-search-input:focus, .topbar-search-input:focus-visible { padding: 0; margin: 0; outline: none; box-shadow: none; }
  :is( .topbar-section > .notics-header-toggle, .topbar-section > .notics-icon-btn, .notics-project-filter-btn, .notics-open-project-btn, .antiscreenshot-zoom button, .antiscreenshot-capture-btn:not(.is-primary), .view-mode-wrap .glass-icon-btn ) { box-shadow: none; background: transparent; border: var(--ui-stroke-thin) solid transparent; }
  :is( .topbar-section > .notics-header-toggle, .topbar-section > .notics-icon-btn, .notics-project-filter-btn, .notics-open-project-btn, .antiscreenshot-capture-btn, .view-mode-wrap .glass-icon-btn ) { min-height: var(--ui-header-control-size); max-height: var(--ui-header-control-size); border-radius: var(--ui-radius-control); font-size: var(--fs-caption); line-height: var(--lh-none); }
  :is( .antiscreenshot-capture-btn ) { padding: 0 var(--ui-space-2); gap: var(--ui-space-1); }
  /* Đang sửa ảnh/video: "Tạo mới" là nút biểu tượng vuông (báo cáo UX 10/10/2026 §4.4). */
  .antiscreenshot-capture-btn.is-compact { padding: 0; width: auto; aspect-ratio: 1 / 1; }
  :is( .topbar-section > .notics-header-toggle, .topbar-section > .notics-icon-btn, .notics-open-project-btn, .view-mode-wrap .glass-icon-btn ) { width: var(--ui-header-control-size); padding: 0; }
  /* Mảnh breadcrumb "Notebook / <phạm vi>" — chữ body 14 như tiêu đề và nút tháng của Lịch,
     không theo cỡ 12 của nút icon header ở rule trên (BA 10/10/2026: hai chữ lệch chân chữ).
     Cần (0,2,0): :is(.topbar-section > …) phía trên mang độ ưu tiên (0,2,0) cho cả danh sách. */
  .notics-project-filter-btn { padding: 0 var(--ui-space-2); gap: var(--ui-space-1); }
  .topbar .notics-project-filter-btn { font-size: var(--fs-body); }
  :is( .topbar-section > .notics-header-toggle, .topbar-section > .notics-icon-btn, .notics-project-filter-btn, .notics-open-project-btn, .antiscreenshot-zoom button, .antiscreenshot-capture-btn:not(.is-primary), .view-mode-wrap .glass-icon-btn ):hover:not(:disabled) { box-shadow: none; background: var(--ui-hover); border-color: transparent; color: var(--ui-text-primary); }
  :is( .topbar-actions .antiscreenshot-capture-btn.is-primary ) { background: var(--ui-accent-solid); border: var(--ui-stroke-thin) solid transparent; color: var(--ui-text-on-accent); box-shadow: none; }
  :is( .topbar-actions .antiscreenshot-capture-btn.is-primary ):hover:not(:disabled) { box-shadow: none; }
  .week-nav-cluster { height: var(--ui-header-control-size); min-height: var(--ui-header-control-size); padding: 0; border-radius: var(--dt-dimension-radius-full); background: transparent; box-shadow: none; backdrop-filter: none; border: var(--ui-stroke-thin) solid transparent; }
  .week-nav-cluster:has([aria-expanded="true"]), .week-nav-cluster:focus-within { box-shadow: none; }
  .week-nav-cluster .icon-btn, .week-nav-cluster .picker-btn { height: var(--ui-header-control-size); min-height: var(--ui-header-control-size); background: transparent; border: none; box-shadow: none; border-radius: var(--dt-dimension-radius-full); }
  .week-nav-cluster .icon-btn { width: var(--ui-header-control-size); border-radius: var(--ui-radius-circle); }
  .week-nav-cluster .icon-btn:hover, .week-nav-cluster .picker-btn:hover { background: var(--ui-hover); }
  .linked-note-editor, .linked-note-editor .ql-editor, .linked-note-editor .ql-editor :is(p, ol, ul, li) { font-family: var(--app-font); font-size: var(--popup-content); }
  @media (prefers-reduced-motion: reduce) {
    .task-state-completing, .task-state-restoring, .task-land-complete, .task-rise-restore { animation: none; }
  }
  @media (prefers-reduced-motion: reduce) {
    .picker-panel { animation: none; }
  }
  @media (prefers-reduced-motion: reduce) {
    .month-nav-btn, .month-today-btn, .month-week-row { transition: none; }
  }
  @media (prefers-reduced-motion: reduce) {
    .sync-status-dot { animation: none; }
  }
  @media (prefers-reduced-motion: reduce) {
    .sync-channel-dot { animation: none; }
  }
  .input-shake { border-color: var(--ui-danger); }
  .overlay.is-overlay-underlay { background: transparent; backdrop-filter: none; -webkit-backdrop-filter: none; }
  @media (prefers-reduced-motion: reduce) {
    :is(.overlay-panel, .overlay-panel--sm, .overlay-panel--md, .overlay-panel--lg, .overlay-panel--xl), .item-detail-drawer { animation: none; }
  }
  .monochrome-task-rows .task-item:not(:is(#grid.multi-week, html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"])) .task-item), html:root.monochrome-task-rows .task-item:not(.done):not(:is(#grid.multi-week, html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"])) .task-item), html:root.monochrome-task-rows .task-item.done:not(:is(#grid.multi-week, html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"])) .task-item), html[data-material="glass"]:root.monochrome-task-rows .task-item:not(.done):not(:is(#grid.multi-week, html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"])) .task-item), html[data-material="glass"]:root.monochrome-task-rows .task-item.done:not(:is(#grid.multi-week, html[data-calendar-surface="flat"] #grid:is([data-view-mode="week"], [data-view-mode="today"], [data-view-mode="agenda"])) .task-item) { background: transparent; }
  :is(.task-item, .gcal-event-item, .outlook-event-item).item-tone-blue, :is(.task-item, .gcal-event-item, .outlook-event-item).item-tone-purple, :is(.task-item, .gcal-event-item, .outlook-event-item).item-tone-pink, :is(.task-item, .gcal-event-item, .outlook-event-item).item-tone-orange, :is(.task-item, .gcal-event-item, .outlook-event-item).item-tone-green { background: var(--task-row-bg); }
  .task-item.dragging { background: rgba(var(--ui-surface-raised-rgb), .96); }
  @media (prefers-reduced-motion: reduce) {
    .grid, .task-item, .completed-chevron, .gcal-event-item, .outlook-event-item, .icon-btn, .picker-btn { transition: none; animation: none; }
  }
  .grid.multi-week .task-item, .grid.multi-week :is(.gcal-event-item, .outlook-event-item), .monochrome-task-rows .grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item), html[data-material="glass"].monochrome-task-rows .grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item), html:root.monochrome-task-rows .grid.multi-week :is(.task-item, .gcal-event-item, .outlook-event-item) { border: 0; background: var(--task-row-bg, var(--tone-blue-bg)); }
  .grid.multi-week :is(.task-prefix-slot, .event-prefix-slot) { width: var(--month-lead-lane, var(--ui-space-1)); min-width: var(--month-lead-lane, var(--ui-space-1)); flex-basis: var(--month-lead-lane, var(--ui-space-1)); }
  :is(.grid.multi-week, .monochrome-task-rows .grid.multi-week) .task-item.has-priority-urgent :is(.task-prefix, .task-priority-dot) { color: var(--tone-pink-bar); background: var(--tone-pink-bar); }
  :is(.grid.multi-week, .monochrome-task-rows .grid.multi-week) .task-item.has-priority-important :is(.task-prefix, .task-priority-dot) { color: var(--tone-purple-bar); background: var(--tone-purple-bar); }
  :is(.grid.multi-week, .monochrome-task-rows .grid.multi-week) .task-item.has-priority-normal :is(.task-prefix, .task-priority-dot) { color: var(--tone-green-bar); background: var(--tone-green-bar); }
  :is(.grid.multi-week, .monochrome-task-rows .grid.multi-week) .task-item.has-priority-personal :is(.task-prefix, .task-priority-dot) { color: var(--tone-blue-bar); background: var(--tone-blue-bar); }
  .grid.multi-week :is(.task-text, .gcal-event-title, .outlook-event-title) { text-overflow: ellipsis; }
  @media (prefers-reduced-motion: reduce) {
    :is(.quick-task-input, .draft-input, .form-input, .form-select, .text-input, .quickadd-choice, .draft-card-item, .btn-join-meeting) { transition: none; }
  }
  .glass-icon-btn { border-radius: var(--ui-radius-circle); background: rgba(var(--ui-surface-raised-rgb), 0.98); backdrop-filter: blur(12px); border: var(--ui-stroke-thin) solid var(--ux-border); }
  .glass-icon-btn:hover { background: var(--ui-hover); border-color: var(--ui-accent); color: var(--ui-text-primary); }
  #tagFilterToggle { transition: width var(--ui-duration-standard) var(--ui-ease), opacity var(--ui-duration-standard), padding var(--ui-duration-standard), margin var(--ui-duration-standard); }
  @media (prefers-reduced-motion: reduce) {
    ::view-transition-group(main-content), ::view-transition-old(main-content), ::view-transition-new(main-content) { animation: none; }
  }
  .token-select-hidden-native { width: 0; height: 0; opacity: 0; border: 0; padding: 0; margin: 0; }
  #noteSpeedExpandBtn.is-on { background: rgba(var(--ui-accent-rgb), 0.12); color: var(--ui-accent); }
  #noteSpeedExportBtn[aria-expanded="true"], #noteSpeedNoteMenuBtn[aria-expanded="true"] { background: rgba(var(--ui-accent-rgb), 0.12); color: var(--ui-accent); }
  :is(.notics-btn-lock-toggle).is-icon-only { padding: 0; gap: 0; }
  /* Thẻ trang (BA 13/10/2026, hướng A): header là dải TRÊN của thẻ thân trang — không khe dưới, không bóng riêng (bóng do thẻ thân trang đổ). */
  html:not(.is-image-canvas) .topbar { height: var(--app-header-height); min-height: var(--app-header-height); max-height: var(--app-header-height); margin: var(--shell-gap) var(--shell-gap) 0; padding: 0 var(--ui-space-3); border: 0; background: var(--ux-frame); box-shadow: none; }
  html[data-material="glass"] .topbar { box-shadow: inset 0 1px 0 light-dark(rgba(var(--ui-white-rgb),.42), rgba(var(--ui-white-rgb),.10)); /* 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 */ }
  html:not(.is-image-canvas) :is( .grid, .notics-page, .feedback-admin-page, .project-page, .dashboard-page, .settings-page, .premium-page, .premium-admin-page, .antiscreenshot-page, .guide-page ) { margin: 0 var(--shell-gap) var(--shell-gap) var(--shell-gap); border: 0; border-radius: 0 0 var(--ui-radius-window) var(--ui-radius-window); box-shadow: none; }
  /* padding-box: nét viền trong suốt 1 nét của .app để lộ nền cửa sổ = viền ngoài. Có hình nền
     (Acrylic/Kính) .app trong suốt nên viền ấy luôn hiện; màn không hình nền (Art Editor,
     WALLPAPER_FREE_VIEWS) mà tô tràn border-box thì mất viền → lệch giữa các màn (BA 14/10/2026). */
  html[data-shell-frame="seamless"]:not(.is-image-canvas) .app { background: var(--ui-chrome-surface); background-clip: padding-box; }
  html[data-shell-frame="seamless"] .nav-rail { width: var(--rail-w); padding-top: 0; border: none; border-radius: 0; box-shadow: none; }
  html[data-shell-frame="seamless"]:not(.is-image-canvas) .nav-rail { background: var(--ui-chrome-surface); }
  html[data-shell-frame="seamless"] .nav-rail-avatar-btn, html[data-shell-frame="seamless"] .nav-rail-avatar-btn:hover, html[data-shell-frame="seamless"] .nav-rail-avatar-btn.is-active { flex: 0 0 var(--ui-header-h, var(--dt-dimension-layout-48)); height: var(--ui-header-h); min-height: var(--ui-header-h); width: 100%; padding: 0; align-items: center; justify-content: center; border-radius: 0; border: none; }
  /* Avatar tròn: cao = rộng = size.md 32 (BA 10/10/2026). Chỉ đổi rộng mà giữ cao 32 ra elip. */
  html[data-shell-frame="seamless"] .nav-rail-avatar-btn .nav-rail-icon { height: var(--ui-size-md); }
  html[data-shell-frame="seamless"] .nav-rail-avatar-btn .menu-avatar-wrap, html[data-shell-frame="seamless"] .nav-rail-avatar-btn .menu-avatar { height: var(--ui-size-md); }
  html[data-shell-frame="seamless"]:not(.is-image-canvas) .topbar { height: var(--ui-header-h); min-height: var(--ui-header-h); max-height: var(--ui-header-h); margin: 0; border: none; border-radius: 0; background: var(--ui-chrome-surface); box-shadow: none; }
  html[data-shell-frame="seamless"]:not(.is-image-canvas) .topbar .week-nav-cluster { background: transparent; }
  html[data-shell-frame="seamless"]:not(.is-image-canvas) :is( .grid, .notics-page, .feedback-admin-page, .project-page, .dashboard-page, .settings-page, .premium-page, .premium-admin-page, .antiscreenshot-page, .guide-page ) { margin: 0 var(--ui-seamless-inset) var(--ui-seamless-inset) 0; border: none; border-radius: var(--ui-seamless-canvas-radius); background-color: var(--surface-page); background-clip: padding-box; }
  html[data-shell-frame="seamless"]:is([data-shell-chrome="neutral"], [data-shell-chrome="white"]):not(.is-image-canvas) :is( .grid, .notics-page, .feedback-admin-page, .project-page, .dashboard-page, .settings-page, .premium-page, .premium-admin-page, .antiscreenshot-page, .guide-page ) { border: var(--ui-resizer-line) solid var(--ux-border); --ux-page-frame-fill: var(--ui-chrome-surface); background-image: linear-gradient(var(--ux-page-frame-fill), var(--ux-page-frame-fill)), none; background-clip: border-area, padding-box; }
  /* Thanh tuần Agenda là đoạn TRÊN của thẻ/tấm thân trang ở cả hai khung. */
  html:not(.is-image-canvas) .agenda-week-bar:not(.hidden) + .grid { border-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; }
  html[data-shell-frame="seamless"] :is( .notics-body, .project-body ) { padding-top: 0; }
  html[data-shell-frame="seamless"] :is( .notics-col-projects, .project-col-list, .settings-nav ) { border-radius: 0; }
  html[data-shell-frame="seamless"] :is( .notics-col-head ) { background: transparent; }
  /* Kính trong + hình nền: header cột mang chữ, thân trang dưới nó chỉ còn .14 → giữ nền header (04/10/2026). */
  html.has-wallpaper[data-material="glass"][data-shell-frame="seamless"]:not(.is-image-canvas) :is( .notics-col-head ) { background: var(--ux-header); }
  /* Thẻ nổi (BA 11/10/2026): rail là thẻ khung trên nền bàn, tách bằng khe — không viền. */
  .nav-rail { background: var(--ux-rail); border-color: var(--ui-rail-divider); box-shadow: var(--ui-float-shadow); }
  html:not([data-shell-frame="seamless"]):not(.is-image-canvas) .app { background: var(--ux-desk); }
  /* Góc cửa sổ = góc DWM của Windows 11 (8px): góc .app lớn hơn thì lộ nền native ở bốn góc. */
  .app { border-radius: var(--ui-radius-control); }
  .nav-rail-item.is-active::before { background: var(--item-accent, var(--ui-accent)); box-shadow: 0 0 9px color-mix(in srgb, var(--item-accent, var(--ui-accent)) 70%, transparent); /* audit-keep: quầng sáng màu trạng thái (glow), không phải bậc độ nổi */ }
  .nav-rail-item:hover .nav-rail-icon svg { filter: none; }
  .nav-rail-item.is-active .nav-rail-icon svg { filter: none; }
  :is(.notics-body, .project-body) { padding-top: 0; }
  :is(.premium-activate-btn) { border-color: transparent; background: var(--ui-accent-solid); color: var(--ui-text-on-accent); box-shadow: var(--elev-2); }
  :is( button:not(.token-date-trigger):not(.token-select-trigger):not(.antiscreenshot-stepper-btn), [role="button"], input[type="checkbox"], input[type="radio"], input[type="range"], input[type="file"] ):focus-visible { outline: var(--ui-focus-ring-width) solid var(--ui-focus-ring); }
  :is( .topbar-search-input, .notespeed-quick-input, .project-notes-search-input, .notics-find-input, .notics-cmdk-input, .notics-note-title, .note-search-input, .antiscreenshot-inspector-input ), :is( .topbar-search-input, .notespeed-quick-input, .project-notes-search-input, .notics-find-input, .notics-cmdk-input, .notics-note-title, .note-search-input, .antiscreenshot-inspector-input ):focus, :is( .topbar-search-input, .notespeed-quick-input, .project-notes-search-input, .notics-find-input, .notics-cmdk-input, .notics-note-title, .note-search-input, .antiscreenshot-inspector-input ):focus-visible { outline: none; border: none; box-shadow: none; border-radius: 0; background: transparent; }
  @media (max-width: 760px) {
    .settings-scroll { padding: var(--ui-space-3-5) var(--ui-space-3-5) var(--ui-space-5); }
  }
  @media (max-width: 760px) {
    :is(.notics-page-header) { min-height: var(--dt-dimension-layout-56); }
  }
  @media (prefers-reduced-motion: reduce) {
    .app-tooltip, .nav-rail-item, :is(.project-weekly-nav-btn, .settings-nav-item) { transition: none; }
  }
  .nav-rail-item.is-active::before { width: var(--ui-nav-indicator-w); border-radius: var(--dt-dimension-radius-full); }
  .notics-icon-btn { border-radius: var(--ui-radius-control); font-size: var(--fs-body); }
  .notics-btn-lock-toggle { border: var(--ui-stroke-thin) solid transparent; background: transparent; color: var(--ui-text-primary); }
  .notics-btn-lock-toggle:hover:not(:disabled) { border-color: transparent; background: var(--ui-hover); color: var(--ui-text-primary); }
  .notics-btn-lock-toggle.is-note-locked { border-color: rgba(var(--ui-warning-rgb), .45); background: rgba(var(--ui-warning-rgb), .12); color: var(--ui-warning); }
    :is(.notics-icon-btn, .notics-btn-note-menu) { padding: 0; }
  /* Tiêu đề trang trên topbar 44 = 14/500 kiểu Linear/Notion (BA 10/10/2026, trước 16/600 — đậm và to gây ngộp). */
  .notics-eyebrow, .dashboard-page .notics-eyebrow { font-size: var(--fs-body); font-weight: var(--fw-medium); letter-spacing: normal; }
  :is(.notics-page-header h1) { font-size: var(--fs-caption); font-weight: var(--fw-overline); }
  .notics-note-title:not(.notics-title-field > .notics-note-title) { font-size: var(--fs-title-lg); font-weight: var(--fw-semibold); }
  :is(.premium-admin-copy small, .premium-admin-summary span, .premium-feature-switches, .premium-card-heading small, .premium-admin-panel-head p) { font-size: var(--fs-caption); }
  :is(.premium-admin-copy strong) { font-size: var(--fs-body); }
  .premium-admin-panel-head h2 { font-size: var(--fs-title); }
  .premium-admin-panel { border-color: var(--ux-border); background: var(--ux-card); }
  .premium-admin-row { background: var(--ux-row); }
  .app-bg-overlay { transition: background var(--ui-duration-fast) var(--ui-ease); }
  :is( .premium-activate-btn, .notics-toolbar button.ql-active, .notics-att-toolbar button.is-active ) { color: var(--on-accent); }
  :is( .premium-activate-btn, .notics-toolbar button.ql-active, .notics-att-toolbar button.is-active ) { background: var(--accent-solid); border-color: transparent; color: var(--on-accent); }
  :is(.premium-activate-btn):hover:not(:disabled) { background: color-mix(in srgb, var(--accent-solid) 88%, var(--ux-raised)); }
  :is(.premium-activate-btn) { box-shadow: var(--elev-2); }
  :is( .edit-panel.expanded-edit-panel, .item-detail-drawer, .event-modal-panel, .config-panel, .overlay-panel, .overlay-panel--sm, .overlay-panel--md, .overlay-panel--lg, .overlay-panel--xl, .overlay-card, .project-dialog, .notics-cmdk, .notics-drawer, .picker-panel, .widget-menu-panel, .priority-picker-panel, .month-picker-panel, .nav-avatar-menu, .menu-panel, .tag-filter-panel, .notics-project-filter-panel, .view-mode-panel, /* GĐ2: popup soạn thảo của Notebook / QuickNote / Painting. Trước đây nó ăn nền nhờ dùng chung class .notics-col-editor với khung vẽ Art Editor — mà Art Editor không phải lớp nổi. Tách ra: khung vẽ nhận .ux-canvas, còn hộp thoại vào đúng hợp đồng lớp nổi này. */ .notespeed-modal-panel ) { background: var(--surface-raised); }
  html.is-view-switching .nav-rail, html.is-view-switching .topbar, html.is-view-switching .app, html.is-view-switching .app-bg-overlay { transition: none; animation: none; }
  :is(.topbar, .nav-rail) { backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat)); -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat)); }
  :is(.notics-page-header) { backdrop-filter: blur(calc(var(--glass-blur) * .75)) saturate(var(--glass-sat)); }
  html[data-material="solid"]:not(.is-image-canvas) :is( .topbar, .nav-rail, .notics-page-header) { backdrop-filter: none; -webkit-backdrop-filter: none; }
  html[data-material="solid"]:not(.is-image-canvas):not([data-shell-frame="seamless"]) :is(.topbar, .nav-rail) { background: rgb(var(--ux-frame-rgb)); }
  .premium-page { padding-top: var(--ui-space-4-5); padding-right: var(--premium-pad-x); padding-left: var(--premium-pad-x); }
  :is(.sys-check, .mode-check, .quickadd-check) { background: var(--accent-solid); color: var(--on-accent); }
  .premium-card-heading > span, .project-portfolio-plan-icon { border-radius: var(--ui-radius-control); color: var(--ui-accent); }
  :is( button:not(.month-today-btn):not(#deleteSeriesConfirmBtn):not(.premium-activate-btn):not(.nav-rail-item):not(.ui-btn):not(.ui-swatch):not(.calendar-item-more), [role="button"]:not(.month-today-btn):not(#deleteSeriesConfirmBtn):not(.premium-activate-btn):not(.nav-rail-item):not(.ui-btn):not(.ui-swatch):not(.calendar-item-more), .glass-icon-btn, .icon-btn, .picker-btn, .widget-menu-item, .settings-nav-item, .source-choice, .notics-icon-btn, .notics-row-action, .notics-item-edit-btn, .project-portfolio-plan-btn, .premium-admin-tabs button ):active:not(:disabled) { background-color: rgba(var(--ink), 0.10); }
  :is( .glass-icon-btn, .icon-btn, .picker-btn, .widget-menu-item, .settings-nav-item, .source-choice, .notics-icon-btn):disabled { box-shadow: none; }
  :is( button:not(.token-date-trigger):not(.token-select-trigger):not(.antiscreenshot-stepper-btn), [role="button"], input[type="checkbox"], input[type="radio"], input[type="range"], input[type="file"], [tabindex] ):focus-visible { outline: none; }
  :is( .topbar-search-input, .notespeed-quick-input, .project-notes-search-input, .notics-find-input, .notics-cmdk-input, .notics-note-title, .note-search-input, .antiscreenshot-inspector-input ):is(:focus, :focus-visible) { outline: none; border: none; box-shadow: none; }
  /* Ô nhập chính + nút chính cạnh nó = bậc lg (AT-UI Rhythm 10/10/2026); mọi control khác 32. */
  .edit-panel.expanded-edit-panel :is(.quick-task-input, .quick-add-btn) { height: var(--ui-size-lg); min-height: var(--ui-size-lg); }
  .qa-full :is(.quick-task-input, .quick-add-btn) { height: var(--ui-control-h-standard); min-height: var(--ui-control-h-standard); }
  :is(.edit-panel.expanded-edit-panel, .qa-full) :is(.form-input, .form-select) { height: var(--ui-control-h-standard); min-height: var(--ui-control-h-standard); }
  :is(.edit-panel.expanded-edit-panel, .qa-full) .quick-add-field .token-select-trigger, :is(.edit-panel.expanded-edit-panel, .qa-full) .quick-add-field :is(.form-input, .form-select) { height: var(--ui-control-h-standard); min-height: var(--ui-control-h-standard); }
  .feedback-admin-header h1 { font-size: var(--fs-title); }
  .feedback-enabled-switch { padding: 0 var(--ui-space-3); }
  .feedback-delete { color: var(--notics-danger); }
  @media (max-width: 680px) {
    .feedback-admin-header { height: auto; min-height: var(--app-header-height); }
  }
  .nav-rail-item, .nav-rail-item:hover, .nav-rail-item:active, .nav-rail-item:focus, .nav-rail-item:focus-visible, .nav-rail-item.is-active, html:root .nav-rail-item.is-active, html:root .nav-rail-item:active { border: 0; background: transparent; background-color: transparent; box-shadow: none; color: var(--ui-text-secondary); } /* bỏ outline: none (01/10/2026): ở layer overrides nó đè vòng aria-current của chế độ Tương phản cao (ui-foundation.css, layer utilities); vòng focus bàn phím do rule :focus-visible bên dưới đặt */
  .nav-rail-item:active, .nav-rail-item:active:not(:disabled), html:root .nav-rail-item:active, html:root .nav-rail-item:active:not(:disabled) { background: transparent; background-color: transparent; box-shadow: none; border: 0; outline: none; }
  .nav-rail-avatar-btn, .nav-rail-avatar-btn:hover, .nav-rail-avatar-btn.is-active { height: var(--ui-size-lg); min-height: var(--ui-size-lg); padding: var(--ui-space-0-5) 0; }
  /* Avatar ở đỉnh (mọi khung): nút khít ảnh để lề trên = lề trái (BA 10/10/2026). #navRail
     để thắng cả luật Liền mạch "avatar cao bằng topbar" (kể cả :hover/.is-active). */
  #navRail .nav-rail-brand .nav-rail-avatar-btn { flex: 0 0 auto; height: var(--ui-size-md); min-height: var(--ui-size-md); padding: 0; }
}

/* GĐ B–E bổ sung: khai báo từng mang cờ important có chú thích đứng trước (lượt đầu bỏ sót). */
@layer overrides {
  .topbar-search-input, .topbar-search-input:focus, .topbar-search-input:focus-visible { /* background: transparent — vốn ép ưu tiên — đã bị đè bởi khối "Unified Fluent/ Liquid Glass product shell" ở dòng ~13983 (cùng giá trị transparent) — xóa hẳn ở đây, khối kia mới là nơi quyết định thật. */ border:none; }
  :is( .topbar-section > .notics-header-toggle, .topbar-section > .notics-icon-btn, .notics-project-filter-btn, .notics-open-project-btn, .antiscreenshot-capture-btn, .view-mode-wrap .glass-icon-btn ) { /* Một token chiều cao duy nhất cho mọi control header — xem ghi chú ở ui-components.css (~dòng 8) và responsive-layout.css (~dòng 278). */ height:var(--ui-header-control-size); }
  html:not(.is-image-canvas) .topbar { /* Thẻ trang (BA 13/10/2026): header + thân trang là MỘT thẻ — bo hai góc trên cùng bậc rail, hai góc dưới vuông nối liền thân trang (thân trang bo hai góc dưới). */ border-radius:var(--ui-radius-window) var(--ui-radius-window) 0 0; }
  html:not(.is-image-canvas) :is( .grid, .notics-page, .feedback-admin-page, .project-page, .dashboard-page, .settings-page, .premium-page, .premium-admin-page, .antiscreenshot-page, .guide-page ) { /* --surface-page = --ux-workspace, đã nhân sẵn --a-content theo material (styles.css:14761). KHÔNG thay bằng rgb() đục cứng ở lớp CSS nào phía sau: đây là bề mặt lớn nhất màn hình, ép đục là mất luôn hiệu ứng vật liệu. */ background-color:var(--surface-page); }
  .premium-card-heading > span, .project-portfolio-plan-icon { /* Đọc qua --icon-tile-bg để biến thể Flat (GĐ5.4) đổi được bằng token thay vì chọi !important; không đặt biến thì giữ nguyên nền cũ. */ background:var(--icon-tile-bg, color-mix(in srgb, var(--ui-accent) 12%, transparent)); }
  :is( button:not(.token-date-trigger):not(.token-select-trigger):not(.antiscreenshot-stepper-btn), [role="button"], input[type="checkbox"], input[type="radio"], input[type="range"], input[type="file"], [tabindex] ):focus-visible { box-shadow:0 0 0 1.5px rgb(var(--ui-surface-raised-rgb)), /* audit-keep: bóng riêng của thành phần, không thuộc bậc elevation chuẩn */ 0 0 0 3.5px rgba(var(--ui-accent-rgb), .9); }
}
