#!/usr/bin/env python3
from pathlib import Path


ROOT = Path(__file__).resolve().parent

FONT_URL = (
    "https://fonts.googleapis.com/css2?"
    "family=Noto+Serif+SC:wght@500;600;700&"
    "family=Noto+Sans+SC:wght@400;500;600;700&"
    "family=IBM+Plex+Mono:wght@400;500;600&display=swap"
)

CSS = r"""
:root{
  --paper:#F7F3EA;--surface:#FCFAF4;--sunken:#EEE8DC;--ink:#181411;
  --muted:#67605A;--faint:#9B9187;--line:#DED5C6;--line2:#CFC3B1;
  --red:#B4202A;--red-dark:#7D121B;--red-soft:#F1D8D8;
  --orange:#D4501E;--orange-soft:#F4DCC8;--green:#667B55;--white:#FFFDF8;
  --serif:"Noto Serif SC",Georgia,serif;--sans:"Noto Sans SC",system-ui,sans-serif;
  --mono:"IBM Plex Mono",ui-monospace,monospace;
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{background:#E6DED1;color:var(--ink);font-family:var(--sans);-webkit-font-smoothing:antialiased}
.deck{display:flex;flex-direction:column;align-items:center;gap:24px;padding:24px}
.slide{position:relative;width:1280px;height:720px;overflow:hidden;background:var(--paper);border-radius:8px}
.slide:after{content:"";position:absolute;inset:0;pointer-events:none;opacity:.45;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.026'/%3E%3C/svg%3E")}
.pad{position:absolute;inset:0;padding:58px 68px 50px;display:flex;flex-direction:column;z-index:1}
.topline{display:none}
.kicker{font-family:var(--mono);font-size:12px;font-weight:600;letter-spacing:.18em;text-transform:uppercase;color:var(--red);display:flex;align-items:center;gap:10px}
.kicker:before{content:"";width:24px;height:1px;background:var(--red)}
.eyebrow{font-family:var(--mono);font-size:11px;letter-spacing:.13em;color:var(--orange);text-transform:uppercase}
h1,h2,h3{font-family:var(--serif);font-weight:600;letter-spacing:-.015em}
h1{font-size:58px;line-height:1.13}
h2{font-size:41px;line-height:1.2}
h3{font-size:21px;line-height:1.35}
.accent{color:var(--red)}
.orange{color:var(--orange)}
.lead{font-size:18px;line-height:1.72;color:var(--muted)}
.small{font-size:13px;line-height:1.65;color:var(--muted)}
.mono{font-family:var(--mono)}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:18px}
.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
.grid4{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.card{background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:22px}
.card.red{border-color:#D7A8AB;background:#F9EEEE}
.card.orange{border-color:#E4B89F;background:#FCF0E8}
.card.dark{background:var(--ink);border-color:var(--ink);color:var(--white)}
.card p{font-size:14px;line-height:1.65;color:var(--muted);margin-top:9px}
.card.dark p{color:#D8CFC5}
.num{font-family:var(--mono);font-size:12px;color:var(--red);letter-spacing:.08em;margin-bottom:10px}
.pill{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--line2);background:var(--surface);border-radius:999px;padding:9px 14px;font-size:13px;color:var(--muted)}
.dot{width:7px;height:7px;border-radius:50%;background:var(--red)}
.take{display:flex;gap:14px;border-left:3px solid var(--red);background:var(--surface);padding:16px 19px;border-radius:0 9px 9px 0;font-size:15px;line-height:1.62;color:var(--muted)}
.take b{color:var(--ink)}
.foot{position:absolute;left:68px;right:68px;bottom:24px;display:flex;align-items:center;justify-content:space-between;font-family:var(--mono);font-size:10.5px;letter-spacing:.06em;color:var(--faint);z-index:2}
.brands{display:flex;align-items:center;gap:18px}.brands img{display:block;object-fit:contain}
.flow{display:flex;align-items:stretch;gap:10px}.flow .node{flex:1;background:var(--surface);border:1px solid var(--line);border-radius:11px;padding:18px}.flow .arrow{display:flex;align-items:center;color:var(--red);font-size:25px}
.node strong{font-family:var(--serif);font-size:18px}.node p{font-size:12.5px;color:var(--muted);line-height:1.55;margin-top:8px}
.metric{font-family:var(--serif);font-size:52px;font-weight:600;color:var(--red);line-height:1}.metric-label{font-size:13px;color:var(--muted);margin-top:10px}
.quote{font-family:var(--serif);font-size:40px;line-height:1.4;max-width:22ch}
.split{display:grid;grid-template-columns:42% 58%;height:100%}
.split .left{padding:62px 52px 52px 68px;display:flex;flex-direction:column}.split .right{padding:52px;display:flex;align-items:center;justify-content:center;background:#EFE9DE}
.shot{width:100%;border:1px solid var(--line2);border-radius:12px;box-shadow:0 24px 60px rgba(37,24,18,.16)}
.role{display:flex;align-items:center;gap:11px;padding:13px 15px;border:1px solid var(--line);background:var(--surface);border-radius:10px}.role .avatar{width:35px;height:35px;border-radius:50%;display:grid;place-items:center;color:white;font-family:var(--mono);font-size:11px;background:var(--ink)}
.role.ai .avatar{background:var(--red)}.role .rt{font-size:13px}.role .rs{font-size:11px;color:var(--muted);margin-top:2px}
.bio-item{display:flex;align-items:flex-start;gap:12px;font-size:15px;color:var(--muted);line-height:1.5}.bio-item:before{content:"";width:8px;height:8px;border-radius:50%;background:var(--red);flex:none;margin-top:7px}.bio-item b{color:var(--ink);font-weight:600}.bio-desc{font-size:12.5px;color:var(--faint);margin-top:3px;line-height:1.5}
.timeline{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}.phase{position:relative;border-top:4px solid var(--line2);padding:17px 15px;background:var(--surface);border-radius:0 0 10px 10px}.phase.active{border-top-color:var(--red)}.phase .week{font-family:var(--mono);font-size:11px;color:var(--red)}.phase h3{font-size:18px;margin-top:8px}.phase p{font-size:12.5px;line-height:1.55;color:var(--muted);margin-top:7px}
.dark-slide{background:var(--ink);color:var(--white)}.dark-slide .lead{color:#CFC3B7}.dark-slide .kicker{color:#F0B4B6}.dark-slide .kicker:before{background:#F0B4B6}.dark-slide .foot{color:#93867B}.dark-slide .accent{color:#F4A1A4}
.ring{position:absolute;border:1px solid rgba(180,32,42,.28);border-radius:50%;pointer-events:none}.ring.one{width:520px;height:520px;right:-170px;top:-170px}.ring.two{width:390px;height:390px;right:-105px;top:-105px}.ring.three{width:260px;height:260px;right:-40px;top:-40px}.ring:after{content:"";position:absolute;width:12px;height:12px;background:var(--orange);border-radius:50%;left:22%;bottom:16%}
.source{font-family:var(--mono);font-size:9px;color:var(--faint);position:absolute;left:68px;bottom:42px}
@page{size:1280px 720px;margin:0}
@media print{html,body{background:#fff}.deck{gap:0;padding:0}.slide{border-radius:0;break-after:page;page-break-after:always}}
"""


