"""Rebuild the poster from original pixels and typeset text. No AI redraw."""
from pathlib import Path
import base64
import json
from PIL import Image

ROOT = Path(__file__).resolve().parent
im = Image.open(ROOT / 'assets/source.png')
boxes = {
    'logo': (48, 54, 235, 96), 'config': (680, 966, 998, 1370),
    'mobile': (380, 1717, 508, 1990), 'kiosk': (850, 1710, 980, 1990),
    'printers': (800, 2294, 984, 2390),
    'ticket-1': (89, 2488, 250, 2940), 'ticket-2': (271, 2488, 433, 2940),
    'ticket-3': (453, 2488, 616, 2940), 'ticket-4': (637, 2488, 800, 2940),
    'ticket-5': (820, 2488, 982, 2768),
    'call-screen': (105, 3668, 568, 3918), 'scanner': (656, 3622, 912, 3930),
    'locker': (718, 4194, 927, 4532),
}
for name, box in boxes.items():
    im.crop(box).save(ROOT / f'assets/{name}.png')
(ROOT / 'assets/crops.json').write_text(json.dumps(boxes, indent=2))

def image(name, alt, cls=''):
    data = base64.b64encode((ROOT / f'assets/{name}.png').read_bytes()).decode()
    return f'<img class="{cls}" data-asset="{name}" src="data:image/png;base64,{data}" alt="{alt}">'

def heading(n, title, note):
    return f'<header class="section-head"><span class="number">{n}</span><div><h2>{title}</h2><p>{note}</p></div></header>'

names = ['二维码小字版', '二维码大字版', '无二维码大字版', '无二维码小字版', '紧凑短票版']
tickets = ''.join(f'<figure class="ticket"><figcaption><b>{i:02}</b><h3>{name}</h3></figcaption>{image(f"ticket-{i}", name)}</figure>' for i, name in enumerate(names, 1))

