备餐时间倒排与购物清单｜备餐工作台
========================
打开 index.html，直接使用三道原创素食的示例。所有运行资源已内嵌，不需要安装、联网、服务器或账号。

第一次操作
1. 顶部改就餐人数、日期和固定上桌时间。时间图立即重算；人数改变只缩放食材，不自动改变步骤耗时，请按实际做法改分钟数。
2. 在“菜谱与步骤”选择一道菜。可改名称、原菜谱人数、是否今晚做；食材名称/原用量/单位和步骤内容/耗时都可增删改。步骤左侧序号可拖动重排，也有上/下按钮。自己的菜谱可以完全替换三道示例。
3. 勾选每一步连续占用的资源。每项勾选消耗该资源一个单位。烤箱内的被动烤制可以不勾人手，洗切或装盘可以勾人手。资源编辑区能改名称、数量和添加新类别。
4. 到“购物与库存”记录家里已有的东西。合计同名且同单位的食材，按人数缩放后扣库存。名称先做全角/半角规范化、首尾空格与连续空格处理、大小写归一；不猜测不同单位的换算。
5. “开工顺序”列出每个实际动作的开始/结束和资源。顶部时间图是同一排程的概览；每道菜旁边显示完成时刻及待上桌分钟数。

带走与保存
- JSON：完整保留菜谱、食材、步骤、启用状态、资源、库存、人数、日期和上桌时间；载入可继续编辑。
- 购物 CSV：合计需求、已有库存、还需采购、预计余量和用于哪些菜。
- 时间表 CSV：每个步骤的完整当地日期时间，包含跨日前一日。
- 打印备餐单 HTML：包含购物表、完整开工顺序和各菜完成时刻。下载后打开，按“打印备餐单”调用自己的打印界面。
- 时间图 PNG：实际同源 Canvas 当前方案图；完整步骤文字见 CSV 或打印单。
- 主要编辑支持撤销/重做；删除、示例与载入都可撤销。暂存失败仍可继续操作和手动保存。方案先完整验证，错误文件或过期读取不会覆盖当前数据。

计算与边界
在分钟格上，从上桌时间向前贪心安排。同道菜保留串行步骤顺序；多道菜共享有限资源，安排期间不超过定义的容量。这是一份可执行的资源计划，不保证最短跨度或理论最晚开工。步骤之间可以等待；菜品提前完成的分钟数明确展示。不能把待上桌时间理解为安全保温承诺。
资源只在每一步所写的时间区间连续占用。如果锅具必须跨几个步骤保留，应合并这些步骤，或每步都标明该锅具。默认动作/食材/耗时是可改的原创素食示例，不计算实际熟度、烹饪安全时间、营养治疗或设备性能。
名称与单位相同才合并，库存多于需求时采购为零，剩余另列。CSV 保留数值精度；极小浮点舍入差按相对 1e-10 的容差清零。用户文字以 CSV 文本写入，开头的公式字符加文本前缀，避免被表格软件当公式执行。

字体与验证
示例字形来自内嵌 SupperText（Noto Sans CJK SC Regular 的改名子集），许可见字体许可.txt。新的其他文字使用设备字体回退；原生 QA 使用完整 Noto 作缺字回退，不把不同系统字体效果说成一模一样。
review/check.cjs 从最终 HTML 执行真实 AppModel 与 Artwork。独立手算汇总、事件扫描资源占用、顺序与时间、跨日、JSON 回读、错误导入均已核对；实际 CSV 和打印单另由 Python CSV/HTML 读取器检查。PNG 是真实 Canvas 绘图与导出路径的原生图，不是网页截图。未完成浏览器整页排版、真实事件、冷启双击与设备验收。