def footer(section: str, page: int, total: int) -> str:
    return f'<div class="foot"><span>TELFORD × SYFO · 组织 AI 转型</span><span>{section}</span><span>{page:02d} / {total:02d}</span></div>'


slides = []


def add(section: str, body: str, cls: str = "") -> None:
    slides.append((section, body, cls))


add('封面', r'''<div class="topline"></div><div class="ring one"></div><div class="ring two"></div><div class="ring three"></div><div class="pad"><div class="brands"><img src="assets/webeye-wordmark.svg" style="width:180px;height:46px"><span style="width:1px;height:38px;background:var(--line2)"></span><img src="assets/syfo-wordmark.svg" style="width:100px;height:38px"></div><div style="margin:auto 0"><div class="kicker">AI AGENT MEETUP · 2026.07.24</div><h1 style="margin-top:24px;max-width:17ch">从“会用 AI”，<br>到 <span class="accent">Agent workflow 进入生产</span>。</h1><p class="lead" style="margin-top:22px;max-width:58ch">AI Native 组织的能力、系统与责任：让 Agent 进入真实业务流程，成为可协作、可管理、可验收的工作系统。</p></div><div class="pill" style="width:max-content"><span class="dot"></span>Tony Ren · ReOrc / Syfo</div></div>''', 'cover')

add('今天的成果', r'''<div class="pad"><div class="kicker">150 分钟 · 分享 + Demo + Clinic</div><h2 style="margin-top:18px">结束时，不只理解概念，还要形成<span class="accent">可行动的生产判断</span>。</h2><div class="grid4" style="margin-top:28px"><div class="card red"><div class="metric">20</div><h3>分钟</h3><p>Agent 时代人的能力要求。</p></div><div class="card"><div class="metric">25</div><h3>分钟</h3><p>企业怎样真正走向 AI Native。</p></div><div class="card"><div class="metric">15</div><h3>分钟</h3><p>Syfo 生产协作 Demo。</p></div><div class="card"><div class="metric">65</div><h3>分钟</h3><p>生产门槛、案例与小组 Clinic。</p></div></div><div class="take" style="margin-top:25px"><b>现场产出：</b>1–2 个试点候选、业务 Owner、30 天目标，以及绝不授权给 Agent 的红线。</div></div>''')

