"""Shared, deterministic UI redraw for the function-linkage demonstration films.
No real personal data; structure grounded in supplied screenshots/code evidence.
The caller provides stage placement/animation. All UI is un-timed inner content.
"""
from html import escape as E

def card(title, body, extra=''):
    return f'<div class="ui-card {extra}"><h3>{title}</h3>{body}</div>'
def row(k,v,unit=''):
    return f'<div class="ui-row"><span>{k}</span><strong>{v}<small>{unit}</small></strong></div>'
def btn(t):return f'<div class="ui-button">{t}<span>›</span></div>'
def chip(t):return f'<span class="ui-chip">{t}</span>'

def phone(view, d, phase=0):
    """720x1240 phone-screen layout; content is fictional, layout based on product."""
    name='AI运动营养师'; body=''; nav='我的'
    energy=E(str(d.get('energy') or '按档案生成'))
    if view in ('claim','claimed'):
        name='领取检测记录'
        body='<div class="ui-hero"><span>一体机检测记录</span><h2>本次检测，<br>存入我的档案。</h2></div>'
        body+=card('本次记录',row('检测日期','09月24日')+row('已到项目','身高体重 · 人体成分')+row('记录归属','本人确认'))
        body+=card('身份关联','<p>登录小程序后，扫码领取本人记录。</p>')
        body+=btn('确认领取' if view=='claim' else '已关联本人 · 查看健康档案')
        if view=='claimed':body+='<div class="ui-success">✓ 本次记录已领取</div>'
    elif view in ('profile','profile_later'):
        name='健康档案'
        body='<div class="ui-tabs"><b>体重数据</b><span>健康数据</span><span>饮食管理</span><span>运动燃脂</span></div>'
        body+='<div class="ui-date">'+('10月08日' if view=='profile_later' else '09月24日')+' · 一体机记录 · 示例</div>'
        body+=card('体重数据',f'<div class="ui-big">{d["weight"]}<small>kg</small></div><div class="ui-metric-pair"><div>BMI<strong>{d["bmi"]}</strong></div><div>体脂率<strong>{d["fat"]}<small>%</small></strong></div></div>')
        body+=card('健康数据',row('健康状态及日常习惯','查看 ›')+row('身高',d['height'],'cm')+row('未获取的检验项目','未记录'))
        body+=card('吃动信息',row('热量摄入','查看记录 ›')+row('运动消耗','查看记录 ›'))
    elif view=='goal':
        name='体重目标'
        body='<div class="ui-hero"><span>让测量接上目标</span><h2>减重目标进行中</h2></div>'
        body+=card('同一次检测的身体记录',row('初始体重',d['weight'],'kg')+row('目标体重',d['target'],'kg'))
        body+=card('个人信息与习惯',row('基础资料','已补充')+row('日常活动','轻体力 · 久坐为主')+row('目标速度','0.5','kg / 周'))
        body+=btn('查看饮食与运动建议')
        body+='<p class="ui-note">示例目标与速度用于展示功能，不代表真实个人建议。</p>'
    elif view=='energy':
        name='健康建议';nav='建议'
        body='<div class="ui-hero"><span>身体记录 ＋ 目标 ＋ 习惯</span><h2>推荐营养目标</h2></div>'
        body+=card('每日推荐能量',f'<div class="ui-energy-text">{energy}</div><p>结合性别、年龄、活动与目标</p>')
        body+=card('三大营养素', ''.join(row(k,str(v),'%') for k,v in d.get('macro_percent',{'碳水化合物':50,'蛋白质':25,'脂肪':25}).items()))
        body+=btn('查看三餐与课程')
    elif view in ('chat','meal'):
        nav='AI';name='AI运动营养师'
        body='<div class="ui-goal-strip">当前目标 <strong>减重</strong><span>身体记录已确认</span></div>'
        body+='<div class="ui-bubble">午餐吃点啥？今天在外面吃。</div>'
        if view=='chat':
            body+=card('建议前，先了解你','<p>你的饮食偏好、过敏和忌口是什么？</p><div class="ui-tags">'+chip('不喝牛奶')+chip('不吃香菜')+'</div>')
            body+='<div class="ui-bubble">食物过敏：无。今晚有30分钟。</div>'
            body+='<div class="ui-assistant">结合目标与日常条件，组织今天的吃动建议。</div>'
        else:
            body+=card('午餐这样搭配','<div class="ui-meal-title">午餐搭配建议</div>'+row('主食','杂粮饭 150','g')+row('蛋白质来源','鸡肉 120','g')+row('蔬菜','时蔬 200','g')+'<div class="ui-tags">'+chip('按口味调整')+chip('避开已知忌口')+'</div><p class="ui-note">餐食内容与份量为功能演示示例。</p>')
            body+='<div class="ui-assistant">在家做，或在外用餐时参考搭配。</div>'
        body+='<div class="ui-input">有什么问题需要问我吗？<span>＋　➤</span></div>'
    elif view in ('training','course'):
        nav='AI';name='AI运动营养师'
        body='<div class="ui-goal-strip">当前目标 <strong>减重</strong><span>今日训练推荐</span></div>'
        body+=card('今日训练推荐','<div class="ui-training-art"><span>01</span><svg width="180" height="95" viewBox="0 0 180 95"><path d="M15 30v35M35 16v63M145 16v63M165 30v35M35 47h110" stroke="currentColor" stroke-width="12" stroke-linecap="round"/></svg></div><div class="ui-meal-title">徒手深蹲＋臀桥训练</div>'+row('训练时间','25','分钟')+row('参考活动热量','160','kcal · 估算')+btn('查看课程' if view=='training' else '课程内容 · 观看中'))
        body+=card('按自己的安排选择','<p>先了解动作与训练内容，再结合身体状态选择。</p><p class="ui-note">课程观看记录与实际训练记录分开。</p>')
    elif view in ('food_log','calendar'):
        name='饮食记录';nav='记录'
        if view=='food_log':
            body='<div class="ui-hero"><span>拍照识别之后</span><h2>核对这一餐，<br>再保存。</h2></div>'
            body+=card('本餐食物',row('杂粮饭','150 → 120','g')+row('鸡肉','120','g')+row('时蔬','200','g')+'<p>可修改份量、删除误识别食物。</p>')+btn('确认份量 · 保存')
        else:
            body='<div class="ui-hero"><span>饮食日历</span><h2>今天的实际记录</h2></div><div class="ui-week"><span>21</span><span>22</span><span>23</span><b>24</b><span>25</span><span>26</span><span>27</span></div>'
            body+=card('午餐 · 已保存',row('杂粮饭','120','g')+row('鸡肉','120','g')+row('时蔬','200','g'))
            body+=card('运动记录',row('今天的实际活动','尚未记录')+'<p class="ui-note">没有记录，不代表消耗为零。</p>')
    elif view=='history':
        name='体重历史';nav='档案'
        body='<div class="ui-hero"><span>同一份健康档案</span><h2>每一次测量，<br>都能回头看。</h2></div>'
        body+=card('按日期查看',row('10月08日',d['weight'],'kg　›')+row('09月24日',d['weight'],'kg　›'))
        body+=card('复测与回看','<p>核对来源与测量条件，结合饮食和活动记录沟通下一步。</p>')
        body+='<p class="ui-note">两次相同示例值，仅演示历史记录，不代表效果。</p>'
    elif view=='review':
        name='AI运动营养师';nav='AI'
        body='<div class="ui-goal-strip">继续围绕你的目标 <strong>减重</strong></div><div class="ui-bubble">这周外食多，下一步怎么安排？</div>'
        body+=card('继续沟通','<p>先确认最近的饮食、活动和复测记录，再讨论更适合的安排。</p><div class="ui-tags">'+chip('饮食记录')+chip('课程安排')+chip('复测历史')+'</div>')
        body+=card('下一步 · 交互示意','<p>把具体困难说清楚，让建议贴近下一餐、下一练。</p>')
    body='<div class="ui-top"><span>‹</span><strong>'+name+'</strong><span>•••</span></div><div class="ui-scroll">'+body+'</div>'
    body+='<div class="ui-nav">'+''.join(f'<span class="{("active" if x==nav else "")}">{x}</span>' for x in ['首页','订餐','AI','订单','我的'])+'</div>'
    return '<div class="ui">'+body+'</div>'