css = '''
:root{--bg:#fff;--surface:#fff8f2;--text-1:#252724;--text-2:#62635f;--accent:#ed571a;--border:#eadfd5;--blue:#277295;--blue-soft:#f1f8fb;--font-sans:"PingFang SC","Microsoft YaHei",sans-serif;--radius:18px;--shadow:none}
*{box-sizing:border-box}html,body{margin:0;padding:0;background:var(--bg);color:var(--text-1);font-family:var(--font-sans);-webkit-font-smoothing:antialiased}body{font-size:25px;line-height:1.75}h1,h2,h3,p,figure{margin:0}img{display:block;max-width:100%;height:auto}b,strong{font-weight:650}svg{display:block;max-width:100%}.page{width:1080px;max-width:100%;margin:auto;padding:54px 60px 48px}.brand{display:flex;justify-content:space-between;align-items:center}.brand img{width:187px}.brand span{font-size:20px;color:var(--text-2)}.hero{padding-bottom:54px}.hero h1{font-size:55px;letter-spacing:-2px;line-height:1.35;margin-top:44px}.orange{color:var(--accent)}.hero .lede{margin-top:20px;font-size:27px;color:var(--text-2)}.hero .benefits{display:flex;gap:28px;margin-top:30px;font-size:21px;color:var(--accent)}section.module{padding:52px 0;border-top:1px solid var(--border)}.section-head{display:flex;align-items:flex-start;gap:22px;margin-bottom:36px}.number{font-size:26px;line-height:52px;min-width:52px;text-align:center;color:var(--accent);border:1px solid var(--accent);border-radius:50%}h2{font-size:35px;line-height:1.45;letter-spacing:-.5px}.section-head p{color:var(--text-2);font-size:23px;margin-top:8px}h3{font-size:28px;line-height:1.5}.tag{display:block;font-size:19px;color:var(--accent);margin-bottom:9px}.tag.blue{color:var(--blue)}.flow{padding:34px;background:var(--surface);border-radius:var(--radius)}.flow-intro{text-align:center;font-size:23px;margin-bottom:25px;color:var(--text-2)}.flow-intro b{color:var(--text-1)}.entry,.endpoints{display:grid;grid-template-columns:1fr 1fr;gap:44px}.flow-node{background:var(--bg);padding:21px 20px;text-align:center;border:1px solid var(--border);border-radius:12px}.flow-node p{font-size:21px;color:var(--text-2);margin-top:5px}.connector{width:100%;height:54px;color:var(--accent)}.center-flow{display:flex;flex-direction:column;align-items:center;max-width:610px;margin:auto}.center-flow .flow-node{width:100%}.center-flow>.arrow{line-height:1.1;transform:rotate(90deg)}.arrow{text-align:center;font-size:37px;color:var(--accent)}.choice{text-align:center;color:var(--text-2);font-size:20px;padding-top:16px}.endpoints .flow-node{background:var(--bg)}.endpoints .flow-node:last-child{border-color:#aecbd9}.endpoints .flow-node:last-child .tag{color:var(--blue)}.config{display:grid;grid-template-columns:1.5fr 1fr;gap:50px;align-items:center}.rules{display:grid;gap:29px}.rule h3{margin-bottom:9px}.rule p{color:var(--text-2);font-size:24px}.figure-note{font-size:19px;color:var(--text-2);text-align:center;margin-top:16px}.config img{width:100%;border:1px solid var(--border);border-radius:12px}.order-grid{display:grid;grid-template-columns:1fr 1fr;gap:36px}.order-card{padding:30px;border:1px solid var(--border);border-radius:var(--radius)}.order-card .device{height:280px;width:auto;max-width:100%;object-fit:contain;margin:26px auto}.order-card p{font-size:24px;color:var(--text-2)}.order-card strong{color:var(--text-1)}.print-intro{display:flex;gap:34px;justify-content:space-between;align-items:center;margin-bottom:35px}.print-intro p{color:var(--text-2);font-size:24px}.print-intro img{width:184px;flex:none}.tickets{display:grid;grid-template-columns:repeat(6,1fr);gap:42px 30px;align-items:start}.ticket{grid-column:span 2;padding:0 12px}.ticket:nth-child(4){grid-column:2 / span 2}.ticket:nth-child(5){grid-column:4 / span 2}.ticket figcaption{margin-bottom:20px;display:flex;align-items:center;gap:12px}.ticket h3{font-size:23px;white-space:nowrap}.ticket b{font-size:19px;color:var(--accent)}.ticket img{width:220px;margin:auto;border:1px solid var(--border)}.notice{padding:22px 28px;margin-top:38px;border-left:4px solid var(--accent);background:var(--surface);font-size:22px}.notice strong{display:block;margin-bottom:5px}.route{border-radius:var(--radius);padding:34px;background:var(--surface);margin-top:28px}.route.blue-route{background:var(--blue-soft);margin-top:44px}.route-title{display:flex;gap:18px;align-items:center;margin-bottom:25px}.route-title b{color:var(--accent);font-size:30px}.blue-route .route-title b{color:var(--blue)}.route-title h3{font-size:30px}.steps{display:grid;grid-template-columns:1fr 35px 1fr 35px 1fr;gap:10px;align-items:start}.step{font-size:23px}.step strong{display:block;font-size:26px;margin-bottom:7px}.step span{display:block;font-size:22px;color:var(--text-2)}.steps .arrow{margin-top:9px;font-size:30px}.route-pics{display:grid;grid-template-columns:1.5fr 1fr;gap:45px;align-items:center;margin:34px 0 20px;background:var(--bg);padding:26px;border-radius:12px}.route-pics img{max-height:272px;width:auto;margin:auto}.state{display:flex;align-items:center;justify-content:center;gap:24px;font-size:23px;margin-top:25px}.state b{font-weight:500;color:var(--accent)}.locker-detail{display:grid;grid-template-columns:1fr 1fr;align-items:center;gap:40px;margin-top:28px}.locker-detail img{height:338px;width:auto;margin:auto}.vertical-state{text-align:center;font-size:25px}.vertical-state .down{color:var(--blue);line-height:1.7}.vertical-state .ready{color:var(--blue);font-weight:600}.route-note{margin-top:24px;font-size:22px;color:var(--text-2)}footer{margin-top:26px;border-top:4px solid var(--accent);padding-top:34px}.summary{font-size:29px;font-weight:600;line-height:1.8}.summary b{color:var(--accent)}.footnote{font-size:19px;color:var(--text-2);margin-top:20px}
@media(max-width:700px){body{font-size:18px}.page{padding:26px 20px}.brand img{width:135px}.brand span{font-size:12px}.hero{padding-bottom:32px}.hero h1{font-size:34px;letter-spacing:-1px;margin-top:30px}.hero h1 .orange{display:block}.hero .lede{font-size:18px}.hero .benefits{font-size:14px;gap:10px;flex-wrap:wrap;margin-top:20px}section.module{padding:32px 0}.section-head{gap:12px;margin-bottom:25px}.number{font-size:18px;line-height:36px;min-width:36px}h2{font-size:25px}.section-head p{font-size:17px}h3{font-size:23px}.flow{padding:20px 14px}.flow-intro{font-size:17px}.entry,.endpoints{gap:12px}.flow-node{padding:16px 7px}.flow-node h3{font-size:19px}.flow-node p{font-size:14px}.tag{font-size:14px}.center-flow{grid-template-columns:1fr 30px 1fr}.arrow{font-size:26px}.connector{height:40px}.choice{font-size:15px}.config,.order-grid{grid-template-columns:1fr;gap:28px}.rules{gap:25px}.rule p,.order-card p{font-size:18px}.config figure{max-width:318px;margin:auto}.figure-note{font-size:14px}.order-card{padding:24px}.order-card .device{height:240px}.print-intro{align-items:start;gap:16px}.print-intro p{font-size:18px}.print-intro img{width:90px}.tickets{grid-template-columns:1fr 1fr;gap:30px 18px}.ticket,.ticket:nth-child(4),.ticket:nth-child(5){grid-column:auto;padding:0}.ticket:nth-child(5){grid-column:1 / -1;width:50%;justify-self:center}.ticket figcaption{display:block;margin-bottom:12px}.ticket h3{font-size:15px}.ticket b{font-size:15px}.notice{font-size:17px;padding:18px;margin-top:28px}.route{padding:24px 18px}.route-title{gap:12px}.route-title h3{font-size:23px}.steps{display:flex;flex-direction:column;gap:12px}.step strong{font-size:21px}.step span{font-size:17px}.steps .arrow{transform:rotate(90deg);font-size:24px;margin:0 0 0 8px;line-height:1}.route-pics{grid-template-columns:1fr;padding:18px;gap:26px}.route-pics img{max-height:235px}.state{font-size:15px;gap:12px}.locker-detail{gap:16px;grid-template-columns:1fr 1fr}.locker-detail img{height:auto}.vertical-state{font-size:18px}.route-note{font-size:17px}.summary{font-size:21px}.footnote{font-size:14px}}
@media print{html,body{print-color-adjust:exact;-webkit-print-color-adjust:exact}.page{margin:0}}
'''