add('讲者', r'''<div class="pad"><div class="kicker">关于讲者</div><div style="display:grid;grid-template-columns:310px 1fr;gap:54px;align-items:center;margin:auto 0"><img src="assets/tony-profile.png" style="width:310px;height:auto;border-radius:16px;border:1px solid var(--line);box-shadow:0 18px 50px rgba(26,22,18,.18)"><div><h1 style="font-size:56px">Tony Ren</h1><p class="lead" style="margin-top:12px;max-width:46ch">长期从事 AI、数据基础设施、企业产品与全球化工作流实践。</p><div style="display:flex;flex-direction:column;gap:13px;margin-top:24px;max-width:58ch"><div class="bio-item"><div><b>香港科技大学</b> · 计算机科学本科、硕士、博士</div></div><div class="bio-item"><div><b>研究员经历</b> · 腾讯、华为诺亚方舟 AI 实验室、日本国立情报学研究所</div></div><div class="bio-item"><div><b>一面数据 · 创始人</b><div class="bio-desc">被 Ascential 收购后，继续负责企业级数据与产品协作。</div></div></div><div class="bio-item"><div><b>前 Flywheel Omnicom</b> · 亚太区首席产品官</div></div><div class="bio-item"><div><b>ReOrc · 联合创始人兼 CEO</b></div></div></div></div></div></div>''')

add('为什么是 WebEye', r'''<div class="pad"><div class="kicker">已经进入“生产化问题”阶段</div><h2 style="margin-top:18px">WebEye 的问题不再是“要不要 AI”，<br>而是<span class="accent">哪些 Agent 能承担业务责任</span>。</h2><div class="grid4" style="margin-top:29px"><div class="card red"><div class="num">GLOBAL GROWTH</div><h3>海外营销</h3><p>市场、渠道、创意、投放、分析和客户协作。</p></div><div class="card"><div class="num">AI AUTOMATION</div><h3>ORCA / Custom AI</h3><p>已有 Agent 产品与 workflow，下一步是可靠性和责任。</p></div><div class="card"><div class="num">CLOUD</div><h3>Cloud MSP / AI</h3><p>运维、成本、安全、数据和生产变更要求强治理。</p></div><div class="card"><div class="num">GROWTH LOOP</div><h3>游戏 / 电商</h3><p>高频实验、跨平台数据与持续复盘。</p></div></div><div class="take" style="margin-top:25px"><b>核心机会：</b>把已经存在的 AI 能力，升级成可观测、可审计、可回滚的人机工作系统。</div></div>''')

add('核心判断', r'''<div class="pad"><div class="kicker">AI Native 组织</div><h1 style="font-size:46px;margin-top:22px;max-width:25ch">AI Native 不是“大家都用 AI”，而是人和 Agent 在<span class="accent">同一责任链</span>里工作。</h1><div class="grid3" style="margin-top:30px"><div class="card"><div class="num">人</div><h3>目标 · 判断 · 关系 · 责任</h3><p>处理例外与权衡，承担客户承诺和最终决策。</p></div><div class="card red"><div class="num">工作系统</div><h3>任务 · 过程 · 审批 · 交付</h3><p>上下文、执行状态、质量和结果都进入团队空间。</p></div><div class="card"><div class="num">Agent</div><h3>研究 · 执行 · 跟进 · 复盘</h3><p>承接高密度信息处理和持续工作。</p></div></div></div>''')

add('三个层级', r'''<div class="pad"><div class="kicker">不要把三个层级混在一起</div><h2 style="margin-top:18px">工具、workflow 与组织，解决的是<span class="accent">不同问题</span>。</h2><div class="flow" style="margin-top:34px"><div class="node"><div class="num">LEVEL 1</div><strong>AI 工具</strong><p>问答、写作、总结。个人更快，过程和经验常留在个人。</p></div><div class="arrow">→</div><div class="node"><div class="num">LEVEL 2</div><strong>Agent workflow</strong><p>调用数据和工具完成流程，但责任与接管可能仍不清楚。</p></div><div class="arrow">→</div><div class="node" style="border-color:#D7A8AB;background:#F9EEEE"><div class="num">LEVEL 3</div><strong>AI Native 组织</strong><p>Agent 有角色，人有责任，过程可见，结果可验收，失败可回滚。</p></div></div></div>''')

add('人的五项能力', r'''<div class="pad"><div class="kicker">Agent 时代的人</div><h2 style="margin-top:18px">价值从“亲手执行”，转向<span class="accent">组织高质量工作</span>。</h2><div class="grid3" style="margin-top:28px"><div class="card red"><div class="num">01</div><h3>任务拆解</h3><p>把模糊目标拆成可认领、可验证、可升级的工作。</p></div><div class="card"><div class="num">02</div><h3>上下文工程</h3><p>知道哪些数据、规则、历史和约束决定质量。</p></div><div class="card"><div class="num">03</div><h3>质量判断</h3><p>把“感觉不错”变成结构化验收标准。</p></div><div class="card"><div class="num">04</div><h3>异常处理</h3><p>识别不确定、冲突、越权和业务例外。</p></div><div class="card"><div class="num">05</div><h3>协作设计</h3><p>让人、Agent 和系统在同一责任链上接力。</p></div><div class="card dark"><div class="num" style="color:#F08C91">管理者</div><h3>定目标、给上下文、设验收、做判断</h3></div></div></div>''')