CSS='''
.ui-energy-text{font-size:50px;line-height:1.3;font-weight:700;color:#147ce3;margin:20px 0}
.ui{position:relative;width:720px;height:1240px;background:linear-gradient(140deg,#edf5ff,#f6faff 50%,#e6f1fb);color:#142841;border:9px solid #122139;border-radius:54px;overflow:hidden;box-shadow:0 35px 80px #061c3626;font-family:system-ui,sans-serif;text-align:left;box-sizing:border-box}
.ui *{box-sizing:border-box}.ui-top{height:100px;padding:28px 28px 16px;display:flex;justify-content:space-between;align-items:center;font-size:28px;background:#ffffffdc}.ui-top strong{font-size:33px;font-weight:650}.ui-scroll{position:absolute;top:100px;left:0;right:0;bottom:89px;padding:24px 26px;overflow:hidden}.ui-hero{padding:10px 6px 16px}.ui-hero>span{font-size:23px;letter-spacing:2px;color:#537395}.ui-hero h2{font-size:41px;line-height:1.35;margin:13px 0;color:#102e53;font-weight:650}.ui-card{background:#fff;border:1px solid #dce7f3;border-radius:27px;padding:24px 26px;margin:0 0 20px;box-shadow:0 5px 18px #0c407d08}.ui-card h3{font-size:27px;line-height:1.4;margin:0 0 14px;font-weight:650;color:#264363}.ui-card p{font-size:26px;line-height:1.55;margin:12px 0}.ui-row{display:flex;justify-content:space-between;gap:12px;align-items:center;min-height:64px;border-top:1px solid #eef2f6;font-size:24px;line-height:1.35}.ui-row>span{color:#64788c}.ui-row strong{text-align:right;font-size:27px;font-weight:600}.ui small{font-size:20px;margin-left:7px;font-weight:400;color:#63758b}.ui-big{font-size:75px;font-weight:700;line-height:1.1;color:#122a44;margin:10px 0 25px}.ui-big small{font-size:29px}.ui-metric-pair{display:grid;grid-template-columns:1fr 1fr;gap:24px}.ui-metric-pair>div{background:#f1f7fe;border-radius:17px;padding:15px 20px;font-size:24px;color:#617993}.ui-metric-pair strong{display:block;margin-top:7px;color:#16365b;font-size:42px}.ui-button{background:linear-gradient(100deg,#1464cd,#257dde);border-radius:18px;padding:21px 24px;color:white;font-size:27px;display:flex;justify-content:space-between;margin:17px 0;font-weight:600;line-height:1.3}.ui-button span{font-size:33px}.ui-tabs{display:flex;justify-content:space-between;gap:12px;white-space:nowrap;font-size:21px;margin-bottom:22px}.ui-tabs b{color:#0674ee;border-bottom:3px solid #2885f7;padding-bottom:11px}.ui-date{color:#6b8196;font-size:22px;margin:3px 7px 18px}.ui-goal-strip{background:#e0eeff;padding:20px 22px;border-radius:19px;color:#41678f;font-size:24px;line-height:1.5;margin-bottom:21px}.ui-goal-strip strong{font-size:35px;margin-left:18px;color:#006bdb}.ui-goal-strip>span{display:block;font-size:21px}.ui-bubble{background:linear-gradient(120deg,#1464cd,#257dde);color:#fff;border-radius:24px 24px 4px 24px;padding:21px 26px;font-size:28px;line-height:1.5;margin:20px 0 22px 58px}.ui-assistant{background:#fff;border:1px solid #dce7f3;border-radius:20px;padding:23px;font-size:26px;line-height:1.55}.ui-tags{display:flex;flex-wrap:wrap;gap:12px;margin:14px 0}.ui-chip{background:#eaf3ff;border-radius:11px;padding:10px 13px;color:#2b6296;font-size:23px}.ui-input{position:absolute;left:28px;right:28px;bottom:19px;border-radius:25px;background:#fff;padding:23px;color:#7b8b9d;font-size:24px;box-shadow:0 2px 20px #1642680c}.ui-input span{float:right;color:#2688ed}.ui-meal-title{font-size:34px;font-weight:650;line-height:1.45;margin:10px 0 22px}.ui .ui-note{font-size:20px;color:#526780;line-height:1.5;margin-top:17px}.ui-nav{position:absolute;left:0;right:0;bottom:0;height:90px;display:flex;justify-content:space-around;align-items:center;background:#fff;border-top:1px solid #dfe9f5;color:#8593a4;font-size:25px}.ui-nav .active{color:#097df0;font-weight:700}.ui-nav span:nth-child(3){background:#1a86f4;color:white;border-radius:50%;width:64px;height:64px;display:flex;align-items:center;justify-content:center}.ui-success{color:#008358;text-align:center;font-size:27px;margin-top:20px}.ui-training-art{height:184px;display:flex;align-items:center;justify-content:space-around;color:#147de4;background:linear-gradient(130deg,#d9ebff,#f2f8ff);border-radius:20px;margin-bottom:24px}.ui-training-art>span{font-size:85px;font-weight:750;color:#9fc9f6}.ui-week{display:flex;justify-content:space-between;align-items:center;background:#fff;border-radius:22px;padding:17px 15px;margin:9px 0 23px;font-size:27px;color:#647d99}.ui-week b{background:#2088f4;border-radius:50%;width:60px;height:60px;color:#fff;display:flex;justify-content:center;align-items:center}
'''
