diff --git a/.codebuddy/rules/workutils-ui.md b/.codebuddy/rules/workutils-ui.md
new file mode 100644
index 0000000..d1cb6f6
--- /dev/null
+++ b/.codebuddy/rules/workutils-ui.md
@@ -0,0 +1,36 @@
+# WorkUtils UI 开发规则
+
+## 1. CSS 优先级铁律(AtlantaFX 环境)
+
+### 文本颜色
+- **禁止**纯 CSS 设置导航栏选中文字色,AtlantaFX `.label` 会覆盖(含 `!important`)。
+- **正确做法**:Java 代码中 `label.setTextFill(Color.WHITE)` 直接设置。
+
+### 背景透明
+- ListView 内部容器透明需覆盖完整链路:`.list-view`, `.viewport`, `.virtual-flow`, `.virtual-flow > *`, `.clipped-container`, `.sheet`, `.corner`。
+- 同时用 Java 代码 `setStyle("-fx-background-color: transparent;")` 做 inline 兜底。
+
+### 选中态
+- **必须同时覆盖** `.list-cell:selected` 和 `.list-cell:filled:selected`。
+- `.list-cell:selected` 设置透明背景兜底 → 防止虚拟化复用时空 cell 闪现蓝色。
+- `.list-cell:filled:selected` 设置激活背景 → CSS 优先级更高,非空选中 cell 生效。
+
+## 2. ListView 虚拟化陷阱
+
+- ListView 使用 VirtualFlow,cell 会被复用。每次 `updateItem(empty=true)` 时:
+ - 必须清理自定义 style class(先 removeAll 再按需 add)。
+ - 禁止 empty 分支中直接用 `setAll()`(会误删 JavaFX 内置 `list-cell` class)。
+- `selectedProperty()` listener 中调用 `updateStyleClass()` 时,要兼容 empty 状态。
+
+## 3. 布局规则
+
+- ListView 导航栏使用 `VBox.setVgrow(navList, Priority.ALWAYS)` 撑满剩余空间。
+- **不要**在 `refreshNavItems()` 中重新设置 prefHeight/minHeight/maxHeight,会与 grow 冲突。
+- 滚动条自然出现在 ListView 右侧底部,无需额外处理。
+
+## 4. 修改验证流程
+
+修改 UI 样式后:
+1. 先检查 AtlantaFX/modena.css 是否有同名规则覆盖。
+2. 优先使用 Java 端代码设置(`setStyle`/`setTextFill`),再补充 CSS。
+3. 对虚拟化组件(ListView/TableView),验证 resize 窗口场景。
diff --git a/.codebuddy/rules/workutils.yaml b/.codebuddy/rules/workutils.yaml
index 822d647..45fb3c4 100644
--- a/.codebuddy/rules/workutils.yaml
+++ b/.codebuddy/rules/workutils.yaml
@@ -69,6 +69,51 @@ rules:
action: "suggest"
suggestion: "echo 'export/' >> .gitignore"
+ # 7. 复杂重构分步提交 —— 避免会话中断丢失工作
+ - id: refactor-step-by-step
+ description: |
+ 涉及 ≥4 个文件 或 ≥200 行变更 的复杂重构,必须分多个 commit 完成,避免单次会话中断丢失全部工作。
+ 典型场景:
+ - 字段/类重命名(如 navButtons → navList)会触发多文件交叉引用更新
+ - 组件替换(Button → ListView)涉及字段、方法、引用、样式、测试多文件
+ - 框架/库升级涉及配置文件、依赖、调用点、文档
+ 推荐步骤:
+ ① 第一步:加新常量/CSS/配置项(与旧实现共存)
+ ② 第二步:替换实现/切换调用点
+ ③ 第三步:删除旧代码(清理 commit)
+ 每步完成后提交,便于回滚。
+ condition: "涉及文件数 >= 4 OR 变更行数 >= 200"
+ action: "warn"
+ severity: high
+
+ # 8. AtlantaFX UI 防中断规则 —— 修改 MainWindow/Theme/CSS 时必读
+ - id: atlantafx-ui-pitfalls
+ description: |
+ 修改 MainWindow.java、Theme.java 或 light-theme.css 时,必须遵守以下规则,避免反复修改同一问题导致会话中断:
+
+ 【CSS 优先级】
+ - AtlantaFX 的 .label 规则优先级极高,!important 也会被覆盖
+ - 导航栏选中文字色:必须用 Java 代码 label.setTextFill(Color.WHITE),不能靠 CSS
+ - ListView 选中态:必须同时覆盖 .list-cell:selected(为空 cell 兜底)和 .list-cell:filled:selected(为非空 cell 设置激活背景)
+ - 背景透明:需要完整覆盖 .list-view → .virtual-flow → .clipped-container → .sheet 全链路
+
+ 【ListView 虚拟化】
+ - cell 会被 VirtualFlow 复用,updateItem(empty=true) 时必须清理自定义 style class
+ - 不要用 getStyleClass().setAll(),会误删 JavaFX 内置 list-cell class;用 removeAll + add
+ - 窗口 resize 时 cell 复用会暴露 empty cell 被 selected 的问题
+
+ 【布局】
+ - 导航 ListView 用 VBox.setVgrow(ALWAYS) 撑满
+ - refreshNavItems() 中不要重新设置 prefHeight/minHeight/maxHeight
+
+ 【修改后自检清单】
+ ① 小窗口(菜单项少)→ 无滚动条,无底部蓝块
+ ② 选中菜单 → 文字白色,背景蓝色,左侧蓝条可见
+ ③ 最大化窗口 → 无额外蓝色块闪现,滚动条在导航栏底部
+ files: ["MainWindow.java", "Theme.java", "light-theme.css"]
+ action: "warn"
+ severity: high
+
# ===== 触发提示 =====
# 当规则被触发时,AI 会看到这些提示
messages:
@@ -79,3 +124,10 @@ messages:
large-file-check: |
⚠️ 目标文件 >500KB,可能是压缩产物或大型导出文件。
建议使用 head/tail 检查结构,或通过单元测试验证行为。
+ refactor-step-by-step: |
+ ⚠️ 检测到复杂重构(≥4 文件 或 ≥200 行)。
+ 建议分步提交:
+ ① 第一步:加新常量/CSS(与旧实现共存)
+ ② 第二步:替换实现/切换调用点
+ ③ 第三步:删除旧代码
+ 每步完成后 git commit,避免会话中断丢失工作。
diff --git a/src/main/java/com/example/workutils/system/ui/MainWindow.java b/src/main/java/com/example/workutils/system/ui/MainWindow.java
index 30aa8c6..18214c6 100644
--- a/src/main/java/com/example/workutils/system/ui/MainWindow.java
+++ b/src/main/java/com/example/workutils/system/ui/MainWindow.java
@@ -1,7 +1,11 @@
package com.example.workutils.system.ui;
import com.example.workutils.system.config.WorkUtilsProperties;
+import javafx.animation.KeyFrame;
+import javafx.animation.KeyValue;
+import javafx.animation.Timeline;
import javafx.application.Platform;
+import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
@@ -10,11 +14,15 @@ import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
+import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
+import javafx.scene.shape.Circle;
+import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.TextAlignment;
import javafx.stage.Stage;
+import javafx.util.Duration;
import java.io.InputStream;
import java.util.*;
@@ -22,7 +30,7 @@ import java.util.*;
/**
* 工作工具集主窗口 —— AtlantaFX 重构版
*
- * 左侧导航栏 + 右侧内容区,使用 CSS 类控制样式。
+ * 左侧导航栏(ListView)+ 右侧内容区,使用 CSS 类控制样式。
*/
public class MainWindow {
@@ -31,6 +39,7 @@ public class MainWindow {
private final WorkUtilsProperties properties;
private VBox navBox;
+ private ListView navList;
private StackPane contentArea;
private NavItem activeNavItem;
private String activePluginId;
@@ -44,7 +53,6 @@ public class MainWindow {
private Label appLabel;
private Label welcomeIcon, welcomeHeading, welcomeDesc;
- private final List