add('管理诊断', r'''<div class="pad"><div class="kicker">团队只是“会用 AI”吗</div><h2 style="margin-top:18px">用六个问题识别<span class="accent">假提效</span>。</h2><div class="grid3" style="margin-top:28px"><div class="card"><h3>谁负责下一步？</h3><p>AI 产出后是否自动进入责任和状态系统？</p></div><div class="card"><h3>失败谁能看见？</h3><p>是否有日志、告警和明确的人工接管？</p></div><div class="card"><h3>质量如何验收？</h3><p>是否有标准、样本、抽检和错误分类？</p></div><div class="card"><h3>权限有多大？</h3><p>能读什么、写什么、执行什么、谁批准？</p></div><div class="card"><h3>经验留下了吗？</h3><p>修订和成功案例是否成为团队资产？</p></div><div class="card red"><h3>业务周期变短了吗？</h3><p>还是只是生成了更多内容和更多审核工作？</p></div></div></div>''')

add('AI Native Operating Model', r'''<div class="pad"><div class="kicker">不是 IT 单部门项目</div><h2 style="margin-top:18px">规模化落地，需要四类角色<span class="accent">共同在场</span>。</h2><div class="grid4" style="margin-top:30px"><div class="card red"><div class="num">SPONSOR</div><h3>一号位</h3><p>示范、优先级、资源与跨部门阻塞。</p></div><div class="card"><div class="num">BUSINESS</div><h3>业务 Owner</h3><p>流程、验收、例外、结果与责任。</p></div><div class="card"><div class="num">PLATFORM</div><h3>技术 / 平台</h3><p>数据、权限、工具、评估、日志与可靠性。</p></div><div class="card"><div class="num">FRONTLINE</div><h3>一线使用者</h3><p>真实案例、失败反馈和流程知识。</p></div></div><div class="take" style="margin-top:26px"><b>最常见失败：</b>技术团队做出 Demo，但业务 Owner 没定义验收，一号位也没有持续投入。</div></div>''')

add('一号位', r'''<div class="pad"><div class="kicker">领导者的责任</div><h2 style="margin-top:18px">一号位不能只“支持 AI”，而要亲自<span class="accent">改变工作方式</span>。</h2><div class="grid2" style="margin-top:30px"><div class="card red"><div class="num">做榜样</div><h3>亲自使用和暴露工作过程</h3><p>把目标、判断和反馈放进系统，而不是只要求团队学习工具。</p></div><div class="card"><div class="num">做选择</div><h3>明确哪些流程值得深做</h3><p>不追求全公司铺开，选择高价值、可验收、有 Owner 的闭环。</p></div><div class="card"><div class="num">配资源</div><h3>数据、权限与技术支持</h3><p>让试点不被部门边界和系统访问卡死。</p></div><div class="card"><div class="num">担责任</div><h3>定义红线与升级机制</h3><p>明确哪些动作不能授权，失败时谁接管。</p></div></div></div>''')

add('场景地图', r'''<div class="pad"><div class="kicker">WebEye 可优先验证的四类场景</div><h2 style="margin-top:18px">先选<span class="accent">业务闭环</span>，再选模型和工具。</h2><div class="grid4" style="margin-top:30px"><div class="card red"><div class="num">01</div><h3>Campaign Launch</h3><p>研究、策略、创意、QA、上线与复盘。</p></div><div class="card"><div class="num">02</div><h3>ORCA 生产化</h3><p>评估、权限、日志、人工接管与客户解释。</p></div><div class="card"><div class="num">03</div><h3>Cloud MSP</h3><p>事故、成本异常、状态更新与回滚。</p></div><div class="card"><div class="num">04</div><h3>增长实验</h3><p>洞察、假设、执行、分析与下一轮任务。</p></div></div><div class="take" style="margin-top:26px"><b>主案例：</b>海外 Campaign Launch 最适合让业务、产品、技术和管理者同时参与。</div></div>''')

add('Syfo 定位', r'''<div class="pad"><div class="kicker">The Organizational Agent Harness</div><h2 style="margin-top:18px">Syfo 是人和 AI 同事一起<span class="accent">完成真实工作</span>的地方。</h2><div class="grid2" style="margin-top:30px"><div class="card"><div class="num">不是</div><h3>另一个孤立聊天框</h3><p>聊天回答通常没有负责人、状态、审批、版本和交付。</p></div><div class="card red"><div class="num">而是</div><h3>组织 Agent 的协作底座</h3><p>Agent 进入频道、认领任务、在线程执行、提交交付并接受审阅。</p></div></div><div class="grid4" style="margin-top:18px"><div class="card"><h3>频道</h3><p>共享业务上下文。</p></div><div class="card"><h3>任务</h3><p>负责人、状态、验收。</p></div><div class="card"><h3>Agent</h3><p>角色、工具、记忆。</p></div><div class="card"><h3>交付物</h3><p>结果、版本、复用。</p></div></div></div>''')

