# Task ID: v0.14-reimpl
# Agent: full-stack-developer
# Task: 放置系统 (Idle Operations) — 采矿无人机舰队 + 6放置工程 + 永久产能加成 + idle徽章

## Work Log

### 1. 类型扩展 (`src/lib/game/types.ts`)
- 新增 `IdleProjectDef` 接口（id/name/desc/durationSec/reward/minAscensions/minCrystalsPerSec/icon/color/order）
- 新增 `IdleProjectSlot` 接口（projectId/startedAt/finishesAt/remainingSec/completed）
- 在 `GameState` 接口 `pendingAttrPoints` 后新增 4 个字段：
  - `idleProjectSlots: (IdleProjectSlot | null)[]`
  - `idleProjectHistory: { projectId: string; finishedAt: number }[]`
  - `idlePermanentBonus: number`
  - `idleStats: { projectsCompleted: number; crystalsFromIdle: number }`

### 2. 新建 `src/lib/game/idle.ts` (~290 行)
- 定义 6 个放置工程（按 order 排序）：
  | id | name | duration | reward | icon | color | unlock |
  |----|------|----------|--------|------|-------|--------|
  | idle_scan | 深空勘探扫描 | 60s | insights +8 | 🛰️ | emerald | cps≥0.5 |
  | idle_refine | 晶体精炼阵列校准 | 180s | permBonus +0.3/s | ⚙️ | rose | cps≥1 |
  | idle_archive | 遗迹碎片整理 | 600s | randomFragment + insights +20 | 📜 | amber | asc≥1 OR cps≥5 |
  | idle_anchor | 维度锚点部署 | 1200s | energy +2 + contact +5 | ⚓ | fuchsia | asc≥1 |
  | idle_drones | 无人机群扩编 | 1800s | permBonus +2/s + crystals +500 | 🛸 | emerald | cps≥10 |
  | idle_resonance | 跨维度谐振标定 | 3600s | permBonus +8/s + contact +15 + insights +100 | 🌌 | fuchsia | asc≥2 |
- 导出：`IDLE_PROJECTS`, `IDLE_SLOT_COUNT=3`, `getIdleProject`, `getUnlockedIdleProjects`, `getLockedIdleProjects`, `isIdleProjectUnlocked` (OR 逻辑：满足任一已设置条件即可解锁), `formatRemaining` (12s/3m 45s/1h 12m), `formatDuration`, `formatReward`, `deriveMinerFleet` (派生 min_1..min_5 采矿无人机，无任何采矿技术时返回休眠 min_1)
- 导出颜色映射 `IDLE_COLOR_CLASSES` (text/border/bg/bgSoft/glow/ring/dot) + `COLOR_HEX` (用于 inline style，绕过 Tailwind 动态类限制)

### 3. 引擎集成 (`src/lib/game/engine.ts`)
- `recomputeStats()` 末尾 `crystalsPerSec += state.idlePermanentBonus ?? 0` (放置永久加成叠加到产能)
- `performPrestige()` 在返回对象中：
  - 清空 `idleProjectSlots: [null, null, null]` (飞升中断当前周目放置工程)
  - 保留 `idleProjectHistory`, `idlePermanentBonus`, `idleStats` (跨周目永久)
  - `recomputeStats` 调用传入 `idlePermanentBonus` 以确保飞升后立即应用永久加成
- `createInitialState()` 新增 4 字段默认值

### 4. Store actions (`src/store/gameStore.ts`)
- 新增 4 个 action：
  - `startIdleProject(slotIndex, projectId)`: 校验槽位空 + 项目已解锁 + 未在他处运行；写入 `{ projectId, startedAt, finishesAt, remainingSec, completed:false }`
  - `cancelIdleProject(slotIndex)`: 置槽位为 null
  - `claimIdleProject(slotIndex)`: 校验已完成 → 应用奖励（crystals 限 crystalCap，energy 限 energyMax，contact 限 100；permBonus 累加到 idlePermanentBonus + 重算 stats；randomFragment 从未解锁碎片中随机一个）→ 追加 history (slice -50) → idleStats.projectsCompleted++ → Toast 提示
  - `tickIdleProjects(now)`: 遍历非空非完成槽位，更新 remainingSec，归零时标记 completed
