PIKI / 纸感编辑杂志
PIKI 示例 · 本地交互
编辑资料
保存 JSON
下载完整 HTML
重播动效
动效
留白 INTERVAL
故事
主题
期刊
关于
搜索
收藏 (0)
给日常,
留一点空。
文字、物件与缓慢发生的事。
阅读本期
一段下午,不必急着结束
光,怎样经过一扇窗
留下手作的痕迹
主题索引
日常 / 1 篇文章
空间 / 1 篇文章
创作 / 2 篇文章
本期推荐
全部故事
阅读 一段下午,不必急着结束
日常
一段下午,不必急着结束
这是一篇独立编写的样例文章,用于展示阅读与编辑结构。
阅读 光,怎样经过一扇窗
空间
光,怎样经过一扇窗
这是一篇独立编写的样例文章,用于展示阅读与编辑结构。
阅读 留下手作的痕迹
创作
留下手作的痕迹
这是一篇独立编写的样例文章,用于展示阅读与编辑结构。
阅读 让想法有处安放
创作
让想法有处安放
这是一篇独立编写的样例文章,用于展示阅读与编辑结构。
编辑资料
关闭
资料只在当前页面处理。图片使用包内 assets 或嵌入图片;正式发布需要自己的内容与服务。
数据 JSON
关闭详情
搜索入口
关闭搜索
{"tool":"piki-free-editorial-magazine","initialRoute":"home","data":{"version":1,"tool":"piki-free-editorial-magazine","kind":"magazine","brand":"留白 INTERVAL","headline":"给日常,留一点空。","description":"文字、物件与缓慢发生的事。","contactEmail":"hello@example.com","location":"示例城市","role":"示例人物","bio":"从一个具体问题开始,把想法整理成可以交付、可以继续修改的成果。","assets":{"desk":"assets/desk.webp","window":"assets/window.webp","clay":"assets/clay.webp"},"isSample":true,"demoOnly":true,"products":[{"id":"issue","title":"留白 · 第一期样例","description":"独立编写的期刊结构示例,不是真实出版物。","category":"期刊","image":"desk","detailImage":"","colour":"","materials":"","care":"","price":49}],"articles":[{"id":"afternoon","title":"一段下午,不必急着结束","description":"这是一篇独立编写的样例文章,用于展示阅读与编辑结构。","category":"日常","image":"desk","date":"2026-10-01","author":"留白编辑部 · 示例","readMinutes":4,"sections":[{"id":"begin","title":"从一个小地方开始","body":"忙碌的时候,我们常常只看见要完成的事情。把目光放回眼前:一张桌子,一束光,一本还没有写满的笔记。这里的内容只是示例,真实网站应放入自己的文字。"},{"id":"notice","title":"给观察一点时间","body":"不必急着给每件事一个结论。先记录看到的,再分清已经知道的与尚未确认的。这样,下一次回到资料时,能够接着往前走。"},{"id":"next","title":"留下可以继续的线索","body":"把来源、选择与下一步放在一起。一篇文章不一定要解决所有问题,但可以留下一个清楚的入口。"}]},{"id":"window","title":"光,怎样经过一扇窗","description":"这是一篇独立编写的样例文章,用于展示阅读与编辑结构。","category":"空间","image":"window","date":"2026-10-02","author":"留白编辑部 · 示例","readMinutes":5,"sections":[{"id":"begin","title":"从一个小地方开始","body":"忙碌的时候,我们常常只看见要完成的事情。把目光放回眼前:一张桌子,一束光,一本还没有写满的笔记。这里的内容只是示例,真实网站应放入自己的文字。"},{"id":"notice","title":"给观察一点时间","body":"不必急着给每件事一个结论。先记录看到的,再分清已经知道的与尚未确认的。这样,下一次回到资料时,能够接着往前走。"},{"id":"next","title":"留下可以继续的线索","body":"把来源、选择与下一步放在一起。一篇文章不一定要解决所有问题,但可以留下一个清楚的入口。"}]},{"id":"clay","title":"留下手作的痕迹","description":"这是一篇独立编写的样例文章,用于展示阅读与编辑结构。","category":"创作","image":"clay","date":"2026-10-03","author":"留白编辑部 · 示例","readMinutes":6,"sections":[{"id":"begin","title":"从一个小地方开始","body":"忙碌的时候,我们常常只看见要完成的事情。把目光放回眼前:一张桌子,一束光,一本还没有写满的笔记。这里的内容只是示例,真实网站应放入自己的文字。"},{"id":"notice","title":"给观察一点时间","body":"不必急着给每件事一个结论。先记录看到的,再分清已经知道的与尚未确认的。这样,下一次回到资料时,能够接着往前走。"},{"id":"next","title":"留下可以继续的线索","body":"把来源、选择与下一步放在一起。一篇文章不一定要解决所有问题,但可以留下一个清楚的入口。"}]},{"id":"notes","title":"让想法有处安放","description":"这是一篇独立编写的样例文章,用于展示阅读与编辑结构。","category":"创作","image":"desk","date":"2026-10-04","author":"留白编辑部 · 示例","readMinutes":7,"sections":[{"id":"begin","title":"从一个小地方开始","body":"忙碌的时候,我们常常只看见要完成的事情。把目光放回眼前:一张桌子,一束光,一本还没有写满的笔记。这里的内容只是示例,真实网站应放入自己的文字。"},{"id":"notice","title":"给观察一点时间","body":"不必急着给每件事一个结论。先记录看到的,再分清已经知道的与尚未确认的。这样,下一次回到资料时,能够接着往前走。"},{"id":"next","title":"留下可以继续的线索","body":"把来源、选择与下一步放在一起。一篇文章不一定要解决所有问题,但可以留下一个清楚的入口。"}]}],"projects":[{"id":"index","title":"资料索引","description":"把资料、来源和下一步放在一个清楚的位置。","category":"产品","image":"product-ui","problem":"示例问题:资料散在不同的文件中,回到原出处需要反复查找。","decision":"保留原始文件,再用可搜索的索引与明确链接组织它们。","result":"示例成果:一份可以修改、可以追溯来源的索引页面。"},{"id":"workbench","title":"演示工作台","description":"用一份材料组织成能讲、能改的演示。","category":"表达","image":"product-ui","problem":"示例问题:文稿与演示之间缺少清楚的结构。","decision":"先确认对象和目标,再逐页安排要点与讲稿。","result":"示例成果:可编辑的页面、备注与源稿。"}],"experiences":[{"id":"studio","title":"设计与内容协作","description":"参与资料整理、交付边界与表达结构的设计。","company":"纸间工作室 · 示例","dates":"2024—2026","category":"设计"},{"id":"product","title":"产品原型与验证","description":"把一个问题缩小为可试验的原型,并记录选择和反馈。","company":"微光项目组 · 示例","dates":"2022—2024","category":"产品"},{"id":"learning","title":"学习与实践","description":"通过小项目积累资料组织和清楚表达的方法。","company":"独立项目 · 示例","dates":"2020—2022","category":"实践"}],"quotes":[{"id":"lin","name":"林初","role":"示例人物","quote":"把想法拆成具体动作,开始就没那么难了。","category":"创作","image":"portrait-1","source":"PIKI 独立编写的结构示例,不是真实客户评价。"},{"id":"xu","name":"许禾","role":"示例人物","quote":"能看到输入、过程和结果,我才知道它适不适合。","category":"产品","image":"portrait-2","source":"PIKI 独立编写的结构示例,不是真实客户评价。"},{"id":"zhou","name":"周简","role":"示例人物","quote":"少一个来回,多一点真正完成的时间。","category":"协作","image":"portrait-3","source":"PIKI 独立编写的结构示例,不是真实客户评价。"},{"id":"ye","name":"叶川","role":"示例人物","quote":"留下一份可修改的源稿,下一次就不用从头开始。","category":"创作","image":"window","source":"PIKI 独立编写的结构示例,不是真实客户评价。"},{"id":"mu","name":"木然","role":"示例人物","quote":"先试一个具体场景,再判断要不要继续。","category":"产品","image":"desk","source":"PIKI 独立编写的结构示例,不是真实客户评价。"},{"id":"han","name":"韩青","role":"示例人物","quote":"把边界说清楚,沟通会轻松许多。","category":"协作","image":"clay","source":"PIKI 独立编写的结构示例,不是真实客户评价。"}],"customers":[],"transactions":[],"tasks":[{"id":"input","title":"整理输入资料","status":"待整理","description":"示例任务:保留原始材料与出处。","owner":"林初","date":"2026-10-07"},{"id":"scope","title":"确认交付范围","status":"进行中","description":"示例任务:明确本次包含什么。","owner":"许禾","date":"2026-10-08"},{"id":"draft","title":"完成第一份源稿","status":"进行中","description":"示例任务:让内容可以继续修改。","owner":"周简","date":"2026-10-09"},{"id":"review","title":"检查实际结果","status":"已完成","description":"示例任务:验证文件与入口。","owner":"林初","date":"2026-10-06"}],"events":[],"plans":[{"id":"solo","title":"个人","description":"示例方案 · 单人资料整理","monthly":29,"yearly":290,"features":["一个工作空间","本地示例流程","可修改的源稿"]},{"id":"team","title":"小团队","description":"示例方案 · 协作交付","monthly":79,"yearly":790,"features":["协作结构样例","明确的交付状态","来源记录"]},{"id":"custom","title":"定制","description":"示例方案 · 按实际范围讨论","monthly":0,"yearly":0,"features":["需求范围确认","内容与交付约定","不在此收款"]}],"faqs":[{"id":"use","title":"样例可以直接用吗?","description":"可以下载源码继续修改;使用自己的资料、图片和真实事实,替换这里的示例内容。","category":"开始"},{"id":"send","title":"表单会发送消息吗?","description":"不会。此处只验证字段并生成本地草稿,不发送邮件、不注册账户,也不接通收款。","category":"交互"},{"id":"offline","title":"如何交付给别人?","description":"下载完整工作流,在自己的 Agent 中生成 HTML 和源数据。正式发布前检查所有入口、内容与权限。","category":"交付"}],"releases":[{"id":"source","title":"源稿与出处","description":"示例更新:资料可以关联来源与下一步。","date":"2026-10-06","category":"功能"},{"id":"notes","title":"交付备注","description":"示例更新:在交付旁保留需要知道的内容。","date":"2026-09-22","category":"改进"}],"uses":[{"id":"editor","title":"文本与代码编辑器","description":"保存可修改的文件。","category":"工具"},{"id":"notes","title":"本地资料目录","description":"保留原始素材与清楚的命名。","category":"资料"}],"education":[{"id":"learning","title":"持续学习 · 示例","description":"以实际项目组织知识、练习判断与清楚表达。","dates":"2020—2026"}],"talks":[{"id":"clarity","title":"把复杂的事情讲清楚","description":"示例分享:先说对象与问题,再展示过程和下一步。","date":"2026-10-06","notes":["明确听众是谁。","用一个具体案例说明结构。","留下可执行的下一步。"]}],"skills":[{"id":"skill-0","title":"资料组织","description":"用具体输入、过程与成果说明能力,而不是堆叠标签。","category":"方法"},{"id":"skill-1","title":"产品原型","description":"用具体输入、过程与成果说明能力,而不是堆叠标签。","category":"方法"},{"id":"skill-2","title":"网页表达","description":"用具体输入、过程与成果说明能力,而不是堆叠标签。","category":"工具"},{"id":"skill-3","title":"交付沟通","description":"用具体输入、过程与成果说明能力,而不是堆叠标签。","category":"工具"}]},"modules":["export const WEB_TOOLS=[\n {id:'piki-free-sneaker-store',kind:'store',name:'生活方式商店',brief:'产品、系列、选款清单与演示结算组成完整的商店原型。'},\n {id:'piki-free-editorial-magazine',kind:'magazine',name:'纸感编辑杂志',brief:'把文章、主题、期刊、收藏与阅读详情组织成编辑网站。'},\n {id:'piki-free-scrapbook-resume',kind:'resume',name:'拼贴个人履历',brief:'以经历、项目、技能、联系和可打印 CV 展示个人故事。'},\n {id:'piki-free-motion-hero',kind:'hero',name:'轻动效首屏',brief:'制作可改内容、重播、暂停并尊重减少动态设置的首屏。'},\n {id:'piki-free-testimonial-wall',kind:'wall',name:'口碑故事墙',brief:'展示可筛选、展开和查看完整出处的观点与体验。'},\n {id:'piki-free-admin-console',kind:'admin',name:'本地管理工作台',brief:'用模拟数据操作分析、账本、客户、看板、日历与设置。'},\n {id:'piki-free-dark-product-site',kind:'dark',name:'暗色产品发布站',brief:'通过产品演示、工作流、方案、更新与申请草稿讲清产品。'},\n {id:'piki-free-light-product-site',kind:'light',name:'明亮产品官网',brief:'组织功能、产品导览、方案、状态与联系等完整页面。'},\n {id:'piki-free-dev-portfolio',kind:'portfolio',name:'开发者作品集',brief:'展示项目案例、经历、写作、分享、工具与联系草稿。'}\n];\nexport const E=value=>String(value??'').replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));\nexport const getWebTool=value=>{const t=WEB_TOOLS.find(t=>t.id===value||t.kind===value);if(!t)throw new Error('Unknown workflow.');return t;};\nconst text=(value,max,label)=>{if(value==null)return '';if(typeof value!=='string'||value.length>max)throw new Error(label+' must be text of at most '+max+' characters.');return value;};\nconst safeId=value=>{if(typeof value!=='string'||!/^[-a-zA-Z0-9_]{1,80}$/.test(value))throw new Error('Use unique safe IDs.');return value;};\nconst number=(v,label)=>{if(!Number.isFinite(v)||v<0||v>1e9)throw new Error(label+' needs a non-negative finite number.');return v;};\nexport function isDate(value){if(!/^\\d{4}-\\d{2}-\\d{2}$/.test(value||''))return false;const d=new Date(value+'T00:00:00Z');return Number.isFinite(d.getTime())&&d.toISOString().slice(0,10)===value;}\nconst fields={products:['title','description','category','image','detailImage','colour','materials','care'],articles:['title','description','category','image','date','author'],projects:['title','description','category','image','problem','decision','result'],experiences:['title','description','company','dates','category'],quotes:['name','role','quote','category','image','source'],customers:['name','email','status','company','note'],transactions:['title','category','date','status','note'],tasks:['title','status','description','owner','date'],events:['title','date','time','description'],plans:['title','description'],faqs:['title','description','category'],releases:['title','description','date','category'],uses:['title','description','category'],education:['title','description','dates'],talks:['title','description','date'],skills:['title','description','category']};\nconst allowedStatus=new Set(['待整理','进行中','已完成','待跟进','活跃','暂停','收入','支出','记录']);\nexport function validateWebData(input,tool){\n if(!input||typeof input!=='object'||Array.isArray(input))throw new Error('Provide a JSON object.');const t=getWebTool(tool||input.tool);\n const data={version:1,tool:t.id,kind:t.kind,brand:text(input.brand,100,'Brand')||t.name,headline:text(input.headline,180,'Headline')||t.name,description:text(input.description,1000,'Description'),contactEmail:text(input.contactEmail,160,'Contact email'),location:text(input.location,120,'Location'),role:text(input.role,160,'Role'),bio:text(input.bio,2500,'Biography'),assets:{},isSample:input.isSample!==false,demoOnly:true};\n if(input.assets!=null&&(typeof input.assets!=='object'||Array.isArray(input.assets)))throw new Error('Assets must be a key/path object.');\n for(const [key,value]of Object.entries(input.assets||{})){safeId(key);const src=text(value,15000000,'Asset');if(src.startsWith('//')||(/^[a-z][a-z0-9+.-]*:/i.test(src)&&!/^data:image\\/(png|jpeg|webp);base64,/i.test(src)&&!/^[A-Za-z]:[\\\\/]/.test(src)))throw new Error('Use local images or embedded PNG/JPEG/WebP, not remote assets.');data.assets[key]=src;}\n for(const [collection,names]of Object.entries(fields)){\n const rows=input[collection]||[];if(!Array.isArray(rows)||rows.length>250)throw new Error(collection+' needs at most 250 records.');const ids=new Set();\n data[collection]=rows.map((row,i)=>{if(!row||typeof row!=='object'||Array.isArray(row))throw new Error('Invalid '+collection+' record.');const id=safeId(row.id||collection+'-'+(i+1));if(ids.has(id))throw new Error('Duplicate '+collection+' ID.');ids.add(id);const result={id};for(const name of names)result[name]=text(row[name],name==='description'||name==='quote'?5000:500,name);\n if(result.date&&!isDate(result.date))throw new Error('Use a real YYYY-MM-DD date.');\n if(result.status&&!allowedStatus.has(result.status))throw new Error('Unknown record status.');\n for(const name of ['price','monthly','yearly','amount','readMinutes'])if(row[name]!=null)result[name]=number(row[name],name);\n for(const name of ['sizes','features','paragraphs','notes','visits','gallery'])if(row[name]!=null){if(!Array.isArray(row[name])||row[name].length>40)throw new Error(name+' needs a short array.');result[name]=row[name].map(s=>text(s,4000,name));if(name==='visits'&&result[name].some(date=>!isDate(date)))throw new Error('Visits need real YYYY-MM-DD dates.');}\n if(row.variants!=null){if(!Array.isArray(row.variants)||row.variants.length>20)throw new Error('Variants need a short array.');result.variants=row.variants.map(v=>({label:text(v.label,100,'Variant label'),image:text(v.image,100,'Variant image')}));}\n if(row.sections!=null){if(!Array.isArray(row.sections)||row.sections.length>30)throw new Error('Sections must be an array.');const sectionIds=new Set();result.sections=row.sections.map((s,j)=>{const sid=safeId(s.id||'section-'+(j+1));if(sectionIds.has(sid))throw new Error('Duplicate section ID.');sectionIds.add(sid);return {id:sid,title:text(s.title,180,'Section title'),body:text(s.body,12000,'Section body')};});}\n return result;});\n }\n if(data.kind==='store'&&!data.products.length)throw new Error('A store needs products.');if(data.kind==='magazine'&&!data.articles.length)throw new Error('A magazine needs articles.');if(data.kind==='wall'&&!data.quotes.length)throw new Error('The wall needs attributed quotes.');\n if(!data.isSample&&data.quotes.some(q=>!q.source))throw new Error('Real testimonials need a declared source.');\n return data;\n}\nexport function routeInventory(data){\n const common=['home','guide','contact','privacy','terms','about'],routes=new Set(common);\n const add=(kind,rows)=>{routes.add(kind);for(const row of rows)routes.add(kind+'/'+row.id);};\n if(data.kind==='store'){['shop','collections','cart','checkout','size','shipping','faq','story','reviews','wishlist','account'].forEach(p=>routes.add(p));add('product',data.products);for(const category of new Set(data.products.map(p=>p.category)))routes.add('collection/'+category);}\n if(data.kind==='magazine'){['stories','topics','archive','saved','issues','shop','bag','checkout','about','newsletter'].forEach(p=>routes.add(p));add('article',data.articles);add('product',data.products);for(const category of new Set(data.articles.map(p=>p.category)))routes.add('topic/'+category);}\n if(data.kind==='resume'||data.kind==='portfolio'){['experience','education','skills','projects','kind-words','cv','about'].forEach(p=>routes.add(p));add('project',data.projects);add('role',data.experiences);}\n if(data.kind==='portfolio'){['writing','talks','uses','repos'].forEach(p=>routes.add(p));add('article',data.articles);add('talk',data.talks);}\n if(data.kind==='dark'||data.kind==='light'){['features','workflow','pricing','tour','signup','signin','changelog','status','story'].forEach(p=>routes.add(p));add('release',data.releases);}\n if(data.kind==='admin')['overview','analytics','finance','customers','roadmap','calendar','settings'].forEach(p=>routes.add(p));\n return [...routes];\n}\nexport function parseRoute(hash){let raw=(hash||'').replace(/^#\\/?/,'');if(!raw)raw='home';try{return decodeURIComponent(raw);}catch{return 'not-found';}}\nexport function asset(data,key){return data.assets[key]||'';}\nexport const money=n=>'¥'+new Intl.NumberFormat('zh-CN',{maximumFractionDigits:2}).format(Number(n)||0);\nexport function cartRows(data,cart=[]){return cart.map(line=>{const product=data.products.find(p=>p.id===line.id);if(!product||!Number.isInteger(line.quantity)||line.quantity<1||line.quantity>99)return null;return {...line,product,subtotal:(product.price||0)*line.quantity};}).filter(Boolean);}\nexport function cartTotal(data,cart,delivery=0){return cartRows(data,cart).reduce((sum,row)=>sum+row.subtotal,0)+delivery;}\nexport function filteredRows(rows,query='',category='',sort=''){let result=rows.filter(row=>(!category||row.category===category||row.status===category)&&(!query||Object.values(row).filter(v=>typeof v==='string').join('\\n').toLowerCase().includes(query.toLowerCase())));if(sort==='price-up')result.sort((a,b)=>(a.price||0)-(b.price||0));if(sort==='price-down')result.sort((a,b)=>(b.price||0)-(a.price||0));if(sort==='title')result.sort((a,b)=>(a.title||a.name||'').localeCompare(b.title||b.name||'','zh-CN'));if(sort==='latest')result.sort((a,b)=>(b.date||'').localeCompare(a.date||''));return result;}\nexport function ledgerTotals(data){const income=data.transactions.filter(r=>r.category==='收入').reduce((n,r)=>n+(r.amount||0),0),expense=data.transactions.filter(r=>r.category==='支出').reduce((n,r)=>n+(r.amount||0),0);return {income,expense,balance:income-expense};}\nexport function customerActivity(data){const months=[...new Set(data.customers.flatMap(c=>(c.visits||[]).map(v=>v.slice(0,7))))].sort();return months.map(month=>({month,new:data.customers.filter(c=>[...(c.visits||[])].sort()[0]?.startsWith(month)).length,active:data.customers.filter(c=>(c.visits||[]).some(v=>v.startsWith(month))).length}));}\nexport function retentionRows(data){const cohorts=new Map(),last=[...data.customers.flatMap(c=>c.visits||[])].sort().at(-1)?.slice(0,7);for(const c of data.customers){const first=[...(c.visits||[])].sort()[0];if(!first)continue;const month=first.slice(0,7);if(!cohorts.has(month))cohorts.set(month,[]);cohorts.get(month).push(c);}return [...cohorts].sort().map(([month,customers])=>({month,customers:customers.length,values:[0,1,2,3].map(offset=>{const [year,m]=month.split('-').map(Number),date=new Date(Date.UTC(year,m-1+offset,1)).toISOString().slice(0,7);if(date>last)return null;return Math.round(customers.filter(c=>c.visits.some(v=>v.startsWith(date))).length/customers.length*100);})}));}\nexport function referencedAssetKeys(data){const keys=new Set();const rows=names=>names.forEach(name=>data[name].forEach(row=>{if(row.image&&row.image!=='product-ui')keys.add(row.image);if(row.detailImage)keys.add(row.detailImage);for(const image of row.gallery||[])keys.add(image);for(const v of row.variants||[])if(v.image)keys.add(v.image);}));if(data.kind==='store'){keys.add('store-hero');rows(['products','quotes']);}if(data.kind==='magazine')rows(['articles','products']);if(data.kind==='resume'){keys.add('portrait-1');keys.add('desk');rows(['quotes']);}if(data.kind==='portfolio'){keys.add('studio-dark');keys.add('portrait-3');rows(['articles','quotes']);}if(data.kind==='hero')keys.add('desk');if(data.kind==='wall')rows(['quotes']);if(['dark','light'].includes(data.kind)){keys.add('desk');if(data.kind==='dark')keys.add('studio-dark');rows(['quotes']);}if(data.kind!=='admin'&&data.kind!=='store'&&data.kind!=='portfolio')keys.add('desk');return [...keys];}\nexport function cashflowMonths(data){const months=[...new Set(data.transactions.map(r=>r.date.slice(0,7)))].sort();return months.map(month=>({month,income:data.transactions.filter(r=>r.date.startsWith(month)&&r.category==='收入').reduce((n,r)=>n+r.amount,0),expense:data.transactions.filter(r=>r.date.startsWith(month)&&r.category==='支出').reduce((n,r)=>n+r.amount,0)}));}\nexport function monthGrid(year,month){if(!Number.isInteger(year)||year<1900||year>2200||!Number.isInteger(month)||month<1||month>12)throw new Error('Choose a valid year/month.');const first=Date.UTC(year,month-1,1),end=Date.UTC(year,month,1),offset=(new Date(first).getUTCDay()+6)%7;const cells=Array(offset).fill(null);for(let d=first;d<end;d+=86400000)cells.push(new Date(d).toISOString().slice(0,10));while(cells.length%7)cells.push(null);return cells;}\nexport const csvValue=value=>{let text=String(value??'');if(/^[=+@-]/.test(text))text=\"'\"+text;return '\"'+text.replaceAll('\"','\"\"')+'\"';};\nexport function sampleWebData(tool){\n const t=getWebTool(tool),base={tool:t.id,brand:t.name,headline:t.name,description:'可编辑的结构样例。人物、价格与数据均为示例。',contactEmail:'hello@example.com',role:'示例人物',location:'示例城市',bio:'从一个具体问题开始,把想法整理成可以交付、可以继续修改的成果。',assets:{},products:[],articles:[],projects:[],experiences:[],quotes:[],customers:[],transactions:[],tasks:[],events:[],plans:[],faqs:[],releases:[],uses:[],education:[],talks:[],skills:[]};\n const articles=[['afternoon','一段下午,不必急着结束','日常','desk'],['window','光,怎样经过一扇窗','空间','window'],['clay','留下手作的痕迹','创作','clay'],['notes','让想法有处安放','创作','desk']].map(([id,title,category,image],i)=>({id,title,category,image,date:'2026-10-0'+(i+1),author:'留白编辑部 · 示例',readMinutes:4+i,description:'这是一篇独立编写的样例文章,用于展示阅读与编辑结构。',sections:[{id:'begin',title:'从一个小地方开始',body:'忙碌的时候,我们常常只看见要完成的事情。把目光放回眼前:一张桌子,一束光,一本还没有写满的笔记。这里的内容只是示例,真实网站应放入自己的文字。'},{id:'notice',title:'给观察一点时间',body:'不必急着给每件事一个结论。先记录看到的,再分清已经知道的与尚未确认的。这样,下一次回到资料时,能够接着往前走。'},{id:'next',title:'留下可以继续的线索',body:'把来源、选择与下一步放在一起。一篇文章不一定要解决所有问题,但可以留下一个清楚的入口。'}]}));\n const quotes=[['lin','林初','创作','把想法拆成具体动作,开始就没那么难了。'],['xu','许禾','产品','能看到输入、过程和结果,我才知道它适不适合。'],['zhou','周简','协作','少一个来回,多一点真正完成的时间。'],['ye','叶川','创作','留下一份可修改的源稿,下一次就不用从头开始。'],['mu','木然','产品','先试一个具体场景,再判断要不要继续。'],['han','韩青','协作','把边界说清楚,沟通会轻松许多。']].map(([id,name,category,quote],i)=>({id,name,category,quote,role:'示例人物',image:i<3?'portrait-'+(i+1):['window','desk','clay'][i-3],source:'PIKI 独立编写的结构示例,不是真实客户评价。'}));\n const projects=[{id:'index',title:'资料索引',category:'产品',image:'product-ui',description:'把资料、来源和下一步放在一个清楚的位置。',problem:'示例问题:资料散在不同的文件中,回到原出处需要反复查找。',decision:'保留原始文件,再用可搜索的索引与明确链接组织它们。',result:'示例成果:一份可以修改、可以追溯来源的索引页面。'},{id:'workbench',title:'演示工作台',category:'表达',image:'product-ui',description:'用一份材料组织成能讲、能改的演示。',problem:'示例问题:文稿与演示之间缺少清楚的结构。',decision:'先确认对象和目标,再逐页安排要点与讲稿。',result:'示例成果:可编辑的页面、备注与源稿。'}];\n const experiences=[{id:'studio',title:'设计与内容协作',company:'纸间工作室 · 示例',dates:'2024—2026',category:'设计',description:'参与资料整理、交付边界与表达结构的设计。'},{id:'product',title:'产品原型与验证',company:'微光项目组 · 示例',dates:'2022—2024',category:'产品',description:'把一个问题缩小为可试验的原型,并记录选择和反馈。'},{id:'learning',title:'学习与实践',company:'独立项目 · 示例',dates:'2020—2022',category:'实践',description:'通过小项目积累资料组织和清楚表达的方法。'}];\n const faqs=[{id:'use',title:'样例可以直接用吗?',category:'开始',description:'可以下载源码继续修改;使用自己的资料、图片和真实事实,替换这里的示例内容。'},{id:'send',title:'表单会发送消息吗?',category:'交互',description:'不会。此处只验证字段并生成本地草稿,不发送邮件、不注册账户,也不接通收款。'},{id:'offline',title:'如何交付给别人?',category:'交付',description:'下载完整工作流,在自己的 Agent 中生成 HTML 和源数据。正式发布前检查所有入口、内容与权限。'}];\n const plans=[{id:'solo',title:'个人',description:'示例方案 · 单人资料整理',monthly:29,yearly:290,features:['一个工作空间','本地示例流程','可修改的源稿']},{id:'team',title:'小团队',description:'示例方案 · 协作交付',monthly:79,yearly:790,features:['协作结构样例','明确的交付状态','来源记录']},{id:'custom',title:'定制',description:'示例方案 · 按实际范围讨论',monthly:0,yearly:0,features:['需求范围确认','内容与交付约定','不在此收款']}];\n base.quotes=quotes;base.faqs=faqs;base.plans=plans;base.projects=projects;base.experiences=experiences;base.articles=articles;base.education=[{id:'learning',title:'持续学习 · 示例',dates:'2020—2026',description:'以实际项目组织知识、练习判断与清楚表达。'}];base.skills=['资料组织','产品原型','网页表达','交付沟通'].map((title,i)=>({id:'skill-'+i,title,category:i<2?'方法':'工具',description:'用具体输入、过程与成果说明能力,而不是堆叠标签。'}));base.uses=[{id:'editor',title:'文本与代码编辑器',category:'工具',description:'保存可修改的文件。'},{id:'notes',title:'本地资料目录',category:'资料',description:'保留原始素材与清楚的命名。'}];base.talks=[{id:'clarity',title:'把复杂的事情讲清楚',date:'2026-10-06',description:'示例分享:先说对象与问题,再展示过程和下一步。',notes:['明确听众是谁。','用一个具体案例说明结构。','留下可执行的下一步。']}];base.releases=[{id:'source',title:'源稿与出处',date:'2026-10-06',category:'功能',description:'示例更新:资料可以关联来源与下一步。'},{id:'notes',title:'交付备注',date:'2026-09-22',category:'改进',description:'示例更新:在交付旁保留需要知道的内容。'}];\n if(t.kind==='store'){base.brand='轻行 LITE';base.headline='轻一点,走远一点。';base.description='虚构鞋履品牌样例 · 只生成选购清单,不收款。';base.products=[['blank','留白日常鞋','日常','shoe-cream',599],['forest','森野步行鞋','步行','shoe-sage',699],['night','暮色城市鞋','日常','shoe-black',649],['clay','赤陶慢行鞋','步行','shoe-rust',699]].map(([id,title,category,image,price])=>({id,title,category,image,price,description:'虚构鞋款,用于展示产品信息、规格与选款流程。',colour:category==='日常'?'奶油白 / 暮黑':'鼠尾草 / 赤陶',materials:'示例材质:织物鞋面与橡胶鞋底。',care:'示例护理说明:按自己的实际产品说明替换。',sizes:['36','37','38','39','40','41','42','43']}));}\n if(t.kind==='magazine'){base.brand='留白 INTERVAL';base.headline='给日常,留一点空。';base.description='文字、物件与缓慢发生的事。';base.products=[{id:'issue',title:'留白 · 第一期样例',category:'期刊',image:'desk',price:49,description:'独立编写的期刊结构示例,不是真实出版物。'}];}\n if(t.kind==='resume'){base.brand='林初 Lin Chu';base.headline='把复杂的事,讲得清楚。';base.role='产品设计与内容表达 · 示例人物';base.description='虚构履历样例。经历、项目与观点均用于展示结构。';}\n if(t.kind==='portfolio'){base.brand='周简 Zhou Jian';base.headline='把好想法,做成能用的工具。';base.role='开发者与创作者 · 示例人物';base.description='项目、写作与实践,组成一份可以继续修改的作品集。';}\n if(t.kind==='hero'){base.headline='把想法,变成可用的东西。';base.description='让第一眼知道,下一步该做什么。';}\n if(t.kind==='wall'){base.headline='让具体的体验,被看见。';base.description='所有观点与人物均为结构示例。';}\n if(t.kind==='dark'||t.kind==='light'){base.brand='轻笺计划 NOTEFRAME';base.headline=t.kind==='dark'?'让交付,有一个清楚的下一步。':'把资料,组织成能行动的计划。';base.description='可编辑的产品站样例,不连接真实服务。';}\n base.tasks=[{id:'input',title:'整理输入资料',status:'待整理',description:'示例任务:保留原始材料与出处。',owner:'林初',date:'2026-10-07'},{id:'scope',title:'确认交付范围',status:'进行中',description:'示例任务:明确本次包含什么。',owner:'许禾',date:'2026-10-08'},{id:'draft',title:'完成第一份源稿',status:'进行中',description:'示例任务:让内容可以继续修改。',owner:'周简',date:'2026-10-09'},{id:'review',title:'检查实际结果',status:'已完成',description:'示例任务:验证文件与入口。',owner:'林初',date:'2026-10-06'}];\n if(t.kind==='admin'){base.brand='样例工作室';base.headline='本地管理工作台';base.description='模拟数据,不连接真实账户。';base.customers=['林初','许禾','周简','叶川','木然','韩青'].map((name,i)=>({id:'customer-'+i,name,email:'person'+i+'@example.com',status:i%3===0?'待跟进':i%3===1?'活跃':'暂停',company:'示例团队 '+(i+1),note:'本地结构示例,非真实客户。',visits:[...new Set(['2026-'+String(i+5).padStart(2,'0')+'-'+String(i+1).padStart(2,'0'),...(i<5?['2026-'+String(i+6).padStart(2,'0')+'-06']:[]),'2026-10-06'])]}));base.transactions=[{id:'income',title:'模拟项目记录',category:'收入',amount:4500,date:'2026-10-01',status:'记录',note:'示例账本,不发生收款。'},{id:'cost',title:'模拟成本记录',category:'支出',amount:800,date:'2026-10-02',status:'记录',note:'示例账本,不发生出款。'}];base.events=[{id:'scope',title:'范围讨论 · 示例',date:'2026-10-07',time:'10:00',description:'确认输入与交付。'},{id:'draft',title:'源稿检查 · 示例',date:'2026-10-09',time:'14:00',description:'检查可修改的结果。'},{id:'review',title:'本地回顾 · 示例',date:'2026-10-14',time:'16:00',description:'记录下一步。'}];}\n return validateWebData(base,t.id);\n}\n","import {routeInventory,parseRoute} from './model.js';\nexport const ROUTE_LABELS={home:'主页',guide:'使用说明',contact:'联系草稿',privacy:'隐私说明',terms:'使用边界',shop:'全部商品',collections:'系列',cart:'选购清单',bag:'书袋',checkout:'演示结算',size:'尺码参考',shipping:'配送示例',faq:'常见问题',story:'品牌故事',reviews:'示例观点',wishlist:'收藏款式',account:'演示账户',product:'商品',collection:'系列',stories:'故事',topics:'主题',topic:'主题',archive:'文章档案',saved:'收藏文章',issues:'期刊',about:'关于',newsletter:'订阅草稿',article:'文章',experience:'经历',role:'经历详情',education:'学习',skills:'技能与工具',projects:'项目',project:'项目案例','kind-words':'示例观点',cv:'打印简历',writing:'写作',talks:'分享',talk:'分享备注',uses:'工具',repos:'项目索引',features:'功能',workflow:'工作流',pricing:'示例方案',tour:'产品导览',signup:'申请草稿',signin:'演示账户',changelog:'更新',release:'更新详情',status:'示例状态',overview:'总览',analytics:'分析',finance:'示例账本',customers:'客户',roadmap:'看板',calendar:'日历',settings:'设置'};\nexport function resolveRoute(data,hash){const path=parseRoute(hash),found=routeInventory(data).includes(path);const parts=path.split('/');return {path,kind:parts[0],id:parts.slice(1).join('/'),found,label:ROUTE_LABELS[parts[0]]||'未找到页面'};}\nexport function mainNavigation(data){const byKind={store:['shop','collections','size','story'],magazine:['stories','topics','issues','about'],resume:['experience','projects','skills','contact','cv'],portfolio:['projects','experience','writing','talks','uses','contact'],dark:['features','workflow','pricing','changelog','signup'],light:['features','pricing','changelog','contact','signin'],admin:['overview','analytics','finance','customers','roadmap','calendar','settings'],hero:['home','guide'],wall:['home','guide']};return (byKind[data.kind]||['home']).map(path=>({path,label:ROUTE_LABELS[path]}));}\nexport function itemTitle(data,route){const map={product:'products',article:'articles',project:'projects',role:'experiences',talk:'talks',release:'releases'};return data[map[route.kind]]?.find(item=>item.id===route.id)?.title||route.label;}\nexport function initialWebState(data){return {route:'home',query:'',category:'',sort:'',cart:[],saved:[],billing:'monthly',delivery:'standard',promo:'',page:1,pageSize:4,selectedCustomers:[],undo:null,theme:data.kind==='dark'||data.kind==='portfolio'?'dark':'light',preset:data.kind==='admin'?'tangerine':'slate',sidebarCollapsed:false,motion:true,expanded:false,tab:'0',month:10,year:2026,selectedDay:'2026-10-06',sessionDemo:false,notice:''};}\nexport function addCartItem(state,product,size='',colour=''){const existing=state.cart.find(line=>line.id===product.id&&line.size===size&&line.colour===colour);if(existing)existing.quantity=Math.min(99,existing.quantity+1);else state.cart.push({id:product.id,size,colour,quantity:1});}\nexport function changeTaskStatus(data,id,status){if(!['待整理','进行中','已完成'].includes(status))throw new Error('Unknown task state.');const task=data.tasks.find(t=>t.id===id);if(!task)throw new Error('Unknown task.');task.status=status;}\nexport function updateCustomerStatuses(data,state,status){if(!['待跟进','活跃','暂停'].includes(status))throw new Error('Unknown customer status.');const selected=new Set(state.selectedCustomers);state.undo=data.customers.filter(row=>selected.has(row.id)).map(row=>({id:row.id,status:row.status}));for(const row of data.customers)if(selected.has(row.id))row.status=status;state.selectedCustomers=[];}\nexport function undoCustomerStatuses(data,state){for(const old of state.undo||[]){const row=data.customers.find(r=>r.id===old.id);if(row)row.status=old.status;}state.undo=null;}\n","import {E,asset,money,filteredRows,cartRows,cartTotal,ledgerTotals,monthGrid,customerActivity,retentionRows,cashflowMonths} from './model.js';\nimport {resolveRoute,mainNavigation,ROUTE_LABELS} from './route-model.js';\nexport const href=route=>'#/'+route.split('/').map(encodeURIComponent).join('/');\nconst link=(route,label,cls='')=>'<a class=\"'+cls+'\" href=\"'+href(route)+'\">'+E(label)+'</a>';\nconst button=(action,label,value='',cls='')=>'<button type=\"button\" class=\"'+cls+'\" data-action=\"'+action+'\" data-value=\"'+E(value)+'\">'+E(label)+'</button>';\nconst img=(data,key,alt,cls='')=>asset(data,key)?'<img class=\"'+cls+'\" src=\"'+E(asset(data,key))+'\" alt=\"'+E(alt)+'\" loading=\"lazy\">':'<div class=\"image-empty '+cls+'\" role=\"img\" aria-label=\"'+E(alt)+'\">请提供自己的图片</div>';\nconst title=(h,p='')=>'<header class=\"page-title\"><h1>'+E(h)+'</h1>'+(p?'<p>'+E(p)+'</p>':'')+'</header>';\nconst headline=data=>{const at=data.headline.indexOf(',');if(at<0)return E(data.headline);const first=E(data.headline.slice(0,at+1)),rest=E(data.headline.slice(at+1));return first+'<br>'+(data.kind==='portfolio'?'<span>'+rest+'</span>':rest);};\nconst empty=text=>'<p class=\"empty-state\">'+E(text)+'</p>';\nfunction chips(values,active=''){return '<div class=\"filter-row\">'+['',...new Set(values.filter(Boolean))].map(v=>button('category',v||'全部',v,'filter-chip'+(v===active?' selected':''))).join('')+'</div>';}\nfunction filters(rows,state,label='搜索内容'){return '<div class=\"list-controls\"><input data-control=\"query\" type=\"search\" aria-label=\"'+E(label)+'\" placeholder=\"'+E(label)+'\" value=\"'+E(state.query)+'\"><select data-control=\"sort\" aria-label=\"排序\"><option value=\"\">默认顺序</option><option value=\"latest\"'+(state.sort==='latest'?' selected':'')+'>最新</option><option value=\"title\"'+(state.sort==='title'?' selected':'')+'>名称</option><option value=\"price-up\"'+(state.sort==='price-up'?' selected':'')+'>价格从低到高</option></select></div>'+chips(rows.map(r=>r.category||r.status),state.category);}\nfunction shell(data,state,body,route){const nav=mainNavigation(data),shop=data.kind==='store'||data.kind==='magazine';return '<header class=\"site-header\">'+link('home',data.brand,'wordmark')+'<nav aria-label=\"站点导航\">'+nav.map(n=>link(n.path,n.label,state.route===n.path?'active':'')).join('')+'</nav><div class=\"site-utilities\">'+button('search','搜索')+(shop?link(data.kind==='store'?'cart':'saved',data.kind==='store'?'选购清单 ('+state.cart.reduce((n,r)=>n+r.quantity,0)+')':'收藏 ('+state.saved.length+')','utility-button'):(data.kind==='light'?button('theme',state.theme==='dark'?'浅色':'深色'):''))+'</div></header><main class=\"site-content\" data-route=\"'+E(route.path)+'\">'+body+'</main>'+footer(data);}\nfunction footer(data){return '<footer class=\"site-footer\"><strong>'+E(data.brand)+'</strong><div>'+link('about','关于')+link('contact','联系草稿')+link('privacy','隐私说明')+link('terms','使用边界')+link('guide','使用说明')+'</div><small>PIKI 独立制作的结构样例 · 不收款、不发送消息</small></footer>';}\nfunction productCard(data,p){return '<article class=\"product-card\">'+link('product/'+p.id,'查看 '+p.title,'card-hit')+img(data,p.image,p.title+' · 虚构鞋款或商品样例')+'<div><h3>'+E(p.title)+'</h3><p>'+E(p.description)+'</p><footer><span>示例价格 <b>'+money(p.price)+'</b></span>'+link('product/'+p.id,'查看详情','text-link')+'</footer></div></article>';}\nfunction articleCard(data,a){return '<article class=\"article-card\">'+link('article/'+a.id,'阅读 '+a.title,'card-hit')+img(data,a.image,a.title+' · 独立制作的编辑照片')+'<small>'+E(a.category)+'</small><h3>'+E(a.title)+'</h3><p>'+E(a.description)+'</p><footer>'+E(a.date)+' · '+(a.readMinutes||0)+' 分钟</footer></article>';}\nfunction projectWindow(data,p){if(p.id==='index')return '<div class=\"product-window\"><aside>资料索引<br><small>示例界面</small></aside><div><header>我的资料 '+button('project-demo','添加资料',p.id)+'</header>'+data.articles.slice(0,4).map(a=>'<div class=\"window-row\"><span>'+E(a.title)+'.md</span><small>'+E(a.category)+'</small></div>').join('')+'</div></div>';if(p.id==='workbench')return '<div class=\"product-window\"><aside>演示工作台<br><small>示例界面</small></aside><div><header>可编辑的表达</header><div class=\"deck-mini\"><strong>把想法,讲清楚。</strong><div>输入资料 · 页面结构 · 讲稿备注</div>'+button('project-demo','查看演示',p.id)+'</div></div></div>';return '<div class=\"product-window\"><aside>'+E(p.title)+'<br><small>结构示意</small></aside><div><header>'+E(p.title)+'</header><div class=\"deck-mini\"><strong>'+E(p.title)+'</strong><div>'+E(p.description)+'</div><small>实际产品界面请用自己的组件与资料替换。</small></div></div></div>';}\nfunction projectCard(data,p){return '<article class=\"project-card\"><div><h3>'+E(p.title)+'</h3><p>'+E(p.description)+'</p>'+link('project/'+p.id,'查看案例','primary')+'</div>'+projectWindow(data,p)+'</article>';}\nfunction portfolioMedia(data){return '<div class=\"portfolio-media\">'+img(data,'studio-dark','安静的工作空间 · 独立制作照片')+'<div class=\"hero-project-window first\">'+projectWindow(data,data.projects[0]||{id:'index'})+'</div><div class=\"hero-project-window second\">'+projectWindow(data,data.projects[1]||{id:'workbench'})+'</div></div>';}\nfunction contactNote(data){return '<aside class=\"resume-contact-note\"><div><h3>联系草稿</h3><p>'+E(data.contactEmail)+'</p>'+button('copy-email','复制邮箱','','text-button')+'</div><div class=\"navy-note\"><p>保持好奇,<br>持续做有价值的事。</p>'+link('contact','写下要讨论的事','text-link')+'</div></aside>';}\nfunction productConsole(data,state){return '<div class=\"product-console-window\"><aside><strong>'+E(data.brand.split(' ')[0])+'</strong><nav><span>任务</span><span>资料</span><span>日历</span><span>设置</span></nav><small>本地界面样例</small></aside><div>'+board(data,state,true)+'<footer><span>'+data.tasks.length+' 项任务</span><span>'+data.events.length+' 个事件</span><span>不连接真实服务</span></footer></div></div>';}\nfunction quoteCard(data,q){const portrait=q.image.startsWith('portrait');return '<article class=\"quote-card\">'+img(data,q.image,q.name+' 的结构示例图')+'<div><blockquote>'+E(q.quote)+'</blockquote><footer>'+(portrait?img(data,q.image,q.name+' · 示例人物','avatar'):'<span class=\"initial-avatar\">'+E(q.name.slice(0,1))+'</span>')+'<span><strong>'+E(q.name)+'</strong><small>'+E(q.role)+' · '+E(q.category)+'</small></span></footer>'+button('quote','查看完整出处',q.id,'text-button')+'</div></article>';}\nfunction board(data,state,compact=false){return '<div class=\"task-board '+(compact?'compact':'')+'\">'+['待整理','进行中','已完成'].map(status=>{const rows=data.tasks.filter(t=>t.status===status);return '<section data-drop-status=\"'+status+'\"><header><h3>'+status+'</h3><span>'+rows.length+'</span></header>'+rows.map(t=>'<article class=\"task-card\" draggable=\"true\" data-task=\"'+E(t.id)+'\"><strong>'+E(t.title)+'</strong><p>'+E(t.description)+'</p><small>'+E(t.owner)+' · '+E(t.date)+'</small><select data-task-status=\"'+E(t.id)+'\" aria-label=\"'+E(t.title)+'的状态\">'+['待整理','进行中','已完成'].map(s=>'<option'+(s===t.status?' selected':'')+'>'+s+'</option>').join('')+'</select></article>').join('')+button('new-task','新增模拟任务',status,'text-button')+'</section>';}).join('')+'</div>';}\nfunction plans(data,state){return '<section class=\"plans-section\"><div class=\"section-heading\"><h2>选择适合你的方式</h2><div>'+button('billing','月度','monthly',state.billing==='monthly'?'selected':'')+button('billing','年度','yearly',state.billing==='yearly'?'selected':'')+'</div></div><p>示例方案,不能付款。</p><div class=\"plans-grid\">'+data.plans.map(p=>'<article><h3>'+E(p.title)+'</h3><p>'+E(p.description)+'</p><strong>'+(p.monthly===0?'按范围讨论':money(state.billing==='yearly'?p.yearly:p.monthly))+'<small>'+((p.monthly||0)>0?(state.billing==='yearly'?'/年':'/月'):'')+'</small></strong><ul>'+(p.features||[]).map(v=>'<li>'+E(v)+'</li>').join('')+'</ul>'+link('signup','生成申请草稿','primary')+'</article>').join('')+'</div></section>';}\nfunction faq(data){return '<section class=\"faq-section\"><h2>常见问题</h2>'+data.faqs.map(f=>'<details><summary>'+E(f.title)+'</summary><p>'+E(f.description)+'</p></details>').join('')+'</section>';}\nfunction draftForm(data,type='contact'){return '<form class=\"draft-form\" data-form=\"'+type+'\"><label>姓名<input name=\"name\" required maxlength=\"100\" autocomplete=\"off\"></label><label>邮箱<input name=\"email\" type=\"email\" required maxlength=\"160\" autocomplete=\"off\" placeholder=\"you@example.com\"></label><label>'+(type==='checkout'?'收件信息(仅演示)':'留言或需求')+'<textarea name=\"message\" required maxlength=\"4000\"></textarea></label><p>只生成本地草稿,不发送邮件、不创建账户、不付款。</p><button class=\"primary\" type=\"submit\">生成'+(type==='signup'?'申请':'联系')+'草稿</button><p class=\"form-result\" role=\"status\"></p></form>';}\nfunction storeHome(data,state){return '<section class=\"campaign\"><div><h1>'+headline(data)+'</h1><p>以更轻的步伐,去看更大的世界。<br>虚构品牌与鞋款,仅用于结构展示。</p>'+link('shop','浏览鞋款','primary')+'</div>'+img(data,'store-hero','完整人物与无品牌鞋履 · 独立制作的样例')+'</section><section class=\"store-home-grid\"><div><h2>新品推荐</h2><p>从日常到远行,选择适合的那一款。</p><div class=\"product-grid\">'+data.products.slice(0,2).map(p=>productCard(data,p)).join('')+'</div></div><div><h2>探索系列</h2><p>不同的生活场景,同样清楚的信息。</p><div class=\"collection-grid\">'+['日常','步行'].map((c,i)=>'<article>'+img(data,i?'shoe-sage':'shoe-cream',c+'系列示例')+'<h3>'+c+'</h3>'+link('collection/'+c,'查看系列','primary')+'</article>').join('')+'</div></div></section><section class=\"service-band\">'+[['size','尺码参考','按自己的产品规格填写'],['shipping','配送示例','只计算演示总额'],['faq','常见问题','公开说明适用边界'],['contact','联系草稿','不在此发送或收款']].map(([r,h,p])=>'<div>'+link(r,h)+'<small>'+p+'</small></div>').join('')+'</section>';}\nfunction magazineHome(data){return '<section class=\"editorial-hero\"><div><h1>'+headline(data)+'</h1><p>'+E(data.description)+'</p>'+link('stories','阅读本期','primary')+'</div><div class=\"paper-fan\">'+data.articles.slice(0,3).map(a=>'<a href=\"'+href('article/'+a.id)+'\">'+img(data,a.image,a.title)+'<strong>'+E(a.title)+'</strong></a>').join('')+'</div></section><section class=\"topic-index\"><h2>主题索引</h2>'+[...new Set(data.articles.map(a=>a.category))].map(c=>link('topic/'+c,c+' / '+data.articles.filter(a=>a.category===c).length+' 篇文章')).join('')+'</section><section><div class=\"section-heading\"><h2>本期推荐</h2>'+link('stories','全部故事','text-link')+'</div><div class=\"editorial-grid\">'+data.articles.slice(0,4).map(a=>articleCard(data,a)).join('')+'</div></section>';}\nfunction resumeHome(data){return '<section class=\"resume-hero\"><div><h1>'+headline(data)+'</h1><h2>'+E(data.role)+'</h2><p>'+E(data.bio)+'</p>'+link('projects','查看我的项目','primary')+link('cv','打印简历','secondary')+'</div><figure class=\"portrait-paper\">'+img(data,'portrait-1','林初 · 虚构履历样例人物')+'<figcaption>'+E(data.brand)+'<small>'+E(data.role)+'</small></figcaption></figure>'+contactNote(data)+'</section><section class=\"resume-summary\"><h2>经历与实践</h2><div class=\"experience-notes\">'+data.experiences.map(x=>'<article><small>'+E(x.dates)+'</small><h3>'+E(x.title)+'</h3><p>'+E(x.description)+'</p>'+link('role/'+x.id,'查看经历')+'</article>').join('')+'</div></section><section><h2>项目</h2>'+data.projects.map(p=>projectCard(data,p)).join('')+'</section>';}\nfunction heroHome(data){return '<section class=\"motion-hero\" data-entrance><div><h1>'+headline(data)+'</h1><p>'+E(data.description)+'</p><div>'+button('scroll','开始体验','config','primary')+button('scroll','看看过程','process','secondary')+'</div><small>一个可修改、可复用的首屏示例</small></div>'+img(data,'desk','阳光下的工作桌 · 独立制作照片')+'</section><section class=\"process-section\" id=\"process\"><h2>想法 · 结构 · 交付</h2><div>'+[['想法','写下要解决的问题。'],['结构','让内容有清楚的顺序。'],['交付','留下可修改的结果。']].map(([h,p],i)=>'<article><b>0'+(i+1)+'</b><h3>'+h+'</h3><p>'+p+'</p></article>').join('')+'</div></section><section class=\"config-section\" id=\"config\"><div><h2>可配置的内容,本地化的数据</h2><p>编辑文案与图片,预览真实交互。数据只在当前页面处理,离开前保存 JSON。</p>'+button('edit-data','编辑资料','','primary')+'</div><pre>'+E(JSON.stringify({brand:data.brand,headline:data.headline,description:data.description},null,2))+'</pre></section>';}\nfunction wallHome(data,state){const rows=filteredRows(data.quotes,state.query,state.category);return '<section class=\"wall-heading\">'+title(data.headline,data.description)+chips(data.quotes.map(q=>q.category),state.category)+'</section><canvas id=\"wallCanvas\" aria-hidden=\"true\"></canvas><section class=\"quote-wall\">'+rows.slice(0,state.expanded?rows.length:3).map(q=>quoteCard(data,q)).join('')+'</section>'+(!rows.length?empty('没有匹配观点,请调整分类。'):rows.length>3?'<div class=\"center-action\">'+button('expand',state.expanded?'收起':'展开更多','','primary')+'</div>':'');}\nfunction productHome(data,state){return '<section class=\"product-hero\"><div><h1>'+headline(data)+'</h1><p>'+E(data.description)+'</p>'+link('tour','查看产品演示','primary')+'</div>'+productConsole(data,state)+'</section><section class=\"workflow-section\"><h2>从想法到交付,只需三步。</h2><div>'+[['收集资料','保留材料与来源。'],['确认范围','明确这次要完成什么。'],['完成交付','检查实际成果与下一步。']].map(([h,p],i)=>'<article><b>0'+(i+1)+'</b><h3>'+h+'</h3><p>'+p+'</p></article>').join('')+'</div>'+link('workflow','了解完整工作流','text-link')+'</section>'+plans(data,state)+faq(data)+'<section class=\"signup-band\"><h2>从一个清楚的输入开始。</h2>'+link('signup','生成申请草稿','primary')+'</section>';}\nfunction portfolioHome(data,state){return '<section class=\"portfolio-hero\"><div><small>'+E(data.role)+'</small><h1>'+headline(data)+'</h1><p>'+E(data.bio)+'</p>'+link('projects','浏览我的项目','primary')+link('about','了解更多','secondary')+'</div>'+portfolioMedia(data)+'</section><section><div class=\"section-heading\"><h2>精选项目</h2>'+link('projects','所有项目')+'</div>'+data.projects.map(p=>projectCard(data,p)).join('')+'</section><section class=\"portfolio-bottom\"><div><h2>工作经历</h2>'+data.experiences.map(x=>'<p>'+E(x.dates)+'<strong>'+E(x.title)+'</strong></p>').join('')+link('experience','更多经历')+'</div><div><h2>最新写作</h2>'+data.articles.slice(0,2).map(a=>link('article/'+a.id,a.title)).join('')+'</div><div><h2>近期分享</h2>'+data.talks.map(t=>link('talk/'+t.id,t.title)).join('')+'</div></section><section><h2>我使用的工具</h2><div class=\"uses-grid\">'+data.uses.map(u=>'<article><h3>'+E(u.title)+'</h3><p>'+E(u.description)+'</p></article>').join('')+'</div></section>';}\nfunction articlePage(data,a,state){if(!a)return notFound();return '<div class=\"article-layout\"><article>'+title(a.title,a.date+' · '+a.category+' · 示例文章')+img(data,a.image,a.title)+'<div class=\"article-body\">'+(a.sections||[]).map(s=>'<section id=\"section-'+E(s.id)+'\"><h2>'+E(s.title)+'</h2><p>'+E(s.body)+'</p></section>').join('')+'</div>'+button('save',state.saved.includes(a.id)?'取消收藏':'收藏文章',a.id,'secondary')+'</article><aside><h2>文章目录</h2>'+(a.sections||[]).map(s=>button('scroll',s.title,'section-'+s.id,'text-button')).join('')+'<h2>继续阅读</h2>'+data.articles.filter(b=>b.id!==a.id).slice(0,3).map(b=>link('article/'+b.id,b.title)).join('')+'</aside></div>';}\nfunction productPage(data,p,state){if(!p)return notFound();return '<div class=\"product-detail\"><div>'+img(data,p.image,p.title,'product-main-image')+'<div class=\"product-gallery\">'+(p.gallery||[p.image]).map(key=>'<button type=\"button\" data-action=\"gallery\" data-value=\"'+E(key)+'\">'+img(data,key,p.title+'的图像')+'</button>').join('')+'</div></div><section>'+title(p.title,p.description)+'<p class=\"price\">示例价格 '+money(p.price)+'</p><label>颜色<select data-control=\"colour\">'+(p.colour||'默认样例').split('/').map(c=>'<option>'+E(c.trim())+'</option>').join('')+'</select></label>'+(p.sizes?.length?'<label>尺码<select data-control=\"size\">'+p.sizes.map(s=>'<option>'+E(s)+'</option>').join('')+'</select></label>':'')+'<label>数量<input data-control=\"quantity\" type=\"number\" min=\"1\" max=\"99\" value=\"1\" aria-label=\"数量\"></label>'+button('add-cart','加入选购清单',p.id,'primary')+button('save',state.saved.includes(p.id)?'取消收藏':'收藏款式',p.id,'secondary')+'<details open><summary>产品信息</summary><p>'+E(p.materials||p.description)+'</p></details><details><summary>使用与适用边界</summary><p>'+E(p.care||'虚构商品,仅用于结构与交互示例,不在此销售。')+'</p></details>'+ (data.kind==='store'?link('size','尺码参考'):'')+'</section></div><section><h2>相关商品</h2><div class=\"product-grid\">'+data.products.filter(x=>x.id!==p.id).slice(0,3).map(x=>productCard(data,x)).join('')+'</div></section>';}\nfunction cartPage(data,state,checkout=false){const rows=cartRows(data,state.cart),subtotal=cartTotal(data,state.cart),fee=state.delivery==='express'?18:0,discount=state.promo==='DEMO'?Math.round(subtotal*10)/100:0,total=subtotal+fee-discount;return title(checkout?'演示结算':'我的选购清单','这里只保存本地选款信息,不发起支付。')+(!rows.length?empty('清单为空,先选择一件样例商品。')+link('shop','浏览商品','primary'):'<div class=\"cart-layout\"><div>'+rows.map(row=>'<article class=\"cart-row\">'+img(data,row.product.image,row.product.title)+'<div><h3>'+E(row.product.title)+'</h3><p>'+E(row.size)+' '+E(row.colour)+'</p><span>'+money(row.product.price)+'</span></div><label>数量<input data-cart-quantity=\"'+E(row.id)+'\" data-cart-size=\"'+E(row.size)+'\" data-cart-colour=\"'+E(row.colour||'')+'\" type=\"number\" min=\"1\" max=\"99\" value=\"'+row.quantity+'\"></label>'+button('remove-cart','删除',JSON.stringify([row.id,row.size||'',row.colour||'']),'text-button')+'</article>').join('')+(checkout?draftForm(data,'checkout'):'')+'</div><aside><h2>演示摘要</h2><p>商品合计 <b>'+money(subtotal)+'</b></p><label>配送<select data-control=\"delivery\"><option value=\"standard\"'+(state.delivery==='standard'?' selected':'')+'>标准示例 · ¥0</option><option value=\"express\"'+(state.delivery==='express'?' selected':'')+'>加急示例 · ¥18</option></select></label><label>演示优惠码<input data-control=\"promo\" maxlength=\"20\" value=\"'+E(state.promo)+'\" placeholder=\"DEMO\"></label>'+button('apply-promo','应用演示码','','secondary')+'<p>演示减免 <b>'+money(discount)+'</b></p><p>演示总额 <strong>'+money(total)+'</strong></p>'+button('update-cart','更新清单','','secondary')+button('export-cart','导出选购清单','','primary')+(checkout?'<button disabled>支付未接通(不收款)</button>':link('checkout','查看演示结算','secondary'))+'</aside></div>');}\nfunction cvPage(data){return '<article class=\"cv-page\">'+title(data.brand,data.role)+'<p>'+E(data.contactEmail)+' · '+E(data.location)+'</p><section><h2>个人简介</h2><p>'+E(data.bio)+'</p></section><section><h2>工作经历</h2>'+data.experiences.map(x=>'<div><strong>'+E(x.dates)+' / '+E(x.title)+'</strong><p>'+E(x.company)+' · '+E(x.description)+'</p></div>').join('')+'</section><section><h2>教育与实践</h2>'+data.education.map(x=>'<p>'+E(x.dates)+' / '+E(x.title)+' · '+E(x.description)+'</p>').join('')+'</section><section><h2>技能与工具</h2><p>'+data.skills.map(s=>E(s.title)).join(' / ')+'</p></section><small>虚构人物与内容,仅用于展示可打印 CV 结构。</small></article><div class=\"print-actions\">'+button('print','打印简历','','primary')+'</div>';}\nfunction notFound(){return title('没有找到这个页面。','回到一个清楚的入口,再继续。')+link('home','返回主页','primary');}\n\nexport function renderWebPage(data,state){const route=resolveRoute(data,state.route),kind=route.kind,id=route.id;if(!route.found)return shell(data,state,notFound(),route);if(data.kind==='admin')return renderAdmin(data,state,route);\n let body='';\n if(kind==='home')body=({store:storeHome,magazine:magazineHome,resume:resumeHome,hero:heroHome,wall:wallHome,dark:productHome,light:productHome,portfolio:portfolioHome}[data.kind])(data,state);\n else if(kind==='article'&&id)body=articlePage(data,data.articles.find(a=>a.id===id),state);\n else if(kind==='product'&&id)body=productPage(data,data.products.find(p=>p.id===id),state);\n else if(['shop','product','wishlist'].includes(kind)){let rows=filteredRows(data.products,state.query,state.category,state.sort);if(kind==='wishlist')rows=rows.filter(r=>state.saved.includes(r.id));body=title(kind==='wishlist'?'收藏款式':'所有商品','虚构商品与价格,仅展示结构。')+filters(data.products,state,'搜索商品')+'<div class=\"product-grid\">'+rows.map(p=>productCard(data,p)).join('')+'</div>'+(!rows.length?empty('没有匹配商品。'):'');}\n else if(kind==='collection'||kind==='collections'){const categories=[...new Set(data.products.map(p=>p.category))];body=title(id||'探索系列','按实际场景组织产品,不用一张模板替代所有商品。')+(id?'<div class=\"product-grid\">'+data.products.filter(p=>p.category===id).map(p=>productCard(data,p)).join('')+'</div>':'<div class=\"collection-grid\">'+categories.map(c=>'<article><h2>'+E(c)+'</h2><p>'+data.products.filter(p=>p.category===c).length+' 件样例商品</p>'+link('collection/'+c,'浏览系列','primary')+'</article>').join('')+'</div>');}\n else if(['cart','bag','checkout'].includes(kind))body=cartPage(data,state,kind==='checkout');\n else if(['stories','topics','topic','archive','saved','writing','article'].includes(kind)){let rows=filteredRows(data.articles,state.query,id||state.category,state.sort);if(kind==='saved')rows=rows.filter(a=>state.saved.includes(a.id));body=title(id||ROUTE_LABELS[kind],data.isSample?'文章与人物均为独立编写的结构示例。':'文章来自输入资料,发布前核对来源与授权。')+filters(data.articles,state,'搜索故事或主题')+'<div class=\"editorial-grid\">'+rows.map(a=>articleCard(data,a)).join('')+'</div>'+(!rows.length?empty('没有找到匹配文章。'):'');}\n else if(kind==='issues')body=title('期刊样例','每一期拥有自己的内容、封面和入口。')+'<div class=\"product-grid\">'+data.products.map(p=>productCard(data,p)).join('')+'</div>'+link('stories','阅读文章档案','secondary');\n else if(kind==='project'&&id){const p=data.projects.find(p=>p.id===id);body=p?title(p.title,p.description)+projectWindow(data,p)+'<div class=\"case-sections\">'+[['问题',p.problem],['选择',p.decision],['示例成果',p.result]].map(([h,b])=>'<section><h2>'+h+'</h2><p>'+E(b)+'</p></section>').join('')+'</div>'+link('projects','返回项目','secondary'):notFound();}\n else if(kind==='projects'||kind==='project'||kind==='repos'){const rows=filteredRows(data.projects,state.query,state.category);body=title('我的项目','从输入、选择与结果说明一个项目。')+filters(data.projects,state,'搜索项目')+rows.slice(0,state.expanded?rows.length:2).map(p=>projectCard(data,p)).join('')+(rows.length>2?button('expand',state.expanded?'收起':'展开更多','','secondary'):'')+(!rows.length?empty('没有匹配项目。'):'');}\n else if(kind==='role'&&id){const x=data.experiences.find(x=>x.id===id);body=x?title(x.title,x.company)+'<article class=\"reading-page\"><small>'+E(x.dates)+'</small><h2>参与的工作</h2><p>'+E(x.description)+'</p><h2>如何描述真实经历</h2><p>替换为自己的职责、选择和交付物。没有资料支持的成绩与评价,不把它写成事实。</p>'+link('experience','返回经历','secondary')+'</article>':notFound();}\n else if(kind==='experience'||kind==='role')body=title('我的经历','日期、组织与成果需要来自真实资料。')+'<div class=\"experience-rail\">'+data.experiences.map(x=>'<article><small>'+E(x.dates)+'</small><h2>'+E(x.title)+'</h2><p>'+E(x.company)+'</p><p>'+E(x.description)+'</p>'+link('role/'+x.id,'查看详情')+'</article>').join('')+'</div>';\n else if(kind==='education'||kind==='skills'||kind==='uses'){const rows=kind==='education'?data.education:kind==='skills'?data.skills:data.uses;body=title(ROUTE_LABELS[kind],'用实际材料展示能力与方法。')+'<div class=\"uses-grid\">'+rows.map(x=>'<article><small>'+E(x.dates||x.category)+'</small><h2>'+E(x.title)+'</h2><p>'+E(x.description)+'</p></article>').join('')+'</div>'+(kind==='skills'?'<h2>日常工具</h2>'+data.uses.map(u=>'<p>'+E(u.title)+' · '+E(u.description)+'</p>').join(''):'');}\n else if(kind==='kind-words'||kind==='reviews')body=title('示例观点','不是已经获得的真实客户评价。')+'<div class=\"quote-wall\">'+data.quotes.map(q=>quoteCard(data,q)).join('')+'</div>';\n else if(kind==='cv')body=cvPage(data);\n else if(kind==='talk'&&id){const t=data.talks.find(t=>t.id===id);body=t?title(t.title,t.date)+'<article class=\"reading-page\"><p>'+E(t.description)+'</p><ol>'+(t.notes||[]).map(p=>'<li>'+E(p)+'</li>').join('')+'</ol>'+link('talks','返回分享','secondary')+'</article>':notFound();}\n else if(kind==='talks'||kind==='talk')body=title('分享与备注','每次表达都留下可继续使用的源稿。')+data.talks.map(t=>'<article class=\"release-row\">'+link('talk/'+t.id,t.title)+'<p>'+E(t.description)+'</p><small>'+E(t.date)+'</small></article>').join('');\n else if(kind==='contact'||kind==='signup'||kind==='newsletter'||kind==='signin'||kind==='account')body=title(kind==='contact'?'联系草稿':kind==='signin'||kind==='account'?'演示账户':'生成申请草稿','无需密码,不创建真实账户,也不会发送消息。')+'<div class=\"form-layout\">'+draftForm(data,kind)+'<aside><h2>清楚说明下一步</h2><p>填写后只生成本地草稿。正式上线需要自己的服务、权限和明确授权。</p><p>联系示例:'+E(data.contactEmail)+'</p>'+button('copy-email','复制示例邮箱','','secondary')+'</aside></div>';\n else if(kind==='pricing')body=title('示例方案','这里只比较结构,不收款。')+plans(data,state)+faq(data);\n else if(kind==='features'||kind==='workflow'||kind==='tour'){body=title(kind==='features'?'把流程说清楚':kind==='workflow'?'从资料到交付':'产品导览','这是本地可操作的界面,不是已接通的 SaaS。')+'<div class=\"tour-tabs\">'+['收集资料','组织计划','查看交付'].map((v,i)=>button('tab',v,String(i),state.tab===String(i)?'selected':'')).join('')+'</div>'+board(data,state)+'<section class=\"reading-page\"><h2>'+['保留输入与来源','明确状态和下一步','检查实际文件'][Number(state.tab)||0]+'</h2><p>用自己的资料替换示例内容;接入真实用户与服务时,数据、权限和状态必须由服务器验证。</p></section>';}\n else if(kind==='changelog'||kind==='release'){const rows=id?data.releases.filter(r=>r.id===id):filteredRows(data.releases,state.query,state.category,'latest');body=title(id?'更新详情':'产品更新','此处为结构示例,不是已上线产品的发布日志。')+(id?'':filters(data.releases,state,'搜索更新'))+rows.map(r=>'<article class=\"release-row\"><small>'+E(r.date)+' · '+E(r.category)+'</small><h2>'+E(r.title)+'</h2><p>'+E(r.description)+'</p>'+(!id?link('release/'+r.id,'查看详情'):'')+'</article>').join('')+(!rows.length?empty('没有匹配更新。'):'');}\n else if(kind==='status')body=title('示例状态','不是实际服务监控,也不代表生产系统健康。')+'<div class=\"uses-grid\">'+['资料视图','交付视图','本地表单'].map(v=>'<article><h2>'+v+'</h2><p>本地交互样例可用</p><small>无远程服务连接</small></article>').join('')+'</div>';\n else if(kind==='faq')body=title('常见问题','保留真实的适用范围与交付边界。')+faq(data);\n else if(kind==='size')body=title('尺码参考','只示范工具结构,实际尺码应按产品资料核验。')+'<section class=\"reading-page\"><label>脚长示例(cm)<input data-control=\"footLength\" type=\"number\" min=\"20\" max=\"32\" step=\"0.1\" value=\"24\"></label>'+button('size-guide','查看示例参考','','primary')+'<p id=\"sizeResult\">这不是实际产品的尺码建议。</p><div class=\"size-table\">'+['36','37','38','39','40','41','42','43'].map(s=>'<span>'+s+'</span>').join('')+'</div></section>';\n else if(kind==='shipping')body=title('配送方式示例','费用与时效需要来自实际商户资料,此处不承诺服务。')+'<div class=\"uses-grid\"><article><h2>标准示例</h2><p>演示费用 ¥0</p><p>用于查看清单总额如何变化。</p></article><article><h2>加急示例</h2><p>演示费用 ¥18</p><p>不是实际配送服务。</p></article></div>'+link('cart','查看选购清单','primary');\n else if(kind==='story'||kind==='about')body=title('关于 '+data.brand,'把一个具体问题,变成清楚的入口。')+'<div class=\"story-split\">'+img(data,data.kind==='store'?'store-hero':data.kind==='portfolio'?'portrait-3':'desk','独立制作的结构示例照片')+'<article><h2>从自己的资料开始</h2><p>'+E(data.bio)+'</p><p>这里的品牌、人物、价格、日期与观点均为样例,不表示真实经营、就业或客户经历。</p><p>实际使用时保留原始材料,确认内容、来源和适用范围,再连接自己的服务。</p>'+link('contact','生成联系草稿','primary')+'</article></div>';\n else if(kind==='privacy'||kind==='terms'||kind==='guide')body=title(ROUTE_LABELS[kind],'本地原型的使用说明,不代替正式服务协议。')+'<article class=\"reading-page\"><h2>数据与动作</h2><p>数据在当前页面处理。表单不会发送消息,清单不会付款,演示账户没有真实权限。分享前确认导出文件中不包含不应公开的资料。</p><h2>内容与许可</h2><p>代码与样例由 PIKI 独立制作,按包内 MIT 许可使用。替换真实人物、商品、公司与数据时,请使用自己的材料并保留来源。</p><h2>正式发布前</h2><p>检查所有页面、状态、表单、键盘和手机端。真实账户、交易、退款、消息与业务记录需要正确的后端验证与用户授权。</p>'+button('edit-data','编辑资料','','primary')+' '+button('export-data','保存 JSON','','secondary')+'</article>';\n else body=notFound();\n return shell(data,state,body,route);\n}\n\nfunction lineChart(values,label){const max=Math.max(1,...values),points=values.map((v,i)=>[40+i*520/Math.max(1,values.length-1),190-v/max*150]),path=points.map(([x,y],i)=>(i?'L':'M')+x+' '+y).join(' ');return '<svg viewBox=\"0 0 600 230\" role=\"img\" aria-label=\"'+E(label)+'\"><path d=\"M40 30V190H570\" fill=\"none\" stroke=\"currentColor\" opacity=\".2\"/><path d=\"'+path+' L560 190 L40 190Z\" fill=\"var(--accent)\" opacity=\".1\"/><path d=\"'+path+'\" fill=\"none\" stroke=\"var(--accent)\" stroke-width=\"3\"/>'+points.map(([x,y],i)=>'<circle cx=\"'+x+'\" cy=\"'+y+'\" r=\"4\" fill=\"var(--accent)\"><title>'+E(label)+':'+values[i]+'</title></circle>').join('')+'</svg>';}\nfunction groupedBars(data){const rows=customerActivity(data),max=Math.max(1,...rows.map(r=>r.active));if(!rows.length)return empty('没有输入访问日期记录。');return '<svg viewBox=\"0 0 620 245\" role=\"img\" aria-label=\"模拟访问日期中的新增与访问客户\">'+rows.map((r,i)=>{const x=30+i*560/rows.length,w=Math.min(26,200/rows.length);return '<rect x=\"'+x+'\" y=\"'+(195-r.new/max*145)+'\" width=\"'+w+'\" height=\"'+(r.new/max*145)+'\" fill=\"currentColor\" opacity=\".3\"/><rect x=\"'+(x+w+4)+'\" y=\"'+(195-r.active/max*145)+'\" width=\"'+w+'\" height=\"'+(r.active/max*145)+'\" fill=\"var(--accent)\"/><text x=\"'+x+'\" y=\"220\" fill=\"currentColor\" font-size=\"10\">'+E(r.month)+'</text>';}).join('')+'</svg><p>浅色:首次记录 · 强调色:有访问记录。只针对输入日期。</p>';}\nfunction retention(data){const rows=retentionRows(data);return rows.length?'<div class=\"retention-grid\"><header><span>首次记录月</span>'+['当月','+1 月','+2 月','+3 月'].map(v=>'<span>'+v+'</span>').join('')+'</header>'+rows.map(r=>'<div><strong>'+E(r.month)+'</strong>'+r.values.map(v=>'<span data-level=\"'+(v===null?'unknown':Math.floor(v/25))+'\">'+(v===null?'—':v+'%')+'</span>').join('')+'</div>').join('')+'</div><p>示例访问记录覆盖率;输入缺失不证明用户流失,超出记录窗口标为未知。</p>':empty('没有可计算的访问记录。');}\nfunction spendDonut(data){const rows=data.transactions.filter(r=>r.category==='支出'&&r.amount>0),total=rows.reduce((n,r)=>n+r.amount,0);if(!total)return empty('没有模拟支出。');let offset=0;return '<svg viewBox=\"0 0 270 180\" role=\"img\" aria-label=\"模拟支出记录分布\"><circle cx=\"105\" cy=\"90\" r=\"60\" fill=\"none\" stroke=\"currentColor\" opacity=\".12\" stroke-width=\"23\"/>'+rows.map((r,i)=>{const portion=r.amount/total*376.99,s='<circle cx=\"105\" cy=\"90\" r=\"60\" fill=\"none\" stroke=\"var(--accent)\" opacity=\"'+(1-i*.13)+'\" stroke-width=\"23\" stroke-dasharray=\"'+portion+' '+(376.99-portion)+'\" stroke-dashoffset=\"'+(-offset)+'\" transform=\"rotate(-90 105 90)\"><title>'+E(r.title)+':'+money(r.amount)+'</title></circle>';offset+=portion;return s;}).join('')+'<text x=\"105\" y=\"96\" text-anchor=\"middle\" fill=\"currentColor\" font-size=\"17\">'+money(total)+'</text></svg>'+rows.map(r=>'<p>'+E(r.title)+' · '+money(r.amount)+'</p>').join('');}\nfunction customerTable(data,state){const rows=filteredRows(data.customers,state.query,state.category,state.sort),pages=Math.max(1,Math.ceil(rows.length/state.pageSize)),page=Math.min(state.page,pages),selected=new Set(state.selectedCustomers);return '<div class=\"table-tools\">'+filters(data.customers,state,'搜索客户')+'<div>'+button('new-customer','新增模拟客户','','primary')+'<select data-control=\"bulkStatus\" aria-label=\"批量状态\"><option value=\"\">批量操作</option>'+['待跟进','活跃','暂停'].map(s=>'<option>'+s+'</option>').join('')+'</select>'+button('undo','撤销上一次','','secondary')+'</div></div><div class=\"table-scroll\"><table><thead><tr><th>选择</th><th>'+button('sort-customers','名称')+'</th><th>状态</th><th>邮箱示例</th><th>组织</th><th>详情</th></tr></thead><tbody>'+rows.slice((page-1)*state.pageSize,page*state.pageSize).map(r=>'<tr><td><input type=\"checkbox\" data-customer-check=\"'+E(r.id)+'\" aria-label=\"选择'+E(r.name)+'\"'+(selected.has(r.id)?' checked':'')+'></td><td>'+E(r.name)+'</td><td><span class=\"status-tag\">'+E(r.status)+'</span></td><td>'+E(r.email)+'</td><td>'+E(r.company)+'</td><td>'+button('customer','查看',r.id,'text-button')+'</td></tr>').join('')+'</tbody></table></div>'+(!rows.length?empty('没有匹配客户。'):'')+'<div class=\"pagination\">'+button('page','上一页',String(Math.max(1,page-1)))+'<span>'+page+' / '+pages+'</span>'+button('page','下一页',String(Math.min(pages,page+1)))+'</div>';}\nfunction adminOverview(data,state){const end=[...data.tasks.map(t=>t.date).filter(Boolean)].sort().at(-1)||state.selectedDay,range=Number(state.chartRange)||7,values=[];for(let offset=range-1;offset>=0;offset--){const date=new Date(Date.parse(end+'T00:00:00Z')-offset*86400000).toISOString().slice(0,10);values.push(data.tasks.filter(t=>t.date===date).length);}return '<div class=\"admin-stats\">'+[['客户记录',data.customers.length],['任务记录',data.tasks.length],['本月事件',data.events.filter(e=>e.date.startsWith(state.year+'-'+String(state.month).padStart(2,'0'))).length],['账本记录',data.transactions.length]].map(([h,n])=>'<article><small>'+h+'</small><strong>'+n+'</strong></article>').join('')+'</div><div class=\"admin-overview-grid\"><section class=\"panel\"><div class=\"section-heading\"><h2>任务日期分布</h2><select data-control=\"chartRange\" aria-label=\"图表时间范围\"><option value=\"7\"'+(range===7?' selected':'')+'>7 天</option><option value=\"30\"'+(range===30?' selected':'')+'>30 天</option></select></div>'+lineChart(values,'按输入日期的任务数')+'<small>按任务日期统计,不是实际经营趋势。</small></section><section class=\"panel\"><div class=\"section-heading\"><h2>客户记录 ('+data.customers.length+')</h2>'+link('customers','查看全部','text-link')+'</div><div class=\"table-scroll\"><table><thead><tr><th>名称</th><th>状态</th><th>邮箱示例</th><th>详情</th></tr></thead><tbody>'+data.customers.slice(0,6).map(c=>'<tr><td>'+E(c.name)+'</td><td><span class=\"status-tag\">'+E(c.status)+'</span></td><td>'+E(c.email)+'</td><td>'+button('customer','查看',c.id,'text-button')+'</td></tr>').join('')+'</tbody></table></div></section></div><div class=\"overview-summary\"><section class=\"panel\"><div class=\"section-heading\"><h2>任务列表 ('+data.tasks.length+')</h2>'+button('new-task','新增任务','','text-button')+'</div>'+data.tasks.map(t=>'<div class=\"summary-row\"><strong>'+E(t.title)+'</strong><select data-task-status=\"'+E(t.id)+'\" aria-label=\"'+E(t.title)+'的状态\">'+['待整理','进行中','已完成'].map(s=>'<option'+(s===t.status?' selected':'')+'>'+s+'</option>').join('')+'</select><small>'+E(t.date)+'</small></div>').join('')+'</section><section class=\"panel\"><div class=\"section-heading\"><h2>日历事件 ('+data.events.length+')</h2>'+link('calendar','查看日历','text-link')+'</div>'+data.events.map(e=>'<div class=\"summary-row\"><strong>'+E(e.title)+'</strong><small>'+E(e.date)+' '+E(e.time)+'</small></div>').join('')+'</section><section class=\"panel\"><div class=\"section-heading\"><h2>示例账本 ('+data.transactions.length+')</h2>'+link('finance','查看记录','text-link')+'</div>'+data.transactions.map(t=>'<div class=\"summary-row\"><strong>'+E(t.title)+'</strong><span>'+E(t.category)+' '+money(t.amount)+'</span><small>'+E(t.date)+'</small></div>').join('')+'<small>不发生真实收款或出款。</small></section></div><section class=\"panel\"><div class=\"section-heading\"><h2>项目看板</h2>'+link('roadmap','打开看板','text-link')+'</div>'+board(data,state,true)+'</section>';}\nfunction calendar(data,state){const days=monthGrid(state.year,state.month),agenda=data.events.filter(e=>e.date===state.selectedDay);return '<div class=\"calendar-controls\">'+button('month','上月','-1')+'<h2>'+state.year+' 年 '+state.month+' 月</h2>'+button('month','下月','1')+button('new-event','新增模拟事件','','primary')+'</div><div class=\"calendar-layout\"><div class=\"month-grid\">'+['一','二','三','四','五','六','日'].map(d=>'<strong>'+d+'</strong>').join('')+days.map(date=>date?'<button data-action=\"day\" data-value=\"'+date+'\" class=\"'+(date===state.selectedDay?'selected':'')+'\"><b>'+Number(date.slice(-2))+'</b><small>'+data.events.filter(e=>e.date===date).length+' 事件</small></button>':'<span></span>').join('')+'</div><aside><h3>'+E(state.selectedDay)+'</h3>'+agenda.map(e=>'<article><strong>'+E(e.time)+' '+E(e.title)+'</strong><p>'+E(e.description)+'</p>'+button('event','编辑',e.id,'text-button')+'</article>').join('')+(!agenda.length?empty('这一天没有模拟事件。'):'')+'</aside></div>';}\nfunction renderAdmin(data,state,route){const page=route.kind==='home'?'overview':route.kind;let body=title(ROUTE_LABELS[page]||route.label,'模拟数据,不连接真实账户。');\n if(page==='overview')body+=adminOverview(data,state);\n else if(page==='customers')body+=customerTable(data,state);\n else if(page==='roadmap')body+=board(data,state);\n else if(page==='calendar')body+=calendar(data,state);\n else if(page==='finance'){const n=ledgerTotals(data);body+='<div class=\"admin-stats\">'+[['模拟收入',n.income],['模拟支出',n.expense],['模拟结余',n.balance]].map(([h,v])=>'<article><small>'+h+'</small><strong>'+money(v)+'</strong></article>').join('')+'</div><div class=\"analytics-chart-grid\"><section class=\"panel\"><h2>现金流示例</h2>'+lineChart(cashflowMonths(data).flatMap(r=>[r.income,r.expense]),'输入月份的模拟收支')+'<p>仅来自本地记录,不代表已到账或已支付。</p></section><section class=\"panel spend-breakdown\"><h2>模拟支出分布</h2>'+spendDonut(data)+'</section></div><div class=\"panel\"><h2>本地账本记录</h2><p>只展示输入记录,不发生收款、出款或对账。</p>'+button('new-transaction','新增模拟记录','','primary')+' '+button('export-ledger','导出 CSV','','secondary')+'<div class=\"table-scroll\"><table><thead><tr><th>日期</th><th>项目</th><th>类别</th><th>模拟金额</th><th>备注</th></tr></thead><tbody>'+data.transactions.map(r=>'<tr><td>'+E(r.date)+'</td><td>'+E(r.title)+'</td><td>'+E(r.category)+'</td><td>'+money(r.amount)+'</td><td>'+E(r.note)+'</td></tr>').join('')+'</tbody></table></div></div>';\n }\n else if(page==='analytics')body+='<div class=\"analytics-chart-grid\"><section class=\"panel\"><h2>新增与访问记录</h2>'+groupedBars(data)+'</section><section class=\"panel retention-scroll\"><h2>记录覆盖窗口</h2>'+retention(data)+'</section></div><section class=\"panel\"><h2>本月活动日历</h2>'+calendar(data,state)+'</section>';\n else if(page==='settings')body+='<form data-form=\"settings\" class=\"settings-form\"><label>工作台名称<input name=\"brand\" value=\"'+E(data.brand)+'\" required maxlength=\"100\"></label><label>说明<textarea name=\"description\">'+E(data.description)+'</textarea></label><label>显示主题<select name=\"theme\"><option value=\"light\"'+(state.theme==='light'?' selected':'')+'>浅色</option><option value=\"dark\"'+(state.theme==='dark'?' selected':'')+'>深色</option></select></label><label>强调色<select name=\"preset\"><option value=\"slate\"'+(state.preset==='slate'?' selected':'')+'>石板</option><option value=\"tangerine\"'+(state.preset==='tangerine'?' selected':'')+'>橘色</option></select></label><button class=\"primary\">应用本地设置</button><p class=\"form-result\" role=\"status\"></p></form>'+button('export-data','保存完整 JSON','','secondary')+' '+button('reset-demo','重置本地演示','','secondary');\n else if(['guide','privacy','terms','contact','about'].includes(page))body+='<article class=\"reading-page\"><h2>这是本地原型</h2><p>没有真实用户权限、支付、消息或外部账户连接。输入记录不等于业务系统的权威数据。</p><h2>正式接入之前</h2><p>客户、交易与权限必须由服务器验证,不能把前端状态当作业务真相。分享前移除不应公开的资料。</p>'+button('edit-data','编辑资料','','primary')+' '+button('export-data','保存 JSON','','secondary')+'</article>';\n else body=notFound();\n return '<div class=\"admin-app '+(state.sidebarCollapsed?'sidebar-collapsed':'')+'\"><aside class=\"admin-sidebar\"><strong>'+E(data.brand)+'</strong><small>PIKI 示例 · 本地交互</small><nav aria-label=\"管理视图\">'+mainNavigation(data).map(n=>link(n.path,n.label,n.path===page?'active':'')).join('')+'</nav><p>模拟数据,不连接真实账户。</p>'+button('sidebar','收起/展开侧栏','','text-button')+'</aside><div><header class=\"admin-toolbar\">'+button('search','搜索视图 (Ctrl K)')+button('theme',state.theme==='dark'?'浅色':'深色')+button('export-data','导出数据','','primary')+'</header><main class=\"admin-content\" data-route=\"'+E(route.path)+'\">'+body+'</main><footer class=\"admin-footer\">'+E(data.brand)+' · 本地结构样例</footer></div></div>';\n}\n","import {getWebTool,validateWebData,E,cartRows,cartTotal,csvValue,isDate,routeInventory} from './model.js';\nimport {initialWebState,resolveRoute,ROUTE_LABELS,addCartItem,changeTaskStatus,updateCustomerStatuses,undoCustomerStatuses} from './route-model.js';\nimport {renderWebPage} from './renderers.js';\nconst payload=JSON.parse(document.getElementById('webData').content.textContent),tool=getWebTool(payload.tool);\nlet data=validateWebData(payload.data,tool.id),state=initialWebState(data),wallFrame=0,recordEdit=null;\nconst $=id=>document.getElementById(id),notify=text=>{$('webStatus').textContent=text;};\nfunction download(value,type,name){const url=URL.createObjectURL(new Blob([value],{type})),a=document.createElement('a');a.href=url;a.download=name;document.body.append(a);a.click();a.remove();setTimeout(()=>URL.revokeObjectURL(url),3000);notify('已导出 '+name+'。');}\nconst hasMotion=()=>state.motion&&!window.matchMedia('(prefers-reduced-motion:reduce)').matches;\nfunction drawWall(){cancelAnimationFrame(wallFrame);const canvas=$('wallCanvas');if(!canvas)return;const width=canvas.clientWidth,height=canvas.clientHeight;canvas.width=width*devicePixelRatio;canvas.height=height*devicePixelRatio;const ctx=canvas.getContext('2d');ctx.scale(devicePixelRatio,devicePixelRatio);let t=0;function paint(){ctx.clearRect(0,0,width,height);ctx.fillStyle='rgba(100,125,99,.12)';for(let i=0;i<42;i++){const x=(i*97)%Math.max(1,width),y=(i*71)%Math.max(1,height);ctx.beginPath();ctx.arc(x+Math.sin(t+i)*2,y,1.5,0,Math.PI*2);ctx.fill();}if(hasMotion()){t+=.008;wallFrame=requestAnimationFrame(paint);}}paint();}\nfunction render(){\n document.body.dataset.kind=data.kind;document.body.dataset.theme=state.theme;document.body.dataset.preset=state.preset;document.body.classList.toggle('no-motion',!hasMotion());\n $('siteRoot').innerHTML=renderWebPage(data,state);document.title=data.brand+' · '+(resolveRoute(data,state.route).label||tool.name);\n $('demoNotice').textContent=data.isSample?'PIKI 示例 · 本地交互':'PIKI 网页原型 · 表单与交易未接通';\n $('motionToggle').checked=state.motion;$('motionTools').hidden=!['hero','wall','dark','light'].includes(data.kind);drawWall();\n}\nfunction routeChanged(){state.route=decodeRoute(location.hash);state.query='';state.category='';state.page=1;render();window.scrollTo({top:0,behavior:'instant'});}\nfunction decodeRoute(hash){try{return (hash||'#/home').replace(/^#\\/?/,'')?decodeURIComponent((hash||'#/home').replace(/^#\\/?/,'')):'home';}catch{return 'not-found';}}\nwindow.addEventListener('hashchange',routeChanged);\nfunction openDialog(title,body){$('detailTitle').textContent=title;$('detailBody').innerHTML=body;$('detailDialog').showModal();}\nfunction editData(){$('jsonInput').value=JSON.stringify(data,null,2);$('jsonError').textContent='';$('dataDialog').showModal();}\n$('editData').onclick=editData;$('closeData').onclick=()=>$('dataDialog').close();$('closeDetail').onclick=()=>$('detailDialog').close();$('closeSearch').onclick=()=>$('searchDialog').close();\n$('applyData').onclick=()=>{try{if($('jsonInput').value.length>25*1024*1024)throw new Error('数据应小于 25 MB。');const next=validateWebData(JSON.parse($('jsonInput').value),tool.id);data=next;state=initialWebState(data);state.route=decodeRoute(location.hash);render();$('dataDialog').close();notify('资料已在当前页面更新,离开前请导出保存。');}catch(error){$('jsonError').textContent=error instanceof SyntaxError?'JSON 格式不正确,请检查括号与引号。':'无法应用:'+error.message;}};\n$('saveData').onclick=()=>download(JSON.stringify(data,null,2)+'\\n','application/json',tool.id+'-data.json');\n$('motionToggle').onchange=()=>{state.motion=$('motionToggle').checked;render();};$('replayMotion').onclick=()=>{state.motion=true;render();notify('已重播;系统减少动态设置优先。');};\nasync function embeddedData(){const next=JSON.parse(JSON.stringify(data));for(const [key,value]of Object.entries(next.assets)){if(value.startsWith('data:image/'))continue;const url=new URL(value,location.href),directory=new URL('.',location.href);if(url.origin!==directory.origin||!url.pathname.startsWith(directory.pathname+'assets/'))throw new Error('导出仅支持当前目录 assets 中的图片或嵌入图片。');const r=await fetch(url);if(!r.ok)throw new Error('图片未能读取:'+key);const blob=await r.blob();if(!['image/png','image/jpeg','image/webp'].includes(blob.type))throw new Error('不支持的图片类型。');next.assets[key]=await new Promise((resolve,reject)=>{const reader=new FileReader();reader.onload=()=>resolve(reader.result);reader.onerror=reject;reader.readAsDataURL(blob);});}return next;}\n$('saveHtml').onclick=async()=>{try{notify('正在打包本地页面与图片…');const next=await embeddedData(),model=JSON.stringify({...payload,data:next}).replaceAll('<','\\\\u003c').replaceAll('&','&'),runtime=payload.modules.map(s=>s.replace(/^import .*from '\\.\\/[^']+';\\n/gm,'')).join('\\n');const html='<!doctype html><html lang=\"zh-CN\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><title>'+E(next.brand)+'</title><style>'+payload.css+'</style></head><body data-kind=\"'+data.kind+'\" data-theme=\"'+state.theme+'\">'+payload.shell+'<template id=\"webData\">'+model+'</template><script type=\"module\">'+runtime.replaceAll('</script','<\\\\/script')+'</'+'script></body></html>';download(html,'text/html',tool.id+'-site.html');}catch(error){notify('无法导出:'+error.message);}};\nfunction searchEntries(){return [...routeInventory(data).map(path=>({label:ROUTE_LABELS[path.split('/')[0]]||path,path})),...data.customers.map(c=>({label:'客户 · '+c.name,action:'customer',value:c.id})),...data.tasks.map(t=>({label:'任务 · '+t.title,action:'task',value:t.id})),...data.events.map(e=>({label:'日历 · '+e.title,action:'event',value:e.id}))];}\nfunction updateSearch(){const query=$('commandQuery').value.toLowerCase();$('commandResults').innerHTML=searchEntries().filter(e=>e.label.toLowerCase().includes(query)||e.path?.toLowerCase().includes(query)).slice(0,30).map(e=>e.path?'<a href=\"#/'+e.path.split('/').map(encodeURIComponent).join('/')+'\">'+E(e.label)+'</a>':'<button type=\"button\" data-action=\"'+e.action+'\" data-value=\"'+E(e.value)+'\">'+E(e.label)+'</button>').join('')||'<p>没有匹配入口。</p>';}\nfunction openSearch(){$('commandQuery').value='';updateSearch();$('searchDialog').showModal();$('commandQuery').focus();}\n$('commandQuery').oninput=updateSearch;$('commandResults').addEventListener('click',event=>{if(event.target.closest('a,button'))$('searchDialog').close();});\nfunction recordForm(type,id=''){const collection={customer:'customers',task:'tasks',event:'events',transaction:'transactions',article:'articles'}[type],row=data[collection].find(r=>r.id===id)||{};recordEdit={type,collection,id};let inputs='';const field=(name,label,kind='text',required=true)=>'<label>'+label+'<input name=\"'+name+'\" type=\"'+kind+'\" value=\"'+E(row[name]||'')+'\"'+(required?' required':'')+' maxlength=\"500\"></label>';\n if(type==='customer')inputs=field('name','名称')+field('email','邮箱','email')+field('company','组织','text',false)+'<label>状态<select name=\"status\">'+['待跟进','活跃','暂停'].map(s=>'<option'+(s===row.status?' selected':'')+'>'+s+'</option>').join('')+'</select></label>'+field('note','备注','text',false);\n if(type==='task')inputs=field('title','任务标题')+field('description','说明','text',false)+field('owner','负责示例','text',false)+field('date','日期','date')+'<label>状态<select name=\"status\">'+['待整理','进行中','已完成'].map(s=>'<option'+(s===(row.status||recordEdit.defaultStatus)?' selected':'')+'>'+s+'</option>').join('')+'</select></label>';\n if(type==='event')inputs=field('title','事件标题')+field('date','日期','date')+field('time','时间','time',false)+field('description','说明','text',false);\n if(type==='transaction')inputs=field('title','记录名称')+field('date','日期','date')+'<label>类别<select name=\"category\"><option>收入</option><option>支出</option></select></label>'+field('amount','模拟金额','number')+field('note','备注','text',false);\n if(type==='article')inputs=field('title','资料标题')+field('date','日期(未知可留空)','date',false)+field('description','说明','text',false);\n openDialog((id?'编辑':'新增')+'模拟记录','<form data-form=\"record\" class=\"record-form\">'+inputs+'<button type=\"submit\" class=\"primary\">保存本地记录</button><p class=\"form-result\" role=\"status\"></p></form>');\n}\nasync function copyEmail(){try{await navigator.clipboard.writeText(data.contactEmail);notify('已复制联系邮箱。');}catch{openDialog('联系邮箱','<p>'+E(data.contactEmail)+'</p><p>复制权限不可用,可手动选择文字。</p>');}}\nasync function action(name,value,target){\n if(name==='search')openSearch();else if(name==='theme'){state.theme=state.theme==='dark'?'light':'dark';render();}\n else if(name==='edit-data')editData();else if(name==='export-data')$('saveData').click();\n else if(name==='gallery'){const image=document.querySelector('.product-main-image');if(image&&data.assets[value])image.src=data.assets[value];}\n else if(name==='category'){state.category=value;state.page=1;render();}\n else if(name==='save'){const at=state.saved.indexOf(value);if(at<0)state.saved.push(value);else state.saved.splice(at,1);render();notify(at<0?'已加入本地收藏。':'已取消收藏。');}\n else if(name==='add-cart'){const product=data.products.find(p=>p.id===value);if(!product)return;const size=document.querySelector('[data-control=\"size\"]')?.value||'',colour=document.querySelector('[data-control=\"colour\"]')?.value||'',quantity=Math.max(1,Math.min(99,Number(document.querySelector('[data-control=\"quantity\"]')?.value||1)));for(let i=0;i<quantity;i++)addCartItem(state,product,size,colour);location.hash=data.kind==='magazine'?'#/bag':'#/cart';notify('已加入本地选购清单,不会创建订单。');}\n else if(name==='remove-cart'){const [id,size,colour]=JSON.parse(value);state.cart=state.cart.filter(line=>!(line.id===id&&(line.size||'')===size&&(line.colour||'')===colour));render();}\n else if(name==='apply-promo'){state.promo=(document.querySelector('[data-control=\"promo\"]')?.value||'').trim().toUpperCase();render();notify(state.promo==='DEMO'?'已应用本地演示减免,不影响真实付款。':'仅支持演示码 DEMO,不影响真实付款。');}\n else if(name==='update-cart'){for(const input of document.querySelectorAll('[data-cart-quantity]')){const row=state.cart.find(r=>r.id===input.dataset.cartQuantity&&(r.size||'')===(input.dataset.cartSize||'')&&(r.colour||'')===(input.dataset.cartColour||''));if(row)row.quantity=Math.max(1,Math.min(99,Math.round(Number(input.value)||1)));}render();notify('已更新本地选购清单。');}\n else if(name==='export-cart')download(JSON.stringify({demoOnly:true,items:cartRows(data,state.cart),subtotal:cartTotal(data,state.cart),payment:'not_connected'},null,2),'application/json',tool.id+'-selection.json');\n else if(name==='scroll'){const node=document.getElementById(value);node?.scrollIntoView({behavior:hasMotion()?'smooth':'instant',block:'start'});}\n else if(name==='expand'){state.expanded=!state.expanded;render();}\n else if(name==='quote'){const q=data.quotes.find(q=>q.id===value);if(q)openDialog(q.name,'<blockquote>'+E(q.quote)+'</blockquote><p>'+E(q.role)+' · '+E(q.category)+'</p><h3>出处</h3><p>'+E(q.source)+'</p>');}\n else if(name==='project-demo'){recordForm('article');}\n else if(name==='billing'){state.billing=value==='yearly'?'yearly':'monthly';render();}\n else if(name==='tab'){state.tab=value;render();}\n else if(name==='print')window.print();else if(name==='copy-email')await copyEmail();\n else if(name==='size-guide'){const n=Number(document.querySelector('[data-control=\"footLength\"]')?.value);$('sizeResult').textContent=Number.isFinite(n)&&n>=20&&n<=32?'示例参考:'+Math.round(2*n-10)+'。不是实际产品尺码建议,请按真实规格核验。':'请输入 20–32 的有效示例脚长。';}\n else if(name==='sidebar'){state.sidebarCollapsed=!state.sidebarCollapsed;render();}\n else if(name==='customer'){const c=data.customers.find(c=>c.id===value);if(c)openDialog(c.name,'<dl>'+Object.entries(c).filter(([k])=>k!=='id').map(([k,v])=>'<dt>'+E(k)+'</dt><dd>'+E(Array.isArray(v)?v.join('、'):v)+'</dd>').join('')+'</dl>'+buttonHtml('edit-customer','编辑本地记录',c.id));}\n else if(name==='edit-customer')recordForm('customer',value);else if(name==='new-customer')recordForm('customer');\n else if(name==='task')recordForm('task',value);else if(name==='new-task'){recordForm('task');const select=document.querySelector('#detailBody select[name=\"status\"]');if(select&&value)select.value=value;}\n else if(name==='event')recordForm('event',value);else if(name==='new-event')recordForm('event');else if(name==='new-transaction')recordForm('transaction');\n else if(name==='sort-customers'){state.sort='title';render();}else if(name==='page'){state.page=Number(value)||1;render();}\n else if(name==='undo'){undoCustomerStatuses(data,state);render();notify('已撤销最近一次批量状态修改。');}\n else if(name==='day'){state.selectedDay=value;render();}\n else if(name==='month'){const d=new Date(Date.UTC(state.year,state.month-1+Number(value),1));state.year=d.getUTCFullYear();state.month=d.getUTCMonth()+1;state.selectedDay=d.toISOString().slice(0,10);render();}\n else if(name==='export-ledger'){const keys=['date','title','category','amount','note'],csv='\\uFEFF'+keys.join(',')+'\\n'+data.transactions.map(row=>keys.map(k=>csvValue(row[k])).join(',')).join('\\n');download(csv,'text/csv',tool.id+'-demo-ledger.csv');}\n else if(name==='reset-demo'){data=validateWebData(payload.data,tool.id);state=initialWebState(data);render();notify('已恢复内置样例,未修改任何远程数据。');}\n}\nfunction buttonHtml(actionName,label,value){return '<button type=\"button\" class=\"primary\" data-action=\"'+actionName+'\" data-value=\"'+E(value)+'\">'+E(label)+'</button>';}\ndocument.addEventListener('click',event=>{const target=event.target.closest('[data-action]');if(target){event.preventDefault();action(target.dataset.action,target.dataset.value||'',target).catch(error=>notify('操作未完成:'+error.message));}});\ndocument.addEventListener('input',event=>{const target=event.target;if(target.matches('[data-control=\"query\"]')){const caret=target.selectionStart;state.query=target.value;state.page=1;render();const next=document.querySelector('[data-control=\"query\"]');next?.focus();try{next?.setSelectionRange(caret,caret);}catch{}}});\ndocument.addEventListener('change',event=>{const target=event.target,key=target.dataset.control;if(target.dataset.taskStatus){try{changeTaskStatus(data,target.dataset.taskStatus,target.value);render();}catch(error){notify(error.message);}return;}if(target.dataset.customerCheck){const id=target.dataset.customerCheck;if(target.checked)state.selectedCustomers.push(id);else state.selectedCustomers=state.selectedCustomers.filter(v=>v!==id);return;}if(target.dataset.cartQuantity)return;if(key==='bulkStatus'){if(target.value){updateCustomerStatuses(data,state,target.value);render();notify('只更新本地模拟记录,可撤销。');}}else if(['sort','delivery','chartRange'].includes(key)){state[key]=target.value;render();}});\ndocument.addEventListener('submit',event=>{const form=event.target;if(!form.dataset.form)return;event.preventDefault();if(!form.reportValidity())return;const values=Object.fromEntries(new FormData(form));try{\n if(form.dataset.form==='record'){const row={...values,id:recordEdit.id||'local-'+crypto.randomUUID().slice(0,10)};if(recordEdit.type==='transaction'){row.amount=Number(values.amount);row.status='记录';}if(recordEdit.type==='article'){row.category='本地资料';row.date=values.date||'';row.sections=[{id:'source',title:'说明',body:values.description||'本地添加的结构记录。'}];}const next=JSON.parse(JSON.stringify(data)),rows=next[recordEdit.collection],index=rows.findIndex(r=>r.id===row.id);if(index<0)rows.unshift(row);else rows[index]={...rows[index],...row};data=validateWebData(next,tool.id);$('detailDialog').close();render();notify('已保存本地记录,不会写入远程账户。');}\n else if(form.dataset.form==='settings'){const next=validateWebData({...data,brand:values.brand,description:values.description},tool.id);data=next;state.theme=values.theme==='dark'?'dark':'light';state.preset=values.preset==='tangerine'?'tangerine':'slate';render();notify('设置已应用到当前页面,请导出保存。');}\n else {const type=form.dataset.form;download(JSON.stringify({kind:type,demoOnly:true,fields:values,networkAction:'none'},null,2),'application/json',tool.id+'-'+type+'-draft.json');form.querySelector('.form-result').textContent='已生成本地草稿,不会发送消息、创建账户或付款。';}\n }catch(error){const status=form.querySelector('.form-result');if(status)status.textContent='未保存:'+error.message;else notify(error.message);}});\nlet dragged='';document.addEventListener('dragstart',event=>{const row=event.target.closest('[data-task]');if(row){dragged=row.dataset.task;event.dataTransfer.setData('text/plain',dragged);}});document.addEventListener('dragover',event=>{if(event.target.closest('[data-drop-status]'))event.preventDefault();});document.addEventListener('drop',event=>{const column=event.target.closest('[data-drop-status]');if(column&&dragged){event.preventDefault();changeTaskStatus(data,dragged,column.dataset.dropStatus);dragged='';render();}});\ndocument.addEventListener('keydown',event=>{if((event.ctrlKey||event.metaKey)&&event.key.toLowerCase()==='k'){event.preventDefault();openSearch();}if(event.key==='/'&&!event.target.matches('input,textarea,select')){event.preventDefault();openSearch();}});\nwindow.addEventListener('scroll',()=>{if(!hasMotion())return;for(const el of document.querySelectorAll('[data-tilt]')){const r=el.getBoundingClientRect();const angle=Math.max(0,Math.min(6,r.top/100));el.setAttribute('data-tilt-level',String(Math.round(angle)));}},{passive:true});\nstate.route=location.hash?decodeRoute(location.hash):(payload.initialRoute||'home');render();\n"],"css":"*{box-sizing:border-box}body{margin:0;background:#FAFAF6;color:#242A2C;font:16px/1.6 Inter,-apple-system,BlinkMacSystemFont,\"PingFang SC\",\"Microsoft YaHei\",sans-serif;--surface:#fff;--ink:#242A2C;--muted:#6B7377;--line:#D9DEDD;--accent:#567B63;--soft:#EEF2EB}button,input,select,textarea{font:inherit;color:inherit}button,a{touch-action:manipulation}a{color:inherit;text-decoration:none}button{cursor:pointer;background:transparent;border:1px solid var(--line);border-radius:6px;padding:10px 17px;font-size:14px}input,select,textarea{border:1px solid var(--line);border-radius:5px;background:var(--surface);padding:10px 12px;font-size:14px;min-width:0}textarea{resize:vertical}button:disabled{opacity:.6;cursor:not-allowed}button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,summary:focus-visible{outline:3px solid var(--accent);outline-offset:3px}img{max-width:100%;display:block}h1,h2,h3,p{overflow-wrap:anywhere}h1{font-size:54px;line-height:1.15;letter-spacing:-.04em;margin:0 0 20px}h2{font-size:25px;line-height:1.3;letter-spacing:-.025em;margin:0 0 14px}h3{font-size:19px;line-height:1.4;margin:0 0 9px}p{margin:0 0 16px;color:var(--muted)}small{font-size:12px;color:var(--muted)}.primary,.secondary{display:inline-flex;align-items:center;justify-content:center;gap:8px;font-size:14px;font-weight:650;border:1px solid var(--accent);padding:12px 22px;border-radius:6px}.primary{background:var(--accent);color:white}.secondary{background:transparent;color:var(--accent);margin-left:10px}.text-link,.text-button{border:0;padding:4px 0;text-decoration:underline;text-underline-offset:5px;font-size:13px}.selected{background:var(--accent)!important;color:#fff!important;border-color:var(--accent)!important}.empty-state{padding:35px;border:1px dashed var(--line);border-radius:8px;margin:25px 0}.image-empty{display:flex;min-height:150px;align-items:center;justify-content:center;background:var(--soft);color:var(--muted);font-size:12px}.creator-bar{min-height:29px;padding:4px 3vw;display:flex;align-items:center;justify-content:space-between;gap:20px;background:var(--soft);border-bottom:1px solid var(--line);font-size:11px}.creator-bar>a{font-weight:700;white-space:nowrap}.creator-bar>div{display:flex;align-items:center;gap:12px}.creator-bar button{font-size:10px;padding:3px 8px;border:0}.creator-bar label{display:flex;align-items:center;gap:5px}.creator-bar input{accent-color:var(--accent)}#motionTools{display:flex;gap:10px;align-items:center}#motionTools[hidden]{display:none}.site-header{height:78px;padding:0 5vw;display:flex;align-items:center;gap:35px;border-bottom:1px solid var(--line);background:var(--surface)}.wordmark{font-size:24px;font-weight:750;letter-spacing:-.025em;white-space:nowrap}.site-header nav{display:flex;align-items:center;gap:26px;margin-left:auto}.site-header nav a{font-size:13px;font-weight:600;white-space:nowrap}.site-header nav a.active{border-bottom:2px solid var(--accent)}.site-utilities{display:flex;gap:10px;align-items:center}.site-utilities button,.utility-button{font-size:12px;padding:8px 13px;white-space:nowrap;border:1px solid var(--line);border-radius:6px}.site-content{max-width:1440px;padding:40px 5vw 60px;margin:auto}.site-content>section{margin-top:40px}.site-content>section:first-child{margin-top:0}.site-footer{padding:30px 5vw;display:flex;align-items:center;gap:30px;flex-wrap:wrap;border-top:1px solid var(--line);background:var(--surface);font-size:12px}.site-footer>strong{font-size:20px}.site-footer>div{display:flex;gap:20px;margin-left:auto}.site-footer>small{font-size:10px}.section-heading{display:flex;align-items:center;justify-content:space-between;gap:20px;margin-bottom:18px}.section-heading h2{margin:0}.page-title{margin-bottom:32px}.page-title p{font-size:17px}.page-title h1{max-width:1000px}.product-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:23px}.product-card{position:relative;background:var(--surface);border-radius:9px;overflow:hidden;border:1px solid var(--line)}.product-card>img{width:100%;aspect-ratio:1.55;object-fit:cover;background:#F1F0EA}.product-card>div{padding:19px}.product-card h3{font-size:17px}.product-card p{font-size:12px;line-height:1.5;min-height:36px}.product-card footer{display:flex;justify-content:space-between;gap:10px;font-size:12px}.product-card footer b{font-size:18px;color:var(--ink);margin-left:8px}.product-card footer a{position:relative;z-index:3}.card-hit{position:absolute;inset:0;z-index:1;text-indent:-9999px;overflow:hidden}.card-hit:focus-visible{outline-offset:-4px}.campaign{height:440px;position:relative;isolation:isolate;background:#B7C6AE;margin:-40px -5vw 0!important;padding:45px 5vw}.campaign>div{position:relative;z-index:2;width:50%}.campaign h1{font-size:74px;line-height:1.07;font-weight:850;margin:0 0 28px;color:#111716}.campaign p{font-size:16px;line-height:1.7;color:#202A24;max-width:430px}.campaign>img{position:absolute;height:100%;width:55%;right:0;top:0;object-fit:contain;object-position:right bottom;z-index:0}.campaign .primary{background:#242A2C;border-color:#242A2C;color:white;border-radius:40px;padding:13px 32px}.store-home-grid{display:grid;grid-template-columns:1fr 1fr;gap:35px}.store-home-grid>div:first-child{border-right:1px solid var(--line);padding-right:30px}.store-home-grid h2{font-size:23px}.store-home-grid>div>p{font-size:13px;margin-bottom:18px}.store-home-grid .product-grid{grid-template-columns:repeat(2,1fr);gap:13px}.collection-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:15px}.collection-grid article{padding:18px;border:1px solid var(--line);border-radius:8px;background:var(--surface)}.collection-grid img{width:100%;height:155px;object-fit:cover;margin-bottom:12px;border-radius:4px}.collection-grid h3{font-size:19px}.collection-grid .primary{font-size:11px;padding:7px 12px}.service-band{display:grid;grid-template-columns:repeat(4,1fr);border-top:1px solid var(--line);padding-top:24px;gap:22px}.service-band a{display:block;font-size:14px;font-weight:650}.service-band small{display:block;font-size:11px}.list-controls{display:flex;gap:15px;justify-content:space-between;margin-bottom:20px}.list-controls input{width:min(480px,70%)}.filter-row{display:flex;gap:10px;flex-wrap:wrap;margin:0 0 25px}.filter-chip{padding:7px 17px;font-size:12px;border-radius:30px;background:var(--surface)}.product-detail{display:grid;grid-template-columns:1.05fr 1fr;gap:50px}.product-detail>div>img{width:100%;aspect-ratio:1.18;object-fit:contain;background:#F1F0EA;border-radius:9px}.product-detail .page-title h1{font-size:38px}.product-detail .page-title p{font-size:15px}.product-detail label{display:flex;gap:18px;align-items:center;margin:17px 0;font-size:13px}.product-detail input{width:90px}.price{font-size:27px;color:var(--ink)}details{border-top:1px solid var(--line);padding:15px 0;margin-top:18px}summary{font-size:15px;font-weight:650;cursor:pointer}details p{font-size:14px;margin-top:12px}.cart-layout{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:35px}.cart-row{display:flex;align-items:center;gap:18px;padding:20px 0;border-bottom:1px solid var(--line)}.cart-row>img{width:110px;height:90px;object-fit:contain;background:#F1F0EA;border-radius:5px}.cart-row>div{flex:1}.cart-row h3{font-size:16px}.cart-row p{font-size:11px;margin:5px 0}.cart-row label{font-size:11px;display:flex;align-items:center;gap:10px}.cart-row input{width:65px}.cart-layout>aside{background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:25px;height:max-content}.cart-layout>aside label{display:grid;gap:7px;font-size:12px;margin:15px 0}.cart-layout>aside p{display:flex;justify-content:space-between;font-size:14px;color:var(--ink)}.cart-layout>aside .primary,.cart-layout>aside .secondary{display:flex;width:100%;margin:12px 0 0}.cart-layout>aside>button:disabled{width:100%;margin-top:12px;background:var(--soft)}.reading-page{max-width:780px;margin:25px auto;padding:30px 0}.reading-page h2{margin-top:30px}.reading-page p,.reading-page li{font-size:17px;line-height:1.9;color:var(--muted)}.uses-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px}.uses-grid article{background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:24px}.uses-grid h2,.uses-grid h3{font-size:20px}.uses-grid p{font-size:14px}.form-layout{display:grid;grid-template-columns:1fr 1fr;gap:60px}.draft-form,.settings-form,.record-form{display:grid;gap:18px;max-width:650px}.draft-form label,.settings-form label,.record-form label{display:grid;gap:7px;font-size:13px;font-weight:600}.draft-form textarea{min-height:130px}.draft-form>p{font-size:12px}.form-layout>aside{padding:30px;background:var(--soft);border-radius:8px;height:max-content}.form-layout>aside p{font-size:15px}.form-result{font-size:13px;color:var(--accent);min-height:22px}.story-split{display:grid;grid-template-columns:1fr 1fr;gap:45px;align-items:center}.story-split>img{width:100%;height:420px;object-fit:cover;border-radius:8px}.story-split article p{line-height:1.9}.size-table{display:grid;grid-template-columns:repeat(8,1fr);border:1px solid var(--line);margin-top:25px}.size-table span{text-align:center;padding:15px 3px;border-left:1px solid var(--line)}.center-action{text-align:center;margin-top:30px}.quote-wall{columns:3;column-gap:20px}.quote-card{break-inside:avoid;margin:0 0 20px;background:var(--surface);border:1px solid var(--line);border-radius:8px;overflow:hidden}.quote-card>img{width:100%;height:190px;object-fit:cover}.quote-card>div{padding:22px}.quote-card blockquote{font-size:21px;line-height:1.7;font-family:Georgia,\"Songti SC\",serif;margin:0 0 24px;color:var(--ink)}.quote-card footer{display:flex;align-items:center;gap:12px;margin-bottom:14px}.quote-card footer strong,.quote-card footer small{display:block}.quote-card footer strong{font-size:15px}.quote-card footer small{font-size:11px}.avatar,.initial-avatar{height:42px;width:42px;border-radius:50%;object-fit:cover;background:var(--soft)}.initial-avatar{display:flex;align-items:center;justify-content:center}.quote-card .text-button{font-size:11px}.wall-heading{position:relative;z-index:1}.wall-heading .page-title h1{font-family:Georgia,\"Songti SC\",serif;font-size:56px}.wall-heading .page-title p{font-size:17px}#wallCanvas{position:fixed;inset:80px 0 0;width:100%;height:calc(100vh - 80px);pointer-events:none;z-index:-1}.motion-hero{display:grid;grid-template-columns:1fr 1.25fr;gap:50px;align-items:center;min-height:520px}.motion-hero h1{font-size:62px}.motion-hero p{font-size:20px}.motion-hero>img{width:100%;height:490px;object-fit:cover;border-radius:8px}.motion-hero small{display:block;margin-top:34px;font-size:12px}.process-section{text-align:center;padding:30px 0}.process-section>div,.workflow-section>div{display:grid;grid-template-columns:repeat(3,1fr);gap:35px;margin-top:30px}.process-section article,.workflow-section article{padding:20px}.process-section article b,.workflow-section article b{font-size:16px;color:var(--accent)}.process-section p,.workflow-section p{font-size:14px}.config-section{display:grid;grid-template-columns:1fr 1fr;gap:45px;background:var(--soft);padding:35px;border-radius:9px;align-items:center}pre{max-width:100%;overflow:auto;padding:25px;background:#22292D;color:#EAF2ED;border-radius:8px;font:13px/1.8 ui-monospace,monospace;margin:0}.editorial-hero{display:grid;grid-template-columns:1fr 1.9fr;gap:40px;align-items:center;min-height:430px}.editorial-hero h1{font-family:Georgia,\"Songti SC\",serif;font-size:66px;font-weight:500;letter-spacing:-.07em}.editorial-hero p{font:18px/1.7 Georgia,\"Songti SC\",serif;color:var(--ink)}.paper-fan{display:flex;align-items:center;justify-content:center;padding:25px 10px;min-width:0}.paper-fan a{background:#fff;padding:10px 10px 20px;box-shadow:0 8px 20px #0002;width:36%;font-size:12px;position:relative}.paper-fan a:nth-child(1){transform:rotate(-5deg);z-index:1}.paper-fan a:nth-child(2){transform:rotate(1deg);z-index:2;margin-left:-12px}.paper-fan a:nth-child(3){transform:rotate(7deg);margin-left:-12px}.paper-fan img{height:280px;width:100%;object-fit:cover;margin-bottom:10px}.paper-fan strong{font-family:Georgia,\"Songti SC\",serif;font-weight:500}.topic-index{display:flex;border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:25px 0;justify-content:space-between;align-items:center;gap:25px}.topic-index h2{font-size:20px;margin:0}.topic-index a{font:25px/1.5 Georgia,\"Songti SC\",serif;border-left:1px solid var(--line);padding-left:30px;flex:1}.editorial-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:22px}.article-card{position:relative}.article-card>img{height:180px;width:100%;object-fit:cover;margin-bottom:12px}.article-card h3{font:21px/1.5 Georgia,\"Songti SC\",serif}.article-card p{font-size:12px;line-height:1.7}.article-card small,.article-card footer{font-size:11px;color:var(--muted)}.article-layout{display:grid;grid-template-columns:minmax(0,780px) 260px;gap:70px;justify-content:center}.article-layout>article>img{width:100%;height:400px;object-fit:cover}.article-layout .page-title h1{font:43px/1.3 Georgia,\"Songti SC\",serif}.article-body h2{font:27px/1.5 Georgia,\"Songti SC\",serif;margin:35px 0 16px}.article-body p{font:18px/1.9 Georgia,\"Songti SC\",serif;color:var(--ink);white-space:pre-line}.article-layout aside{border-left:1px solid var(--line);padding-left:25px;align-self:start;position:sticky;top:25px}.article-layout aside h2{font-size:17px;margin:20px 0}.article-layout aside a,.article-layout aside button{display:block;font-size:13px;margin:12px 0}.resume-hero{display:grid;grid-template-columns:1.05fr 1fr;gap:80px;align-items:center;min-height:500px}.resume-hero h1{font:60px/1.35 \"Kaiti SC\",\"STKaiti\",Georgia,\"Songti SC\",serif;letter-spacing:-.03em}.resume-hero h2{font-size:22px}.resume-hero p{max-width:510px;font-size:17px;line-height:1.9}.portrait-paper{margin:0;background:white;padding:14px 14px 30px;transform:rotate(-3deg);box-shadow:0 10px 25px #0002;position:relative;max-width:420px}.portrait-paper:before{content:'';position:absolute;width:110px;height:28px;background:#DECFAB90;left:34%;top:-12px;transform:rotate(5deg)}.portrait-paper img{width:100%;height:370px;object-fit:cover}.portrait-paper figcaption{font:24px/1.5 \"Kaiti SC\",Georgia,serif;padding:10px 10px 0}.portrait-paper small{display:block;font-size:13px}.experience-notes{display:grid;grid-template-columns:repeat(3,1fr);gap:25px;margin-top:25px}.experience-notes article{background:#FBF8F0;padding:28px;border:1px solid #E5DFD1;box-shadow:2px 3px 7px #0001;transform:rotate(.6deg)}.experience-notes article:nth-child(2){transform:rotate(-.5deg)}.experience-notes small{font-size:12px;color:var(--accent)}.experience-notes h3{font:24px/1.5 Georgia,\"Songti SC\",serif;margin-top:13px}.experience-notes p{font-size:14px;line-height:1.8}.experience-rail{border-left:1px solid var(--line);margin-left:10px;padding-left:35px}.experience-rail article{margin:25px 0 40px;position:relative}.experience-rail article:before{content:'';position:absolute;left:-41px;top:5px;width:11px;height:11px;border-radius:50%;background:var(--accent)}.project-card{display:grid;grid-template-columns:.85fr 1.5fr;gap:30px;align-items:center;padding:30px;margin:25px 0;border:1px solid var(--line);border-radius:9px;background:var(--surface)}.project-card h3{font-size:28px}.project-card p{font-size:15px;line-height:1.8}.product-window{display:grid;grid-template-columns:145px 1fr;border:1px solid var(--line);border-radius:8px;overflow:hidden;background:var(--surface);min-height:255px;font-size:12px;box-shadow:0 8px 18px #0001}.product-window>aside{padding:22px;background:var(--soft);border-right:1px solid var(--line);font-weight:600}.product-window>aside small{font-size:10px}.product-window>div{min-width:0}.product-window header{padding:15px;border-bottom:1px solid var(--line);display:flex;align-items:center;justify-content:space-between;gap:10px;font-weight:700}.product-window button{font-size:9px;padding:5px 8px}.window-row{display:flex;justify-content:space-between;gap:10px;padding:13px 15px;border-bottom:1px solid var(--line);font-size:11px}.window-row small{font-size:9px}.deck-mini{padding:25px}.deck-mini strong{display:block;font-size:24px;color:var(--accent)}.deck-mini div{font-size:11px;margin:20px 0}.case-sections{display:grid;grid-template-columns:repeat(3,1fr);gap:28px;margin:35px 0}.case-sections section{border-top:1px solid var(--line);padding-top:20px}.case-sections p{font-size:16px;line-height:1.9}.portfolio-hero{position:relative;min-height:410px;display:grid;grid-template-columns:1.1fr 1fr;align-items:center;gap:50px;isolation:isolate}.portfolio-hero>div{z-index:1}.portfolio-hero h1{font-size:61px;line-height:1.15}.portfolio-hero h1 span{color:var(--accent)}.portfolio-hero p{font-size:16px;line-height:1.8;max-width:570px}.portfolio-hero small{display:block;margin-bottom:20px;font-size:11px;letter-spacing:.08em;color:var(--accent)}.portfolio-hero>img{width:100%;height:390px;object-fit:cover;border-radius:8px}.portfolio-bottom{display:grid;grid-template-columns:repeat(3,1fr);gap:35px;border-top:1px solid var(--line);padding-top:30px}.portfolio-bottom a{display:block;padding:10px 0;font-size:14px;border-bottom:1px solid var(--line)}.portfolio-bottom p{font-size:12px}.portfolio-bottom p strong{display:block;font-size:14px;color:var(--ink)}.saas-hero{text-align:center;max-width:1000px;margin:20px auto 40px!important}.saas-hero h1{font-size:60px;max-width:1050px;margin:auto auto 22px}.saas-hero p{font-size:17px}.saas-console{max-width:1160px;border:1px solid var(--line);border-radius:12px;background:var(--surface);padding:25px;box-shadow:0 20px 45px #0001;transition:transform .2s ease;transform-origin:center bottom}.saas-console[data-tilt-level=\"6\"]{transform:perspective(1200px) rotateX(6deg)}.saas-console[data-tilt-level=\"5\"]{transform:perspective(1200px) rotateX(5deg)}.saas-console[data-tilt-level=\"4\"]{transform:perspective(1200px) rotateX(4deg)}.saas-console[data-tilt-level=\"3\"]{transform:perspective(1200px) rotateX(3deg)}.saas-console[data-tilt-level=\"2\"]{transform:perspective(1200px) rotateX(2deg)}.saas-console[data-tilt-level=\"1\"]{transform:perspective(1200px) rotateX(1deg)}.workflow-section{padding:30px 0;border-top:1px solid var(--line)}.workflow-section>div{margin-bottom:25px}.plans-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}.plans-grid>article{background:var(--surface);padding:25px;border:1px solid var(--line);border-radius:9px}.plans-grid strong{font-size:36px;display:block;margin:24px 0;color:var(--ink)}.plans-grid strong small{font-size:13px;margin-left:8px}.plans-grid ul{padding-left:19px;margin:25px 0;font-size:14px}.plans-grid .primary{width:100%}.faq-section{max-width:950px}.signup-band{border:1px solid var(--line);border-radius:9px;background:var(--soft);padding:35px;display:flex;align-items:center;justify-content:space-between;gap:30px}.signup-band h2{margin:0}.tour-tabs{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:28px}.release-row{border-top:1px solid var(--line);padding:23px 0}.release-row a{display:block;font-size:20px;margin-bottom:10px}.release-row h2{font-size:24px;margin:10px 0}.release-row p{font-size:15px;line-height:1.9}.task-board{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:15px;min-width:0}.task-board>section{background:var(--soft);border:1px solid var(--line);border-radius:8px;padding:15px;min-width:0}.task-board>section>header{display:flex;justify-content:space-between;align-items:center;gap:15px;margin-bottom:14px}.task-board h3{font-size:15px;margin:0}.task-board>section>header span{font-size:12px;color:var(--muted)}.task-card{background:var(--surface);border:1px solid var(--line);border-radius:7px;padding:16px;margin-bottom:14px;cursor:grab;min-width:0}.task-card strong{font-size:14px}.task-card p{font-size:11px;margin:10px 0}.task-card small{display:block;font-size:10px}.task-card select{font-size:10px;padding:5px;width:100%;margin-top:11px}.compact .task-card p{line-height:1.5}.cv-page{max-width:800px;background:var(--surface);padding:35px;margin:auto;border:1px solid var(--line);font-size:13px}.cv-page h1{font-size:30px;margin-bottom:10px}.cv-page .page-title{margin:0 0 15px}.cv-page .page-title p{font-size:14px}.cv-page h2{font-size:17px;margin:20px 0 10px;border-bottom:1px solid var(--line);padding-bottom:7px}.cv-page p{font-size:12px;line-height:1.7}.cv-page small{font-size:9px}.print-actions{text-align:center;margin-top:25px}.admin-app{display:grid;grid-template-columns:220px minmax(0,1fr);background:#F3F5F6;min-height:calc(100vh - 29px);font-size:14px}.admin-sidebar{border-right:1px solid var(--line);padding:24px 15px;position:sticky;top:0;align-self:start;min-height:calc(100vh - 29px);display:flex;flex-direction:column;gap:12px}.admin-sidebar>strong{font-size:21px;padding:0 10px}.admin-sidebar>small{padding:0 10px;font-size:11px}.admin-sidebar nav{display:grid;gap:7px;margin-top:14px}.admin-sidebar nav a{padding:12px 16px;border-radius:6px;font-size:14px;font-weight:600}.admin-sidebar nav a.active{background:#F4E7DC;color:#C25B26}.admin-sidebar>p{font-size:11px;margin-top:auto;padding:20px 10px}.admin-sidebar>button{font-size:11px;text-align:left;padding-left:10px}.sidebar-collapsed{grid-template-columns:115px minmax(0,1fr)}.sidebar-collapsed .admin-sidebar>strong{font-size:15px}.sidebar-collapsed .admin-sidebar nav a{padding:10px 3px;font-size:12px}.sidebar-collapsed .admin-sidebar>small,.sidebar-collapsed .admin-sidebar>p{display:none}.admin-toolbar{height:60px;background:var(--surface);border-bottom:1px solid var(--line);display:flex;align-items:center;padding:0 25px;gap:14px}.admin-toolbar>button:first-child{width:min(650px,70%);text-align:left;font-size:12px;background:#F6F8FA}.admin-toolbar>button:nth-child(2){margin-left:auto}.admin-content{padding:24px 25px 40px;min-width:0}.admin-content h1{font-size:30px;margin-bottom:10px}.admin-content .page-title p{font-size:13px}.admin-footer{padding:18px 25px;font-size:11px;color:var(--muted);border-top:1px solid var(--line)}.admin-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:17px;margin-bottom:20px}.admin-stats article{background:var(--surface);border:1px solid var(--line);padding:20px;border-radius:8px;min-width:0}.admin-stats small{display:block;font-size:11px;margin-bottom:8px}.admin-stats strong{font-size:32px;line-height:1.3}.admin-overview-grid{display:grid;grid-template-columns:1fr 1.2fr;gap:20px;margin-bottom:20px}.panel{padding:20px;background:var(--surface);border:1px solid var(--line);border-radius:8px;min-width:0;margin-bottom:20px}.panel h2{font-size:18px}.panel svg{width:100%;height:auto;max-height:280px}.panel p{font-size:12px}.panel .task-board{margin-top:18px}.table-scroll{max-width:100%;overflow:auto}table{width:100%;border-collapse:collapse;white-space:nowrap;font-size:12px}th,td{text-align:left;padding:11px 12px;border-bottom:1px solid var(--line)}th{background:var(--soft);font-size:11px;font-weight:600}.table-tools{display:grid;gap:10px;margin-bottom:14px}.table-tools .list-controls{margin:0}.table-tools .filter-row{margin:0;gap:6px}.table-tools .filter-chip{font-size:10px;padding:4px 9px}.table-tools input{font-size:11px;padding:7px 9px}.table-tools>div:last-child{display:flex;gap:10px}.table-tools button,.table-tools select{font-size:10px;padding:7px 11px}.status-tag{font-size:10px;border-radius:5px;padding:4px 7px;background:var(--soft)}.pagination{display:flex;justify-content:end;align-items:center;gap:12px;margin-top:15px;font-size:11px}.pagination button{font-size:10px;padding:6px 9px}.bar-chart{display:flex;gap:30px;min-height:190px;align-items:end;justify-content:center;padding:20px 0}.bar-chart>div{display:flex;flex-direction:column;align-items:center;gap:10px;font-size:12px}.bar-chart meter{width:125px;height:25px;accent-color:var(--accent)}.calendar-controls{display:flex;align-items:center;gap:15px;margin-bottom:22px}.calendar-controls h2{font-size:21px;margin:0}.calendar-controls .primary{margin-left:auto;font-size:12px}.calendar-layout{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:25px}.month-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:7px}.month-grid>strong{text-align:center;font-size:12px;padding:8px}.month-grid>button{padding:14px 5px;background:var(--surface);min-height:76px;text-align:center}.month-grid b{font-size:16px}.month-grid small{display:block;font-size:9px}.calendar-layout>aside{border-left:1px solid var(--line);padding-left:22px}.calendar-layout aside h3{font-size:16px}.calendar-layout aside article{border-bottom:1px solid var(--line);padding:16px 0}.calendar-layout aside strong{font-size:13px}.calendar-layout aside p{font-size:12px;margin-top:8px}.calendar-layout .empty-state{font-size:12px;padding:18px}.settings-form{background:var(--surface);padding:25px;border-radius:8px;border:1px solid var(--line);margin-bottom:24px}dialog{border:1px solid var(--line);border-radius:10px;background:var(--surface);color:var(--ink);width:min(850px,calc(100vw - 32px));padding:28px;max-height:calc(100vh - 45px);overflow:auto}dialog::backdrop{background:#0008}dialog>header{display:flex;align-items:center;justify-content:space-between;gap:20px;margin-bottom:20px}dialog>header h2{font-size:24px;margin:0}dialog>header button{font-size:13px;padding:7px 12px}dialog textarea#jsonInput{width:100%;height:430px;font:12px/1.7 ui-monospace,monospace;white-space:pre;resize:vertical}dialog label{font-size:13px}dialog>footer{display:flex;justify-content:end;margin-top:18px}dialog p{font-size:14px;line-height:1.8}#jsonError{font-size:12px;color:#AD4D2D;min-height:20px}#webStatus{position:fixed;right:22px;bottom:18px;z-index:30;max-width:min(430px,calc(100vw - 40px));font-size:12px;line-height:1.5;color:var(--ink);background:var(--surface);border:1px solid var(--line);padding:10px 17px;border-radius:8px;box-shadow:0 5px 15px #0002}#webStatus:empty{display:none}#commandQuery{width:100%;font-size:15px;padding:13px}#commandResults{display:grid;margin-top:18px;gap:8px;max-height:420px;overflow:auto}#commandResults a,#commandResults button{display:block;text-align:left;padding:11px 14px;border:1px solid var(--line);border-radius:6px;font-size:13px}.record-form input,.record-form select{width:100%}#detailBody dl{display:grid;grid-template-columns:120px minmax(0,1fr);gap:12px;font-size:13px}#detailBody dt{font-weight:700}#detailBody dd{margin:0;white-space:pre-wrap;overflow-wrap:anywhere}#detailBody blockquote{font:24px/1.6 Georgia,\"Songti SC\",serif}.site-content [data-entrance]{animation:entrance .8s ease both}.no-motion *{animation:none!important;transition:none!important;scroll-behavior:auto!important}.no-motion [data-tilt]{transform:none!important}body[data-kind=store]{background:#F7F7F3;--accent:#28392C;--surface:#FCFCF9;--soft:#E7EDE3}body[data-kind=store] .site-content{max-width:none}body[data-kind=store] .site-header{background:#F8F8F5}.store-home-grid .product-card>img{aspect-ratio:1.6}.store-home-grid .product-card>div{padding:13px}.store-home-grid .product-card h3{font-size:14px}.store-home-grid .product-card p{font-size:10px;min-height:30px}.store-home-grid .product-card footer b{font-size:16px}.store-home-grid .product-card footer a{font-size:10px}body[data-kind=magazine]{background:white;--surface:#fff;--ink:#272623;--muted:#77756F;--line:#DAD9D4;--accent:#302F2B;--soft:#F6F5F0;font-family:Georgia,\"Songti SC\",serif}body[data-kind=magazine] .wordmark{font:27px Georgia,\"Songti SC\",serif;letter-spacing:.06em}body[data-kind=magazine] .site-header nav,body[data-kind=magazine] button,body[data-kind=magazine] input,body[data-kind=magazine] select{font-family:system-ui,\"PingFang SC\",sans-serif}body[data-kind=magazine] .primary{border-radius:0}body[data-kind=resume]{background:#F4EEE2;color:#123751;--surface:#FCF9F0;--ink:#123751;--muted:#52677A;--accent:#123B5D;--line:#DCD5C8;--soft:#EDE6D6}body[data-kind=resume] .wordmark{font:26px \"Kaiti SC\",Georgia,serif}body[data-kind=resume] .site-header{background:#FBF8F0}body[data-kind=hero]{background:#FAF8F3;--accent:#3A7351;--surface:#FFF;--soft:#F1F3EA}body[data-kind=wall]{background:#F6F0E6;color:#293C33;--surface:#FCFAF5;--ink:#293C33;--accent:#294D40;--muted:#777970;--line:#E4DDD2;--soft:#EBEFE5}body[data-kind=admin]{--surface:#FFF;--ink:#252E37;--accent:#CF6F36;--soft:#F1F4F7;--line:#DDE3E7;--muted:#71808D;background:#F3F5F6}body[data-kind=dark],body[data-kind=portfolio],body[data-theme=dark]{background:#191F22;color:#F2F6F3;--surface:#20292D;--ink:#F2F6F3;--muted:#A6B6BA;--line:#344448;--accent:#8CCBB7;--soft:#1D3030}body[data-kind=dark] .primary,body[data-kind=portfolio] .primary,body[data-theme=dark] .primary{color:#172928}body[data-kind=dark] .site-header,body[data-kind=portfolio] .site-header{background:#172023}body[data-kind=dark] .saas-hero h1{color:#DCF3E9}body[data-kind=portfolio] .site-header{height:70px}body[data-kind=portfolio] .project-card{background:#1F2A2C}body[data-kind=light]{background:#FAFAF6;--surface:white;--ink:#252C31;--muted:#687881;--accent:#7399BD;--line:#DCE4EA;--soft:#EEF4F9}.admin-app .creator-bar{display:none}body[data-kind=admin][data-theme=dark] .admin-app{background:#1A2227}body[data-kind=admin][data-theme=dark] .admin-toolbar>button:first-child{background:#263238}body[data-kind=admin][data-theme=dark] .admin-sidebar nav a.active{background:#3A302B;color:#F0B080}body[data-preset=tangerine]{--accent:#D66F32}body[data-kind=hero] .site-header,body[data-kind=wall] .site-header{height:66px}body[data-kind=hero] .site-header nav,body[data-kind=wall] .site-header nav{display:none}.block-header{height:65px}.block-header .wordmark{font-size:24px}.data-hero-contact{display:none}@keyframes entrance{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:translateY(0)}}@media(min-width:1450px){.site-content{padding:40px 5vw 55px;max-width:1600px}.campaign{height:440px}.campaign h1{font-size:80px}.campaign>img{width:55%}.site-header{height:70px}.site-header nav a{font-size:14px}.wordmark{font-size:30px}.editorial-hero{min-height:480px;grid-template-columns:1fr 2.3fr}.editorial-hero h1{font-size:76px}.paper-fan img{height:350px}.topic-index{padding:28px 0}.article-card>img{height:160px}.resume-hero{min-height:515px;grid-template-columns:1fr 1.15fr;gap:60px}.resume-hero h1{font-size:68px}.portrait-paper{max-width:445px}.portrait-paper img{height:415px}.portfolio-hero h1{font-size:74px}.motion-hero h1{font-size:71px}.motion-hero>img{height:510px}.admin-content{padding:25px 26px 45px}.admin-overview-grid{grid-template-columns:.82fr 1.18fr}.admin-sidebar{width:220px}.admin-content .task-card{padding:18px}.admin-content h1{font-size:31px}}@media(max-width:1100px){.site-header{padding:0 25px;gap:20px}.site-header nav{gap:15px}.site-header nav a{font-size:12px}.site-utilities{gap:6px}.site-utilities button{font-size:11px;padding:7px 9px}.wordmark{font-size:20px}.site-content{padding:30px 25px 50px}.campaign{margin:-30px -25px 0!important;padding:40px 25px}.campaign h1{font-size:64px}.store-home-grid{grid-template-columns:1fr}.store-home-grid>div:first-child{padding-right:0;border:0}.product-grid{grid-template-columns:repeat(2,1fr)}.editorial-hero{grid-template-columns:.9fr 1.2fr;gap:25px}.editorial-hero h1{font-size:55px}.paper-fan img{height:230px}.editorial-grid{grid-template-columns:repeat(2,1fr)}.article-layout{grid-template-columns:1fr 230px;gap:30px}.resume-hero{gap:40px}.resume-hero h1{font-size:50px}.portrait-paper img{height:320px}.project-card{grid-template-columns:1fr}.quote-wall{columns:2}.admin-app{grid-template-columns:170px minmax(0,1fr)}.admin-sidebar{width:auto}.admin-sidebar>strong{font-size:18px}.admin-overview-grid{grid-template-columns:1fr}.calendar-layout{grid-template-columns:1fr}.calendar-layout>aside{border-left:0;padding:0;border-top:1px solid var(--line)}.admin-stats{gap:10px}.admin-stats article{padding:15px}.admin-stats strong{font-size:27px}.task-board{gap:10px}.task-card{padding:12px}.motion-hero h1{font-size:50px}.motion-hero{gap:30px;min-height:420px}.motion-hero>img{height:390px}}@media(max-width:760px){.creator-bar{padding:7px 15px;flex-wrap:wrap;gap:6px}.creator-bar>div{gap:4px;flex-wrap:wrap}.site-header{height:auto;min-height:70px;padding:18px 20px;flex-wrap:wrap;gap:14px}.site-header nav{order:3;width:100%;overflow:auto;margin:0;gap:18px;padding-bottom:4px}.site-utilities{margin-left:auto}.wordmark{font-size:20px}.site-content{padding:25px 20px 40px;max-width:100%;overflow:hidden}h1{font-size:36px}.page-title p{font-size:15px}.campaign{height:auto;min-height:650px;margin:-25px -20px 0!important;padding:35px 20px}.campaign>div{width:100%}.campaign h1{font-size:49px;max-width:85%}.campaign p{font-size:13px;max-width:65%}.campaign>img{height:380px;width:100%;right:-35px;top:auto;bottom:0;object-position:right bottom;z-index:0}.campaign .primary{position:relative;z-index:3}.campaign>div{z-index:2}.store-home-grid{gap:25px}.store-home-grid h2{font-size:22px}.store-home-grid .product-grid{grid-template-columns:1fr 1fr;gap:10px}.store-home-grid .product-card>div{padding:12px}.store-home-grid .product-card h3{font-size:13px}.store-home-grid .product-card p{font-size:10px}.store-home-grid .product-card footer{display:block}.store-home-grid .product-card footer b{font-size:15px;margin-left:0;display:block}.store-home-grid .product-card footer a{display:inline-block;margin-top:8px}.service-band{grid-template-columns:1fr 1fr;gap:20px}.collection-grid{gap:12px}.collection-grid article{padding:12px}.collection-grid img{height:110px}.product-grid{gap:13px}.product-card footer{flex-direction:column}.product-card h3{font-size:15px}.product-card p{font-size:11px}.product-detail{grid-template-columns:1fr;gap:25px}.product-detail .page-title h1{font-size:30px}.cart-layout{grid-template-columns:1fr;gap:25px}.cart-row{gap:12px;flex-wrap:wrap}.cart-row>img{width:75px;height:65px}.cart-row h3{font-size:14px}.cart-row label{font-size:10px}.cart-row input{width:60px}.editorial-hero{display:block;min-height:0}.editorial-hero h1{font-size:52px;line-height:1.2}.editorial-hero p{font-size:16px}.paper-fan{margin-top:25px;padding:25px 5px}.paper-fan img{height:180px}.paper-fan a{padding:7px 7px 15px;font-size:10px}.topic-index{display:grid;grid-template-columns:1fr 1fr;gap:18px;padding:20px 0}.topic-index h2{grid-column:1/-1}.topic-index a{font-size:19px;padding-left:12px}.editorial-grid{gap:18px}.article-card>img{height:135px}.article-card h3{font-size:17px}.article-card p{font-size:11px}.article-layout{grid-template-columns:1fr}.article-layout>aside{position:static;border-left:0;padding:0;border-top:1px solid var(--line)}.article-layout>article>img{height:260px}.article-layout .page-title h1{font-size:29px}.article-body p{font-size:16px}.article-body h2{font-size:24px}.resume-hero{display:flex;flex-direction:column;align-items:start;gap:35px}.resume-hero h1{font-size:45px}.resume-hero h2{font-size:19px}.resume-hero p{font-size:15px}.portrait-paper{max-width:90%;margin:0 0 15px}.portrait-paper img{height:320px}.experience-notes{grid-template-columns:1fr;gap:18px}.experience-notes article{padding:25px}.project-card{padding:20px;gap:20px}.product-window{grid-template-columns:95px minmax(0,1fr);min-height:225px}.product-window>aside{padding:15px;font-size:11px}.window-row{font-size:9px;padding:12px 10px}.window-row small{display:none}.product-window header{font-size:10px;padding:11px 10px}.deck-mini{padding:18px}.deck-mini strong{font-size:20px}.case-sections{grid-template-columns:1fr;gap:20px}.motion-hero{grid-template-columns:1fr;gap:25px;min-height:0}.motion-hero h1{font-size:42px}.motion-hero p{font-size:17px}.motion-hero>img{height:300px}.motion-hero small{margin-top:22px}.process-section>div,.workflow-section>div{grid-template-columns:1fr;gap:5px}.process-section article{text-align:left;padding:16px}.config-section{grid-template-columns:1fr;padding:23px;gap:25px}.wall-heading .page-title h1{font-size:39px;line-height:1.3}.quote-wall{columns:1}.quote-card>img{height:190px}.quote-card blockquote{font-size:21px}.portfolio-hero{display:block;min-height:0}.portfolio-hero h1{font-size:44px}.portfolio-hero p{font-size:14px}.portfolio-hero>img{margin-top:30px;height:270px}.portfolio-bottom{grid-template-columns:1fr;gap:28px}.uses-grid,.plans-grid{grid-template-columns:1fr;gap:18px}.saas-hero h1{font-size:38px}.saas-hero p{font-size:15px}.saas-console{padding:12px}.task-board{grid-template-columns:1fr;gap:15px}.task-board .task-card{padding:15px}.task-board>section{padding:15px}.task-card p{font-size:12px}.task-card strong{font-size:15px}.task-card small,.task-card select{font-size:11px}.plans-grid>article{padding:25px}.signup-band{display:block;padding:25px}.signup-band h2{margin-bottom:20px}.form-layout,.story-split{grid-template-columns:1fr;gap:25px}.form-layout>aside{padding:23px}.story-split>img{height:320px}.site-footer{display:block;padding:25px 20px}.site-footer>div{margin:18px 0;flex-wrap:wrap;gap:14px}.site-footer>small{font-size:10px}.admin-app{display:block}.admin-sidebar{position:static;min-height:0;padding:15px}.admin-sidebar>strong{font-size:19px}.admin-sidebar>small,.admin-sidebar>p,.admin-sidebar>button{display:none}.admin-sidebar nav{display:flex;gap:6px;overflow:auto;margin:5px 0 0}.admin-sidebar nav a{padding:8px 10px;white-space:nowrap;font-size:12px}.admin-toolbar{padding:0 15px;gap:8px}.admin-toolbar>button:first-child{width:auto;flex:1;min-width:0;font-size:10px}.admin-toolbar button{font-size:10px;padding:8px 10px}.admin-content{padding:22px 15px 35px}.admin-content h1{font-size:28px}.admin-stats{grid-template-columns:1fr 1fr;gap:10px}.admin-stats article{padding:15px}.admin-stats strong{font-size:29px}.panel{padding:15px}.table-tools>div:last-child{flex-wrap:wrap}.table-tools .list-controls{gap:8px}.table-tools .list-controls input{width:65%}.calendar-controls{flex-wrap:wrap;gap:8px}.calendar-controls .primary{font-size:10px;padding:8px 10px}.calendar-controls h2{font-size:17px}.month-grid{gap:3px}.month-grid>button{padding:9px 2px;min-height:62px}.month-grid b{font-size:13px}.month-grid small{font-size:8px}.calendar-layout{gap:20px}.cv-page{padding:20px}.cv-page h1{font-size:28px}.creator-bar button{font-size:9px;padding:3px 5px}dialog{padding:22px}dialog>header h2{font-size:20px}dialog textarea#jsonInput{height:330px}}@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important;scroll-behavior:auto!important}[data-tilt]{transform:none!important}}@media print{@page{size:A4;margin:14mm}.creator-bar,.site-header,.site-footer,.print-actions,dialog,#webStatus{display:none!important}body{background:white!important;color:black!important}.site-content{padding:0;margin:0;max-width:none}.cv-page{border:0;padding:0;margin:0;width:100%;font-size:11pt;break-inside:avoid}.cv-page h1{font-size:24pt}.cv-page h2{font-size:12pt;margin-top:12pt}.cv-page p{font-size:9pt;color:black}.cv-page .page-title p{font-size:10pt}}\n#siteRoot{position:relative;isolation:isolate}body[data-kind=light][data-theme=dark]{background:#191F22;color:#F2F6F3;--surface:#20292D;--ink:#F2F6F3;--muted:#A6B6BA;--line:#344448;--accent:#8BB9DD;--soft:#21333F}body[data-kind=admin][data-preset=slate]{--accent:#596B7A}body[data-kind=admin][data-preset=slate] .admin-sidebar nav a.active{background:var(--soft);color:var(--accent)}\n.retention-grid{min-width:420px;font-size:11px}.retention-grid>div,.retention-grid>header{display:grid;grid-template-columns:115px repeat(4,1fr);gap:7px;margin-bottom:7px}.retention-grid span,.retention-grid strong{padding:9px 5px;text-align:center}.retention-grid strong{text-align:left;font-weight:500}.retention-grid [data-level=\"0\"]{background:var(--soft)}.retention-grid [data-level=\"1\"]{background:#EDDCCF}.retention-grid [data-level=\"2\"]{background:#E3B99B}.retention-grid [data-level=\"3\"]{background:#D88F5C}.retention-grid [data-level=\"4\"]{background:var(--accent);color:white}.retention-grid [data-level=\"unknown\"]{border:1px dashed var(--line);color:var(--muted)}.panel .retention-grid{max-width:100%;overflow:auto}.analytics-chart-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px}.spend-breakdown svg{max-width:330px;max-height:220px}.spend-breakdown p{font-size:13px}.retention-scroll{overflow:auto}@media(max-width:760px){.analytics-chart-grid{grid-template-columns:1fr}.retention-grid{min-width:360px;grid-template-columns:100px repeat(4,1fr)}}\n.portfolio-media{position:relative;height:430px;min-width:0;isolation:isolate}.portfolio-media>img{height:100%;width:100%;object-fit:cover;border-radius:9px}.hero-project-window{position:absolute;box-shadow:0 18px 30px #0006;border:8px solid #11191C;border-radius:13px;background:#11191C;overflow:hidden;z-index:2}.hero-project-window.first{width:74%;left:0;top:20px;transform:rotate(-3deg)}.hero-project-window.second{width:57%;right:-3px;top:110px;transform:rotate(3deg);z-index:3}.hero-project-window .product-window{min-height:280px;grid-template-columns:105px 1fr;border:0;border-radius:2px;box-shadow:none}.hero-project-window .product-window>aside{font-size:10px;padding:15px}.hero-project-window .window-row{font-size:10px;padding:12px}.hero-project-window .product-window header{font-size:11px;padding:12px}.hero-project-window .deck-mini strong{font-size:22px}.hero-project-window .deck-mini{padding:22px}.product-hero{display:grid;grid-template-columns:1fr 1.45fr;gap:40px;align-items:center;min-height:470px;position:relative;isolation:isolate;margin-top:0!important}.product-hero>div:first-child{max-width:570px}.product-hero h1{font-size:58px;line-height:1.2;margin-bottom:28px}.product-hero p{font-size:17px;line-height:1.8;max-width:550px}.product-console-window{display:grid;grid-template-columns:130px minmax(0,1fr);border:1px solid var(--line);border-radius:11px;background:var(--surface);padding:12px;box-shadow:0 18px 35px #0002;min-width:0}.product-console-window>aside{padding:15px;border-right:1px solid var(--line);font-size:12px}.product-console-window>aside strong{font-size:13px}.product-console-window nav{display:grid;gap:10px;margin:28px 0}.product-console-window nav span{font-size:11px;padding:7px 0}.product-console-window>aside small{font-size:9px}.product-console-window>div{padding:8px 12px;min-width:0}.product-console-window .task-board{gap:8px}.product-console-window .task-board>section{padding:10px}.product-console-window .task-board h3{font-size:11px}.product-console-window .task-board header span{font-size:9px}.product-console-window .task-card{padding:10px;min-height:150px}.product-console-window .task-card strong{font-size:11px}.product-console-window .task-card p{font-size:9px}.product-console-window .task-card small{font-size:8px}.product-console-window .task-card select{font-size:9px;padding:4px}.product-console-window .task-board .text-button{font-size:9px}.product-console-window footer{display:flex;gap:15px;justify-content:space-between;border-top:1px solid var(--line);padding:15px 3px 5px;font-size:10px;color:var(--muted)}body[data-kind=dark] .product-hero h1{color:var(--accent)}body[data-kind=light] .product-console-window{border:8px solid #171C20;border-radius:16px}.resume-contact-note{display:none}@media(min-width:1450px){.product-hero h1{font-size:63px}.product-hero{min-height:510px}.product-console-window{grid-template-columns:135px minmax(0,1fr)}.portfolio-hero{grid-template-columns:1fr 1.15fr}}@media(max-width:1100px){.product-hero{gap:25px;grid-template-columns:.9fr 1.15fr}.product-hero h1{font-size:45px}.product-console-window{grid-template-columns:90px minmax(0,1fr);padding:8px}.product-console-window .task-board{grid-template-columns:1fr}.product-console-window .task-board>section:nth-child(n+2){display:none}.portfolio-media{height:380px}.hero-project-window.first{width:80%}.hero-project-window.second{width:65%}}@media(max-width:760px){.product-hero{display:block;min-height:0}.product-hero h1{font-size:39px}.product-hero p{font-size:15px}.product-console-window{margin-top:30px;grid-template-columns:80px minmax(0,1fr)}.product-console-window>aside{padding:10px}.product-console-window>div{padding:3px 8px}.product-console-window footer{flex-wrap:wrap;font-size:9px}.product-console-window .task-board>section:nth-child(n+2){display:block}.product-console-window .task-board{grid-template-columns:1fr}.portfolio-media{height:330px;margin-top:25px}.hero-project-window.first{width:85%;top:10px}.hero-project-window.second{width:68%;top:140px;right:0}.hero-project-window .product-window{min-height:190px;grid-template-columns:75px minmax(0,1fr)}.hero-project-window .product-window>aside{font-size:9px;padding:11px}.hero-project-window .product-window header{font-size:9px;padding:8px}.hero-project-window .window-row{font-size:8px;padding:9px}.hero-project-window .deck-mini{padding:14px}.hero-project-window .deck-mini strong{font-size:17px}.hero-project-window .deck-mini div{font-size:9px;margin:14px 0}}\n@media(min-width:761px) and (max-width:1100px){.product-console-window>div{overflow:auto}.product-console-window .task-board{grid-template-columns:repeat(3,minmax(110px,1fr));min-width:350px}.product-console-window .task-board>section:nth-child(n+2){display:block}}\n.product-gallery{display:flex;gap:10px;margin-top:15px;flex-wrap:wrap}.product-gallery button{width:90px;height:75px;padding:0;border:1px solid var(--line);border-radius:5px;overflow:hidden}.product-gallery img{width:100%;height:100%;object-fit:contain}\n.site-header nav{margin-left:0;flex:1;justify-content:center}.campaign>img{right:21%;width:45%;mask-image:linear-gradient(to right,transparent,black 18%,black)}.quote-card>img{object-position:center 30%}@keyframes entrance{from{opacity:.93;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@media(max-width:760px){.campaign>img{right:-10%;width:100%;mask-image:linear-gradient(to right,transparent,black 15%,black)}.site-header nav{justify-content:start}}\n.resume-contact-note{display:grid;gap:25px;align-content:center}.resume-contact-note>div{padding:28px 22px;background:#FBF5E5;box-shadow:2px 5px 16px #0002;transform:rotate(4deg);font-family:\"Kaiti SC\",Georgia,serif}.resume-contact-note h3{font-size:25px}.resume-contact-note p{font-size:16px}.resume-contact-note .navy-note{background:#183C56;color:#F5EEE2;transform:rotate(-3deg);min-height:190px;display:flex;flex-direction:column;justify-content:center}.resume-contact-note .navy-note p{color:inherit;font-size:25px;line-height:1.6}.resume-contact-note .navy-note a{font-size:13px}@media(min-width:1450px){.resume-hero{grid-template-columns:1fr 1.05fr .64fr;gap:35px}.resume-hero h1{font-size:66px}.resume-hero .portrait-paper{max-width:445px}}@media(min-width:761px) and (max-width:1449px){.resume-contact-note{display:none}}@media(max-width:760px){.resume-contact-note{display:grid;width:100%;grid-template-columns:1fr 1fr;gap:15px}.resume-contact-note>div{padding:22px 15px}.resume-contact-note h3{font-size:18px}.resume-contact-note p{font-size:12px}.resume-contact-note .navy-note p{font-size:20px}}\n.admin-overview-grid>.panel{margin-bottom:0}.admin-overview-grid .panel svg{height:225px}.overview-summary{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px;margin:20px 0}.overview-summary .panel{margin-bottom:0}.overview-summary .section-heading h2{font-size:16px}.overview-summary .section-heading{gap:10px}.overview-summary .text-button,.overview-summary .text-link{font-size:10px}.summary-row{display:flex;gap:12px;align-items:center;flex-wrap:wrap;border-top:1px solid var(--line);padding:13px 0;font-size:11px}.summary-row strong{font-size:12px;flex:1;min-width:90px}.summary-row select{font-size:10px;padding:5px}.summary-row small{font-size:9px}.summary-row>span{font-size:11px}.admin-content .page-title{margin-bottom:20px}.admin-stats article{padding:15px 20px}.admin-overview-grid .panel table th,.admin-overview-grid .panel table td{font-size:11px;padding:9px 10px}.admin-overview-grid .panel .section-heading select{font-size:11px;padding:5px 10px}.admin-content .task-board.compact .task-card{padding:12px}.admin-content .task-board.compact .task-card p{font-size:10px}.admin-content .task-board.compact .task-card select{font-size:9px}.admin-content .task-board.compact .task-card strong{font-size:12px}@media(max-width:1100px){.overview-summary{grid-template-columns:1fr 1fr}.overview-summary>section:last-child{grid-column:1/-1}}@media(max-width:760px){.overview-summary{grid-template-columns:1fr}.overview-summary>section:last-child{grid-column:auto}}\n.campaign>img{mask-image:none;right:22%;width:43%}@media(max-width:760px){.campaign>img{mask-image:none;right:-8%;width:100%}}\n.product-hero{grid-template-columns:1.15fr 1.4fr;gap:25px}.product-hero h1{font-size:clamp(35px,3.5vw,54px);text-wrap:balance}.portfolio-hero h1,.motion-hero h1,.resume-hero h1{text-wrap:balance}\n","shell":"<header class=\"creator-bar\"><a href=\"https://skills.siliconstory.cn/free-tools/index.html\">PIKI / 纸感编辑杂志</a><span id=\"demoNotice\">PIKI 示例 · 本地交互</span><div><button id=\"editData\" type=\"button\">编辑资料</button><button id=\"saveData\" type=\"button\">保存 JSON</button><button id=\"saveHtml\" type=\"button\">下载完整 HTML</button><span id=\"motionTools\" hidden><button id=\"replayMotion\" type=\"button\">重播动效</button><label><input id=\"motionToggle\" type=\"checkbox\" checked>动效</label></span></div></header><div id=\"siteRoot\"></div><dialog id=\"dataDialog\" aria-labelledby=\"dataTitle\"><header><h2 id=\"dataTitle\">编辑资料</h2><button id=\"closeData\" type=\"button\">关闭</button></header><p>资料只在当前页面处理。图片使用包内 assets 或嵌入图片;正式发布需要自己的内容与服务。</p><label for=\"jsonInput\">数据 JSON</label><textarea id=\"jsonInput\" spellcheck=\"false\"></textarea><p id=\"jsonError\" role=\"alert\"></p><footer><button id=\"applyData\" type=\"button\" class=\"primary\">应用资料</button></footer></dialog><dialog id=\"detailDialog\" aria-labelledby=\"detailTitle\"><header><h2 id=\"detailTitle\"></h2><button id=\"closeDetail\" type=\"button\">关闭详情</button></header><div id=\"detailBody\"></div></dialog><dialog id=\"searchDialog\" aria-labelledby=\"searchTitle\"><header><h2 id=\"searchTitle\">搜索入口</h2><button id=\"closeSearch\" type=\"button\">关闭搜索</button></header><input id=\"commandQuery\" type=\"search\" aria-label=\"搜索入口\" placeholder=\"输入页面或记录名称\"><div id=\"commandResults\"></div></dialog><p id=\"webStatus\" role=\"status\" aria-live=\"polite\"></p>"}