add('产品现场', r'''<div class="topline"></div><div class="split"><div class="left"><div class="kicker">不是另一个聊天框</div><h2 style="margin-top:20px">讨论会变成任务，<br>任务会变成<span class="accent">交付</span>。</h2><p class="lead" style="margin-top:22px">人在频道里给目标和边界；Agent 认领任务、在线程执行；结果以交付物回到团队。</p><div class="take" style="margin-top:auto"><b>观察重点：</b>不要只看回答质量，要看谁负责、做到哪、谁批准、如何失败和交付了什么。</div></div><div class="right"><img class="shot" src="assets/syfo-ui.png"></div></div>''')

add('工作闭环', r'''<div class="pad"><div class="kicker">业务进入 Syfo 的方式</div><h2 style="margin-top:18px">让每次工作都形成<span class="accent">责任、交付与记忆</span>。</h2><div class="flow" style="margin-top:34px"><div class="node"><div class="num">01</div><strong>目标</strong><p>人类提出业务结果、边界和资料。</p></div><div class="arrow">→</div><div class="node"><div class="num">02</div><strong>认领</strong><p>成员或 Agent 明确责任和下一步。</p></div><div class="arrow">→</div><div class="node"><div class="num">03</div><strong>执行</strong><p>在线程调用工具、协作并更新状态。</p></div><div class="arrow">→</div><div class="node"><div class="num">04</div><strong>审阅</strong><p>高风险输出由人类确认或驳回。</p></div><div class="arrow">→</div><div class="node" style="border-color:#D7A8AB;background:#F9EEEE"><div class="num">05</div><strong>记忆</strong><p>交付、反馈和规则成为下一次上下文。</p></div></div></div>''')

add('场景一', r'''<div class="pad"><div class="kicker">跨渠道海外 Campaign Launch</div><h2 style="margin-top:18px">从客户 brief 到上线检查，形成一条<span class="accent">可审阅的增长流水线</span>。</h2><div class="grid4" style="margin-top:28px"><div class="card"><div class="num">研究</div><h3>市场 / 受众 / 竞品</h3><p>整合历史表现与外部信息。</p></div><div class="card"><div class="num">策略</div><h3>目标 / 渠道 / 假设</h3><p>形成预算和实验边界草案。</p></div><div class="card red"><div class="num">创意与 QA</div><h3>素材矩阵 / 平台检查</h3><p>适配规则、链接、命名和追踪。</p></div><div class="card"><div class="num">运营</div><h3>上线 / 异常 / 复盘</h3><p>维护状态、问题与下一轮行动。</p></div></div><div class="take" style="margin-top:26px"><b>人类保留：</b>客户承诺、预算、品牌判断、广告账户高权限、正式上线 / 暂停。</div></div>''')

add('场景二', r'''<div class="pad"><div class="kicker">ORCA / AI Automation</div><h2 style="margin-top:18px">从“任务能跑通”，升级为<span class="accent">客户敢依赖的生产系统</span>。</h2><div class="grid3" style="margin-top:28px"><div class="card"><div class="num">EVAL</div><h3>评估集代表真实吗</h3><p>覆盖正常、边界、异常、长尾与高风险样本。</p></div><div class="card red"><div class="num">CONTROL</div><h3>权限和接管清楚吗</h3><p>最小权限、审批、停止、人工接管与回滚。</p></div><div class="card"><div class="num">EXPLAIN</div><h3>客户能理解责任吗</h3><p>输入、工具调用、输出、失败与修改可追溯。</p></div></div><div class="take" style="margin-top:26px"><b>生产问题：</b>不是模型偶尔答得好不好，而是系统能否稳定处理真实分布和失败。</div></div>''')

add('场景三', r'''<div class="pad"><div class="kicker">Cloud MSP 事故与成本异常</div><h2 style="margin-top:18px">Agent 准备上下文，人类掌握<span class="accent">生产变更与回滚</span>。</h2><div class="flow" style="margin-top:31px"><div class="node"><div class="num">01</div><strong>告警</strong><p>汇总监控、日志、成本异常与近期变更。</p></div><div class="arrow">→</div><div class="node"><div class="num">02</div><strong>判断准备</strong><p>影响范围、可能原因、证据与处置选项。</p></div><div class="arrow">→</div><div class="node"><div class="num">03</div><strong>人工批准</strong><p>工程师确认变更、回滚和客户沟通。</p></div><div class="arrow">→</div><div class="node" style="border-color:#D7A8AB;background:#F9EEEE"><div class="num">04</div><strong>复盘</strong><p>时间线、根因、行动项与知识更新。</p></div></div></div>''')

add('场景四', r'''<div class="pad"><div class="kicker">游戏 / 电商增长实验</div><h2 style="margin-top:18px">让每一轮实验，都成为下一轮的<span class="accent">高质量上下文</span>。</h2><div class="grid4" style="margin-top:28px"><div class="card"><div class="num">洞察</div><h3>数据与用户信号</h3><p>问题、机会和历史表现。</p></div><div class="card"><div class="num">假设</div><h3>变量与预期</h3><p>明确影响机制和成功条件。</p></div><div class="card red"><div class="num">执行</div><h3>任务与质量控制</h3><p>素材、配置、上线与异常。</p></div><div class="card"><div class="num">复盘</div><h3>结论与下一轮</h3><p>证据、限制、决策与新任务。</p></div></div></div>''')