- **persist migrate 函数**：persist 配置增加 `version: 1` + `migrate` 函数，自动补全 idleProjectSlots/idleProjectHistory/idlePermanentBonus/idleStats 4 字段，旧存档加载不崩溃
- 全部 14 处 syncStats 调用更新为传入 `idlePermanentBonus: s.idlePermanentBonus ?? 0`，确保 recomputeStats 计算时纳入永久加成
- `init()` 中也补全 4 个 idle 字段（defense in depth）

### 5. 主循环 (`src/hooks/useGameLoop.ts`)
- 新增 `tickIdleProjects` 选择器
- setInterval 回调中 `autoDecodeTick()` 后调用 `tickIdleProjects(now)`
- visibilitychange 回调中也调用 `tickIdleProjects(now)`

### 6. 新建 `src/components/game/IdleOperationsPanel.tsx` (~490 行)
- 主「放置」标签内容，4 个 section 在 `max-h-[520px] overflow-y-auto` 容器中：
  1. **放置收益概览**：3 stat tiles (放置产能 / 永久加成 / 完成工程) + 离线效率 progress bar + 累计放置晶体统计
  2. **采矿无人机舰队**：grid 展示 deriveMinerFleet(state)，每张卡：emoji + name + Lv + output/s + 状态点（active=emerald ping 脉冲，dormant=灰）
  3. **放置工程槽位**：3 张槽位卡（空槽=虚线占位，运行中=大字号倒计时+自定义进度条+取消按钮，已完成=奖励预览+领取按钮带 glow 辉光）
  4. **可派遣工程**：2 列 grid 展示已解锁工程（icon+name+duration+desc+reward+3 个数字派遣按钮 1/2/3），下方列出未解锁工程及解锁条件
- 使用 `useShallow` 订阅多个 store 字段
- 本地 `now` state 每 1s 刷新倒计时
- 严格 4 色全息（emerald/rose/amber/fuchsia），无蓝/靛
- 自定义滚动条样式 (fuchsia 主题)

### 7. 新建 `src/components/game/IdleStatusBadge.tsx` (~100 行)
- 紧凑徽章：脉冲点 (emerald 若 cps>0，否则灰) + "放置中 +X/s" (或 "休眠中")
- Tooltip 悬停展示分解：基础产能 / 永久加成 / 运行中工程 / 待领取工程数
- `h-8 px-2.5 text-[11px]`，点击切换到放置标签
- `data-tut="idle-status-badge"` 锚点

### 8. 新建 `src/components/game/IdleProjectBar.tsx` (~90 行)
- 晶体球下方的细长进度条
- 显示最多 3 个运行/已完成工程为 mini pill：`[icon] name 12s ▓▓▓░░`
- 完成时显示 "✓ 待领取" + glow 辉光
- 无工程时返回 null
- 本地 `now` state 每 1s 刷新倒计时
- 进度条颜色用 inline style 控制（COLOR_HEX 映射）

### 9. 主页面集成 (`src/app/page.tsx`)
- 引入 3 个新组件 + `Clock` 图标 + `getUnlockedIdleProjects`
- 新增 `idleProjectSlots` / `createdAt` store 订阅
- 新增 `activeTab` / `tabInited` state，controlled Tabs：`<Tabs value={activeTab} onValueChange={setActiveTab}>`
- 挂载后 useEffect 一次性设置默认 tab：hasActiveExpedition → "expedition"，hasPendingPerk → "constellation"，否则 → "idle"
- 版本号 v0.8 → v0.14
- Header 在 StarTideIndicator 后加 IdleStatusBadge
- 左侧 CrystalOrb 后加 IdleProjectBar
- TabsList grid-cols-8 → grid-cols-9，新增 `value="idle"` 的 TabsTrigger 作为第一个 tab（Clock 图标，emerald 主题，待领取时显示数量红点）
- 新增 TabsContent value="idle" 渲染 IdleOperationsPanel
- 新增 idle 相关 goal 提示（高优先级）：
  - 待领取 > 0 → "✦ 放置工程已完成 X 项，请前往「放置」标签领取奖励"
  - 全空 + 有解锁 + 时长 > 60s → "「放置」标签可派遣工程项目，离线自动产出"