body = f'''
<section class="hero">
 <div class="brand">{image('logo','CPT 康比特')}<span>营养结算服务系统 · 线上订餐</span></div>
 <h1>线上选好餐，<span class="orange">就餐少排队。</span></h1>
 <p class="lede">提前看营养、选好饭；食堂按单准备，到点凭码领取。</p>
 <div class="benefits"><span>提前选餐</span><span>缓解高峰排队</span><span>改善就餐体验</span><span>增强福利感知</span></div>
</section>
<section class="module" id="flow">
 <header class="section-head"><div><h2>全流程总览</h2><p>从食堂配置到就餐者取餐，看清各环节如何衔接。</p></div></header>
 <div class="flow">
  <p class="flow-intro"><b>开始前：</b>食堂先设好菜单、订餐时间和取餐方式</p>
  <div class="entry"><div class="flow-node"><span class="tag blue">就餐者 · 入口一</span><h3>手机提前下单</h3><p>查看营养，选餐付款</p></div><div class="flow-node"><span class="tag blue">就餐者 · 入口二</span><h3>到店点餐机下单</h3><p>选餐付款，拿好小票</p></div></div>
  <svg class="connector" viewBox="0 0 900 54" aria-label="两个下单入口汇合"><path d="M210 0 V22 H690 V0 M450 22 V48 M441 37 L450 48 L459 37" fill="none" stroke="currentColor" stroke-width="3"/></svg>
  <div class="center-flow"><div class="flow-node"><span class="tag">系统</span><h3>自动打印订单</h3><p>订单发到对应档口</p></div><span class="arrow">→</span><div class="flow-node"><span class="tag">食堂工作人员</span><h3>按订单备餐</h3><p>做好餐食，准备交付</p></div></div>
  <p class="choice">按所选的取餐方式，走下面一条</p>
  <svg class="connector" viewBox="0 0 900 54" aria-label="分为窗口和餐柜两种取餐方式"><path d="M450 0 V20 M210 47 V20 H690 V47 M201 37 L210 47 L219 37 M681 37 L690 47 L699 37" fill="none" stroke="currentColor" stroke-width="3"/></svg>
  <div class="endpoints"><div class="flow-node"><span class="tag">A · 堂食 / 自提</span><h3>叫号后，凭码领餐</h3></div><div class="flow-node"><span class="tag">B · 取餐柜</span><h3>存好餐，到柜扫码取</h3></div></div>
 </div>
</section>
<section class="module" id="rules">
 {heading('01','食堂怎么设置','在电脑端，每个档口都能独立设置规则。')}
 <div class="config"><div class="rules">
  <div class="rule"><h3>卖什么</h3><p>建立档口、关联餐厅，<br>设置营业时间和可售餐品。</p></div>
  <div class="rule"><h3>什么时候订、什么时候取</h3><p>按日期、按周或当日安排预订；<br>可设置一个或多个取餐时段。</p></div>
  <div class="rule"><h3>在哪取、怎么收费</h3><p>开放堂食、自提或取餐柜；<br>自提与取餐柜可分别设置打包费。</p></div>
 </div><figure>{image('config','原图中的档口配置界面')}<figcaption class="figure-note">档口配置界面<br>时间与费用为示例</figcaption></figure></div>
</section>
<section class="module" id="order">
 {heading('02','怎么下单：两个入口任选一个','手机提前订，也能到食堂现场自助点餐。')}
 <div class="order-grid"><article class="order-card"><span class="tag blue">手机端</span><h3>提前选好，减少现场等待</h3>{image('mobile','原图手机选餐页面','device')}<p>查看餐品营养 → 选餐付款<br><strong>在【订单】里查看取餐码</strong></p></article><article class="order-card"><span class="tag blue">现场点餐机</span><h3>到店自助点，不用口头报菜</h3>{image('kiosk','原图中的现场点餐机','device')}<p>选餐付款 → 打印小票<br><strong>拿好小票，等候叫号</strong></p></article></div>
</section>
<section class="module" id="receipts">
 {heading('03','订单自动打印，5 种小票按需选','大字、小字、带码或短票，打印张数也能配置。')}
 <div class="print-intro"><p>订单从云端发到档口，自动打印。<br>工作人员照着订单备餐，减少人工传单。</p>{image('printers','原图中的两款小票打印机')}</div>
 <div class="tickets">{tickets}</div>
 <div class="notice"><strong>需要拿纸质小票扫码取餐？请选择带二维码的样式。</strong>打印机需联网，并关联对应档口。</div>
</section>
<section class="module" id="pickup">
 {heading('04','饭做好后，怎么取','两种方式按需选择，按对应流程领取。')}
 <article class="route"><header class="route-title"><b>A</b><h3>堂食 / 自提：叫号后领取</h3></header>
  <div class="steps"><div class="step"><strong>食堂按单备餐</strong><span>支付后生成取餐号，<br>工作人员准备餐食。</span></div><span class="arrow">→</span><div class="step"><strong>饭做好，叫号</strong><span>工作人员确认出餐，<br>大屏显示并语音叫号。</span></div><span class="arrow">→</span><div class="step"><strong>就餐者凭码领餐</strong><span>出示手机订单码或<br>带码小票，扫码领取。</span></div></div>
  <div class="route-pics"><figure>{image('call-screen','原图备餐与待取餐叫号大屏')}<figcaption class="figure-note">大屏区分“备餐中”和“待取餐”</figcaption></figure><figure>{image('scanner','原图消费机扫码取餐入口')}<figcaption class="figure-note">扫码核对后领取</figcaption></figure></div>
  <div class="state"><span>备餐中</span><b>→</b><span>待取餐</span><b>→</b><span>扫码取餐</span></div>
  <p class="route-note">备好再叫号，减少等餐与反复核对。</p>
 </article>
 <article class="route blue-route"><header class="route-title"><b>B</b><h3>取餐柜：先存好，再扫码取</h3></header>
  <div class="steps"><div class="step"><strong>食堂按单备餐</strong><span>照着订单做好餐食。</span></div><span class="arrow">→</span><div class="step"><strong>工作人员存餐</strong><span>存餐成功后，<br>订单更新为可取餐。</span></div><span class="arrow">→</span><div class="step"><strong>就餐者扫码取餐</strong><span>到柜前刷订单码；<br>取餐成功，结果回传。</span></div></div>
  <div class="locker-detail"><figure>{image('locker','原图中的智能取餐柜')}<figcaption class="figure-note">智能取餐柜</figcaption></figure><div class="vertical-state"><p>未存餐</p><div class="down">↓</div><p class="ready">已存餐 · 可取餐</p><div class="down">↓</div><p>已取餐</p></div></div>
  <p class="route-note">先存餐、后领取，无需与工作人员同时交接。</p>
 </article>
</section>
<footer><p class="summary"><b>就餐者：</b>选餐付款 → 等待备餐 → 凭码取餐</p><p class="footnote">适用于政府机关及企事业单位食堂。<br>具体订餐时间、费用及取餐方式，以食堂配置为准。</p></footer>
'''
# Scaffold follows pakco-html/templates/webpage.html: webpage > page > sections.
html = f'<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="康比特线上订餐与取餐流程，含五种原始小票样式。"><title>线上订餐与取餐 · 清晰流程版</title><style>{css}</style></head><body class="webpage"><main class="page">{body}</main></body></html>'
(ROOT / 'index.html').write_text(html)
print('Built index.html with 13 original crops and 5 receipt styles')