add('Demo 设置', r'''<div class="pad"><div class="kicker">虚构项目 · NovaGame 东南亚 Campaign</div><h2 style="margin-top:18px">15 分钟，只演示一条完整链，<br>不追求功能大全。</h2><div class="grid3" style="margin-top:30px"><div class="card red"><div class="num">目标</div><h3>48 小时形成上线计划</h3><p>市场研究、渠道策略、素材矩阵、QA 与任务分工。</p></div><div class="card"><div class="num">Agent</div><h3>五个角色</h3><p>市场、策略、创意、QA、运营。</p></div><div class="card"><div class="num">红线</div><h3>全部数据虚构</h3><p>不使用真实客户、账户、预算或用户数据。</p></div></div><div class="take" style="margin-top:26px"><b>观众观察：</b>谁负责、做到哪、缺什么、谁批准、交了什么、失败如何接管。</div></div>''')

add('Demo 流程', r'''<div class="pad"><div class="kicker">目标 → 分工 → 交付 → 审阅</div><h2 style="margin-top:18px">让 Agent 的能力进入<span class="accent">可验收流程</span>。</h2><div class="grid2" style="margin-top:26px"><div class="card red"><div class="num">0–4 MIN</div><h3>创建项目现场</h3><p>发布目标，转换为任务，明确 Owner、状态、下一步和验收。</p></div><div class="card"><div class="num">4–9 MIN</div><h3>五个 Agent 分工</h3><p>在线程研究、拆解、识别缺失信息和风险。</p></div><div class="card"><div class="num">9–12 MIN</div><h3>提交交付物</h3><p>市场摘要、Campaign brief、素材矩阵、上线检查单。</p></div><div class="card"><div class="num">12–15 MIN</div><h3>人类审批</h3><p>修改预算和客户承诺，批准或驳回上线建议。</p></div></div></div>''')

add('生产六道门', r'''<div class="pad"><div class="kicker">Production Readiness</div><h2 style="margin-top:18px">能完成任务，不等于<span class="accent">可以进入生产</span>。</h2><div class="grid3" style="margin-top:28px"><div class="card red"><div class="num">GATE 1</div><h3>价值与 Owner</h3><p>业务结果、责任与失败成本。</p></div><div class="card"><div class="num">GATE 2</div><h3>数据与上下文</h3><p>来源、质量、时效、版本与证据。</p></div><div class="card"><div class="num">GATE 3</div><h3>工具与权限</h3><p>只读、草拟、执行、审批与隔离。</p></div><div class="card"><div class="num">GATE 4</div><h3>质量与评估</h3><p>测试集、抽检、错误分类与阈值。</p></div><div class="card"><div class="num">GATE 5</div><h3>可观测与审计</h3><p>日志、成本、来源、版本和失败原因。</p></div><div class="card"><div class="num">GATE 6</div><h3>接管与回滚</h3><p>停止、升级、撤回和责任。</p></div></div></div>''')

add('Gate 1–2', r'''<div class="pad"><div class="kicker">先确认做什么、凭什么做</div><h2 style="margin-top:18px">没有 Owner 和可信上下文，<br>Agent 只会<span class="accent">更快地制造不确定</span>。</h2><div class="grid2" style="margin-top:30px"><div class="card red"><div class="num">GATE 1 · 价值与 Owner</div><h3>谁承担业务结果？</h3><p>高频或关键流程；成功可衡量；失败成本清楚；有单一业务 Owner。</p></div><div class="card"><div class="num">GATE 2 · 数据与上下文</div><h3>Agent 根据什么工作？</h3><p>数据来源、质量、时效、合规、版本、规则与历史案例明确；输出能引用证据。</p></div></div><div class="take" style="margin-top:26px"><b>红灯：</b>“大家都负责”、没有真实样本、没有错误案例、只靠提示词补背景。</div></div>''')

add('Gate 3–4', r'''<div class="pad"><div class="kicker">控制动作，定义质量</div><h2 style="margin-top:18px">权限越大，越需要<span class="accent">严格评估和分级授权</span>。</h2><div class="grid2" style="margin-top:30px"><div class="card"><div class="num">GATE 3 · 工具与权限</div><h3>能做什么？</h3><p>最小权限；环境隔离；密钥管理；只读、草拟、执行和审批层级。</p></div><div class="card red"><div class="num">GATE 4 · 质量与评估</div><h3>什么叫合格？</h3><p>离线测试集、线上抽检、错误分类；准确、完整、一致、合规与业务约束。</p></div></div><div class="take" style="margin-top:26px"><b>红灯：</b>用平均准确率掩盖高风险错误；Agent 可以直接触发不可逆动作。</div></div>''')