- StatsPanel 新增 3 行：放置永久加成 / 完成放置工程 / 放置产出晶体

### 10. 教程更新 (`src/lib/game/tutorial.ts`)
- TUTORIAL_STEPS 在 decode 与 tech 之间插入新步骤：
  - id: "idle", target: "tab-idle", placement: "top"
  - 标题 "③ 放置工程 · 离线产出"
  - 介绍放置标签的工程派遣 + 顶部徽章 + 晶体球下方进度条
- 原 tech/expedition/prestige 步骤编号顺延为 ④⑤⑥

## QA 验证

### Lint
- `bun run lint` → 零错误零警告 ✅

### HTTP
- `curl http://localhost:3000/` → 200 OK ✅

### Dev log
- 全程无 runtime error，所有请求 200 OK，编译 < 250ms ✅

### agent-browser 烟雾测试
1. ✅ 版本标签 "v0.14" 可见
2. ✅ 默认 tab 是 "放置"（data-state="active" 在第一个 tab）
3. ✅ 头部 idle 徽章可见（"放置中 +0.4/s" 或 "休眠中"）
4. ✅ IdleOperationsPanel 4 个 section 全部可见（放置收益概览 / 采矿无人机舰队 / 放置工程槽位 / 可派遣工程 / 未解锁工程）
5. ✅ 采矿无人机舰队在无采矿技术时显示休眠 min_1（emoji ⛏️ + 灰色状态点）
6. ✅ 设置 insights=50 → buyTech('min_1') → crystalsPerSec 0.4→1.0 → 解锁 idle_scan + idle_refine
7. ✅ 点击 idle_scan 派遣按钮 → 槽位 0 写入 { projectId: "idle_scan", finishesAt: now+60000 } → 倒计时正确递减
8. ✅ 60s 后自动标记 completed=true → 槽位卡显示 "✓ 完成" + 领取按钮
9. ✅ 点击领取 → Toast "✦ 工程奖励已领取 · 深空勘探扫描 · +8 洞见" → insights 8→16 → history 追加 → idleStats.projectsCompleted 0→1
10. ✅ 派遣 idle_refine (180s) → 强制完成 → 领取 → crystalsPerSec 1.0→1.3 → idlePermanentBonus 0→0.3 ✅ 永久产能加成正确应用
11. ✅ IdleProjectBar 在晶体球下方显示：`🛰️ 深空勘探扫描 55s ▓▓▓░░`
12. ✅ Footer goal 文字根据状态动态切换为放置相关提示
13. ✅ Footer 产能显示 "产能 1.3/s" (含 idle 永久加成)

### Migration 测试
- 旧存档（无 idle 字段）通过 migrate 函数自动补全为默认值，加载不崩溃 ✅

## Stage Summary
- ✅ 类型层：新增 IdleProjectDef + IdleProjectSlot + 4 GameState 字段
- ✅ 逻辑层：新建 idle.ts (~290 行)，6 工程定义 + 派生函数 + 颜色映射
- ✅ 引擎层：recomputeStats / performPrestige / createInitialState 全部接入 idle 永久加成
- ✅ Store 层：4 新 action + persist migrate (version 1) + 14 处 syncStats 调用全部传 idlePermanentBonus
- ✅ 主循环：tickIdleProjects 接入 setInterval + visibilitychange
- ✅ UI 层：3 新组件 (IdleOperationsPanel ~490 行 / IdleStatusBadge ~100 行 / IdleProjectBar ~90 行)
- ✅ 主页面：默认放置 tab + 头部徽章 + 晶体球下方进度条 + 版本 v0.14 + 9 标签页
- ✅ 教程：新增 idle 步骤 (③ 放置工程)
- ✅ 严格 4 色全息 (emerald/rose/amber/fuchsia)，零蓝/靛
- ✅ lint 零错误 + HTTP 200 + agent-browser 全流程烟雾测试通过
- ✅ 5 秒内可见三要素：头部徽章 + 默认放置 tab + 晶体球下方进度条（派遣后）