add('Gate 5–6', r'''<div class="pad"><div class="kicker">看得见，接得住，退得回</div><h2 style="margin-top:18px">生产系统必须为<span class="accent">失败</span>而设计。</h2><div class="grid2" style="margin-top:30px"><div class="card"><div class="num">GATE 5 · 可观测与审计</div><h3>发生了什么？</h3><p>输入、模型、工具调用、输出、耗时、成本、版本、修改和失败原因可追踪。</p></div><div class="card red"><div class="num">GATE 6 · 接管与回滚</div><h3>谁来停止和恢复？</h3><p>不确定时停止；明确升级对象；动作可撤回；高风险操作人工确认。</p></div></div><div class="take" style="margin-top:26px"><b>红灯：</b>只能看到最终答案；失败后靠人工翻聊天记录；没有可执行回滚方案。</div></div>''')

add('验收指标', r'''<div class="pad"><div class="kicker">拒绝只看“准确率”</div><h2 style="margin-top:18px">评估一个 Agent workflow，要同时看<span class="accent">质量、效率和业务一致性</span>。</h2><div class="grid4" style="margin-top:30px"><div class="card"><div class="metric">Q</div><h3>质量</h3><p>准确、完整、一致、合规和高风险错误。</p></div><div class="card"><div class="metric">T</div><h3>时效</h3><p>端到端周期、等待时间和 SLA。</p></div><div class="card red"><div class="metric">H</div><h3>人工介入</h3><p>接管率、修改率、升级率与审核负担。</p></div><div class="card"><div class="metric">B</div><h3>业务结果</h3><p>转化、成本、稳定性和结果一致性。</p></div></div><div class="take" style="margin-top:26px"><b>还要看：</b>失败成本、复用率、漂移、单次成本和用户信任。</div></div>''')

add('成熟度阶梯', r'''<div class="pad"><div class="kicker">不要从 Demo 直接跳生产</div><h2 style="margin-top:18px">授权应该随着<span class="accent">证据</span>逐步增加。</h2><div class="flow" style="margin-top:34px"><div class="node"><div class="num">0</div><strong>Demo</strong><p>少量样本，证明可行。</p></div><div class="arrow">→</div><div class="node"><div class="num">1</div><strong>影子运行</strong><p>Agent 给建议，不影响真实流程。</p></div><div class="arrow">→</div><div class="node"><div class="num">2</div><strong>辅助模式</strong><p>人确认后进入流程。</p></div><div class="arrow">→</div><div class="node"><div class="num">3</div><strong>受控执行</strong><p>低风险动作自动，高风险审批。</p></div><div class="arrow">→</div><div class="node" style="border-color:#D7A8AB;background:#F9EEEE"><div class="num">4</div><strong>持续优化</strong><p>监控漂移、复盘错误、调整授权。</p></div></div></div>''')

add('Production Readiness Clinic', r'''<div class="pad"><div class="kicker">25 分钟小组实战</div><h2 style="margin-top:18px">用一个真实 workflow，完成<span class="accent">红黄绿生产诊断</span>。</h2><div class="grid3" style="margin-top:28px"><div class="card red"><div class="num">12 MIN</div><h3>小组填写 Canvas</h3><p>流程、Owner、上下文、人 / Agent 责任、指标、权限与回滚。</p></div><div class="card"><div class="num">8 MIN</div><h3>两组分享</h3><p>重点说红灯：为什么现在不能直接进生产。</p></div><div class="card"><div class="num">5 MIN</div><h3>讲师点评</h3><p>确定应该影子运行、辅助模式，还是受控执行。</p></div></div><div class="take" style="margin-top:26px"><b>规则：</b>存在红项的流程不能直接进入生产，只能缩小范围、补条件或降低授权。</div></div>''')

add('30 天试点', r'''<div class="pad"><div class="kicker">从一个闭环获得证据</div><h2 style="margin-top:18px">30 天不追求“大平台”，只验证<span class="accent">一个高价值流程</span>。</h2><div class="grid4" style="margin-top:29px"><div class="card red"><div class="num">WEEK 1</div><h3>定义</h3><p>Owner、样本、指标、数据、权限、红线。</p></div><div class="card"><div class="num">WEEK 2</div><h3>影子运行</h3><p>不影响真实业务，收集错误与缺口。</p></div><div class="card"><div class="num">WEEK 3</div><h3>辅助模式</h3><p>人工确认；观察修改率与介入率。</p></div><div class="card"><div class="num">WEEK 4</div><h3>复盘</h3><p>决定扩大、调整、降低授权或停止。</p></div></div><div class="grid2" style="margin-top:18px"><div class="card"><h3>推荐试点 A</h3><p>跨渠道 Campaign Launch：资料、策略、创意、QA、任务和复盘。</p></div><div class="card"><h3>推荐试点 B</h3><p>ORCA workflow 生产门诊：评估、日志、权限、接管和客户解释。</p></div></div></div>''')

add('今天的承诺', r'''<div class="pad"><div class="kicker">现场填空</div><h2 style="margin-top:18px">离开前，确定<span class="accent">1 个流程、1 位 Owner、1 条红线</span>。</h2><div class="grid2" style="margin-top:30px"><div class="card"><div class="num">试点</div><h3>流程：________________</h3><p>30 天希望改变的业务指标：________________</p></div><div class="card red"><div class="num">责任</div><h3>业务 Owner：________________</h3><p>绝不授权给 Agent 的动作：________________</p></div></div><div class="take" style="margin-top:26px"><b>下一步：</b>24 小时内整理场景候选和红黄绿结果；一周内完成试点定义。</div></div>''')

add('结束', r'''<div class="topline"></div><div class="ring one"></div><div class="ring two"></div><div class="ring three"></div><div class="pad"><div class="brands"><img src="assets/webeye-wordmark.svg" style="width:180px;height:46px"><span style="width:1px;height:38px;background:var(--line2)"></span><img src="assets/syfo-wordmark.svg" style="width:100px;height:38px"></div><div style="margin:auto 0"><h1 style="max-width:16ch">真正的 AI Native，<br>不是更多 Demo，<br>而是<span class="accent">更多可承担责任的工作系统</span>。</h1><p class="lead" style="margin-top:24px;max-width:52ch">让 Agent 做得动，让组织看得见，让人接得住，让失败退得回。</p></div><div class="pill" style="width:max-content"><span class="dot"></span>Q&A · 选择第一批生产化试点</div></div>''', 'cover')
TOTAL = len(slides)
sections = []
for index, (section, body, cls) in enumerate(slides, start=1):
    sections.append(f'<section class="slide {cls}">{body}{footer(section, index, TOTAL)}</section>')

PRINT_HEAD = f"""<!doctype html><html lang="zh-CN"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>WebEye AI Native Workshop · WebEye × Syfo</title>
<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="{FONT_URL}" rel="stylesheet"><style>{CSS}</style></head>"""

slides_html = f"{PRINT_HEAD}<body><div class=\"deck\">{''.join(sections)}</div></body></html>"
(ROOT / "slides.html").write_text(slides_html, encoding="utf-8")

WEB_CSS = r"""
html,body{height:100%;overflow:hidden}.web .deck{display:block;padding:0;height:100vh;width:100vw;position:relative}
.web .slide{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%) scale(var(--scale,1));transform-origin:center;opacity:0;visibility:hidden;border-radius:0;box-shadow:0 24px 70px rgba(24,20,17,.24);transition:opacity .22s ease}
.web .slide.on{opacity:1;visibility:visible}.nav{position:fixed;left:0;right:0;bottom:0;z-index:20;display:flex;justify-content:center;gap:15px;align-items:center;padding:14px;background:linear-gradient(0deg,rgba(230,222,209,.9),transparent);font-family:var(--mono);font-size:12px;opacity:0;transition:opacity .2s}.web:hover .nav{opacity:1}.nav button{font:inherit;border:1px solid var(--line2);background:var(--surface);padding:7px 13px;border-radius:8px;color:var(--ink);cursor:pointer}.bar{position:fixed;left:0;top:0;height:3px;background:var(--red);z-index:30;transition:width .2s}.zone{position:fixed;top:0;bottom:45px;width:18%;z-index:15}.zone.left{left:0}.zone.right{right:0}
"""
WEB_JS = r"""
<script>
const slides=[...document.querySelectorAll('.slide')];let i=Math.max(0,(parseInt(location.hash.slice(1))||1)-1);
function fit(){document.documentElement.style.setProperty('--scale',Math.min(innerWidth/1280,innerHeight/720));}
function show(n){i=Math.max(0,Math.min(slides.length-1,n));slides.forEach((s,k)=>s.classList.toggle('on',k===i));document.getElementById('count').textContent=`${i+1} / ${slides.length}`;document.getElementById('bar').style.width=`${(i+1)/slides.length*100}%`;history.replaceState(null,'',`#${i+1}`)}
addEventListener('resize',fit);addEventListener('keydown',e=>{if(['ArrowRight','ArrowDown','PageDown',' '].includes(e.key)){e.preventDefault();show(i+1)}else if(['ArrowLeft','ArrowUp','PageUp'].includes(e.key)){e.preventDefault();show(i-1)}else if(e.key==='Home')show(0);else if(e.key==='End')show(slides.length-1);else if(e.key.toLowerCase()==='f'){document.fullscreenElement?document.exitFullscreen():document.documentElement.requestFullscreen()}});fit();show(i);
</script>
"""
web_html = f"""<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>WebEye AI Native Workshop · WebEye × Syfo</title><link href="{FONT_URL}" rel="stylesheet"><style>{CSS}{WEB_CSS}</style></head><body class="web"><div class="deck">{''.join(sections)}</div><div class="bar" id="bar"></div><div class="zone left" onclick="show(i-1)"></div><div class="zone right" onclick="show(i+1)"></div><div class="nav"><button onclick="show(i-1)">‹ 上一页</button><span id="count"></span><button onclick="show(i+1)">下一页 ›</button></div>{WEB_JS}</body></html>"""
(ROOT / "index.html").write_text(web_html, encoding="utf-8")
print(f"wrote {TOTAL} slides")
