Ethscriptions commited on
Commit
d61897b
·
verified ·
1 Parent(s): 68fdb58

Step 6-7: 播放器 + MP4 导出 + 文案 + 封面

Browse files
README.md CHANGED
@@ -61,8 +61,8 @@ pinned: false
61
  3. ✅ 程序化 3D 手部解剖模型:皮肤 / 骨骼 / 肌腱 / 腱鞘 / 关节骨架绑定 / 疼痛发光 / 器械与道具。
62
  4. ✅ 分镜时间轴:11 镜头 + 结尾的相机运动、姿态、图层、字幕、HUD。
63
  5. ✅ 程序化音乐与音效、旁白混音、ducking。
64
- 6. ⏳ 播放器 UI(手机竖屏适配、全屏、进度条)+ MP4 本地导出(24/30/60fps)。
65
- 7. ⏳ 四平台文案(标题 / 话题 / 正文,严格字数校验)+ 封面生成与下载。
66
  8. ⏳ 生产构建、检查,推送最终静态站点。
67
 
68
  ## 五、目录结构(推送到 Space 的内容)
@@ -80,3 +80,5 @@ README.md ← 本文件(计划 + 进度)
80
  - [x] Step 2:旁白 46 句逐句生成(zh-CN 神经网络语音,语速 +38%),自动裁剪静音并对齐时间轴,全片总长 **88.2 秒**(12 段)
81
  - [x] Step 3-4:程序化 3D 手部解剖模型(皮肤透视 / 骨骼 / 肌腱 / 腱鞘、疼痛红光、原创器械与生活道具)+ 12 段分镜时间轴(镜头运动、分屏、字幕、HUD、超声示意、截面图),全时间轴逐帧验证无运行错误
82
  - [x] Step 5:程序化配乐(紧张心跳前奏 → 小调解析 → 节奏推进 → 大调恢复)+ 10 类音效(疼痛脉冲、扫描、松解释放、提示音等,与画面事件逐帧对齐)+ 旁白自动闪避混音,离线渲染为 88.2 秒母带
 
 
 
61
  3. ✅ 程序化 3D 手部解剖模型:皮肤 / 骨骼 / 肌腱 / 腱鞘 / 关节骨架绑定 / 疼痛发光 / 器械与道具。
62
  4. ✅ 分镜时间轴:11 镜头 + 结尾的相机运动、姿态、图层、字幕、HUD。
63
  5. ✅ 程序化音乐与音效、旁白混音、ducking。
64
+ 6. ✅ 播放器 UI(手机竖屏适配、全屏、进度条)+ MP4 本地导出(24/30/60fps)。
65
+ 7. ✅ 四平台文案(标题 / 话题 / 正文,严格字数校验)+ 封面生成与下载。
66
  8. ⏳ 生产构建、检查,推送最终静态站点。
67
 
68
  ## 五、目录结构(推送到 Space 的内容)
 
80
  - [x] Step 2:旁白 46 句逐句生成(zh-CN 神经网络语音,语速 +38%),自动裁剪静音并对齐时间轴,全片总长 **88.2 秒**(12 段)
81
  - [x] Step 3-4:程序化 3D 手部解剖模型(皮肤透视 / 骨骼 / 肌腱 / 腱鞘、疼痛红光、原创器械与生活道具)+ 12 段分镜时间轴(镜头运动、分屏、字幕、HUD、超声示意、截面图),全时间轴逐帧验证无运行错误
82
  - [x] Step 5:程序化配乐(紧张心跳前奏 → 小调解析 → 节奏推进 → 大调恢复)+ 10 类音效(疼痛脉冲、扫描、松解释放、提示音等,与画面事件逐帧对齐)+ 旁白自动闪避混音,离线渲染为 88.2 秒母带
83
+ - [x] Step 6:竖屏播放器(手机全宽 / 桌面居中、点击暂停、分镜刻度进度条、全屏、静音、键盘快捷键)+ 浏览器本地 MP4 导出:1080×1920,24 / 30 / 60 fps 可选,H.264 + AAC(不支持时自动回退 Opus),带进度、剩余时间与取消
84
+ - [x] Step 7:四平台文案(标题 / 话题 / 正文实时字数校验,均在限制内,一键复制)+ 8 张封面实时渲染(小红书 3:4 / 4:3、抖音 3:4 / 4:3、B站 4:3 / 16:9、视频号 3:4 / 4:3),PNG 下载
assets/ADebug-BJNllebx.js ADDED
@@ -0,0 +1 @@
 
 
1
+ import{r as u}from"./index-Br42UDbl.js";import{g}from"./audio-BSS1MXf9.js";import{S as x}from"./scenes-oUf6rtD_.js";import"./index-BlGQAcOD.js";import"./state-B_bTBsCz.js";function S(){return u.useEffect(()=>{const h=performance.now();g(void 0,!0).then(o=>{const e=o.getChannelData(0),d=x.map(t=>{let s=0,i=0;const c=Math.floor(t.start*o.sampleRate),f=Math.floor(t.end*o.sampleRate);for(let a=c;a<f;a++)s+=e[a]*e[a],i=Math.max(i,Math.abs(e[a]));return`${t.index}:${Math.sqrt(s/(f-c)).toFixed(3)}/${i.toFixed(2)}`}),n=o.getChannelData(0),p=o.getChannelData(1),r=new Int16Array(n.length*2);for(let t=0;t<n.length;t++)r[2*t]=Math.max(-1,Math.min(1,n[t]))*32767,r[2*t+1]=Math.max(-1,Math.min(1,p[t]))*32767;const l=new Uint8Array(r.buffer);let m="";for(let t=0;t<l.length;t+=32768)m+=String.fromCharCode(...l.subarray(t,t+32768));window.__pcm=btoa(m),console.log("INFO dur="+o.duration.toFixed(2)+" ms="+(performance.now()-h).toFixed(0)+" "+d.join(" "))}).catch(o=>console.log("INFO ERROR "+o)).finally(()=>{window.__done=!0})},[]),null}export{S as default};
assets/App-Ckrxctng.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./Debug-Bc9dFGVg.js","./jsx-dev-runtime-Czb3f8pQ.js","./index-BlGQAcOD.js","./index-Br42UDbl.js","./engine-Bmw5iF75.js","./state-B_bTBsCz.js","./TDebug-C_pplWnw.js","./scenes-oUf6rtD_.js","./ADebug-BJNllebx.js","./audio-BSS1MXf9.js","./XDebug-COl9Ua8s.js","./exporter-CgYwbdYV.js","./Studio-1jRM1joF.js"])))=>i.map(i=>d[i]);
2
+ import{_ as t}from"./index-CXVdwQTy.js";import{j as e}from"./jsx-dev-runtime-Czb3f8pQ.js";import{r as s}from"./index-Br42UDbl.js";import"./index-BlGQAcOD.js";const i=s.lazy(()=>t(()=>import("./Debug-Bc9dFGVg.js"),__vite__mapDeps([0,1,2,3,4,5]),import.meta.url)),o=s.lazy(()=>t(()=>import("./TDebug-C_pplWnw.js"),__vite__mapDeps([6,1,2,3,4,5,7]),import.meta.url)),u=s.lazy(()=>t(()=>import("./ADebug-BJNllebx.js"),__vite__mapDeps([8,3,2,9,7,5]),import.meta.url)),m=s.lazy(()=>t(()=>import("./XDebug-COl9Ua8s.js"),__vite__mapDeps([10,3,2,11,4,5,7,9]),import.meta.url)),a=s.lazy(()=>t(()=>import("./Studio-1jRM1joF.js"),__vite__mapDeps([12,1,2,3,4,5,7,9,11]),import.meta.url));function n(){return e.jsxDEV("div",{className:"min-h-screen bg-[#04080f] flex items-center justify-center text-cyan-200 text-sm tracking-widest",children:"腱鞘炎 · 3D 医学科普动画 加载中…"},void 0,!1,{fileName:"/workspaces/frontend/src/App.tsx",lineNumber:11,columnNumber:5},this)}function N(){const[r,l]=s.useState(null);return s.useEffect(()=>{l(new URLSearchParams(window.location.search)),document.title="腱鞘炎 · 3D 医学科普动画",document.documentElement.lang="zh-CN"},[]),r?r.has("debug")?e.jsxDEV(s.Suspense,{fallback:null,children:e.jsxDEV(i,{},void 0,!1,{fileName:"/workspaces/frontend/src/App.tsx",lineNumber:21,columnNumber:56},this)},void 0,!1,{fileName:"/workspaces/frontend/src/App.tsx",lineNumber:21,columnNumber:30},this):r.has("tdebug")?e.jsxDEV(s.Suspense,{fallback:null,children:e.jsxDEV(o,{},void 0,!1,{fileName:"/workspaces/frontend/src/App.tsx",lineNumber:22,columnNumber:57},this)},void 0,!1,{fileName:"/workspaces/frontend/src/App.tsx",lineNumber:22,columnNumber:31},this):r.has("adebug")?e.jsxDEV(s.Suspense,{fallback:null,children:e.jsxDEV(u,{},void 0,!1,{fileName:"/workspaces/frontend/src/App.tsx",lineNumber:23,columnNumber:57},this)},void 0,!1,{fileName:"/workspaces/frontend/src/App.tsx",lineNumber:23,columnNumber:31},this):r.has("xdebug")?e.jsxDEV(s.Suspense,{fallback:null,children:e.jsxDEV(m,{},void 0,!1,{fileName:"/workspaces/frontend/src/App.tsx",lineNumber:24,columnNumber:57},this)},void 0,!1,{fileName:"/workspaces/frontend/src/App.tsx",lineNumber:24,columnNumber:31},this):e.jsxDEV(s.Suspense,{fallback:e.jsxDEV(n,{},void 0,!1,{fileName:"/workspaces/frontend/src/App.tsx",lineNumber:25,columnNumber:30},this),children:e.jsxDEV(a,{},void 0,!1,{fileName:"/workspaces/frontend/src/App.tsx",lineNumber:25,columnNumber:42},this)},void 0,!1,{fileName:"/workspaces/frontend/src/App.tsx",lineNumber:25,columnNumber:10},this):e.jsxDEV(n,{},void 0,!1,{fileName:"/workspaces/frontend/src/App.tsx",lineNumber:20,columnNumber:18},this)}export{N as default};
assets/Debug-Bc9dFGVg.js ADDED
@@ -0,0 +1 @@
 
 
1
+ import{j as x}from"./jsx-dev-runtime-Czb3f8pQ.js";import{r as u}from"./index-Br42UDbl.js";import{E as l}from"./engine-Bmw5iF75.js";import{b as g,P as b,o as w}from"./state-B_bTBsCz.js";import"./index-BlGQAcOD.js";function J(){const d=u.useRef(null);return u.useEffect(()=>{const t=JSON.parse(decodeURIComponent(new URLSearchParams(location.search).get("debug")||"{}")),i=new l;i.setSize(540,960);const c=d.current;c.width=540,c.height=960;const h=t.target??[0,.2,0],f=g({cam:{pos:w(h,t.dist??5,t.yaw??0,t.pitch??.1),target:h,fov:35},arm:{pos:[0,0,0],rot:t.rot??[0,.6,0]},pose:t.poseArr??[...b[t.pose??"rest"]],xray:t.xray??0,bone:t.bone??1,tendon:t.tendon??1,sheath:t.sheath??1,thick:t.thick??0,pain:t.pain??0,friction:t.friction??0,props:Object.fromEntries((t.props??[]).map(r=>[r,{vis:1,depth:.3}])),time:1});i.render({views:[{rect:[0,0,1,1],state:f}]},c.getContext("2d"),1,{w:540,h:960});const o=i.model,p=i.cams[0],n=(r,a)=>{const e=r.localToWorld(new o.anchors.pain.constructor(0,a,0)),s=o.project(e,p);return[Math.round(s.x*540),Math.round(s.y*960),+e.x.toFixed(2),+e.y.toFixed(2),+e.z.toFixed(2)]},m={thumbTip:n(o.thumbJoints[2],.27),idxTip:n(o.fingerJoints[0][2],.2),midTip:n(o.fingerJoints[1][2],.21),litTip:n(o.fingerJoints[3][2],.18),wrist:n(o.wrist,0),elbow:n(o.forearm,-2.6),pain:(()=>{const r=o.project(o.anchors.pain,p);return[Math.round(r.x*540),Math.round(r.y*960)]})()};for(const[r,a]of Object.entries(o.props))if(a.visible){const e=a.getWorldPosition(new o.anchors.pain.constructor),s=o.project(e,p);m["prop_"+r]=[Math.round(s.x*540),Math.round(s.y*960),+e.x.toFixed(2),+e.y.toFixed(2),+e.z.toFixed(2)]}console.log("INFO "+JSON.stringify(m)),window.__done=!0},[]),x.jsxDEV("canvas",{ref:d,style:{width:540,height:960}},void 0,!1,{fileName:"/workspaces/frontend/src/video/Debug.tsx",lineNumber:34,columnNumber:10},this)}export{J as default};
assets/ErrorBoundary-DwultlP_.js ADDED
@@ -0,0 +1 @@
 
 
1
+ var m=Object.defineProperty;var p=(e,r,t)=>r in e?m(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var i=(e,r,t)=>p(e,typeof r!="symbol"?r+"":r,t);import{j as o}from"./jsx-dev-runtime-Czb3f8pQ.js";import{r as f}from"./index-Br42UDbl.js";import"./index-BlGQAcOD.js";const u="__dep_reload",a=6,c=6e4,g=["reading 'useState'","reading 'useEffect'","reading 'useRef'","reading 'useCallback'","reading 'useMemo'","reading 'useContext'","reading 'useReducer'"];function d(e){return g.some(r=>e.includes(r))}function l(){try{const e=sessionStorage.getItem(u);if(e)return JSON.parse(e)}catch{}return{c:0,t:0}}class N extends f.Component{constructor(){super(...arguments);i(this,"state",{error:null})}static getDerivedStateFromError(t){return{error:t}}componentDidCatch(t){if(!d(t.message))return;const s=l(),n=Date.now()-s.t>c?0:s.c;n<a&&(sessionStorage.setItem(u,JSON.stringify({c:n+1,t:Date.now()})),setTimeout(()=>location.reload(),3e3))}render(){if(this.state.error){if(this.props.fallback)return this.props.fallback;if(d(this.state.error.message)){const{c:t,t:s}=l();if(!(Date.now()-s<=c)||t<a)return o.jsxDEV("div",{style:{padding:"24px",margin:"16px",borderRadius:"12px",background:"rgba(59,130,246,0.06)",border:"1px solid rgba(59,130,246,0.15)",color:"#3b82f6",fontSize:"13px",fontFamily:"system-ui, sans-serif",textAlign:"center"},children:[o.jsxDEV("p",{style:{fontWeight:600,marginBottom:"4px"},children:"Loading dependencies..."},void 0,!1,{fileName:"/workspaces/frontend/src/ErrorBoundary.tsx",lineNumber:81,columnNumber:15},this),o.jsxDEV("p",{style:{opacity:.7,fontSize:"12px"},children:"Reloading automatically"},void 0,!1,{fileName:"/workspaces/frontend/src/ErrorBoundary.tsx",lineNumber:82,columnNumber:15},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/ErrorBoundary.tsx",lineNumber:70,columnNumber:13},this)}return o.jsxDEV("div",{style:{padding:"24px",margin:"16px",borderRadius:"12px",background:"rgba(245,34,45,0.06)",border:"1px solid rgba(245,34,45,0.15)",color:"#c0392b",fontSize:"13px",fontFamily:"monospace"},children:[o.jsxDEV("p",{style:{fontWeight:600,marginBottom:"8px"},children:"Component Error"},void 0,!1,{fileName:"/workspaces/frontend/src/ErrorBoundary.tsx",lineNumber:99,columnNumber:11},this),o.jsxDEV("p",{style:{opacity:.8},children:this.state.error.message},void 0,!1,{fileName:"/workspaces/frontend/src/ErrorBoundary.tsx",lineNumber:100,columnNumber:11},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/ErrorBoundary.tsx",lineNumber:89,columnNumber:9},this)}return this.props.children}}export{N as default};
assets/Studio-1jRM1joF.js ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{j as e}from"./jsx-dev-runtime-Czb3f8pQ.js";import{r as n}from"./index-Br42UDbl.js";import{E as Q}from"./engine-Bmw5iF75.js";import{r as le,C as F,l as ne,F as ae,S as U,f as ee,D as y,s as de}from"./scenes-oUf6rtD_.js";import{g as ce}from"./audio-BSS1MXf9.js";import{e as ue}from"./exporter-CgYwbdYV.js";import{o as me}from"./state-B_bTBsCz.js";import"./index-BlGQAcOD.js";const te=t=>Array.from(t).length,se=t=>t.topics.map(i=>"#"+i).join(" ");function q(t){return t.topics.length?t.body+`
2
+
3
+ `+se(t):t.body}function fe(t){return te(t.limits.bodyIncludesTopics?q(t):t.body)}const xe=[{key:"xhs",name:"小红书",color:"#ff2442",limits:{title:20,topics:10,body:1e3,bodyIncludesTopics:!0},title:"拇指一动就疼?3D看懂腱鞘炎",body:`抱娃、刷手机、拧瓶盖……
4
+ 手腕靠拇指这一侧,一用力就像被“卡住”一样疼?
5
+
6
+ 做了一条 3D 解剖动画,把皮肤“变透明”,直接看里面发生了什么👇
7
+
8
+ 🔹 腱鞘=包住肌腱的“小通道”
9
+ 正常时肌腱在里面顺畅滑动;反复用力后,腱鞘增厚、通道变窄,肌腱一滑就摩擦 → 疼
10
+
11
+ 🔹 为什么一动就疼
12
+ 抓、捏、拧这些动作,都会让肌腱在狭窄处来回拉扯
13
+
14
+ 🔹 谁更容易中招
15
+ 宝妈抱娃|长时间用手机|键盘鼠标党|经常用力的手工活
16
+
17
+ 🔹 处理顺序很重要
18
+ 先判断:疼在哪、哪个动作最明显、是否反复发作
19
+ 再选择:休息制动、护具、理疗、药物、局部注射等
20
+ 反复发作、保守效果不好时,部分情况会考虑小针刀等微创松解
21
+
22
+ 🔹 小针刀到底在干什么
23
+ 不是“切开手腕”,而是:定位 → 消毒 → 局部麻醉 → 在影像引导下对狭窄处做“精准、有限、局部”的松解
24
+ 目标只有一个:让肌腱重新顺畅滑动
25
+
26
+ 🔹 恢复期
27
+ 疼痛减轻 → 活动改善 → 逐步回到抱娃、打字、拿东西
28
+ 别一好就猛用手,循序渐进最重要
29
+
30
+ 📌 一句话记住:腱鞘炎的核心不是“手腕疼”,而是肌腱在狭窄的腱鞘里滑不动。
31
+
32
+ 你是抱娃疼、手机疼,还是打字疼?评论区说说你最疼的那个动作👇
33
+
34
+ ⚠️ 原创 3D 示意动画,仅作健康科普,不能替代面诊。具体是否适合某种治疗,请由专业医生评估。`,topics:["腱鞘炎","妈妈手","手腕疼","拇指疼","健康科普","3D动画","医学科普","小针刀","打工人","护手"],tips:"建议封面用 3:4 竖版;标题≤20字,话题已计入正文 1000 字。"},{key:"douyin",name:"抖音",color:"#25f4ee",limits:{title:30,topics:5,body:1e3,bodyIncludesTopics:!0},title:"手腕拇指侧一用力就疼?3D动画带你看清腱鞘炎",body:`抱娃、刷手机、拧瓶盖,拇指一侧一用力就疼?
35
+ 90 秒 3D 解剖动画,把皮肤变透明:
36
+ ✅ 腱鞘增厚 → 空间变窄 → 肌腱一滑就摩擦
37
+ ✅ 先判断,再处理:休息、护具、理疗、药物、注射……
38
+ ✅ 反复发作时,小针刀做的是“精准、有限、局部”的松解
39
+ ✅ 目标只有一个:让肌腱重新顺畅滑动
40
+ 记住:腱鞘炎不是简单的手腕疼,而是肌腱在狭窄的腱鞘里滑不动。
41
+ 你最疼的是哪个动作?评论区告诉我👇
42
+ (原创3D示意动画,仅供科普,不替代面诊)`,topics:["腱鞘炎","妈妈手","手腕疼","健康科普","3D医学动画"],tips:"竖屏 9:16 原生发布;封面准备 3:4 与 4:3 两版。"},{key:"bili",name:"B站",color:"#00aeec",limits:{title:80,topics:10,body:2e3,bodyIncludesTopics:!1},title:"【3D解剖动画】拇指一动就疼?90秒看懂腱鞘炎:为什么疼、怎么判断、小针刀如何精准松解",body:`这是一条原创 3D 医学科普动画,用一只“可以透视”的手,把腱鞘炎从疼痛到恢复的完整过程讲清楚。
43
+
44
+ 【时间轴】
45
+ 00:00 疼痛开始:拇指一侧,一用力就疼
46
+ 00:06 腱鞘炎到底发生了什么:腱鞘=肌腱的“小通道”,增厚 → 变窄 → 摩擦
47
+ 00:15 为什么一动就疼:抓、捏、拧
48
+ 00:20 哪些人更容易出现:抱娃、手机、键盘鼠标、反复用力
49
+ 00:26 不要一上来就直接治疗:先定位、先判断
50
+ 00:34 常见治疗方法:休息制动、护具、理疗、药物、注射
51
+ 00:44 重点进入小针刀:适合什么情况、解决什么问题
52
+ 00:51 小针刀治疗过程:定位 → 消毒 → 麻醉 → 精准松解
53
+ 01:01 松解前后对比:狭窄 vs 顺畅
54
+ 01:07 从疼痛到恢复:疼痛减轻、活动改善、回归日常
55
+ 01:14 最后的记忆点
56
+
57
+ 【一句话总结】
58
+ 腱鞘炎的核心不是“手腕疼”,而是肌腱在狭窄的腱鞘里滑不动。处理的思路是:先判断,再选择;即使做松解,也强调精准、有限、局部,目标是让肌腱重新顺畅滑动。
59
+
60
+ 【制作说明】
61
+ · 全部 3D 模型、器械、动画、配乐与音效均为原创程序化生成;
62
+ · 片中器械为示意模型,不代表任何品牌产品;
63
+ · 动画为原理示意,比例与操作细节经过简化,不能作为操作指导。
64
+
65
+ ⚠️ 本视频仅作健康科���,不替代面诊。是否适合任何一种治疗,请由专业医生面诊评估。
66
+
67
+ 你最疼的是哪个动作?抱娃、刷手机、拧瓶盖还是打字?弹幕/评论区告诉我~`,topics:["腱鞘炎","妈妈手","医学科普","3D动画","人体解剖","健康","手腕疼","科普","小针刀","原创动画"],tips:"建议投稿分区:知识 › 医学健康;个人空间封面使用 16:9,投稿封面使用 4:3。"},{key:"sph",name:"视频号",color:"#fa9d3b",limits:{title:16,topics:null,body:null,bodyIncludesTopics:!0},title:"拇指一动就疼?看懂腱鞘炎",body:`抱娃、刷手机、拧瓶盖,拇指一侧一用力就疼?
68
+ 这条 3D 解剖动画,带你看清腱鞘炎从疼痛到恢复的全过程:
69
+
70
+ 1️⃣ 腱鞘增厚、通道变窄,肌腱一滑就摩擦
71
+ 2️⃣ 抓、捏、拧,都会加重拉扯
72
+ 3️⃣ 先判断,再处理:休息、护具、理疗、药物、注射
73
+ 4️⃣ 反复发作时,小针刀强调“精准、有限、局部”的松解
74
+ 5️⃣ 目标:让肌腱重新顺畅滑动,慢慢回归日常
75
+
76
+ 记住一句话:腱鞘炎的核心,是肌腱在狭窄的腱鞘里滑不动。
77
+
78
+ 转给家里经常抱娃、天天看手机的人👇
79
+ (原创3D示意动画,仅供科普,不替代面诊)`,topics:["腱鞘炎","妈妈手","手腕疼","拇指疼","健康科普","医学科普","3D动画","中老年健康","宝妈"],tips:"主页卡片用 3:4,转发分享卡片用 4:3。"}],T=[{key:"xhs-34",platform:"小红书",label:"3:4 竖版",w:1080,h:1440,l1:"拇指一动就疼?",l2:"3D看懂腱鞘炎",hot:"腱鞘炎",color:"#ff2442"},{key:"xhs-43",platform:"小红书",label:"4:3 横版",w:1440,h:1080,l1:"拇指一动就疼?",l2:"3D看懂腱鞘炎",hot:"腱鞘炎",color:"#ff2442"},{key:"dy-34",platform:"抖音",label:"3:4 竖版",w:1080,h:1440,l1:"一用力就疼?",l2:"透视腱鞘炎",hot:"腱鞘炎",color:"#25f4ee"},{key:"dy-43",platform:"抖音",label:"4:3 横版",w:1440,h:1080,l1:"一用力就疼?",l2:"透视腱鞘炎",hot:"腱鞘炎",color:"#25f4ee"},{key:"bili-43",platform:"B站",label:"4:3 投稿封面",w:1440,h:1080,l1:"【3D解剖】",l2:"看懂腱鞘炎",hot:"腱鞘炎",color:"#00aeec"},{key:"bili-169",platform:"B站",label:"16:9 个人空间",w:1920,h:1080,l1:"拇指一动就疼?",l2:"90秒看懂腱鞘炎",hot:"腱鞘炎",color:"#00aeec"},{key:"sph-34",platform:"视频号",label:"3:4 主页卡片",w:1080,h:1440,l1:"拇指疼?",l2:"看懂腱鞘炎",hot:"腱鞘炎",color:"#fa9d3b"},{key:"sph-43",platform:"视频号",label:"4:3 分享卡片",w:1440,h:1080,l1:"拇指疼?",l2:"看懂腱鞘炎",hot:"腱鞘炎",color:"#fa9d3b"}];let H=null;function Ne(t){const i=U[1].start+8.6;return{...ee(i).views[0].state,pain:1,friction:1,thick:1,xray:1,skin:.8,bone:1,tendon:1,sheath:1,focus:.5,cam:{pos:me([0,0,0],t?2.35:2,.05,.14),target:[0,0,0],fov:35,follow:1,shift:t?[.56,.64]:[.66,.54]}}}function Y(t,i,s,l,c,a){t.beginPath(),t.moveTo(i+a,s),t.arcTo(i+l,s,i+l,s+c,a),t.arcTo(i+l,s+c,i,s+c,a),t.arcTo(i,s+c,i,s,a),t.arcTo(i,s,i+l,s,a),t.closePath()}function re(t,i){const{w:s,h:l}=t;i.width=s,i.height=l;const c=i.getContext("2d");H||(H=new Q),H.setSize(s,l);const a=l>s,m=Ne(a),d=m.time;return H.render({views:[{rect:[0,0,1,1],state:m,bg:"lab"}],overlay:(r,N)=>{const f=Math.min(s,l),b=ae,g=a?r.createLinearGradient(0,0,0,l*.55):r.createLinearGradient(0,0,s*.6,0);g.addColorStop(0,"rgba(2,8,18,0.92)"),g.addColorStop(.6,"rgba(2,8,18,0.55)"),g.addColorStop(1,"rgba(2,8,18,0)"),r.fillStyle=g,r.fillRect(0,0,s,l);const V=N.anchor("pain"),x=N.anchor("sheath");le(r,V.x,V.y,f*.075,1,d,F.red,1),r.save(),r.scale(f/1080,f/1080);const w=1080/f;ne(r,x.x*w,x.y*w,x.x*w+(a?170:190),x.y*w+(a?230:210),"腱鞘增厚 · 通道变窄",1,F.yellow,34),r.restore();const S=f*.07,$=a?f*.09:f*.12;r.textBaseline="top",r.textAlign="left";const E=f*.036;r.font=`900 ${E}px ${b}`;const A="3D 解剖动画 · 医学科普",z=r.measureText(A).width+E*1.4;Y(r,S,$,z,E*1.8,E*.9),r.fillStyle="rgba(95,212,255,0.16)",r.fill(),r.strokeStyle=F.cyan,r.lineWidth=2,r.stroke(),r.fillStyle=F.cyan,r.fillText(A,S+E*.7,$+E*.4);const B=f*(t.l1.length>6?.105:.125);r.font=`900 ${B}px ${b}`,r.shadowColor="rgba(0,0,0,0.6)",r.shadowBlur=20,r.fillStyle="#fff",r.fillText(t.l1,S,$+E*2.6);const C=f*(t.l2.length>6?.115:.135);r.font=`900 ${C}px ${b}`;const D=$+E*2.6+B*1.2,R=t.l2.indexOf(t.hot),L=R>=0?t.l2.slice(0,R):t.l2;if(r.fillStyle="#fff",r.fillText(L,S,D),R>=0){const k=S+r.measureText(L).width;r.shadowColor="rgba(255,40,40,0.9)",r.shadowBlur=40;const j=r.createLinearGradient(0,D,0,D+C);j.addColorStop(0,"#ff7a6a"),j.addColorStop(1,"#ff2a2a"),r.fillStyle=j,r.fillText(t.hot,k,D),r.fillText(t.l2.slice(R+t.hot.length),k+r.measureText(t.hot).width,D)}r.shadowBlur=0;const o=f*.03;r.font=`800 ${o}px ${b}`;let u=S;const p=D+C*1.35,M=["疼痛","定位","处理","松解","恢复"];M.forEach((k,j)=>{const I=r.measureText(k).width+o*1.2;Y(r,u,p,I,o*1.7,o*.5),r.fillStyle=j===0?"rgba(255,59,59,0.85)":j===4?"rgba(62,224,143,0.85)":"rgba(255,255,255,0.14)",r.fill(),r.fillStyle="#fff",r.fillText(k,u+o*.6,p+o*.35),u+=I,j<M.length-1&&(r.fillStyle="rgba(255,255,255,0.6)",r.fillText("›",u+o*.3,p+o*.3),u+=o*1.1)}),r.fillStyle=t.color,r.fillRect(0,l-f*.012,s,f*.012),r.font=`600 ${f*.022}px ${b}`,r.fillStyle="rgba(255,255,255,0.6)",r.textBaseline="bottom",r.fillText("原创3D医学示意动画 · 仅供科普,不替代面诊",S,l-f*.04)}},c,d,{w:s,h:l}),i}function be(t){const i=re(t,document.createElement("canvas"));return new Promise((s,l)=>i.toBlob(c=>c?s(c):l(new Error("toBlob")),"image/png"))}/**
80
+ * @license lucide-react v0.454.0 - ISC
81
+ *
82
+ * This source code is licensed under the ISC license.
83
+ * See the LICENSE file in the root directory of this source tree.
84
+ */const he=t=>t.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),oe=(...t)=>t.filter((i,s,l)=>!!i&&i.trim()!==""&&l.indexOf(i)===s).join(" ").trim();/**
85
+ * @license lucide-react v0.454.0 - ISC
86
+ *
87
+ * This source code is licensed under the ISC license.
88
+ * See the LICENSE file in the root directory of this source tree.
89
+ */var pe={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/**
90
+ * @license lucide-react v0.454.0 - ISC
91
+ *
92
+ * This source code is licensed under the ISC license.
93
+ * See the LICENSE file in the root directory of this source tree.
94
+ */const ve=n.forwardRef(({color:t="currentColor",size:i=24,strokeWidth:s=2,absoluteStrokeWidth:l,className:c="",children:a,iconNode:m,...d},r)=>n.createElement("svg",{ref:r,...pe,width:i,height:i,stroke:t,strokeWidth:l?Number(s)*24/Number(i):s,className:oe("lucide",c),...d},[...m.map(([N,f])=>n.createElement(N,f)),...Array.isArray(a)?a:[a]]));/**
95
+ * @license lucide-react v0.454.0 - ISC
96
+ *
97
+ * This source code is licensed under the ISC license.
98
+ * See the LICENSE file in the root directory of this source tree.
99
+ */const v=(t,i)=>{const s=n.forwardRef(({className:l,...c},a)=>n.createElement(ve,{ref:a,iconNode:i,className:oe(`lucide-${he(t)}`,l),...c}));return s.displayName=`${t}`,s};/**
100
+ * @license lucide-react v0.454.0 - ISC
101
+ *
102
+ * This source code is licensed under the ISC license.
103
+ * See the LICENSE file in the root directory of this source tree.
104
+ */const ie=v("Check",[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]]);/**
105
+ * @license lucide-react v0.454.0 - ISC
106
+ *
107
+ * This source code is licensed under the ISC license.
108
+ * See the LICENSE file in the root directory of this source tree.
109
+ */const we=v("Copy",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]]);/**
110
+ * @license lucide-react v0.454.0 - ISC
111
+ *
112
+ * This source code is licensed under the ISC license.
113
+ * See the LICENSE file in the root directory of this source tree.
114
+ */const W=v("Download",[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["polyline",{points:"7 10 12 15 17 10",key:"2ggqvy"}],["line",{x1:"12",x2:"12",y1:"15",y2:"3",key:"1vk2je"}]]);/**
115
+ * @license lucide-react v0.454.0 - ISC
116
+ *
117
+ * This source code is licensed under the ISC license.
118
+ * See the LICENSE file in the root directory of this source tree.
119
+ */const ke=v("FileText",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M10 9H8",key:"b1mrlr"}],["path",{d:"M16 13H8",key:"t4e002"}],["path",{d:"M16 17H8",key:"z1uh3a"}]]);/**
120
+ * @license lucide-react v0.454.0 - ISC
121
+ *
122
+ * This source code is licensed under the ISC license.
123
+ * See the LICENSE file in the root directory of this source tree.
124
+ */const ye=v("Film",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M7 3v18",key:"bbkbws"}],["path",{d:"M3 7.5h4",key:"zfgn84"}],["path",{d:"M3 12h18",key:"1i2n21"}],["path",{d:"M3 16.5h4",key:"1230mu"}],["path",{d:"M17 3v18",key:"in4fa5"}],["path",{d:"M17 7.5h4",key:"myr1c1"}],["path",{d:"M17 16.5h4",key:"go4c1d"}]]);/**
125
+ * @license lucide-react v0.454.0 - ISC
126
+ *
127
+ * This source code is licensed under the ISC license.
128
+ * See the LICENSE file in the root directory of this source tree.
129
+ */const ge=v("Image",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2",key:"1m3agn"}],["circle",{cx:"9",cy:"9",r:"2",key:"af1f0g"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21",key:"1xmnt7"}]]);/**
130
+ * @license lucide-react v0.454.0 - ISC
131
+ *
132
+ * This source code is licensed under the ISC license.
133
+ * See the LICENSE file in the root directory of this source tree.
134
+ */const Se=v("Maximize",[["path",{d:"M8 3H5a2 2 0 0 0-2 2v3",key:"1dcmit"}],["path",{d:"M21 8V5a2 2 0 0 0-2-2h-3",key:"1e4gt3"}],["path",{d:"M3 16v3a2 2 0 0 0 2 2h3",key:"wsl5sc"}],["path",{d:"M16 21h3a2 2 0 0 0 2-2v-3",key:"18trek"}]]);/**
135
+ * @license lucide-react v0.454.0 - ISC
136
+ *
137
+ * This source code is licensed under the ISC license.
138
+ * See the LICENSE file in the root directory of this source tree.
139
+ */const Ee=v("Minimize",[["path",{d:"M8 3v3a2 2 0 0 1-2 2H3",key:"hohbtr"}],["path",{d:"M21 8h-3a2 2 0 0 1-2-2V3",key:"5jw1f3"}],["path",{d:"M3 16h3a2 2 0 0 1 2 2v3",key:"198tvr"}],["path",{d:"M16 21v-3a2 2 0 0 1 2-2h3",key:"ph8mxp"}]]);/**
140
+ * @license lucide-react v0.454.0 - ISC
141
+ *
142
+ * This source code is licensed under the ISC license.
143
+ * See the LICENSE file in the root directory of this source tree.
144
+ */const De=v("Pause",[["rect",{x:"14",y:"4",width:"4",height:"16",rx:"1",key:"zuxfzm"}],["rect",{x:"6",y:"4",width:"4",height:"16",rx:"1",key:"1okwgv"}]]);/**
145
+ * @license lucide-react v0.454.0 - ISC
146
+ *
147
+ * This source code is licensed under the ISC license.
148
+ * See the LICENSE file in the root directory of this source tree.
149
+ */const J=v("Play",[["polygon",{points:"6 3 20 12 6 21 6 3",key:"1oa8hb"}]]);/**
150
+ * @license lucide-react v0.454.0 - ISC
151
+ *
152
+ * This source code is licensed under the ISC license.
153
+ * See the LICENSE file in the root directory of this source tree.
154
+ */const je=v("RotateCcw",[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]]);/**
155
+ * @license lucide-react v0.454.0 - ISC
156
+ *
157
+ * This source code is licensed under the ISC license.
158
+ * See the LICENSE file in the root directory of this source tree.
159
+ */const Ve=v("Volume2",[["path",{d:"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z",key:"uqj9uw"}],["path",{d:"M16 9a5 5 0 0 1 0 6",key:"1q6k2b"}],["path",{d:"M19.364 18.364a9 9 0 0 0 0-12.728",key:"ijwkga"}]]);/**
160
+ * @license lucide-react v0.454.0 - ISC
161
+ *
162
+ * This source code is licensed under the ISC license.
163
+ * See the LICENSE file in the root directory of this source tree.
164
+ */const Ce=v("VolumeX",[["path",{d:"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z",key:"uqj9uw"}],["line",{x1:"22",x2:"16",y1:"9",y2:"15",key:"1ewh16"}],["line",{x1:"16",x2:"22",y1:"9",y2:"15",key:"5ykzw1"}]]);/**
165
+ * @license lucide-react v0.454.0 - ISC
166
+ *
167
+ * This source code is licensed under the ISC license.
168
+ * See the LICENSE file in the root directory of this source tree.
169
+ */const Me=v("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]),_=t=>`${Math.floor(t/60)}:${String(Math.floor(t%60)).padStart(2,"0")}`;function X(t,i){const s=document.createElement("a");s.href=URL.createObjectURL(t),s.download=i,document.body.appendChild(s),s.click(),s.remove(),setTimeout(()=>URL.revokeObjectURL(s.href),6e4)}function Te(){const t=n.useRef(null),i=n.useRef(null),s=n.useRef(null),l=n.useRef({t:0,playing:!1,startAt:0,startT:0,dirty:!0}),c=n.useRef({ctx:null,buf:null,src:null,gain:null}),[a,m]=n.useState(0),[d,r]=n.useState(!1),[N,f]=n.useState(!1),[b,g]=n.useState(!1),[V,x]=n.useState({p:0,label:"加载音频"}),[w,S]=n.useState(null),[$,E]=n.useState(!1);n.useEffect(()=>{ce((o,u)=>x({p:o,label:u})).then(o=>{c.current.buf=o,x(null)}).catch(o=>{S("音频加载失败:"+o.message),x(null)})},[]),n.useEffect(()=>{const o=i.current,u=Math.min(window.innerWidth,window.innerHeight)<600,p=u?540:720,M=u?960:1280;o.width=p,o.height=M;let k;try{k=new Q,k.setSize(p,M),s.current=k}catch(h){S("当前浏览器不支持 WebGL:"+h.message);return}const j=o.getContext("2d",{alpha:!1});let I=0,Z=0;const K=()=>{I=requestAnimationFrame(K);const h=l.current;if(h.playing){const P=c.current.ctx;h.t=h.startT+(P?P.currentTime-h.startAt:performance.now()/1e3-h.startAt),h.t>=y&&(h.t=y,A(),r(!1)),h.dirty=!0}if(h.dirty){h.dirty=!1,k.render(ee(h.t),j,h.t);const P=performance.now();(P-Z>100||!h.playing)&&(Z=P,m(h.t))}};return K(),()=>{cancelAnimationFrame(I),k.renderer.dispose()}},[]);const A=()=>{var u;const o=c.current;try{(u=o.src)==null||u.stop()}catch{}o.src=null,l.current.playing=!1},z=n.useCallback(async()=>{const o=c.current,u=l.current;if(u.t>=y-.05&&(u.t=0),o.ctx||(o.ctx=new AudioContext({sampleRate:48e3}),o.gain=o.ctx.createGain(),o.gain.connect(o.ctx.destination)),await o.ctx.resume(),o.gain.gain.value=N?0:1,o.buf){const p=o.ctx.createBufferSource();p.buffer=o.buf,p.connect(o.gain),p.start(o.ctx.currentTime+.03,Math.min(u.t,o.buf.duration-.01)),o.src=p,u.startAt=o.ctx.currentTime+.03}else u.startAt=o.ctx.currentTime;u.startT=u.t,u.playing=!0,r(!0),E(!0)},[N]),B=n.useCallback(()=>{A(),r(!1)},[]),C=()=>l.current.playing?B():z(),D=o=>{const u=l.current.playing;u&&A(),l.current.t=o,l.current.dirty=!0,m(o),u&&z()};n.useEffect(()=>{c.current.gain&&(c.current.gain.gain.value=N?0:1)},[N]);const R=async()=>{const o=t.current;if(document.fullscreenElement){await document.exitFullscreen();return}if(b){g(!1);return}if(o.requestFullscreen)try{await o.requestFullscreen();return}catch{}g(!0)};n.useEffect(()=>{const o=()=>g(!!document.fullscreenElement);return document.addEventListener("fullscreenchange",o),()=>document.removeEventListener("fullscreenchange",o)},[]),n.useEffect(()=>{const o=u=>{var p,M;((p=u.target)==null?void 0:p.tagName)==="TEXTAREA"||((M=u.target)==null?void 0:M.tagName)==="INPUT"||(u.code==="Space"&&(u.preventDefault(),C()),u.code==="ArrowRight"&&D(Math.min(y,l.current.t+5)),u.code==="ArrowLeft"&&D(Math.max(0,l.current.t-5)))};return window.addEventListener("keydown",o),()=>window.removeEventListener("keydown",o)});const L=de(a);return e.jsxDEV("div",{ref:t,className:b?"fixed inset-0 z-50 bg-black flex items-center justify-center":"relative w-full flex items-center justify-center",children:e.jsxDEV("div",{className:"relative bg-black overflow-hidden shadow-[0_0_80px_rgba(60,180,255,0.15)] sm:rounded-2xl",style:{aspectRatio:"9 / 16",height:b?"100%":"min(100svh - 24px, calc(100vw * 16 / 9))",maxWidth:"100%"},children:[e.jsxDEV("canvas",{ref:i,className:"w-full h-full block cursor-pointer",onClick:C},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:137,columnNumber:9},this),!d&&e.jsxDEV("button",{onClick:C,className:"absolute inset-0 flex flex-col items-center justify-center gap-4 bg-black/25 hover:bg-black/15 transition",children:[e.jsxDEV("span",{className:"w-20 h-20 rounded-full bg-white/90 flex items-center justify-center shadow-2xl",children:e.jsxDEV(J,{className:"w-9 h-9 text-slate-900 ml-1",fill:"currentColor"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:141,columnNumber:15},this)},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:140,columnNumber:13},this),!$&&e.jsxDEV("span",{className:"text-white/90 text-sm font-semibold tracking-wide px-3 py-1 rounded-full bg-black/40",children:"点击播放 · 有声音"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:143,columnNumber:26},this),V&&e.jsxDEV("span",{className:"text-cyan-200 text-xs",children:[V.label," ",Math.round(V.p*100),"%"]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:144,columnNumber:22},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:139,columnNumber:11},this),w&&e.jsxDEV("div",{className:"absolute top-3 left-3 right-3 text-xs bg-red-900/80 text-red-100 rounded px-3 py-2",children:w},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:147,columnNumber:17},this),e.jsxDEV("div",{className:`absolute left-0 right-0 bottom-0 px-3 ${b?"pb-3":"pb-12 sm:pb-3"} pt-8 bg-gradient-to-t from-black/80 to-transparent`,onClick:o=>o.stopPropagation(),children:[e.jsxDEV("div",{className:"relative h-5 flex items-center group",children:[e.jsxDEV("div",{className:"absolute inset-x-0 h-1 rounded bg-white/20 top-1/2 -translate-y-1/2"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:152,columnNumber:13},this),U.map(o=>e.jsxDEV("div",{className:"absolute w-px h-2 bg-white/50 top-1/2 -translate-y-1/2",style:{left:`${o.start/y*100}%`}},o.index,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:153,columnNumber:29},this)),e.jsxDEV("div",{className:"absolute h-1 rounded bg-cyan-400 top-1/2 -translate-y-1/2 left-0",style:{width:`${a/y*100}%`}},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:154,columnNumber:13},this),e.jsxDEV("input",{type:"range",min:0,max:y,step:.01,value:a,onChange:o=>D(+o.target.value),className:"absolute inset-0 w-full opacity-0 cursor-pointer","aria-label":"进度"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:155,columnNumber:13},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:151,columnNumber:11},this),e.jsxDEV("div",{className:"flex items-center gap-3 text-white text-xs mt-1",children:[e.jsxDEV("button",{onClick:C,"aria-label":"播放/暂停",children:d?e.jsxDEV(De,{className:"w-5 h-5"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:159,columnNumber:68},this):e.jsxDEV(J,{className:"w-5 h-5"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:159,columnNumber:100},this)},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:159,columnNumber:13},this),e.jsxDEV("span",{className:"tabular-nums opacity-80",children:[_(a)," / ",_(y)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:160,columnNumber:13},this),e.jsxDEV("span",{className:"truncate opacity-70 flex-1",children:[String(L+1).padStart(2,"0")," · ",U[L].title]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:161,columnNumber:13},this),e.jsxDEV("button",{onClick:()=>f(o=>!o),"aria-label":"静音",children:N?e.jsxDEV(Ce,{className:"w-5 h-5"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:162,columnNumber:80},this):e.jsxDEV(Ve,{className:"w-5 h-5"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:162,columnNumber:114},this)},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:162,columnNumber:13},this),e.jsxDEV("button",{onClick:R,"aria-label":"全屏",children:b?e.jsxDEV(Ee,{className:"w-5 h-5"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:163,columnNumber:66},this):e.jsxDEV(Se,{className:"w-5 h-5"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:163,columnNumber:101},this)},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:163,columnNumber:13},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:158,columnNumber:11},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:149,columnNumber:9},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:135,columnNumber:7},this)},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:133,columnNumber:5},this)}function $e(){const[t,i]=n.useState(30),[s,l]=n.useState(null),[c,a]=n.useState(!1),[m,d]=n.useState(null),[r,N]=n.useState(null),f=n.useRef(null),b=typeof window<"u"&&"VideoEncoder"in window,g=async()=>{N(null),d(null),a(!0),f.current=new AbortController;const x=performance.now();try{const w=await ue(t,l,f.current.signal);d({blob:w,fps:t,sec:(performance.now()-x)/1e3}),X(w,`腱鞘炎3D科普_1080x1920_${t}fps.mp4`)}catch(w){w.name!=="AbortError"&&N(w.message)}finally{a(!1),l(null)}},V=(t===60?16:t===30?12:10)*y/8+2;return e.jsxDEV("div",{className:"space-y-5",children:[e.jsxDEV("div",{children:[e.jsxDEV("div",{className:"text-sm text-slate-400 mb-2",children:"帧率"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:198,columnNumber:9},this),e.jsxDEV("div",{className:"grid grid-cols-3 gap-2",children:[24,30,60].map(x=>e.jsxDEV("button",{disabled:c,onClick:()=>i(x),className:`rounded-xl py-3 border text-center transition ${t===x?"border-cyan-400 bg-cyan-400/10 text-white":"border-white/10 text-slate-300 hover:border-white/30"}`,children:[e.jsxDEV("div",{className:"text-xl font-black",children:[x,e.jsxDEV("span",{className:"text-xs font-semibold ml-0.5",children:"fps"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:203,columnNumber:54},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:203,columnNumber:15},this),e.jsxDEV("div",{className:"text-[11px] opacity-60",children:x===24?"电影感 · 体积小":x===30?"平台推荐":"最流畅"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:204,columnNumber:15},this)]},x,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:201,columnNumber:13},this))},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:199,columnNumber:9},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:197,columnNumber:7},this),e.jsxDEV("div",{className:"text-xs text-slate-400 leading-relaxed bg-white/5 rounded-xl p-3",children:["输出:1080×1920 竖屏 MP4 · H.264 + AAC 立体声 · 时长 ",y.toFixed(1)," 秒 · 预计约 ",Math.round(V)," MB",e.jsxDEV("br",{},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:210,columnNumber:105},this),"全程在你的浏览器本地逐帧渲染,不上传任何数据。导出时请保持此页面在前台。"]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:209,columnNumber:7},this),!b&&e.jsxDEV("div",{className:"text-xs text-amber-300",children:"当前浏览器不支持本地视频编码,请使用电脑版 Chrome / Edge 最新版。"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:213,columnNumber:22},this),c?e.jsxDEV("div",{className:"space-y-2",children:[e.jsxDEV("div",{className:"flex justify-between text-sm",children:[e.jsxDEV("span",{className:"text-cyan-300",children:(s==null?void 0:s.phase)??"准备中"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:216,columnNumber:57},this),e.jsxDEV("span",{className:"tabular-nums",children:[Math.round(((s==null?void 0:s.p)??0)*100),"%"]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:216,columnNumber:118},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:216,columnNumber:11},this),e.jsxDEV("div",{className:"h-2 rounded bg-white/10 overflow-hidden",children:e.jsxDEV("div",{className:"h-full bg-gradient-to-r from-cyan-400 to-emerald-400 transition-[width]",style:{width:`${((s==null?void 0:s.p)??0)*100}%`}},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:217,columnNumber:68},this)},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:217,columnNumber:11},this),e.jsxDEV("div",{className:"flex justify-between text-xs text-slate-400",children:[e.jsxDEV("span",{children:s!=null&&s.frame?`第 ${s.frame} / ${s.total} 帧`:""},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:219,columnNumber:13},this),e.jsxDEV("span",{children:(s==null?void 0:s.eta)!=null?`剩余约 ${_(s.eta)}`:""},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:220,columnNumber:13},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:218,columnNumber:11},this),e.jsxDEV("button",{onClick:()=>{var x;return(x=f.current)==null?void 0:x.abort()},className:"w-full mt-2 rounded-xl py-2.5 border border-white/15 text-slate-200 flex items-center justify-center gap-2 hover:bg-white/5",children:[e.jsxDEV(Me,{className:"w-4 h-4"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:222,columnNumber:191},this),"取消导出"]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:222,columnNumber:11},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:215,columnNumber:9},this):e.jsxDEV("button",{onClick:g,disabled:!b,className:"w-full rounded-xl py-3.5 font-bold text-slate-950 bg-gradient-to-r from-cyan-300 to-emerald-300 hover:brightness-110 disabled:opacity-40 flex items-center justify-center gap-2",children:[e.jsxDEV(W,{className:"w-5 h-5"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:227,columnNumber:11},this),"导出 MP4(",t,"fps)"]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:225,columnNumber:9},this),m&&e.jsxDEV("div",{className:"rounded-xl bg-emerald-500/10 border border-emerald-400/30 p-3 text-sm flex items-center gap-3",children:[e.jsxDEV(ie,{className:"w-5 h-5 text-emerald-300 shrink-0"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:232,columnNumber:11},this),e.jsxDEV("div",{className:"flex-1",children:["已导出 ",m.fps,"fps · ",(m.blob.size/1048576).toFixed(1)," MB · 用时 ",_(m.sec)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:233,columnNumber:11},this),e.jsxDEV("button",{onClick:()=>X(m.blob,`腱鞘炎3D科普_1080x1920_${m.fps}fps.mp4`),className:"text-emerald-300 underline",children:"再次下载"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:234,columnNumber:11},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:231,columnNumber:9},this),r&&e.jsxDEV("div",{className:"text-sm text-red-300 bg-red-500/10 rounded-xl p-3",children:["导出失败:",r]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:237,columnNumber:15},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:196,columnNumber:5},this)}function O({text:t,label:i="复制"}){const[s,l]=n.useState(!1),c=async()=>{try{await navigator.clipboard.writeText(t)}catch{const a=document.createElement("textarea");a.value=t,document.body.appendChild(a),a.select(),document.execCommand("copy"),a.remove()}l(!0),setTimeout(()=>l(!1),1400)};return e.jsxDEV("button",{onClick:c,className:`shrink-0 text-xs px-2.5 py-1 rounded-lg border flex items-center gap-1 transition ${s?"border-emerald-400 text-emerald-300":"border-white/15 text-slate-300 hover:border-white/40"}`,children:[s?e.jsxDEV(ie,{className:"w-3.5 h-3.5"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:253,columnNumber:13},this):e.jsxDEV(we,{className:"w-3.5 h-3.5"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:253,columnNumber:49},this),s?"已复制":i]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:252,columnNumber:5},this)}function G({n:t,max:i}){const s=i==null||t<=i;return e.jsxDEV("span",{className:`text-[11px] tabular-nums px-1.5 py-0.5 rounded ${s?"bg-emerald-500/15 text-emerald-300":"bg-red-500/20 text-red-300"}`,children:[t,i!=null?` / ${i}`:" 字"]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:260,columnNumber:10},this)}function Ae({p:t}){const i=`${t.title}
170
+
171
+ ${q(t)}`;return e.jsxDEV("div",{className:"rounded-2xl border border-white/10 bg-white/[0.03] overflow-hidden",children:[e.jsxDEV("div",{className:"flex items-center gap-2 px-4 py-3 border-b border-white/10",children:[e.jsxDEV("span",{className:"w-2.5 h-2.5 rounded-full",style:{background:t.color}},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:268,columnNumber:9},this),e.jsxDEV("span",{className:"font-bold",children:t.name},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:269,columnNumber:9},this),e.jsxDEV("span",{className:"text-[11px] text-slate-500 flex-1 truncate",children:t.tips},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:270,columnNumber:9},this),e.jsxDEV(O,{text:i,label:"复制全部"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:271,columnNumber:9},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:267,columnNumber:7},this),e.jsxDEV("div",{className:"p-4 space-y-4 text-sm",children:[e.jsxDEV("div",{children:[e.jsxDEV("div",{className:"flex items-center gap-2 mb-1.5",children:[e.jsxDEV("span",{className:"text-slate-400 text-xs",children:"标题"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:275,columnNumber:59},this),e.jsxDEV(G,{n:te(t.title),max:t.limits.title},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:275,columnNumber:109},this),e.jsxDEV("span",{className:"flex-1"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:275,columnNumber:160},this),e.jsxDEV(O,{text:t.title},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:275,columnNumber:187},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:275,columnNumber:11},this),e.jsxDEV("div",{className:"font-bold text-white text-base leading-snug",children:t.title},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:276,columnNumber:11},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:274,columnNumber:9},this),e.jsxDEV("div",{children:[e.jsxDEV("div",{className:"flex items-center gap-2 mb-1.5",children:[e.jsxDEV("span",{className:"text-slate-400 text-xs",children:"话题"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:279,columnNumber:59},this),e.jsxDEV(G,{n:t.topics.length,max:t.limits.topics},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:279,columnNumber:109},this),e.jsxDEV("span",{className:"text-[11px] text-slate-500",children:"个"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:279,columnNumber:160},this),e.jsxDEV("span",{className:"flex-1"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:279,columnNumber:213},this),e.jsxDEV(O,{text:se(t)},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:279,columnNumber:240},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:279,columnNumber:11},this),e.jsxDEV("div",{className:"flex flex-wrap gap-1.5",children:t.topics.map(s=>e.jsxDEV("span",{className:"text-xs px-2 py-0.5 rounded-full bg-cyan-400/10 text-cyan-200",children:["#",s]},s,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:280,columnNumber:71},this))},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:280,columnNumber:11},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:278,columnNumber:9},this),e.jsxDEV("div",{children:[e.jsxDEV("div",{className:"flex items-center gap-2 mb-1.5",children:[e.jsxDEV("span",{className:"text-slate-400 text-xs",children:["正文",t.limits.bodyIncludesTopics&&t.limits.body?"(含话题)":""]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:284,columnNumber:13},this),e.jsxDEV(G,{n:fe(t),max:t.limits.body},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:285,columnNumber:13},this),e.jsxDEV("span",{className:"flex-1"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:285,columnNumber:59},this),e.jsxDEV(O,{text:t.limits.bodyIncludesTopics?q(t):t.body},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:286,columnNumber:13},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:283,columnNumber:11},this),e.jsxDEV("pre",{className:"whitespace-pre-wrap font-sans text-slate-300 text-[13px] leading-relaxed max-h-64 overflow-auto bg-black/30 rounded-xl p-3",children:t.limits.bodyIncludesTopics?q(t):t.body},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:288,columnNumber:11},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:282,columnNumber:9},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:273,columnNumber:7},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:266,columnNumber:5},this)}function Re(){const t=n.useRef({}),[i,s]=n.useState(0);n.useEffect(()=>{let m=!0,d=0;const r=()=>{if(!m||d>=T.length)return;const N=T[d],f=t.current[N.key];if(f)try{re(N,f)}catch(b){console.error(b)}d++,s(d),setTimeout(r,30)};return setTimeout(r,50),()=>{m=!1}},[]);const l=async m=>{const d=T.find(r=>r.key===m);X(await be(d),`封面_${d.platform}_${d.label.split(" ")[0].replace(":","x")}_${d.w}x${d.h}.png`)},c=async()=>{for(const m of T)await l(m.key),await new Promise(d=>setTimeout(d,350))},a=[...new Set(T.map(m=>m.platform))];return e.jsxDEV("div",{className:"space-y-5",children:[e.jsxDEV("div",{className:"flex items-center gap-3",children:[e.jsxDEV("div",{className:"text-xs text-slate-400 flex-1",children:["由动画真实画面实时渲染,PNG 原尺寸下载。",i<T.length?`生成中 ${i}/${T.length}…`:""]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:316,columnNumber:9},this),e.jsxDEV("button",{onClick:c,className:"text-xs px-3 py-1.5 rounded-lg bg-cyan-400/15 text-cyan-200 border border-cyan-400/30 flex items-center gap-1",children:[e.jsxDEV(W,{className:"w-3.5 h-3.5"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:317,columnNumber:155},this),"全部下载"]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:317,columnNumber:9},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:315,columnNumber:7},this),a.map(m=>e.jsxDEV("div",{children:[e.jsxDEV("div",{className:"text-sm font-bold mb-2",children:m},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:321,columnNumber:11},this),e.jsxDEV("div",{className:"grid grid-cols-2 gap-3 items-start",children:T.filter(d=>d.platform===m).map(d=>e.jsxDEV("div",{className:"rounded-xl overflow-hidden border border-white/10 bg-black/40",children:[e.jsxDEV("canvas",{ref:r=>{t.current[d.key]=r},className:"w-full block",style:{aspectRatio:`${d.w} / ${d.h}`}},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:325,columnNumber:17},this),e.jsxDEV("div",{className:"flex items-center justify-between px-2.5 py-2 text-xs",children:[e.jsxDEV("span",{className:"text-slate-300",children:[d.label," ",e.jsxDEV("span",{className:"text-slate-500",children:[d.w,"×",d.h]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:327,columnNumber:62},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:327,columnNumber:19},this),e.jsxDEV("button",{onClick:()=>l(d.key),className:"text-cyan-300 flex items-center gap-1",children:[e.jsxDEV(W,{className:"w-3.5 h-3.5"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:328,columnNumber:103},this),"PNG"]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:328,columnNumber:19},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:326,columnNumber:17},this)]},d.key,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:324,columnNumber:15},this))},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:322,columnNumber:11},this)]},m,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:320,columnNumber:9},this))]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:314,columnNumber:5},this)}function qe(){const[t,i]=n.useState("export"),s=[{k:"export",n:"导出视频",i:ye},{k:"copy",n:"平台文案",i:ke},{k:"cover",n:"封面",i:ge}];return e.jsxDEV("div",{className:"min-h-screen bg-[#04080f] text-slate-100",style:{backgroundImage:"radial-gradient(1200px 600px at 20% -10%, rgba(40,140,255,0.12), transparent), radial-gradient(800px 500px at 100% 100%, rgba(255,60,60,0.06), transparent)"},children:e.jsxDEV("div",{className:"mx-auto max-w-6xl lg:flex lg:gap-8 lg:p-6 lg:items-start",children:[e.jsxDEV("div",{className:"lg:sticky lg:top-6 sm:pt-3 lg:pt-0 lg:w-auto",children:e.jsxDEV(Te,{},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:351,columnNumber:11},this)},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:350,columnNumber:9},this),e.jsxDEV("div",{className:"flex-1 min-w-0 px-4 py-6 lg:px-0 lg:py-0",children:[e.jsxDEV("div",{className:"mb-5",children:[e.jsxDEV("div",{className:"text-[11px] tracking-[0.25em] text-cyan-300/80 font-bold",children:"ORIGINAL 3D MEDICAL ANIMATION"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:355,columnNumber:13},this),e.jsxDEV("h1",{className:"text-2xl lg:text-3xl font-black mt-1",children:"腱鞘炎 · 从疼痛到恢复"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:356,columnNumber:13},this),e.jsxDEV("p",{className:"text-sm text-slate-400 mt-1.5",children:["实时 3D 解剖动画 · 竖屏 9:16 · ",y.toFixed(0)," 秒 · 旁白 + 配乐 + 音效"]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:357,columnNumber:13},this),e.jsxDEV("div",{className:"flex flex-wrap gap-1.5 mt-3",children:["疼痛","定位","处理","松解","恢复"].map((l,c)=>e.jsxDEV("span",{className:`text-xs px-2.5 py-1 rounded-full ${c===0?"bg-red-500/20 text-red-200":c===4?"bg-emerald-500/20 text-emerald-200":"bg-white/5 text-slate-300"}`,children:l},l,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:360,columnNumber:17},this))},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:358,columnNumber:13},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:354,columnNumber:11},this),e.jsxDEV("div",{className:"flex gap-1 p-1 rounded-xl bg-white/5 mb-5 sticky top-0 z-10 backdrop-blur",children:s.map(({k:l,n:c,i:a})=>e.jsxDEV("button",{onClick:()=>i(l),className:`flex-1 py-2 rounded-lg text-sm font-semibold flex items-center justify-center gap-1.5 transition ${t===l?"bg-white/10 text-white":"text-slate-400 hover:text-slate-200"}`,children:[e.jsxDEV(a,{className:"w-4 h-4"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:367,columnNumber:17},this),c]},l,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:366,columnNumber:15},this))},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:364,columnNumber:11},this),t==="export"&&e.jsxDEV($e,{},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:371,columnNumber:32},this),t==="copy"&&e.jsxDEV("div",{className:"space-y-4",children:xe.map(l=>e.jsxDEV(Ae,{p:l},l.key,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:372,columnNumber:72},this))},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:372,columnNumber:30},this),t==="cover"&&e.jsxDEV(Re,{},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:373,columnNumber:31},this),e.jsxDEV("div",{className:"text-[11px] text-slate-500 mt-8 leading-relaxed flex gap-2",children:[e.jsxDEV(je,{className:"w-3.5 h-3.5 shrink-0 mt-0.5"},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:375,columnNumber:13},this),"所有模型、器械、动画、配乐与音效均为原创程序化生成;内容仅供健康科普,不替代医生面诊。"]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:374,columnNumber:11},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:353,columnNumber:9},this)]},void 0,!0,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:349,columnNumber:7},this)},void 0,!1,{fileName:"/workspaces/frontend/src/video/Studio.tsx",lineNumber:348,columnNumber:5},this)}export{qe as default};
assets/TDebug-C_pplWnw.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{j as b}from"./jsx-dev-runtime-Czb3f8pQ.js";import{r as x}from"./index-Br42UDbl.js";import{E}from"./engine-Bmw5iF75.js";import{f as R}from"./scenes-oUf6rtD_.js";import"./index-BlGQAcOD.js";import"./state-B_bTBsCz.js";function y(){const f=x.useRef(null);return x.useEffect(()=>{var l;const w=(new URLSearchParams(location.search).get("tdebug")||"3").split(",").map(Number),u=new E;u.setSize(540,960);const c=f.current;c.width=540,c.height=960;const d=c.getContext("2d"),a=[];for(const r of w)try{const i=performance.now();u.render(R(r),d,r);const $=performance.now()-i,t=d.getImageData(0,0,540,960).data;let p=0,g=0,h=0;for(let e=0;e<t.length;e+=16){const o=t[e],s=t[e+1],n=t[e+2];p+=(o+s+n)/3,o>170&&s<90&&n<90&&g++,o>150&&s>100&&n>70&&o>s&&s>n&&o-n>40&&h++}const m=t.length/16;a.push(`t=${r} ms=${$.toFixed(0)} lum=${(p/m).toFixed(1)} red=${(g/m*100).toFixed(1)}% skin=${(h/m*100).toFixed(1)}%`)}catch(i){a.push(`t=${r} ERROR ${i.message} ${(l=i.stack)==null?void 0:l.split(`
2
+ `).slice(0,3).join(" | ")}`)}console.log("INFO "+a.join(" ;; ")),window.__done=!0},[]),b.jsxDEV("canvas",{ref:f,style:{width:540,height:960}},void 0,!1,{fileName:"/workspaces/frontend/src/video/TDebug.tsx",lineNumber:36,columnNumber:10},this)}export{y as default};
assets/XDebug-COl9Ua8s.js ADDED
@@ -0,0 +1 @@
 
 
1
+ import{r as a}from"./index-Br42UDbl.js";import{e as i}from"./exporter-CgYwbdYV.js";import"./index-BlGQAcOD.js";import"./engine-Bmw5iF75.js";import"./state-B_bTBsCz.js";import"./scenes-oUf6rtD_.js";import"./audio-BSS1MXf9.js";function g(){return a.useEffect(()=>{const t=window;i(24,()=>{},new AbortController().signal,3).then(async r=>{const e=new Uint8Array(await r.arrayBuffer());let n="";for(let o=0;o<e.length;o+=32768)n+=String.fromCharCode(...e.subarray(o,o+32768));t.__mp4=btoa(n),console.log("INFO mp4 bytes "+r.size)}).catch(r=>console.log("INFO ERROR "+r)).finally(()=>{t.__done=!0})},[]),null}export{g as default};
assets/audio-BSS1MXf9.js ADDED
@@ -0,0 +1 @@
 
 
1
+ import{D as k,L as F,S as O,a as E}from"./scenes-oUf6rtD_.js";const M=48e3,I=100,G=60/I,B=G*4,w=e=>440*Math.pow(2,(e-69)/12);function D(e,o){const u=e.createBuffer(1,Math.ceil(o*e.sampleRate),e.sampleRate),r=u.getChannelData(0);let h=1234567;for(let l=0;l<r.length;l++)h=h*16807%2147483647,r[l]=h/2147483647*2-1;return u}function L(e,o,u){const r=Math.ceil(o*e.sampleRate),h=e.createBuffer(2,r,e.sampleRate);let l=98765;for(let f=0;f<2;f++){const n=h.getChannelData(f);for(let c=0;c<r;c++)l=l*16807%2147483647,n[c]=(l/2147483647*2-1)*Math.pow(1-c/r,u)}return h}function b(e,o,u,r,h,l){e.gain.setValueAtTime(0,o),e.gain.linearRampToValueAtTime(r,o+u),e.gain.setValueAtTime(r,o+u+h),e.gain.exponentialRampToValueAtTime(1e-4,o+u+h+l)}function N(){const e=h=>O[h].start,o=[[50,57,60,64,65],[46,53,57,60,62],[43,50,53,58,62],[45,52,57,59,64]],u=[[38,50,53,57],[38,50,52,57]],r=[[41,53,57,60,64],[48,55,60,64,67],[50,57,60,62,65],[46,53,58,62,65]];return[{a:0,b:e(1),chords:u,arp:!1,kick:!1,bright:.2},{a:e(1),b:e(4),chords:o,arp:!0,kick:!1,bright:.45},{a:e(4),b:e(8),chords:o,arp:!0,kick:!0,bright:.6},{a:e(8),b:k,chords:r,arp:!0,kick:!0,bright:.85}]}function Q(e,o,u){const r=N(),h=D(e,1);for(const f of r){const n=Math.ceil((f.b-f.a)/B);for(let c=0;c<n;c++){const i=f.a+c*B;if(i>=f.b)break;const t=Math.min(B,f.b-i)+.6,p=f.chords[c%f.chords.length];if(p.forEach((a,m)=>{for(const d of[-7,7]){const s=e.createOscillator();s.type=m===0?"sine":"sawtooth",s.frequency.value=w(m===0?a-12:a),s.detune.value=d;const T=e.createBiquadFilter();T.type="lowpass",T.frequency.setValueAtTime(500+900*f.bright,i),T.frequency.linearRampToValueAtTime(900+1600*f.bright,i+t*.6);const A=e.createGain();b(A,i,.5,m===0?.11:.028,t-1.1,.9),s.connect(T).connect(A),A.connect(o),A.connect(u),s.start(i),s.stop(i+t+.3)}}),f.arp){const a=f.kick?G/4:G/2,m=p.slice(1).concat(p.slice(1).map(s=>s+12)),d=[0,2,1,3,2,4,3,5];for(let s=0;s*a<B&&i+s*a<f.b;s++){const T=i+s*a,A=m[d[s%d.length]%m.length],y=e.createOscillator();y.type="triangle",y.frequency.value=w(A+12);const g=e.createGain();b(g,T,.004,(s%4===0?.05:.032)*(.7+f.bright*.4),.02,a*1.6);const q=e.createStereoPanner();q.pan.value=Math.sin(s*1.3)*.5,y.connect(g).connect(q),q.connect(o),q.connect(u),y.start(T),y.stop(T+a*2+.1)}}if(!f.arp)for(let a=0;a<4;a+=2)for(const m of[0,.22]){const d=i+a*G+m;if(d>f.b)continue;const s=e.createOscillator();s.frequency.setValueAtTime(70,d),s.frequency.exponentialRampToValueAtTime(38,d+.18);const T=e.createGain();b(T,d,.005,m?.22:.32,.02,.25),s.connect(T).connect(o),s.start(d),s.stop(d+.35)}if(f.kick)for(let a=0;a<4;a++){const m=i+a*G;if(m>f.b)continue;const d=e.createOscillator();d.frequency.setValueAtTime(120,m),d.frequency.exponentialRampToValueAtTime(42,m+.12);const s=e.createGain();b(s,m,.003,.26,.01,.22),d.connect(s).connect(o),d.start(m),d.stop(m+.3);const T=e.createBufferSource();T.buffer=h;const A=e.createBiquadFilter();A.type="highpass",A.frequency.value=7e3;const y=e.createGain();b(y,m+G/2,.002,.035,0,.05),T.connect(A).connect(y).connect(o),T.start(m+G/2,(c*4+a)%5*.1,.1)}}}const l=O[O.length-1].start+.4;[41,53,60,65,69,72].forEach(f=>{const n=e.createOscillator();n.type="sine",n.frequency.value=w(f);const c=e.createGain();b(c,l,.8,.05,2,Math.max(.5,k-l-2.8)),n.connect(c),c.connect(o),c.connect(u),n.start(l),n.stop(k)})}function $(e,o,u){const r=D(e,2),h=(n,c)=>{const i=e.createBufferSource();return i.buffer=r,i.start(n,0,c),i},l=(n,c,i,t,p)=>{const a=e.createOscillator();return a.type=c,a.frequency.setValueAtTime(i,n),a.frequency.exponentialRampToValueAtTime(t,n+p),a.start(n),a.stop(n+p+.05),a},f={whoosh:(n,c)=>{const i=h(n,.6),t=e.createBiquadFilter();t.type="bandpass",t.Q.value=2,t.frequency.setValueAtTime(300,n),t.frequency.exponentialRampToValueAtTime(3500,n+.45);const p=e.createGain();b(p,n,.25,.22*c,0,.3),i.connect(t).connect(p),p.connect(o),p.connect(u)},pain:(n,c)=>{const i=l(n,"sawtooth",110,55,.5),t=e.createBiquadFilter();t.type="lowpass",t.frequency.value=600;const p=e.createGain();b(p,n,.01,.2*c,.05,.45),i.connect(t).connect(p).connect(o);const a=l(n,"sine",80,40,.4),m=e.createGain();b(m,n,.005,.4*c,.02,.35),a.connect(m).connect(o);const d=l(n+.02,"sine",1900,1500,.35),s=e.createGain();b(s,n+.02,.01,.03*c,0,.3),d.connect(s),s.connect(o),s.connect(u)},tick:(n,c)=>{const i=l(n,"sine",2400,2300,.04),t=e.createGain();b(t,n,.002,.08*c,0,.04),i.connect(t).connect(o)},scan:(n,c)=>{const i=l(n,"sine",500,1800,.8),t=e.createGain();b(t,n,.05,.06*c,.4,.35);const p=e.createOscillator();p.frequency.value=18;const a=e.createGain();a.gain.value=.03*c,p.connect(a).connect(t.gain),p.start(n),p.stop(n+.9),i.connect(t),t.connect(o),t.connect(u)},pop:(n,c)=>{const i=l(n,"sine",520,980,.08),t=e.createGain();b(t,n,.003,.12*c,0,.12),i.connect(t),t.connect(o),t.connect(u)},release:(n,c)=>{const i=h(n,1.2),t=e.createBiquadFilter();t.type="lowpass",t.frequency.setValueAtTime(2500,n),t.frequency.exponentialRampToValueAtTime(200,n+1.1);const p=e.createGain();b(p,n,.02,.12*c,.05,1),i.connect(t).connect(p),p.connect(o),p.connect(u),[72,76,79,84].forEach((a,m)=>{const d=l(n+m*.07,"sine",w(a),w(a)*.998,1.4),s=e.createGain();b(s,n+m*.07,.01,.05*c,0,1.3),d.connect(s),s.connect(o),s.connect(u)})},chime:(n,c)=>{for(const[i,t]of[[1,1],[2.76,.5],[5.4,.25]]){const p=l(n,"sine",880*i,880*i,1.6),a=e.createGain();b(a,n,.003,.06*c*t,0,1.5),p.connect(a),a.connect(o),a.connect(u)}},thud:(n,c)=>{const i=l(n,"sine",90,38,.3),t=e.createGain();b(t,n,.003,.45*c,.02,.3),i.connect(t).connect(o)},click:(n,c)=>{const i=l(n,"square",1600,1200,.02),t=e.createGain();b(t,n,.001,.04*c,0,.03),i.connect(t).connect(o);const p=h(n,.04),a=e.createBiquadFilter();a.type="highpass",a.frequency.value=3e3;const m=e.createGain();b(m,n,.001,.08*c,0,.03),p.connect(a).connect(m).connect(o)},swipe:(n,c)=>{const i=h(n,.3),t=e.createBiquadFilter();t.type="highpass",t.frequency.setValueAtTime(1200,n),t.frequency.linearRampToValueAtTime(4e3,n+.25);const p=e.createGain();b(p,n,.06,.1*c,0,.2),i.connect(t).connect(p).connect(o)}};for(const n of E())n.t>=0&&n.t<k&&f[n.k](n.t,n.v??1)}async function j(e,o){const u=new OfflineAudioContext(1,1,M);let r=0;return Promise.all(F.map(async h=>{const l=await fetch(e+"audio/"+h.file);if(!l.ok)throw new Error("voice "+h.file+" "+l.status);const f=await u.decodeAudioData(await l.arrayBuffer());return o==null||o(++r/F.length),{l:h,buf:f}}))}let R=null;function z(e,o=!1){return R||(R=(o?C(e):H(e).catch(()=>C(e))).catch(u=>{throw R=null,u})),R}async function H(e){const o="./".replace(/\/?$/,"/");e==null||e(.1,"加载配乐");const u=await fetch(o+"audio/soundtrack.mp3");if(!u.ok)throw new Error("soundtrack "+u.status);const r=await u.arrayBuffer();e==null||e(.6,"解码音频");const l=await new OfflineAudioContext(2,1,M).decodeAudioData(r);return e==null||e(1,"完成"),l}async function C(e){const o="./".replace(/\/?$/,"/"),u=await j(o,y=>e==null?void 0:e(y*.6,"加载旁白"));e==null||e(.65,"合成配乐");const r=new OfflineAudioContext(2,Math.ceil(k*M),M),h=r.createGain();h.gain.value=.9;const l=r.createDynamicsCompressor();l.threshold.value=-10,l.knee.value=6,l.ratio.value=8,l.attack.value=.003,l.release.value=.15,h.connect(l).connect(r.destination),h.gain.setValueAtTime(.9,k-1.2),h.gain.linearRampToValueAtTime(0,k);const f=r.createConvolver();f.buffer=L(r,2.6,3);const n=r.createGain();n.gain.value=.35,f.connect(n).connect(h);const c=r.createGain();c.connect(h);const i=r.createGain();i.connect(f);const t=.85,p=.38;for(const y of[c.gain,i.gain]){y.setValueAtTime(0,0),y.linearRampToValueAtTime(t,1.2);const g=[];for(const{l:q}of u){const v=q.start,S=q.start+q.dur,V=g[g.length-1];V&&v-V[1]<.5?V[1]=Math.max(V[1],S):g.push([v,S])}for(const[q,v]of g)y.setTargetAtTime(p,Math.max(0,q-.12),.06),y.setTargetAtTime(t,v+.05,.25)}Q(r,c,i);const a=r.createGain();a.gain.value=.9,a.connect(h),$(r,a,f);const m=r.createGain();m.gain.value=1.15;const d=r.createBiquadFilter();d.type="highpass",d.frequency.value=90;const s=r.createBiquadFilter();s.type="peaking",s.frequency.value=3e3,s.gain.value=2.5,s.Q.value=.8,m.connect(d).connect(s).connect(h);const T=r.createGain();T.gain.value=.06,m.connect(T).connect(f);for(const{l:y,buf:g}of u){const q=r.createBufferSource();q.buffer=g,q.connect(m),q.start(y.start,y.off,Math.min(y.dur,g.duration-y.off))}const A=await r.startRendering();return e==null||e(1,"完成"),A}export{z as g};
assets/client-BlQxAbrl.js ADDED
The diff for this file is too large to render. See raw diff
 
assets/engine-Bmw5iF75.js ADDED
@@ -0,0 +1 @@
 
 
1
+ var j=Object.defineProperty;var A=(r,t,e)=>t in r?j(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var h=(r,t,e)=>A(r,typeof t!="symbol"?t+"":t,e);import{a as R,W as z,S as W,A as G,H as V,V as y,C as L}from"./state-B_bTBsCz.js";const k=1080,x=1920,v={};function B(r){if(v[r])return v[r];const t=document.createElement("canvas");t.width=540,t.height=960;const e=t.getContext("2d"),n={lab:["#123257","#081a33","#020711"],warm:["#3a2a3f","#1b1426","#07050c"],red:["#4a1626","#1e0b19","#06030a"],clean:["#1d4a6e","#0b2441","#030b18"]},[s,a,i]=n[r]??n.lab,o=e.createRadialGradient(270,400,20,270,480,620);o.addColorStop(0,s),o.addColorStop(.5,a),o.addColorStop(1,i),e.fillStyle=o,e.fillRect(0,0,540,960),e.strokeStyle="rgba(120,190,255,0.05)",e.lineWidth=1;for(let l=0;l<=540;l+=30)e.beginPath(),e.moveTo(l,0),e.lineTo(l,960),e.stroke();for(let l=0;l<=960;l+=30)e.beginPath(),e.moveTo(0,l),e.lineTo(540,l),e.stroke();const c=new L(t);return c.colorSpace=W,v[r]=c,c}class q{constructor(){h(this,"gl");h(this,"renderer");h(this,"model");h(this,"camera",new R(35,9/16,.05,100));h(this,"cams",[]);h(this,"W",1080);h(this,"H",1920);this.gl=document.createElement("canvas"),this.renderer=new z({canvas:this.gl,antialias:!0,preserveDrawingBuffer:!0,alpha:!1,powerPreference:"high-performance"}),this.renderer.outputColorSpace=W,this.renderer.toneMapping=G,this.renderer.toneMappingExposure=1.05,this.renderer.setPixelRatio(1),this.model=new V(this.renderer),this.setSize(1080,1920)}setSize(t,e){this.W=t,this.H=e,this.renderer.setSize(t,e,!1)}setupCam(t,e,n){t.aspect=n,t.fov=e.cam.fov,t.position.set(...e.cam.pos);const s=new y(...e.cam.target),a=e.cam.follow??0;if(a>0){const o=this.model.anchors.pain.clone().sub(s).multiplyScalar(a);t.position.add(o),s.add(o)}t.up.set(0,1,0),e.cam.roll&&t.up.applyAxisAngle(new y(0,0,1),e.cam.roll),t.lookAt(s),t.updateProjectionMatrix();const i=e.cam.shift;i&&(t.projectionMatrix.elements[8]-=2*i[0]-1,t.projectionMatrix.elements[9]-=1-2*i[1],t.projectionMatrixInverse.copy(t.projectionMatrix).invert()),t.updateMatrixWorld()}render(t,e,n,s={w:k,h:x}){const{W:a,H:i,renderer:o}=this;for(o.setScissorTest(!0),o.autoClear=!1,o.setClearColor("#02060d",1),o.setViewport(0,0,a,i),o.setScissor(0,0,a,i),o.clear();this.cams.length<t.views.length;)this.cams.push(new R);const c=[];t.views.forEach((d,w)=>{const[p,u,M,m]=d.rect,S=Math.round(p*a),b=Math.round(u*i),g=Math.round(M*a),f=Math.round(m*i);this.model.apply(d.state),this.model.scene.background=B(d.bg??"lab");const T=this.cams[w];this.setupCam(T,d.state,g/f),o.setViewport(S,i-b-f,g,f),o.setScissor(S,i-b-f,g,f),o.render(this.model.scene,T);const P={};for(const[E,H]of Object.entries(this.model.anchors))P[E]=H.clone();c.push(P)}),o.setScissorTest(!1),e.save(),e.setTransform(1,0,0,1,0,0),e.clearRect(0,0,a,i),e.drawImage(this.gl,0,0,a,i);const l=a/s.w,C=i/s.h;if(e.setTransform(l,0,0,C,0,0),I(e,n,s.w,s.h),t.overlay){const d={W:s.w,H:s.h,t:n,model:this.model,world:(w,p=0)=>{const u=t.views[p],M=this.cams[p],m=w.clone().project(M),[S,b,g,f]=u.rect;return{x:(S+(m.x+1)/2*g)*s.w,y:(b+(1-m.y)/2*f)*s.h,z:m.z}},anchor:(w,p=0)=>{var u;return d.world(((u=c[p])==null?void 0:u[w])??new y,p)}};t.overlay(e,d)}t.fade&&t.fade>0&&(e.fillStyle=`rgba(0,0,0,${Math.min(1,t.fade)})`,e.fillRect(0,0,s.w,s.h)),e.restore()}}function I(r,t,e,n){r.save(),r.globalCompositeOperation="lighter";for(let a=0;a<40;a++){const i=Math.sin(a*91.7)*.5+.5,o=Math.sin(a*37.3+1)*.5+.5,c=Math.sin(a*13.1+2)*.5+.5,l=(i*e+Math.sin(t*.2+a)*30)%e,C=((o*n-t*(8+c*18))%n+n)%n,d=1.2+c*2.4;r.fillStyle=`rgba(120,200,255,${.05+c*.12})`,r.beginPath(),r.arc(l,C,d,0,Math.PI*2),r.fill()}r.restore();const s=r.createRadialGradient(e/2,n*.45,n*.3,e/2,n*.5,n*.78);s.addColorStop(0,"rgba(0,0,0,0)"),s.addColorStop(1,"rgba(0,0,0,0.55)"),r.fillStyle=s,r.fillRect(0,0,e,n)}export{q as E,k as L,x as a};
assets/exporter-CgYwbdYV.js ADDED
The diff for this file is too large to render. See raw diff
 
assets/index-BlGQAcOD.js ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function Ue(p){return p&&p.__esModule&&Object.prototype.hasOwnProperty.call(p,"default")?p.default:p}var Q={exports:{}},b={exports:{}};b.exports;var Ee;function Ye(){return Ee||(Ee=1,(function(p,u){/**
2
+ * @license React
3
+ * react.development.js
4
+ *
5
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */(function(){function Re(e,t){Object.defineProperty(m.prototype,e,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",t[0],t[1])}})}function Te(e){return e===null||typeof e!="object"?null:(e=se&&e[se]||e["@@iterator"],typeof e=="function"?e:null)}function M(e,t){e=(e=e.constructor)&&(e.displayName||e.name)||"ReactClass";var r=e+"."+t;ie[r]||(console.error("Can't call %s on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to `this.state` directly or define a `state = {};` class property with the desired state in the %s component.",t,e),ie[r]=!0)}function m(e,t,r){this.props=e,this.context=t,this.refs=H,this.updater=r||ce}function B(){}function N(e,t,r){this.props=e,this.context=t,this.refs=H,this.updater=r||ce}function L(){}function K(e){return""+e}function R(e){try{K(e);var t=!1}catch{t=!0}if(t){t=console;var r=t.error,n=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return r.call(t,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",n),K(e)}}function T(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===Me?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case q:return"Fragment";case re:return"Profiler";case te:return"StrictMode";case ue:return"Suspense";case Pe:return"SuspenseList";case ae:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case ee:return"Portal";case ne:return e.displayName||"Context";case W:return(e._context.displayName||"Context")+".Consumer";case oe:var t=e.render;return e=e.displayName,e||(e=t.displayName||t.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case z:return t=e.displayName||null,t!==null?t:T(e.type)||"Memo";case w:t=e._payload,e=e._init;try{return T(e(t))}catch{}}return null}function F(e){if(e===q)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===w)return"<...>";try{var t=T(e);return t?"<"+t+">":"<...>"}catch{return"<...>"}}function X(){var e=s.A;return e===null?null:e.getOwner()}function V(){return Error("react-stack-top-frame")}function Z(e){if(A.call(e,"key")){var t=Object.getOwnPropertyDescriptor(e,"key").get;if(t&&t.isReactWarning)return!1}return e.key!==void 0}function Oe(e,t){function r(){pe||(pe=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",t))}r.isReactWarning=!0,Object.defineProperty(e,"key",{get:r,configurable:!0})}function ke(){var e=T(this.type);return me[e]||(me[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function $(e,t,r,n,o,i){var a=r.ref;return e={$$typeof:I,type:e,key:t,props:r,_owner:n},(a!==void 0?a:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:ke}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:o}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:i}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function Se(e,t){return t=$(e.type,t,e.props,e._owner,e._debugStack,e._debugTask),e._store&&(t._store.validated=e._store.validated),t}function J(e){y(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===w&&(e._payload.status==="fulfilled"?y(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function y(e){return typeof e=="object"&&e!==null&&e.$$typeof===I}function Ae(e){var t={"=":"=0",":":"=2"};return"$"+e.replace(/[=:]/g,function(r){return t[r]})}function D(e,t){return typeof e=="object"&&e!==null&&e.key!=null?(R(e.key),Ae(""+e.key)):t.toString(36)}function Ce(e){switch(e.status){case"fulfilled":return e.value;case"rejected":throw e.reason;default:switch(typeof e.status=="string"?e.then(L,L):(e.status="pending",e.then(function(t){e.status==="pending"&&(e.status="fulfilled",e.value=t)},function(t){e.status==="pending"&&(e.status="rejected",e.reason=t)})),e.status){case"fulfilled":return e.value;case"rejected":throw e.reason}}throw e}function g(e,t,r,n,o){var i=typeof e;(i==="undefined"||i==="boolean")&&(e=null);var a=!1;if(e===null)a=!0;else switch(i){case"bigint":case"string":case"number":a=!0;break;case"object":switch(e.$$typeof){case I:case ee:a=!0;break;case w:return a=e._init,g(a(e._payload),t,r,n,o)}}if(a){a=e,o=o(a);var f=n===""?"."+D(a,0):n;return le(o)?(r="",f!=null&&(r=f.replace(ge,"$&/")+"/"),g(o,t,r,"",function(h){return h})):o!=null&&(y(o)&&(o.key!=null&&(a&&a.key===o.key||R(o.key)),r=Se(o,r+(o.key==null||a&&a.key===o.key?"":(""+o.key).replace(ge,"$&/")+"/")+f),n!==""&&a!=null&&y(a)&&a.key==null&&a._store&&!a._store.validated&&(r._store.validated=2),o=r),t.push(o)),1}if(a=0,f=n===""?".":n+":",le(e))for(var c=0;c<e.length;c++)n=e[c],i=f+D(n,c),a+=g(n,t,r,i,o);else if(c=Te(e),typeof c=="function")for(c===e.entries&&(ye||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),ye=!0),e=c.call(e),c=0;!(n=e.next()).done;)n=n.value,i=f+D(n,c++),a+=g(n,t,r,i,o);else if(i==="object"){if(typeof e.then=="function")return g(Ce(e),t,r,n,o);throw t=String(e),Error("Objects are not valid as a React child (found: "+(t==="[object Object]"?"object with keys {"+Object.keys(e).join(", ")+"}":t)+"). If you meant to render a collection of children, use an array instead.")}return a}function O(e,t,r){if(e==null)return e;var n=[],o=0;return g(e,n,"","",function(i){return t.call(r,i,o++)}),n}function je(e){if(e._status===-1){var t=e._ioInfo;t!=null&&(t.start=t.end=performance.now()),t=e._result;var r=t();if(r.then(function(o){if(e._status===0||e._status===-1){e._status=1,e._result=o;var i=e._ioInfo;i!=null&&(i.end=performance.now()),r.status===void 0&&(r.status="fulfilled",r.value=o)}},function(o){if(e._status===0||e._status===-1){e._status=2,e._result=o;var i=e._ioInfo;i!=null&&(i.end=performance.now()),r.status===void 0&&(r.status="rejected",r.reason=o)}}),t=e._ioInfo,t!=null){t.value=r;var n=r.displayName;typeof n=="string"&&(t.name=n)}e._status===-1&&(e._status=0,e._result=r)}if(e._status===1)return t=e._result,t===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
10
+
11
+ Your code should look like:
12
+ const MyComponent = lazy(() => import('./MyComponent'))
13
+
14
+ Did you accidentally put curly braces around the import?`,t),"default"in t||console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
15
+
16
+ Your code should look like:
17
+ const MyComponent = lazy(() => import('./MyComponent'))`,t),t.default;throw e._result}function l(){var e=s.H;return e===null&&console.error(`Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
18
+ 1. You might have mismatching versions of React and the renderer (such as React DOM)
19
+ 2. You might be breaking the Rules of Hooks
20
+ 3. You might have more than one copy of React in the same app
21
+ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.`),e}function x(){s.asyncTransitions--}function k(e){if(C===null)try{var t=("require"+Math.random()).slice(0,7);C=(p&&p[t]).call(p,"timers").setImmediate}catch{C=function(n){ve===!1&&(ve=!0,typeof MessageChannel>"u"&&console.error("This browser does not have a MessageChannel implementation, so enqueuing tasks via await act(async () => ...) will fail. Please file an issue at https://github.com/facebook/react/issues if you encounter this warning."));var o=new MessageChannel;o.port1.onmessage=n,o.port2.postMessage(void 0)}}return C(e)}function v(e){return 1<e.length&&typeof AggregateError=="function"?new AggregateError(e):e[0]}function S(e,t){t!==j-1&&console.error("You seem to have overlapping act() calls, this is not supported. Be sure to await previous act() calls before making a new one. "),j=t}function Y(e,t,r){var n=s.actQueue;if(n!==null)if(n.length!==0)try{U(n),k(function(){return Y(e,t,r)});return}catch(o){s.thrownErrors.push(o)}else s.actQueue=null;0<s.thrownErrors.length?(n=v(s.thrownErrors),s.thrownErrors.length=0,r(n)):t(e)}function U(e){if(!G){G=!0;var t=0;try{for(;t<e.length;t++){var r=e[t];do{s.didUsePromise=!1;var n=r(!1);if(n!==null){if(s.didUsePromise){e[t]=r,e.splice(0,t);return}r=n}else break}while(!0)}e.length=0}catch(o){e.splice(0,t+1),s.thrownErrors.push(o)}finally{G=!1}}}typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart=="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());var I=Symbol.for("react.transitional.element"),ee=Symbol.for("react.portal"),q=Symbol.for("react.fragment"),te=Symbol.for("react.strict_mode"),re=Symbol.for("react.profiler"),W=Symbol.for("react.consumer"),ne=Symbol.for("react.context"),oe=Symbol.for("react.forward_ref"),ue=Symbol.for("react.suspense"),Pe=Symbol.for("react.suspense_list"),z=Symbol.for("react.memo"),w=Symbol.for("react.lazy"),ae=Symbol.for("react.activity"),se=Symbol.iterator,ie={},ce={isMounted:function(){return!1},enqueueForceUpdate:function(e){M(e,"forceUpdate")},enqueueReplaceState:function(e){M(e,"replaceState")},enqueueSetState:function(e){M(e,"setState")}},fe=Object.assign,H={};Object.freeze(H),m.prototype.isReactComponent={},m.prototype.setState=function(e,t){if(typeof e!="object"&&typeof e!="function"&&e!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")},m.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")};var d={isMounted:["isMounted","Instead, make sure to clean up subscriptions and pending requests in componentWillUnmount to prevent memory leaks."],replaceState:["replaceState","Refactor your code to use setState instead (see https://github.com/facebook/react/issues/3236)."]};for(E in d)d.hasOwnProperty(E)&&Re(E,d[E]);B.prototype=m.prototype,d=N.prototype=new B,d.constructor=N,fe(d,m.prototype),d.isPureReactComponent=!0;var le=Array.isArray,Me=Symbol.for("react.client.reference"),s={H:null,A:null,T:null,S:null,actQueue:null,asyncTransitions:0,isBatchingLegacy:!1,didScheduleLegacyUpdate:!1,didUsePromise:!1,thrownErrors:[],getCurrentStack:null,recentlyCreatedOwnerStacks:0},A=Object.prototype.hasOwnProperty,de=console.createTask?console.createTask:function(){return null};d={react_stack_bottom_frame:function(e){return e()}};var pe,he,me={},Ne=d.react_stack_bottom_frame.bind(d,V)(),Le=de(F(V)),ye=!1,ge=/\/+/g,_e=typeof reportError=="function"?reportError:function(e){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var t=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof e=="object"&&e!==null&&typeof e.message=="string"?String(e.message):String(e),error:e});if(!window.dispatchEvent(t))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",e);return}console.error(e)},ve=!1,C=null,j=0,P=!1,G=!1,we=typeof queueMicrotask=="function"?function(e){queueMicrotask(function(){return queueMicrotask(e)})}:k;d=Object.freeze({__proto__:null,c:function(e){return l().useMemoCache(e)}});var E={map:O,forEach:function(e,t,r){O(e,function(){t.apply(this,arguments)},r)},count:function(e){var t=0;return O(e,function(){t++}),t},toArray:function(e){return O(e,function(t){return t})||[]},only:function(e){if(!y(e))throw Error("React.Children.only expected to receive a single React element child.");return e}};u.Activity=ae,u.Children=E,u.Component=m,u.Fragment=q,u.Profiler=re,u.PureComponent=N,u.StrictMode=te,u.Suspense=ue,u.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=s,u.__COMPILER_RUNTIME=d,u.act=function(e){var t=s.actQueue,r=j;j++;var n=s.actQueue=t!==null?t:[],o=!1;try{var i=e()}catch(c){s.thrownErrors.push(c)}if(0<s.thrownErrors.length)throw S(t,r),e=v(s.thrownErrors),s.thrownErrors.length=0,e;if(i!==null&&typeof i=="object"&&typeof i.then=="function"){var a=i;return we(function(){o||P||(P=!0,console.error("You called act(async () => ...) without await. This could lead to unexpected testing behaviour, interleaving multiple act calls and mixing their scopes. You should - await act(async () => ...);"))}),{then:function(c,h){o=!0,a.then(function(_){if(S(t,r),r===0){try{U(n),k(function(){return Y(_,c,h)})}catch(De){s.thrownErrors.push(De)}if(0<s.thrownErrors.length){var $e=v(s.thrownErrors);s.thrownErrors.length=0,h($e)}}else c(_)},function(_){S(t,r),0<s.thrownErrors.length&&(_=v(s.thrownErrors),s.thrownErrors.length=0),h(_)})}}}var f=i;if(S(t,r),r===0&&(U(n),n.length!==0&&we(function(){o||P||(P=!0,console.error("A component suspended inside an `act` scope, but the `act` call was not awaited. When testing React components that depend on asynchronous data, you must await the result:\n\nawait act(() => ...)"))}),s.actQueue=null),0<s.thrownErrors.length)throw e=v(s.thrownErrors),s.thrownErrors.length=0,e;return{then:function(c,h){o=!0,r===0?(s.actQueue=n,k(function(){return Y(f,c,h)})):c(f)}}},u.cache=function(e){return function(){return e.apply(null,arguments)}},u.cacheSignal=function(){return null},u.captureOwnerStack=function(){var e=s.getCurrentStack;return e===null?null:e()},u.cloneElement=function(e,t,r){if(e==null)throw Error("The argument must be a React element, but you passed "+e+".");var n=fe({},e.props),o=e.key,i=e._owner;if(t!=null){var a;e:{if(A.call(t,"ref")&&(a=Object.getOwnPropertyDescriptor(t,"ref").get)&&a.isReactWarning){a=!1;break e}a=t.ref!==void 0}a&&(i=X()),Z(t)&&(R(t.key),o=""+t.key);for(f in t)!A.call(t,f)||f==="key"||f==="__self"||f==="__source"||f==="ref"&&t.ref===void 0||(n[f]=t[f])}var f=arguments.length-2;if(f===1)n.children=r;else if(1<f){a=Array(f);for(var c=0;c<f;c++)a[c]=arguments[c+2];n.children=a}for(n=$(e.type,o,n,i,e._debugStack,e._debugTask),o=2;o<arguments.length;o++)J(arguments[o]);return n},u.createContext=function(e){return e={$$typeof:ne,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null},e.Provider=e,e.Consumer={$$typeof:W,_context:e},e._currentRenderer=null,e._currentRenderer2=null,e},u.createElement=function(e,t,r){for(var n=2;n<arguments.length;n++)J(arguments[n]);n={};var o=null;if(t!=null)for(c in he||!("__self"in t)||"key"in t||(he=!0,console.warn("Your app (or one of its dependencies) is using an outdated JSX transform. Update to the modern JSX transform for faster performance: https://react.dev/link/new-jsx-transform")),Z(t)&&(R(t.key),o=""+t.key),t)A.call(t,c)&&c!=="key"&&c!=="__self"&&c!=="__source"&&(n[c]=t[c]);var i=arguments.length-2;if(i===1)n.children=r;else if(1<i){for(var a=Array(i),f=0;f<i;f++)a[f]=arguments[f+2];Object.freeze&&Object.freeze(a),n.children=a}if(e&&e.defaultProps)for(c in i=e.defaultProps,i)n[c]===void 0&&(n[c]=i[c]);o&&Oe(n,typeof e=="function"?e.displayName||e.name||"Unknown":e);var c=1e4>s.recentlyCreatedOwnerStacks++;return $(e,o,n,X(),c?Error("react-stack-top-frame"):Ne,c?de(F(e)):Le)},u.createRef=function(){var e={current:null};return Object.seal(e),e},u.forwardRef=function(e){e!=null&&e.$$typeof===z?console.error("forwardRef requires a render function but received a `memo` component. Instead of forwardRef(memo(...)), use memo(forwardRef(...))."):typeof e!="function"?console.error("forwardRef requires a render function but was given %s.",e===null?"null":typeof e):e.length!==0&&e.length!==2&&console.error("forwardRef render functions accept exactly two parameters: props and ref. %s",e.length===1?"Did you forget to use the ref parameter?":"Any additional parameter will be undefined."),e!=null&&e.defaultProps!=null&&console.error("forwardRef render functions do not support defaultProps. Did you accidentally pass a React component?");var t={$$typeof:oe,render:e},r;return Object.defineProperty(t,"displayName",{enumerable:!1,configurable:!0,get:function(){return r},set:function(n){r=n,e.name||e.displayName||(Object.defineProperty(e,"name",{value:n}),e.displayName=n)}}),t},u.isValidElement=y,u.lazy=function(e){e={_status:-1,_result:e};var t={$$typeof:w,_payload:e,_init:je},r={name:"lazy",start:-1,end:-1,value:null,owner:null,debugStack:Error("react-stack-top-frame"),debugTask:console.createTask?console.createTask("lazy()"):null};return e._ioInfo=r,t._debugInfo=[{awaited:r}],t},u.memo=function(e,t){e==null&&console.error("memo: The first argument must be a component. Instead received: %s",e===null?"null":typeof e),t={$$typeof:z,type:e,compare:t===void 0?null:t};var r;return Object.defineProperty(t,"displayName",{enumerable:!1,configurable:!0,get:function(){return r},set:function(n){r=n,e.name||e.displayName||(Object.defineProperty(e,"name",{value:n}),e.displayName=n)}}),t},u.startTransition=function(e){var t=s.T,r={};r._updatedFibers=new Set,s.T=r;try{var n=e(),o=s.S;o!==null&&o(r,n),typeof n=="object"&&n!==null&&typeof n.then=="function"&&(s.asyncTransitions++,n.then(x,x),n.then(L,_e))}catch(i){_e(i)}finally{t===null&&r._updatedFibers&&(e=r._updatedFibers.size,r._updatedFibers.clear(),10<e&&console.warn("Detected a large number of updates inside startTransition. If this is due to a subscription please re-write it to use React provided hooks. Otherwise concurrent mode guarantees are off the table.")),t!==null&&r.types!==null&&(t.types!==null&&t.types!==r.types&&console.error("We expected inner Transitions to have transferred the outer types set and that you cannot add to the outer Transition while inside the inner.This is a bug in React."),t.types=r.types),s.T=t}},u.unstable_useCacheRefresh=function(){return l().useCacheRefresh()},u.use=function(e){return l().use(e)},u.useActionState=function(e,t,r){return l().useActionState(e,t,r)},u.useCallback=function(e,t){return l().useCallback(e,t)},u.useContext=function(e){var t=l();return e.$$typeof===W&&console.error("Calling useContext(Context.Consumer) is not supported and will cause bugs. Did you mean to call useContext(Context) instead?"),t.useContext(e)},u.useDebugValue=function(e,t){return l().useDebugValue(e,t)},u.useDeferredValue=function(e,t){return l().useDeferredValue(e,t)},u.useEffect=function(e,t){return e==null&&console.warn("React Hook useEffect requires an effect callback. Did you forget to pass a callback to the hook?"),l().useEffect(e,t)},u.useEffectEvent=function(e){return l().useEffectEvent(e)},u.useId=function(){return l().useId()},u.useImperativeHandle=function(e,t,r){return l().useImperativeHandle(e,t,r)},u.useInsertionEffect=function(e,t){return e==null&&console.warn("React Hook useInsertionEffect requires an effect callback. Did you forget to pass a callback to the hook?"),l().useInsertionEffect(e,t)},u.useLayoutEffect=function(e,t){return e==null&&console.warn("React Hook useLayoutEffect requires an effect callback. Did you forget to pass a callback to the hook?"),l().useLayoutEffect(e,t)},u.useMemo=function(e,t){return l().useMemo(e,t)},u.useOptimistic=function(e,t){return l().useOptimistic(e,t)},u.useReducer=function(e,t,r){return l().useReducer(e,t,r)},u.useRef=function(e){return l().useRef(e)},u.useState=function(e){return l().useState(e)},u.useSyncExternalStore=function(e,t,r){return l().useSyncExternalStore(e,t,r)},u.useTransition=function(){return l().useTransition()},u.version="19.2.4",typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop=="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error())})()})(b,b.exports)),b.exports}var be;function Ie(){return be||(be=1,Q.exports=Ye()),Q.exports}export{Ue as g,Ie as r};
assets/index-Br42UDbl.js ADDED
@@ -0,0 +1 @@
 
 
1
+ import{g as i,r as c}from"./index-BlGQAcOD.js";function f(t,n){for(var o=0;o<n.length;o++){const e=n[o];if(typeof e!="string"&&!Array.isArray(e)){for(const r in e)if(r!=="default"&&!(r in t)){const a=Object.getOwnPropertyDescriptor(e,r);a&&Object.defineProperty(t,r,a.get?a:{enumerable:!0,get:()=>e[r]})}}}return Object.freeze(Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}))}var s=c();const p=i(s),g=f({__proto__:null,default:p},[s]);export{g as i,s as r};
assets/index-CXVdwQTy.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./index-Br42UDbl.js","./index-BlGQAcOD.js","./client-BlQxAbrl.js","./index-tKuM8enU.js","./App-Ckrxctng.js","./jsx-dev-runtime-Czb3f8pQ.js","./ErrorBoundary-DwultlP_.js"])))=>i.map(i=>d[i]);
2
+ (function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const e of document.querySelectorAll('link[rel="modulepreload"]'))d(e);new MutationObserver(e=>{for(const t of e)if(t.type==="childList")for(const s of t.addedNodes)s.tagName==="LINK"&&s.rel==="modulepreload"&&d(s)}).observe(document,{childList:!0,subtree:!0});function i(e){const t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin==="use-credentials"?t.credentials="include":e.crossOrigin==="anonymous"?t.credentials="omit":t.credentials="same-origin",t}function d(e){if(e.ep)return;e.ep=!0;const t=i(e);fetch(e.href,t)}})();const E="modulepreload",v=function(r,o){return new URL(r,o).href},w={},y=function(o,i,d){let e=Promise.resolve();if(i&&i.length>0){let s=function(n){return Promise.all(n.map(u=>Promise.resolve(u).then(p=>({status:"fulfilled",value:p}),p=>({status:"rejected",reason:p}))))};const l=document.getElementsByTagName("link"),f=document.querySelector("meta[property=csp-nonce]"),h=(f==null?void 0:f.nonce)||(f==null?void 0:f.getAttribute("nonce"));e=s(i.map(n=>{if(n=v(n,d),n in w)return;w[n]=!0;const u=n.endsWith(".css"),p=u?'[rel="stylesheet"]':"";if(!!d)for(let m=l.length-1;m>=0;m--){const g=l[m];if(g.href===n&&(!u||g.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${n}"]${p}`))return;const c=document.createElement("link");if(c.rel=u?"stylesheet":E,u||(c.as="script"),c.crossOrigin="",c.href=n,h&&c.setAttribute("nonce",h),document.head.appendChild(c),u)return new Promise((m,g)=>{c.addEventListener("load",m),c.addEventListener("error",()=>g(new Error(`Unable to preload CSS for ${n}`)))})}))}function t(s){const l=new Event("vite:preloadError",{cancelable:!0});if(l.payload=s,window.dispatchEvent(l),!l.defaultPrevented)throw s}return e.then(s=>{for(const l of s||[])l.status==="rejected"&&t(l.reason);return o().catch(t)})},_="__dep_reload",L=6,O=6e4;function P(){try{return JSON.parse(sessionStorage.getItem(_)||"{}")}catch{return{c:0,t:0}}}async function R(){const r=document.getElementById("root");try{let o=function(){if(!document.querySelector("[data-surf-placeholder]"))try{window.parent.postMessage({type:"surf-app-ready"},"*")}catch{}};const i=await y(()=>import("./index-Br42UDbl.js").then(a=>a.i),__vite__mapDeps([0,1]),import.meta.url);if(typeof i.useState!="function")throw new Error("dep-stub");const{createElement:d}=i,{createRoot:e,hydrateRoot:t}=await y(async()=>{const{createRoot:a,hydrateRoot:c}=await import("./client-BlQxAbrl.js").then(m=>m.c);return{createRoot:a,hydrateRoot:c}},__vite__mapDeps([2,1]),import.meta.url),{QueryClient:s,QueryClientProvider:l}=await y(async()=>{const{QueryClient:a,QueryClientProvider:c}=await import("./index-tKuM8enU.js");return{QueryClient:a,QueryClientProvider:c}},__vite__mapDeps([3,0,1]),import.meta.url),{default:f}=await y(async()=>{const{default:a}=await import("./App-Ckrxctng.js");return{default:a}},__vite__mapDeps([4,5,1,0]),import.meta.url),{default:h}=await y(async()=>{const{default:a}=await import("./ErrorBoundary-DwultlP_.js");return{default:a}},__vite__mapDeps([6,5,1,0]),import.meta.url),n=new s({defaultOptions:{queries:{refetchOnWindowFocus:!1,retry:3,retryDelay:a=>Math.min(1e3*2**a,1e4),staleTime:3e4}}}),u=d(h,null,d(l,{client:n},d(f))),p=!!r.querySelector("[data-surf-placeholder]");r.childNodes.length>0&&r.innerHTML!=="<!--ssr-outlet-->"&&!p?t(r,u):(r.innerHTML="",e(r).render(u)),window.__reactOk=!0,sessionStorage.removeItem(_),o(),new MutationObserver(o).observe(r,{childList:!0,subtree:!0})}catch{const o=P(),i=Date.now()-o.t>O?0:o.c;i<L?(r.innerHTML=['<div style="padding:24px;text-align:center;font-family:system-ui,sans-serif">','<p style="color:#3b82f6;font-weight:600;margin:0 0 4px">Loading dependencies...</p>','<p style="color:#3b82f6;opacity:0.7;font-size:12px;margin:0">Reloading automatically</p>',"</div>"].join(""),sessionStorage.setItem(_,JSON.stringify({c:i+1,t:Date.now()})),setTimeout(()=>location.reload(),3e3+i*1e3)):r.innerHTML=['<div style="padding:24px;text-align:center;font-family:system-ui,sans-serif">','<p style="color:#c0392b;font-weight:600;margin:0 0 4px">Failed to load dependencies</p>','<p style="color:#c0392b;opacity:0.8;font-size:12px;margin:0">Please refresh the page</p>',"</div>"].join("")}}R();export{y as _};
assets/index-D8uigG9a.css ADDED
@@ -0,0 +1 @@
 
 
1
+ @import"https://fonts.googleapis.com/css2?family=Lato:wght@400;600;700;900&family=Roboto+Mono:wght@400;500&display=swap";/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-content:"";--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-900:oklch(39.6% .141 25.723);--color-amber-300:oklch(87.9% .169 91.605);--color-emerald-200:oklch(90.5% .093 164.15);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-cyan-200:oklch(91.7% .08 205.041);--color-cyan-300:oklch(86.5% .127 207.078);--color-cyan-400:oklch(78.9% .154 211.53);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-900:oklch(20.8% .042 265.755);--color-slate-950:oklch(12.9% .042 264.695);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-lg:32rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-black:900;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-widest:.1em;--leading-snug:1.375;--leading-relaxed:1.625;--radius-2xl:1rem;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--blur-2xl:40px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-background:var(--background);--color-foreground:var(--foreground);--color-border:var(--border)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*,:after,:before{border-color:var(--color-border)}body{background-color:var(--color-background);color:var(--color-foreground);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:Lato,PingFang SC,sans-serif}}@layer components;@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.inset-x-0{inset-inline:calc(var(--spacing) * 0)}.inset-y-0{inset-block:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.-top-12{top:calc(var(--spacing) * -12)}.top-0{top:calc(var(--spacing) * 0)}.top-1{top:calc(var(--spacing) * 1)}.top-1\/2{top:50%}.top-3{top:calc(var(--spacing) * 3)}.top-4{top:calc(var(--spacing) * 4)}.top-\[1px\]{top:1px}.top-\[50\%\]{top:50%}.top-\[60\%\]{top:60%}.top-full{top:100%}.-right-12{right:calc(var(--spacing) * -12)}.right-0{right:calc(var(--spacing) * 0)}.right-1{right:calc(var(--spacing) * 1)}.right-2{right:calc(var(--spacing) * 2)}.right-3{right:calc(var(--spacing) * 3)}.right-4{right:calc(var(--spacing) * 4)}.-bottom-12{bottom:calc(var(--spacing) * -12)}.bottom-0{bottom:calc(var(--spacing) * 0)}.-left-12{left:calc(var(--spacing) * -12)}.left-0{left:calc(var(--spacing) * 0)}.left-1\/2{left:50%}.left-2{left:calc(var(--spacing) * 2)}.left-3{left:calc(var(--spacing) * 3)}.left-\[50\%\]{left:50%}.z-10{z-index:10}.z-50{z-index:50}.z-\[1\]{z-index:1}.z-\[100\]{z-index:100}.-mx-1{margin-inline:calc(var(--spacing) * -1)}.mx-auto{margin-inline:auto}.my-1{margin-block:calc(var(--spacing) * 1)}.-mt-4{margin-top:calc(var(--spacing) * -4)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-24{margin-top:calc(var(--spacing) * 24)}.mt-auto{margin-top:auto}.mr-2{margin-right:calc(var(--spacing) * 2)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.-ml-4{margin-left:calc(var(--spacing) * -4)}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-flex{display:inline-flex}.table{display:table}.aspect-square{aspect-ratio:1}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-\[--cell-size\]{width:--cell-size;height:--cell-size}.h-1{height:calc(var(--spacing) * 1)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-20{height:calc(var(--spacing) * 20)}.h-\[--cell-size\]{height:--cell-size}.h-\[1px\]{height:1px}.h-\[var\(--radix-navigation-menu-viewport-height\)\]{height:var(--radix-navigation-menu-viewport-height)}.h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-\[--radix-context-menu-content-available-height\]{max-height:--radix-context-menu-content-available-height}.max-h-\[--radix-select-content-available-height\]{max-height:--radix-select-content-available-height}.max-h-\[300px\]{max-height:300px}.max-h-\[var\(--radix-dropdown-menu-content-available-height\)\]{max-height:var(--radix-dropdown-menu-content-available-height)}.max-h-screen{max-height:100vh}.min-h-\[60px\]{min-height:60px}.min-h-screen{min-height:100vh}.w-2{width:calc(var(--spacing) * 2)}.w-2\.5{width:calc(var(--spacing) * 2.5)}.w-3{width:calc(var(--spacing) * 3)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-3\/4{width:75%}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-8{width:calc(var(--spacing) * 8)}.w-9{width:calc(var(--spacing) * 9)}.w-10{width:calc(var(--spacing) * 10)}.w-20{width:calc(var(--spacing) * 20)}.w-64{width:calc(var(--spacing) * 64)}.w-72{width:calc(var(--spacing) * 72)}.w-\[--cell-size\]{width:--cell-size}.w-\[1px\]{width:1px}.w-\[100px\]{width:100px}.w-fit{width:fit-content}.w-full{width:100%}.w-max{width:max-content}.w-px{width:1px}.max-w-6xl{max-width:var(--container-6xl)}.max-w-lg{max-width:var(--container-lg)}.max-w-max{max-width:max-content}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-8{min-width:calc(var(--spacing) * 8)}.min-w-9{min-width:calc(var(--spacing) * 9)}.min-w-10{min-width:calc(var(--spacing) * 10)}.min-w-\[--cell-size\]{min-width:--cell-size}.min-w-\[8rem\]{min-width:8rem}.min-w-\[12rem\]{min-width:12rem}.min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.grow-0{flex-grow:0}.basis-full{flex-basis:100%}.caption-bottom{caption-side:bottom}.border-collapse{border-collapse:collapse}.origin-\[--radix-context-menu-content-transform-origin\]{transform-origin:--radix-context-menu-content-transform-origin}.origin-\[--radix-dropdown-menu-content-transform-origin\]{transform-origin:--radix-dropdown-menu-content-transform-origin}.origin-\[--radix-hover-card-content-transform-origin\]{transform-origin:--radix-hover-card-content-transform-origin}.origin-\[--radix-menubar-content-transform-origin\]{transform-origin:--radix-menubar-content-transform-origin}.origin-\[--radix-popover-content-transform-origin\]{transform-origin:--radix-popover-content-transform-origin}.origin-\[--radix-select-content-transform-origin\]{transform-origin:--radix-select-content-transform-origin}.origin-\[--radix-tooltip-content-transform-origin\]{transform-origin:--radix-tooltip-content-transform-origin}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-\[-50\%\]{--tw-translate-x:-50%;translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-y-\[-50\%\]{--tw-translate-y:-50%;translate:var(--tw-translate-x) var(--tw-translate-y)}.rotate-45{rotate:45deg}.rotate-90{rotate:90deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-in{animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.animate-pulse{animation:var(--animate-pulse)}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.list-none{list-style-type:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-x-1>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 1) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-2>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 2) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-x-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-\[10px\]{border-radius:10px}.rounded-\[inherit\]{border-radius:inherit}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-none{border-radius:0}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:calc(var(--radius) + 4px)}.rounded-t-\[10px\]{border-top-left-radius:10px;border-top-right-radius:10px}.rounded-l-md{border-top-left-radius:calc(var(--radius) - 2px);border-bottom-left-radius:calc(var(--radius) - 2px)}.rounded-tl-sm{border-top-left-radius:calc(var(--radius) - 4px)}.rounded-r-md{border-top-right-radius:calc(var(--radius) - 2px);border-bottom-right-radius:calc(var(--radius) - 2px)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-\[var\(--border-base\)\]{border-color:var(--border-base)}.border-cyan-400{border-color:var(--color-cyan-400)}.border-cyan-400\/30{border-color:#00d2ef4d}@supports (color:color-mix(in lab,red,red)){.border-cyan-400\/30{border-color:color-mix(in oklab,var(--color-cyan-400) 30%,transparent)}}.border-destructive,.border-destructive\/50{border-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.border-destructive\/50{border-color:color-mix(in oklab,var(--destructive) 50%,transparent)}}.border-emerald-400{border-color:var(--color-emerald-400)}.border-emerald-400\/30{border-color:#00d2944d}@supports (color:color-mix(in lab,red,red)){.border-emerald-400\/30{border-color:color-mix(in oklab,var(--color-emerald-400) 30%,transparent)}}.border-input{border-color:var(--input)}.border-primary,.border-primary\/50{border-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.border-primary\/50{border-color:color-mix(in oklab,var(--primary) 50%,transparent)}}.border-transparent{border-color:#0000}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.border-white\/10{border-color:color-mix(in oklab,var(--color-white) 10%,transparent)}}.border-white\/15{border-color:#ffffff26}@supports (color:color-mix(in lab,red,red)){.border-white\/15{border-color:color-mix(in oklab,var(--color-white) 15%,transparent)}}.border-t-transparent{border-top-color:#0000}.border-l-transparent{border-left-color:#0000}.bg-\[\#04080f\]{background-color:#04080f}.bg-\[var\(--bg-subtle\)\]{background-color:var(--bg-subtle)}.bg-\[var\(--neutral-0\)\]{background-color:var(--neutral-0)}.bg-accent{background-color:var(--accent)}.bg-background{background-color:var(--background)}.bg-black{background-color:var(--color-black)}.bg-black\/25{background-color:#00000040}@supports (color:color-mix(in lab,red,red)){.bg-black\/25{background-color:color-mix(in oklab,var(--color-black) 25%,transparent)}}.bg-black\/30{background-color:#0000004d}@supports (color:color-mix(in lab,red,red)){.bg-black\/30{background-color:color-mix(in oklab,var(--color-black) 30%,transparent)}}.bg-black\/40{background-color:#0006}@supports (color:color-mix(in lab,red,red)){.bg-black\/40{background-color:color-mix(in oklab,var(--color-black) 40%,transparent)}}.bg-black\/80{background-color:#000c}@supports (color:color-mix(in lab,red,red)){.bg-black\/80{background-color:color-mix(in oklab,var(--color-black) 80%,transparent)}}.bg-border{background-color:var(--border)}.bg-card{background-color:var(--card)}.bg-cyan-400{background-color:var(--color-cyan-400)}.bg-cyan-400\/10{background-color:#00d2ef1a}@supports (color:color-mix(in lab,red,red)){.bg-cyan-400\/10{background-color:color-mix(in oklab,var(--color-cyan-400) 10%,transparent)}}.bg-cyan-400\/15{background-color:#00d2ef26}@supports (color:color-mix(in lab,red,red)){.bg-cyan-400\/15{background-color:color-mix(in oklab,var(--color-cyan-400) 15%,transparent)}}.bg-destructive{background-color:var(--destructive)}.bg-emerald-500\/10{background-color:#00bb7f1a}@supports (color:color-mix(in lab,red,red)){.bg-emerald-500\/10{background-color:color-mix(in oklab,var(--color-emerald-500) 10%,transparent)}}.bg-emerald-500\/15{background-color:#00bb7f26}@supports (color:color-mix(in lab,red,red)){.bg-emerald-500\/15{background-color:color-mix(in oklab,var(--color-emerald-500) 15%,transparent)}}.bg-emerald-500\/20{background-color:#00bb7f33}@supports (color:color-mix(in lab,red,red)){.bg-emerald-500\/20{background-color:color-mix(in oklab,var(--color-emerald-500) 20%,transparent)}}.bg-foreground\/5{background-color:var(--foreground)}@supports (color:color-mix(in lab,red,red)){.bg-foreground\/5{background-color:color-mix(in oklab,var(--foreground) 5%,transparent)}}.bg-muted,.bg-muted\/50{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.bg-muted\/50{background-color:color-mix(in oklab,var(--muted) 50%,transparent)}}.bg-popover{background-color:var(--popover)}.bg-primary,.bg-primary\/20{background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.bg-primary\/20{background-color:color-mix(in oklab,var(--primary) 20%,transparent)}}.bg-red-500\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/10{background-color:color-mix(in oklab,var(--color-red-500) 10%,transparent)}}.bg-red-500\/20{background-color:#fb2c3633}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/20{background-color:color-mix(in oklab,var(--color-red-500) 20%,transparent)}}.bg-red-900\/80{background-color:#82181acc}@supports (color:color-mix(in lab,red,red)){.bg-red-900\/80{background-color:color-mix(in oklab,var(--color-red-900) 80%,transparent)}}.bg-secondary{background-color:var(--secondary)}.bg-transparent{background-color:#0000}.bg-white\/5{background-color:#ffffff0d}@supports (color:color-mix(in lab,red,red)){.bg-white\/5{background-color:color-mix(in oklab,var(--color-white) 5%,transparent)}}.bg-white\/10{background-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.bg-white\/10{background-color:color-mix(in oklab,var(--color-white) 10%,transparent)}}.bg-white\/20{background-color:#fff3}@supports (color:color-mix(in lab,red,red)){.bg-white\/20{background-color:color-mix(in oklab,var(--color-white) 20%,transparent)}}.bg-white\/50{background-color:#ffffff80}@supports (color:color-mix(in lab,red,red)){.bg-white\/50{background-color:color-mix(in oklab,var(--color-white) 50%,transparent)}}.bg-white\/90{background-color:#ffffffe6}@supports (color:color-mix(in lab,red,red)){.bg-white\/90{background-color:color-mix(in oklab,var(--color-white) 90%,transparent)}}.bg-white\/\[0\.03\]{background-color:#ffffff08}@supports (color:color-mix(in lab,red,red)){.bg-white\/\[0\.03\]{background-color:color-mix(in oklab,var(--color-white) 3%,transparent)}}.bg-gradient-to-r{--tw-gradient-position:to right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-t{--tw-gradient-position:to top in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-black\/80{--tw-gradient-from:#000c}@supports (color:color-mix(in lab,red,red)){.from-black\/80{--tw-gradient-from:color-mix(in oklab, var(--color-black) 80%, transparent)}}.from-black\/80{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-cyan-300{--tw-gradient-from:var(--color-cyan-300);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-cyan-400{--tw-gradient-from:var(--color-cyan-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-emerald-300{--tw-gradient-to:var(--color-emerald-300);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-emerald-400{--tw-gradient-to:var(--color-emerald-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-transparent{--tw-gradient-to:transparent;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.fill-current{fill:currentColor}.fill-primary{fill:var(--primary)}.p-0{padding:calc(var(--spacing) * 0)}.p-1{padding:calc(var(--spacing) * 1)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.p-\[1px\]{padding:1px}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-8{padding-inline:calc(var(--spacing) * 8)}.px-\[--cell-size\]{padding-inline:--cell-size}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-6{padding-block:calc(var(--spacing) * 6)}.pt-0{padding-top:calc(var(--spacing) * 0)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-8{padding-top:calc(var(--spacing) * 8)}.pr-1{padding-right:calc(var(--spacing) * 1)}.pr-2{padding-right:calc(var(--spacing) * 2)}.pr-6{padding-right:calc(var(--spacing) * 6)}.pr-8{padding-right:calc(var(--spacing) * 8)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-12{padding-bottom:calc(var(--spacing) * 12)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-4{padding-left:calc(var(--spacing) * 4)}.pl-8{padding-left:calc(var(--spacing) * 8)}.text-center{text-align:center}.text-left{text-align:left}.align-middle{vertical-align:middle}.font-sans{font-family:var(--font-sans)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[0\.8rem\]{font-size:.8rem}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.font-black{--tw-font-weight:var(--font-weight-black);font-weight:var(--font-weight-black)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[0\.25em\]{--tw-tracking:.25em;letter-spacing:.25em}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.text-balance{text-wrap:balance}.break-words{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-\[var\(--fg-subtle\)\]{color:var(--fg-subtle)}.text-accent-foreground{color:var(--accent-foreground)}.text-amber-300{color:var(--color-amber-300)}.text-card-foreground{color:var(--card-foreground)}.text-current{color:currentColor}.text-cyan-200{color:var(--color-cyan-200)}.text-cyan-300{color:var(--color-cyan-300)}.text-cyan-300\/80{color:#53eafdcc}@supports (color:color-mix(in lab,red,red)){.text-cyan-300\/80{color:color-mix(in oklab,var(--color-cyan-300) 80%,transparent)}}.text-destructive{color:var(--destructive)}.text-destructive-foreground{color:var(--destructive-foreground)}.text-emerald-200{color:var(--color-emerald-200)}.text-emerald-300{color:var(--color-emerald-300)}.text-foreground,.text-foreground\/50{color:var(--foreground)}@supports (color:color-mix(in lab,red,red)){.text-foreground\/50{color:color-mix(in oklab,var(--foreground) 50%,transparent)}}.text-muted-foreground{color:var(--muted-foreground)}.text-popover-foreground{color:var(--popover-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-red-100{color:var(--color-red-100)}.text-red-200{color:var(--color-red-200)}.text-red-300{color:var(--color-red-300)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-slate-100{color:var(--color-slate-100)}.text-slate-200{color:var(--color-slate-200)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-900{color:var(--color-slate-900)}.text-slate-950{color:var(--color-slate-950)}.text-white{color:var(--color-white)}.text-white\/90{color:#ffffffe6}@supports (color:color-mix(in lab,red,red)){.text-white\/90{color:color-mix(in oklab,var(--color-white) 90%,transparent)}}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.opacity-90{opacity:.9}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_0_80px_rgba\(60\,180\,255\,0\.15\)\]{--tw-shadow:0 0 80px var(--tw-shadow-color,#3cb4ff26);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-0{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-offset-background{--tw-ring-offset-color:var(--background)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.backdrop-blur-2xl{--tw-backdrop-blur:blur(var(--blur-2xl));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[color\,box-shadow\]{transition-property:color,box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.fade-in-0{--tw-enter-opacity:0}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.zoom-in-95{--tw-enter-scale:.95}.\[--cell-size\:2rem\]{--cell-size:2rem}.running{animation-play-state:running}@media(hover:hover){.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.group-data-\[focused\=true\]\/day\:relative:is(:where(.group\/day)[data-focused=true] *){position:relative}.group-data-\[focused\=true\]\/day\:z-10:is(:where(.group\/day)[data-focused=true] *){z-index:10}.group-data-\[focused\=true\]\/day\:border-ring:is(:where(.group\/day)[data-focused=true] *){border-color:var(--ring)}.group-data-\[focused\=true\]\/day\:ring-\[3px\]:is(:where(.group\/day)[data-focused=true] *){--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.group-data-\[focused\=true\]\/day\:ring-ring\/50:is(:where(.group\/day)[data-focused=true] *){--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab,red,red)){.group-data-\[focused\=true\]\/day\:ring-ring\/50:is(:where(.group\/day)[data-focused=true] *){--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.group-data-\[state\=open\]\:rotate-180:is(:where(.group)[data-state=open] *){rotate:180deg}.group-\[\.destructive\]\:border-muted\/40:is(:where(.group).destructive *){border-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.group-\[\.destructive\]\:border-muted\/40:is(:where(.group).destructive *){border-color:color-mix(in oklab,var(--muted) 40%,transparent)}}.group-\[\.destructive\]\:text-red-300:is(:where(.group).destructive *){color:var(--color-red-300)}.group-\[\.toast\]\:bg-muted:is(:where(.group).toast *){background-color:var(--muted)}.group-\[\.toast\]\:bg-primary:is(:where(.group).toast *){background-color:var(--primary)}.group-\[\.toast\]\:text-muted-foreground:is(:where(.group).toast *){color:var(--muted-foreground)}.group-\[\.toast\]\:text-primary-foreground:is(:where(.group).toast *){color:var(--primary-foreground)}.group-\[\.toaster\]\:border-border:is(:where(.group).toaster *){border-color:var(--border)}.group-\[\.toaster\]\:bg-background:is(:where(.group).toaster *){background-color:var(--background)}.group-\[\.toaster\]\:text-foreground:is(:where(.group).toaster *){color:var(--foreground)}.group-\[\.toaster\]\:shadow-lg:is(:where(.group).toaster *){--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\:opacity-70:is(:where(.peer):disabled~*){opacity:.7}.file\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\:bg-transparent::file-selector-button{background-color:#0000}.file\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\:text-foreground::file-selector-button{color:var(--foreground)}.placeholder\:text-muted-foreground::placeholder{color:var(--muted-foreground)}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:inset-y-0:after{content:var(--tw-content);inset-block:calc(var(--spacing) * 0)}.after\:left-1\/2:after{content:var(--tw-content);left:50%}.after\:w-1:after{content:var(--tw-content);width:calc(var(--spacing) * 1)}.after\:-translate-x-1\/2:after{content:var(--tw-content);--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}@media(hover:hover){.hover\:border-white\/30:hover{border-color:#ffffff4d}@supports (color:color-mix(in lab,red,red)){.hover\:border-white\/30:hover{border-color:color-mix(in oklab,var(--color-white) 30%,transparent)}}.hover\:border-white\/40:hover{border-color:#fff6}@supports (color:color-mix(in lab,red,red)){.hover\:border-white\/40:hover{border-color:color-mix(in oklab,var(--color-white) 40%,transparent)}}.hover\:bg-accent:hover{background-color:var(--accent)}.hover\:bg-black\/15:hover{background-color:#00000026}@supports (color:color-mix(in lab,red,red)){.hover\:bg-black\/15:hover{background-color:color-mix(in oklab,var(--color-black) 15%,transparent)}}.hover\:bg-destructive\/80:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-destructive\/80:hover{background-color:color-mix(in oklab,var(--destructive) 80%,transparent)}}.hover\:bg-destructive\/90:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab,var(--destructive) 90%,transparent)}}.hover\:bg-muted:hover,.hover\:bg-muted\/50:hover{background-color:var(--muted)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab,var(--muted) 50%,transparent)}}.hover\:bg-primary\/80:hover{background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-primary\/80:hover{background-color:color-mix(in oklab,var(--primary) 80%,transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab,var(--primary) 90%,transparent)}}.hover\:bg-secondary:hover,.hover\:bg-secondary\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab,var(--secondary) 80%,transparent)}}.hover\:bg-white\/5:hover{background-color:#ffffff0d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-white\/5:hover{background-color:color-mix(in oklab,var(--color-white) 5%,transparent)}}.hover\:text-accent-foreground:hover{color:var(--accent-foreground)}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:text-muted-foreground:hover{color:var(--muted-foreground)}.hover\:text-slate-200:hover{color:var(--color-slate-200)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}.hover\:brightness-110:hover{--tw-brightness:brightness(110%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.group-\[\.destructive\]\:hover\:border-destructive\/30:is(:where(.group).destructive *):hover{border-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.group-\[\.destructive\]\:hover\:border-destructive\/30:is(:where(.group).destructive *):hover{border-color:color-mix(in oklab,var(--destructive) 30%,transparent)}}.group-\[\.destructive\]\:hover\:bg-destructive:is(:where(.group).destructive *):hover{background-color:var(--destructive)}.group-\[\.destructive\]\:hover\:text-destructive-foreground:is(:where(.group).destructive *):hover{color:var(--destructive-foreground)}.group-\[\.destructive\]\:hover\:text-red-50:is(:where(.group).destructive *):hover{color:var(--color-red-50)}}.focus\:bg-accent:focus{background-color:var(--accent)}.focus\:text-accent-foreground:focus{color:var(--accent-foreground)}.focus\:opacity-100:focus{opacity:1}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-ring:focus{--tw-ring-color:var(--ring)}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.group-\[\.destructive\]\:focus\:ring-destructive:is(:where(.group).destructive *):focus{--tw-ring-color:var(--destructive)}.group-\[\.destructive\]\:focus\:ring-red-400:is(:where(.group).destructive *):focus{--tw-ring-color:var(--color-red-400)}.group-\[\.destructive\]\:focus\:ring-offset-red-600:is(:where(.group).destructive *):focus{--tw-ring-offset-color:var(--color-red-600)}.focus-visible\:border-\[var\(--fg-base\)\]:focus-visible{border-color:var(--fg-base)}.focus-visible\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color:var(--ring)}.focus-visible\:ring-offset-1:focus-visible{--tw-ring-offset-width:1px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus-visible\:ring-offset-background:focus-visible{--tw-ring-offset-color:var(--background)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.has-focus\:border-ring:has(:focus){border-color:var(--ring)}.has-focus\:ring-\[3px\]:has(:focus){--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.has-focus\:ring-ring\/50:has(:focus){--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab,red,red)){.has-focus\:ring-ring\/50:has(:focus){--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.aria-disabled\:opacity-50[aria-disabled=true]{opacity:.5}.aria-selected\:text-muted-foreground[aria-selected=true]{color:var(--muted-foreground)}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[disabled\=true\]\:pointer-events-none[data-disabled=true]{pointer-events:none}.data-\[disabled\=true\]\:opacity-50[data-disabled=true]{opacity:.5}.data-\[motion\=from-end\]\:slide-in-from-right-52[data-motion=from-end]{--tw-enter-translate-x:calc(52*var(--spacing))}.data-\[motion\=from-start\]\:slide-in-from-left-52[data-motion=from-start]{--tw-enter-translate-x:calc(52*var(--spacing)*-1)}.data-\[motion\=to-end\]\:slide-out-to-right-52[data-motion=to-end]{--tw-exit-translate-x:calc(52*var(--spacing))}.data-\[motion\=to-start\]\:slide-out-to-left-52[data-motion=to-start]{--tw-exit-translate-x:calc(52*var(--spacing)*-1)}.data-\[motion\^\=from-\]\:animate-in[data-motion^=from-]{animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[motion\^\=from-\]\:fade-in[data-motion^=from-]{--tw-enter-opacity:0}.data-\[motion\^\=to-\]\:animate-out[data-motion^=to-]{animation:exit var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[motion\^\=to-\]\:fade-out[data-motion^=to-]{--tw-exit-opacity:0}.data-\[panel-group-direction\=vertical\]\:h-px[data-panel-group-direction=vertical]{height:1px}.data-\[panel-group-direction\=vertical\]\:w-full[data-panel-group-direction=vertical]{width:100%}.data-\[panel-group-direction\=vertical\]\:flex-col[data-panel-group-direction=vertical]{flex-direction:column}.data-\[panel-group-direction\=vertical\]\:after\:left-0[data-panel-group-direction=vertical]:after{content:var(--tw-content);left:calc(var(--spacing) * 0)}.data-\[panel-group-direction\=vertical\]\:after\:h-1[data-panel-group-direction=vertical]:after{content:var(--tw-content);height:calc(var(--spacing) * 1)}.data-\[panel-group-direction\=vertical\]\:after\:w-full[data-panel-group-direction=vertical]:after{content:var(--tw-content);width:100%}.data-\[panel-group-direction\=vertical\]\:after\:translate-x-0[data-panel-group-direction=vertical]:after{content:var(--tw-content);--tw-translate-x:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[panel-group-direction\=vertical\]\:after\:-translate-y-1\/2[data-panel-group-direction=vertical]:after{content:var(--tw-content);--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[placeholder\]\:text-muted-foreground[data-placeholder]{color:var(--muted-foreground)}.data-\[range-end\=true\]\:rounded-md[data-range-end=true]{border-radius:calc(var(--radius) - 2px)}.data-\[range-end\=true\]\:bg-primary[data-range-end=true]{background-color:var(--primary)}.data-\[range-end\=true\]\:text-primary-foreground[data-range-end=true]{color:var(--primary-foreground)}.data-\[range-middle\=true\]\:rounded-none[data-range-middle=true]{border-radius:0}.data-\[range-middle\=true\]\:bg-accent[data-range-middle=true]{background-color:var(--accent)}.data-\[range-middle\=true\]\:text-accent-foreground[data-range-middle=true]{color:var(--accent-foreground)}.data-\[range-start\=true\]\:rounded-md[data-range-start=true]{border-radius:calc(var(--radius) - 2px)}.data-\[range-start\=true\]\:bg-primary[data-range-start=true]{background-color:var(--primary)}.data-\[range-start\=true\]\:text-primary-foreground[data-range-start=true]{color:var(--primary-foreground)}.data-\[selected-single\=true\]\:bg-primary[data-selected-single=true]{background-color:var(--primary)}.data-\[selected-single\=true\]\:text-primary-foreground[data-selected-single=true]{color:var(--primary-foreground)}.data-\[selected\=true\]\:rounded-none[data-selected=true]{border-radius:0}.data-\[selected\=true\]\:bg-accent[data-selected=true]{background-color:var(--accent)}.data-\[selected\=true\]\:text-accent-foreground[data-selected=true]{color:var(--accent-foreground)}.data-\[side\=bottom\]\:translate-y-1[data-side=bottom]{--tw-translate-y:calc(var(--spacing) * 1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=bottom\]\:slide-in-from-top-2[data-side=bottom]{--tw-enter-translate-y:calc(2*var(--spacing)*-1)}.data-\[side\=left\]\:-translate-x-1[data-side=left]{--tw-translate-x:calc(var(--spacing) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=left\]\:slide-in-from-right-2[data-side=left]{--tw-enter-translate-x:calc(2*var(--spacing))}.data-\[side\=right\]\:translate-x-1[data-side=right]{--tw-translate-x:calc(var(--spacing) * 1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=right\]\:slide-in-from-left-2[data-side=right]{--tw-enter-translate-x:calc(2*var(--spacing)*-1)}.data-\[side\=top\]\:-translate-y-1[data-side=top]{--tw-translate-y:calc(var(--spacing) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=top\]\:slide-in-from-bottom-2[data-side=top]{--tw-enter-translate-y:calc(2*var(--spacing))}.data-\[state\=active\]\:bg-background[data-state=active]{background-color:var(--background)}.data-\[state\=active\]\:text-foreground[data-state=active]{color:var(--foreground)}.data-\[state\=active\]\:shadow[data-state=active]{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.data-\[state\=checked\]\:translate-x-4[data-state=checked]{--tw-translate-x:calc(var(--spacing) * 4);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[state\=checked\]\:bg-primary[data-state=checked]{background-color:var(--primary)}.data-\[state\=checked\]\:text-primary-foreground[data-state=checked]{color:var(--primary-foreground)}.data-\[state\=closed\]\:animate-accordion-up[data-state=closed]{animation:.2s ease-out accordion-up}.data-\[state\=closed\]\:animate-out[data-state=closed]{animation:exit var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[state\=closed\]\:duration-300[data-state=closed]{--tw-duration:.3s;transition-duration:.3s}.data-\[state\=closed\]\:fade-out-0[data-state=closed]{--tw-exit-opacity:0}.data-\[state\=closed\]\:fade-out-80[data-state=closed]{--tw-exit-opacity:.8}.data-\[state\=closed\]\:zoom-out-95[data-state=closed]{--tw-exit-scale:.95}.data-\[state\=closed\]\:slide-out-to-bottom[data-state=closed]{--tw-exit-translate-y:100%}.data-\[state\=closed\]\:slide-out-to-left[data-state=closed]{--tw-exit-translate-x:-100%}.data-\[state\=closed\]\:slide-out-to-left-1\/2[data-state=closed]{--tw-exit-translate-x: -50% }.data-\[state\=closed\]\:slide-out-to-right[data-state=closed]{--tw-exit-translate-x:100%}.data-\[state\=closed\]\:slide-out-to-right-full[data-state=closed]{--tw-exit-translate-x: 100% }.data-\[state\=closed\]\:slide-out-to-top[data-state=closed]{--tw-exit-translate-y:-100%}.data-\[state\=closed\]\:slide-out-to-top-\[48\%\][data-state=closed]{--tw-exit-translate-y: -48% }.data-\[state\=hidden\]\:animate-out[data-state=hidden]{animation:exit var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[state\=hidden\]\:fade-out[data-state=hidden]{--tw-exit-opacity:0}.data-\[state\=on\]\:bg-accent[data-state=on]{background-color:var(--accent)}.data-\[state\=on\]\:text-accent-foreground[data-state=on]{color:var(--accent-foreground)}.data-\[state\=open\]\:animate-accordion-down[data-state=open]{animation:.2s ease-out accordion-down}.data-\[state\=open\]\:animate-in[data-state=open]{animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[state\=open\]\:bg-accent[data-state=open],.data-\[state\=open\]\:bg-accent\/50[data-state=open]{background-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.data-\[state\=open\]\:bg-accent\/50[data-state=open]{background-color:color-mix(in oklab,var(--accent) 50%,transparent)}}.data-\[state\=open\]\:bg-secondary[data-state=open]{background-color:var(--secondary)}.data-\[state\=open\]\:text-accent-foreground[data-state=open]{color:var(--accent-foreground)}.data-\[state\=open\]\:text-muted-foreground[data-state=open]{color:var(--muted-foreground)}.data-\[state\=open\]\:duration-500[data-state=open]{--tw-duration:.5s;transition-duration:.5s}.data-\[state\=open\]\:fade-in-0[data-state=open]{--tw-enter-opacity:0}.data-\[state\=open\]\:zoom-in-90[data-state=open]{--tw-enter-scale:.9}.data-\[state\=open\]\:zoom-in-95[data-state=open]{--tw-enter-scale:.95}.data-\[state\=open\]\:slide-in-from-bottom[data-state=open]{--tw-enter-translate-y:100%}.data-\[state\=open\]\:slide-in-from-left[data-state=open]{--tw-enter-translate-x:-100%}.data-\[state\=open\]\:slide-in-from-left-1\/2[data-state=open]{--tw-enter-translate-x: -50% }.data-\[state\=open\]\:slide-in-from-right[data-state=open]{--tw-enter-translate-x:100%}.data-\[state\=open\]\:slide-in-from-top[data-state=open]{--tw-enter-translate-y:-100%}.data-\[state\=open\]\:slide-in-from-top-\[48\%\][data-state=open]{--tw-enter-translate-y: -48% }.data-\[state\=open\]\:slide-in-from-top-full[data-state=open]{--tw-enter-translate-y: -100% }@media(hover:hover){.data-\[state\=open\]\:hover\:bg-accent[data-state=open]:hover{background-color:var(--accent)}}.data-\[state\=open\]\:focus\:bg-accent[data-state=open]:focus{background-color:var(--accent)}.data-\[state\=selected\]\:bg-muted[data-state=selected]{background-color:var(--muted)}.data-\[state\=unchecked\]\:translate-x-0[data-state=unchecked]{--tw-translate-x:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[state\=unchecked\]\:bg-input[data-state=unchecked]{background-color:var(--input)}.data-\[state\=visible\]\:animate-in[data-state=visible]{animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[state\=visible\]\:fade-in[data-state=visible]{--tw-enter-opacity:0}.data-\[swipe\=cancel\]\:translate-x-0[data-swipe=cancel]{--tw-translate-x:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[swipe\=end\]\:translate-x-\[var\(--radix-toast-swipe-end-x\)\][data-swipe=end]{--tw-translate-x:var(--radix-toast-swipe-end-x);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[swipe\=end\]\:animate-out[data-swipe=end]{animation:exit var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[swipe\=move\]\:translate-x-\[var\(--radix-toast-swipe-move-x\)\][data-swipe=move]{--tw-translate-x:var(--radix-toast-swipe-move-x);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[swipe\=move\]\:transition-none[data-swipe=move]{transition-property:none}@media(min-width:40rem){.sm\:top-auto{top:auto}.sm\:right-0{right:calc(var(--spacing) * 0)}.sm\:bottom-0{bottom:calc(var(--spacing) * 0)}.sm\:max-w-sm{max-width:var(--container-sm)}.sm\:flex-col{flex-direction:column}.sm\:flex-row{flex-direction:row}.sm\:justify-end{justify-content:flex-end}.sm\:gap-2\.5{gap:calc(var(--spacing) * 2.5)}:where(.sm\:space-x-2>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 2) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-x-reverse)))}.sm\:rounded-2xl{border-radius:var(--radius-2xl)}.sm\:rounded-lg{border-radius:var(--radius)}.sm\:pt-3{padding-top:calc(var(--spacing) * 3)}.sm\:pb-3{padding-bottom:calc(var(--spacing) * 3)}.sm\:text-left{text-align:left}.data-\[state\=open\]\:sm\:slide-in-from-bottom-full[data-state=open]{--tw-enter-translate-y: 100% }}@media(min-width:48rem){.md\:absolute{position:absolute}.md\:w-\[var\(--radix-navigation-menu-viewport-width\)\]{width:var(--radix-navigation-menu-viewport-width)}.md\:w-auto{width:auto}.md\:max-w-\[420px\]{max-width:420px}.md\:flex-row{flex-direction:row}.md\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}@media(min-width:64rem){.lg\:sticky{position:sticky}.lg\:top-6{top:calc(var(--spacing) * 6)}.lg\:flex{display:flex}.lg\:w-auto{width:auto}.lg\:items-start{align-items:flex-start}.lg\:gap-8{gap:calc(var(--spacing) * 8)}.lg\:p-6{padding:calc(var(--spacing) * 6)}.lg\:px-0{padding-inline:calc(var(--spacing) * 0)}.lg\:py-0{padding-block:calc(var(--spacing) * 0)}.lg\:pt-0{padding-top:calc(var(--spacing) * 0)}.lg\:text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}}@media(prefers-color-scheme:dark){.dark\:border-destructive{border-color:var(--destructive)}}.\[\&_\[cmdk-group-heading\]\]\:px-2 [cmdk-group-heading]{padding-inline:calc(var(--spacing) * 2)}.\[\&_\[cmdk-group-heading\]\]\:py-1\.5 [cmdk-group-heading]{padding-block:calc(var(--spacing) * 1.5)}.\[\&_\[cmdk-group-heading\]\]\:text-xs [cmdk-group-heading]{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.\[\&_\[cmdk-group-heading\]\]\:font-medium [cmdk-group-heading]{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.\[\&_\[cmdk-group-heading\]\]\:text-muted-foreground [cmdk-group-heading]{color:var(--muted-foreground)}.\[\&_\[cmdk-group\]\]\:px-2 [cmdk-group]{padding-inline:calc(var(--spacing) * 2)}.\[\&_\[cmdk-group\]\:not\(\[hidden\]\)_\~\[cmdk-group\]\]\:pt-0 [cmdk-group]:not([hidden])~[cmdk-group]{padding-top:calc(var(--spacing) * 0)}.\[\&_\[cmdk-input-wrapper\]_svg\]\:h-5 [cmdk-input-wrapper] svg{height:calc(var(--spacing) * 5)}.\[\&_\[cmdk-input-wrapper\]_svg\]\:w-5 [cmdk-input-wrapper] svg{width:calc(var(--spacing) * 5)}.\[\&_\[cmdk-input\]\]\:h-12 [cmdk-input]{height:calc(var(--spacing) * 12)}.\[\&_\[cmdk-item\]\]\:px-2 [cmdk-item]{padding-inline:calc(var(--spacing) * 2)}.\[\&_\[cmdk-item\]\]\:py-3 [cmdk-item]{padding-block:calc(var(--spacing) * 3)}.\[\&_\[cmdk-item\]_svg\]\:h-5 [cmdk-item] svg{height:calc(var(--spacing) * 5)}.\[\&_\[cmdk-item\]_svg\]\:w-5 [cmdk-item] svg{width:calc(var(--spacing) * 5)}.\[\&_p\]\:leading-relaxed p{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_tr\]\:border-b tr{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.\[\&_tr\:last-child\]\:border-0 tr:last-child{border-style:var(--tw-border-style);border-width:0}.\[\&\+div\]\:text-xs+div{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.\[\&\:first-child\[data-selected\=true\]_button\]\:rounded-l-md:first-child[data-selected=true] button{border-top-left-radius:calc(var(--radius) - 2px);border-bottom-left-radius:calc(var(--radius) - 2px)}.\[\&\:has\(\[role\=checkbox\]\)\]\:pr-0:has([role=checkbox]){padding-right:calc(var(--spacing) * 0)}:is(.rtl\:\*\*\:\[\.rdp-button\\_next\>svg\]\:rotate-180:where(:dir(rtl),[dir=rtl],[dir=rtl] *) *):is(.rdp-button_next>svg),:is(.rtl\:\*\*\:\[\.rdp-button\\_previous\>svg\]\:rotate-180:where(:dir(rtl),[dir=rtl],[dir=rtl] *) *):is(.rdp-button_previous>svg){rotate:180deg}.\[\&\:last-child\[data-selected\=true\]_button\]\:rounded-r-md:last-child[data-selected=true] button{border-top-right-radius:calc(var(--radius) - 2px);border-bottom-right-radius:calc(var(--radius) - 2px)}.\[\&\>\[role\=checkbox\]\]\:translate-y-\[2px\]>[role=checkbox]{--tw-translate-y:2px;translate:var(--tw-translate-x) var(--tw-translate-y)}.\[\&\>span\]\:line-clamp-1>span{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.\[\&\>span\]\:text-xs>span{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.\[\&\>span\]\:opacity-70>span{opacity:.7}.\[\&\>svg\]\:absolute>svg{position:absolute}.\[\&\>svg\]\:top-4>svg{top:calc(var(--spacing) * 4)}.\[\&\>svg\]\:left-4>svg{left:calc(var(--spacing) * 4)}.\[\&\>svg\]\:size-3\.5>svg{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.\[\&\>svg\]\:size-4>svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&\>svg\]\:h-3\.5>svg{height:calc(var(--spacing) * 3.5)}.\[\&\>svg\]\:w-3\.5>svg{width:calc(var(--spacing) * 3.5)}.\[\&\>svg\]\:shrink-0>svg{flex-shrink:0}.\[\&\>svg\]\:text-destructive>svg{color:var(--destructive)}.\[\&\>svg\]\:text-foreground>svg{color:var(--foreground)}.\[\&\>svg\]\:text-muted-foreground>svg{color:var(--muted-foreground)}.\[\&\>svg\+div\]\:translate-y-\[-3px\]>svg+div{--tw-translate-y:-3px;translate:var(--tw-translate-x) var(--tw-translate-y)}.\[\&\>svg\~\*\]\:pl-7>svg~*{padding-left:calc(var(--spacing) * 7)}.\[\&\>tr\]\:last\:border-b-0>tr:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.\[\&\[data-panel-group-direction\=vertical\]\>div\]\:rotate-90[data-panel-group-direction=vertical]>div{rotate:90deg}.\[\&\[data-state\=open\]\>svg\]\:rotate-180[data-state=open]>svg{rotate:180deg}[data-slot=card-content] .\[\[data-slot\=card-content\]_\&\]\:bg-transparent,[data-slot=popover-content] .\[\[data-slot\=popover-content\]_\&\]\:bg-transparent{background-color:#0000}}@property --tw-animation-delay{syntax:"*";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:"*";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:"*";inherits:false}@property --tw-animation-fill-mode{syntax:"*";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:"*";inherits:false;initial-value:0}@keyframes accordion-down{0%{height:0}to{height:var(--radix-accordion-content-height,var(--bits-accordion-content-height,var(--reka-accordion-content-height,var(--kb-accordion-content-height,var(--ngp-accordion-content-height,auto)))))}}@keyframes accordion-up{0%{height:var(--radix-accordion-content-height,var(--bits-accordion-content-height,var(--reka-accordion-content-height,var(--kb-accordion-content-height,var(--ngp-accordion-content-height,auto)))))}to{height:0}}:root{--background:#fff;--foreground:#212121;--card:#fff;--card-foreground:#212121;--popover:#fff;--popover-foreground:#212121;--primary:#ff2974;--primary-foreground:#fff;--secondary:#f3f2f2;--secondary-foreground:#212121;--muted:#f3f2f2;--muted-foreground:#7a7a7a;--accent:#f3f2f2;--accent-foreground:#212121;--destructive:#f5242e;--destructive-foreground:#fff;--border:#e8e8e8;--input:#e8e8e8;--ring:#212121;--radius:.5rem;--neutral-0:#fff;--neutral-50:#fafafa;--neutral-100:#f5f4f4;--neutral-200:#e7e7e7;--neutral-300:#d8d8d8;--neutral-400:#aaa;--neutral-500:#7a7a7a;--neutral-600:#5b5b5b;--neutral-700:#464646;--neutral-800:#2a2a2a;--neutral-900:#212121;--neutral-950:#1b1b1b;--neutral-1000:#101010;--brand-100:#ff2882;--brand-60:#ff288299;--brand-30:#ff28824d;--brand-10:#ff28821a;--brand-seafoam:#b6cfd0;--brand-dusty-teal:#6ba4b8;--brand-black-aqua:#002f38;--brand-deep-teal-blue:#07272d;--visualizer-rose-pop:#fd4b96;--visualizer-indigo-breeze:#6366f1;--visualizer-emerald-mint:#10b981;--visualizer-golden-amber:#f59e0b;--visualizer-royal-blue:#1d4ed8;--visualizer-crimson-spark:#ef4444;--visualizer-aqua-glow:#06b6d4;--visualizer-sunbeam-yellow:#facc15;--bg-subtle:#2a2a2a0a;--bg-subtle-hover:#2a2a2a0f;--bg-base:#ffffffe0;--bg-base-opaque:#fff;--bg-menu:#fff;--bg-chat:#fcfcfc;--bg-chat-nav:#f4f4f4;--fg-base:#212121;--fg-subtle:#7a7a7a;--fg-muted:#aaa;--fg-disabled:#d8d8d8;--border-base:#2a2a2a0a;--border-strong:#2a2a2a14;--border-contrast:#2a2a2a1f;--border-focus:#2a2a2a66;--tag-blue-10:#5bb5ff1a;--tag-blue-100:#5bb5ff;--tag-yellow-10:#dec3781a;--tag-yellow-100:#dec378;--tag-purple-10:#908eb81a;--tag-purple-100:#908eb8;--tag-cyan-10:#74ada41a;--tag-cyan-100:#74ada4;--tag-pink-10:#b88ea71a;--tag-pink-100:#b88ea7;--tag-orange-10:#b8a08e1a;--tag-orange-100:#b8a08e;--gradient-max-dark:linear-gradient(213deg, #8c421d 2%, #fbe67b 31%, #fcfbe7 53%, #f7d14e 77%, #d4a041 100%);--gradient-max-light:linear-gradient(125deg, #8c421d 22%, #d2af00 47%, #cd9124 67%, #d4a041 88%);--gradient-pro-dark:linear-gradient(213deg, #7a96ac 1%, #c5d6e2 27%, #eaeff3 47%, #c5d6e2 65%, #a3bccf 89%);--gradient-pro-light:linear-gradient(129deg, #7a96ac 4%, #6d7f8d 27%, #9fb9ce 55%, #6d7f8d 90%);--gradient-plus-dark:linear-gradient(214deg, #986732 0%, #a7825b 23%, #f6d0ab 45%, #a07043 66%, #9d774e 100%);--gradient-plus-light:linear-gradient(129deg, #9e8976 5%, #7a5e50 19%, #f6d0ab 35%, #9d774e 49%, #c99b70 65%, #795f52 78%);--gradient-upgrade-dark:linear-gradient(214deg, #ffedf3 0%, #ff9fbf 30%, #fd5d92 59%, #ffdab2 100%);--gradient-upgrade-light:linear-gradient(32deg, #fc3bb2 6%, #f7906e 79%);--gradient-new-function:linear-gradient(33deg, #6e86ff 17%, #ff2882 55%, #ff98a4 103%);--gradient-suggestion:linear-gradient(32deg, #fd538c 4%, #5aa6e0 47%, #ffdab2 98%);--gradient-g1:linear-gradient(189deg, #ffacc6 6%, #b6e0f5 99%);--gradient-g2:linear-gradient(34deg, #9796f0 9%, #fbc7d4 84%);--gradient-g3:linear-gradient(to right, #ed4264, #ffedbc);--gradient-g4:linear-gradient(232deg, #fedc2a 4%, #dd5789 56%, #7a2c9e 104%);--gradient-g5:linear-gradient(32deg, #fc3bb2 6%, #f7906e 79%);--gradient-max:var(--gradient-max-light);--gradient-pro:var(--gradient-pro-light);--gradient-plus:var(--gradient-plus-light);--gradient-upgrade:var(--gradient-upgrade-light);--spacing-2:2px;--spacing-4:4px;--spacing-6:6px;--spacing-8:8px;--spacing-10:10px;--spacing-12:12px;--spacing-16:16px;--spacing-24:24px;--spacing-32:32px;--spacing-40:40px;--spacing-64:64px;--spacing-96:96px;--spacing-128:128px;--radius-2:2px;--radius-4:4px;--radius-6:6px;--radius-8:8px;--radius-10:10px;--radius-12:12px;--radius-16:16px;--radius-20:20px;--radius-24:24px;--radius-full:999px;--font-family-header:"Lato", "PingFang SC", sans-serif;--font-family-body:"Lato", "PingFang SC", sans-serif;--font-family-code:"Roboto Mono", monospace}.dark{--background:#171717;--foreground:#e8e8e8;--card:#171717;--card-foreground:#e8e8e8;--popover:#262626;--popover-foreground:#e8e8e8;--primary:#ff2974;--primary-foreground:#fff;--secondary:#292929;--secondary-foreground:#e8e8e8;--muted:#292929;--muted-foreground:#ababab;--accent:#292929;--accent-foreground:#e8e8e8;--destructive:#ff4c4f;--destructive-foreground:#fff;--border:#333;--input:#333;--ring:#e7e7e7;--gradient-max:var(--gradient-max-dark);--gradient-pro:var(--gradient-pro-dark);--gradient-plus:var(--gradient-plus-dark);--gradient-upgrade:var(--gradient-upgrade-dark);--bg-subtle:#ffffff0a;--bg-subtle-hover:#ffffff1f;--bg-base:#2a2a2acc;--bg-base-opaque:#171717;--bg-menu:#252525;--bg-chat:#101010;--bg-chat-nav:#171717;--fg-base:#e7e7e7;--fg-subtle:#aaa;--fg-muted:#7a7a7a;--fg-disabled:#5b5b5b;--border-base:#ffffff0a;--border-strong:#ffffff14;--border-contrast:#ffffff1f;--border-focus:#fff6}@media(max-width:768px){:root{--spacing-96:64px;--spacing-128:64px}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"<length-percentage>";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"<length-percentage>";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"<length-percentage>";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@keyframes pulse{50%{opacity:.5}}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0));filter:blur(var(--tw-enter-blur,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,0));filter:blur(var(--tw-exit-blur,0))}}
assets/index-tKuM8enU.js ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var us=t=>{throw TypeError(t)};var Ft=(t,e,s)=>e.has(t)||us("Cannot "+s);var i=(t,e,s)=>(Ft(t,e,"read from private field"),s?s.call(t):e.get(t)),f=(t,e,s)=>e.has(t)?us("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,s),h=(t,e,s,r)=>(Ft(t,e,"write to private field"),r?r.call(t,s):e.set(t,s),s),w=(t,e,s)=>(Ft(t,e,"access private method"),s);var St=(t,e,s,r)=>({set _(n){h(t,e,n,s)},get _(){return i(t,e,r)}});import{r as Q}from"./index-Br42UDbl.js";import{r as ar}from"./index-BlGQAcOD.js";var Ue=class{constructor(){this.listeners=new Set,this.subscribe=this.subscribe.bind(this)}subscribe(t){return this.listeners.add(t),this.onSubscribe(),()=>{this.listeners.delete(t),this.onUnsubscribe()}}hasListeners(){return this.listeners.size>0}onSubscribe(){}onUnsubscribe(){}},Ce,pe,Le,Os,or=(Os=class extends Ue{constructor(){super();f(this,Ce);f(this,pe);f(this,Le);h(this,Le,e=>{if(typeof window<"u"&&window.addEventListener){const s=()=>e();return window.addEventListener("visibilitychange",s,!1),()=>{window.removeEventListener("visibilitychange",s)}}})}onSubscribe(){i(this,pe)||this.setEventListener(i(this,Le))}onUnsubscribe(){var e;this.hasListeners()||((e=i(this,pe))==null||e.call(this),h(this,pe,void 0))}setEventListener(e){var s;h(this,Le,e),(s=i(this,pe))==null||s.call(this),h(this,pe,e(r=>{typeof r=="boolean"?this.setFocused(r):this.onFocus()}))}setFocused(e){i(this,Ce)!==e&&(h(this,Ce,e),this.onFocus())}onFocus(){const e=this.isFocused();this.listeners.forEach(s=>{s(e)})}isFocused(){var e;return typeof i(this,Ce)=="boolean"?i(this,Ce):((e=globalThis.document)==null?void 0:e.visibilityState)!=="hidden"}},Ce=new WeakMap,pe=new WeakMap,Le=new WeakMap,Os),Xt=new or,ur={setTimeout:(t,e)=>setTimeout(t,e),clearTimeout:t=>clearTimeout(t),setInterval:(t,e)=>setInterval(t,e),clearInterval:t=>clearInterval(t)},te,Qe,Rs,cr=(Rs=class{constructor(){f(this,te,ur);f(this,Qe,!1)}setTimeoutProvider(t){i(this,Qe)&&t!==i(this,te)&&console.error("[timeoutManager]: Switching provider after calls to previous provider might result in unexpected behavior.",{previous:i(this,te),provider:t}),h(this,te,t),h(this,Qe,!1)}setTimeout(t,e){return h(this,Qe,!0),i(this,te).setTimeout(t,e)}clearTimeout(t){i(this,te).clearTimeout(t)}setInterval(t,e){return h(this,Qe,!0),i(this,te).setInterval(t,e)}clearInterval(t){i(this,te).clearInterval(t)}},te=new WeakMap,Qe=new WeakMap,Rs),Ee=new cr;function hr(t){setTimeout(t,0)}var lr=typeof window>"u"||"Deno"in globalThis;function _(){}function fr(t,e){return typeof t=="function"?t(e):t}function At(t){return typeof t=="number"&&t>=0&&t!==1/0}function ks(t,e){return Math.max(t+(e||0)-Date.now(),0)}function Pe(t,e){return typeof t=="function"?t(e):t}function X(t,e){return typeof t=="function"?t(e):t}function cs(t,e){const{type:s="all",exact:r,fetchStatus:n,predicate:a,queryKey:o,stale:c}=t;if(o){if(r){if(e.queryHash!==Zt(o,e.options))return!1}else if(!nt(e.queryKey,o))return!1}if(s!=="all"){const y=e.isActive();if(s==="active"&&!y||s==="inactive"&&y)return!1}return!(typeof c=="boolean"&&e.isStale()!==c||n&&n!==e.state.fetchStatus||a&&!a(e))}function hs(t,e){const{exact:s,status:r,predicate:n,mutationKey:a}=t;if(a){if(!e.options.mutationKey)return!1;if(s){if(je(e.options.mutationKey)!==je(a))return!1}else if(!nt(e.options.mutationKey,a))return!1}return!(r&&e.state.status!==r||n&&!n(e))}function Zt(t,e){return((e==null?void 0:e.queryKeyHashFn)||je)(t)}function je(t){return JSON.stringify(t,(e,s)=>xt(s)?Object.keys(s).sort().reduce((r,n)=>(r[n]=s[n],r),{}):s)}function nt(t,e){return t===e?!0:typeof t!=typeof e?!1:t&&e&&typeof t=="object"&&typeof e=="object"?Object.keys(e).every(s=>nt(t[s],e[s])):!1}var dr=Object.prototype.hasOwnProperty;function at(t,e,s=0){if(t===e)return t;if(s>500)return e;const r=ls(t)&&ls(e);if(!r&&!(xt(t)&&xt(e)))return e;const a=(r?t:Object.keys(t)).length,o=r?e:Object.keys(e),c=o.length,y=r?new Array(c):{};let m=0;for(let v=0;v<c;v++){const l=r?v:o[v],d=t[l],p=e[l];if(d===p){y[l]=d,(r?v<a:dr.call(t,l))&&m++;continue}if(d===null||p===null||typeof d!="object"||typeof p!="object"){y[l]=p;continue}const P=at(d,p,s+1);y[l]=P,P===d&&m++}return a===c&&m===a?t:y}function ot(t,e){if(!e||Object.keys(t).length!==Object.keys(e).length)return!1;for(const s in t)if(t[s]!==e[s])return!1;return!0}function ls(t){return Array.isArray(t)&&t.length===Object.keys(t).length}function xt(t){if(!fs(t))return!1;const e=t.constructor;if(e===void 0)return!0;const s=e.prototype;return!(!fs(s)||!s.hasOwnProperty("isPrototypeOf")||Object.getPrototypeOf(t)!==Object.prototype)}function fs(t){return Object.prototype.toString.call(t)==="[object Object]"}function yr(t){return new Promise(e=>{Ee.setTimeout(e,t)})}function Dt(t,e,s){if(typeof s.structuralSharing=="function")return s.structuralSharing(t,e);if(s.structuralSharing!==!1){try{return at(t,e)}catch(r){throw console.error(`Structural sharing requires data to be JSON serializable. To fix this, turn off structuralSharing or return JSON-serializable data from your queryFn. [${s.queryHash}]: ${r}`),r}return at(t,e)}return e}function $r(t){return t}function Is(t,e,s=0){const r=[...t,e];return s&&r.length>s?r.slice(1):r}function pr(t,e,s=0){const r=[e,...t];return s&&r.length>s?r.slice(0,-1):r}var qe=Symbol();function _s(t,e){return t.queryFn===qe&&console.error(`Attempted to invoke queryFn when set to skipToken. This is likely a configuration error. Query hash: '${t.queryHash}'`),!t.queryFn&&(e!=null&&e.initialPromise)?()=>e.initialPromise:!t.queryFn||t.queryFn===qe?()=>Promise.reject(new Error(`Missing queryFn: '${t.queryHash}'`)):t.queryFn}function es(t,e){return typeof t=="function"?t(...e):!!t}function js(t,e,s){let r=!1,n;return Object.defineProperty(t,"signal",{enumerable:!0,get:()=>(n??(n=e()),r||(r=!0,n.aborted?s():n.addEventListener("abort",s,{once:!0})),n)}),t}var ut=(()=>{let t=()=>lr;return{isServer(){return t()},setIsServer(e){t=e}}})();function kt(){let t,e;const s=new Promise((n,a)=>{t=n,e=a});s.status="pending",s.catch(()=>{});function r(n){Object.assign(s,n),delete s.resolve,delete s.reject}return s.resolve=n=>{r({status:"fulfilled",value:n}),t(n)},s.reject=n=>{r({status:"rejected",reason:n}),e(n)},s}function mr(t){var s;let e;if((s=t.then(r=>(e=r,r),_))==null||s.catch(_),e!==void 0)return{data:e}}function qs(t){return t}function vr(t){return{mutationKey:t.options.mutationKey,state:t.state,...t.options.scope&&{scope:t.options.scope},...t.meta&&{meta:t.meta}}}function gr(t,e,s){const r=()=>{var a;const n=(a=t.promise)==null?void 0:a.then(e).catch(o=>s(o)?(console.error(`A query that was dehydrated as pending ended up rejecting. [${t.queryHash}]: ${o}; The error will be redacted in production builds`),Promise.reject(new Error("redacted"))):Promise.reject(o));return n==null||n.catch(_),n};return{dehydratedAt:Date.now(),state:{...t.state,...t.state.data!==void 0&&{data:e(t.state.data)}},queryKey:t.queryKey,queryHash:t.queryHash,...t.state.status==="pending"&&{promise:r()},...t.meta&&{meta:t.meta}}}function br(t){return t.state.isPaused}function Sr(t){return t.state.status==="success"}function wr(t){return!0}function Gr(t,e={}){var y,m,v,l;const s=e.shouldDehydrateMutation??((y=t.getDefaultOptions().dehydrate)==null?void 0:y.shouldDehydrateMutation)??br,r=t.getMutationCache().getAll().flatMap(d=>s(d)?[vr(d)]:[]),n=e.shouldDehydrateQuery??((m=t.getDefaultOptions().dehydrate)==null?void 0:m.shouldDehydrateQuery)??Sr,a=e.shouldRedactErrors??((v=t.getDefaultOptions().dehydrate)==null?void 0:v.shouldRedactErrors)??wr,o=e.serializeData??((l=t.getDefaultOptions().dehydrate)==null?void 0:l.serializeData)??qs,c=t.getQueryCache().getAll().flatMap(d=>n(d)?[gr(d,o,a)]:[]);return{mutations:r,queries:c}}function ds(t,e,s){var y,m;if(typeof e!="object"||e===null)return;const r=t.getMutationCache(),n=t.getQueryCache(),a=((y=s==null?void 0:s.defaultOptions)==null?void 0:y.deserializeData)??((m=t.getDefaultOptions().hydrate)==null?void 0:m.deserializeData)??qs,o=e.mutations||[],c=e.queries||[];o.forEach(({state:v,...l})=>{var d,p;r.build(t,{...(d=t.getDefaultOptions().hydrate)==null?void 0:d.mutations,...(p=s==null?void 0:s.defaultOptions)==null?void 0:p.mutations,...l},v)}),c.forEach(({queryKey:v,state:l,queryHash:d,meta:p,promise:P,dehydratedAt:g})=>{var j,B;const b=P?mr(P):void 0,O=l.data===void 0?b==null?void 0:b.data:l.data,M=O===void 0?O:a(O);let R=n.get(d);const S=(R==null?void 0:R.state.status)==="pending",D=(R==null?void 0:R.state.fetchStatus)==="fetching";if(R){const T=b&&g!==void 0&&g>R.state.dataUpdatedAt;if(l.dataUpdatedAt>R.state.dataUpdatedAt||T){const{fetchStatus:x,...q}=l;R.setState({...q,data:M})}}else R=n.build(t,{...(j=t.getDefaultOptions().hydrate)==null?void 0:j.queries,...(B=s==null?void 0:s.defaultOptions)==null?void 0:B.queries,queryKey:v,queryHash:d,meta:p},{...l,data:M,fetchStatus:"idle",status:M!==void 0?"success":l.status});P&&!S&&!D&&(g===void 0||g>R.state.dataUpdatedAt)&&R.fetch(void 0,{initialPromise:Promise.resolve(P).then(a)}).catch(_)})}var Or=hr;function Rr(){let t=[],e=0,s=c=>{c()},r=c=>{c()},n=Or;const a=c=>{e?t.push(c):n(()=>{s(c)})},o=()=>{const c=t;t=[],c.length&&n(()=>{r(()=>{c.forEach(y=>{s(y)})})})};return{batch:c=>{let y;e++;try{y=c()}finally{e--,e||o()}return y},batchCalls:c=>(...y)=>{a(()=>{c(...y)})},schedule:a,setNotifyFunction:c=>{s=c},setBatchNotifyFunction:c=>{r=c},setScheduler:c=>{n=c}}}var A=Rr(),He,me,ze,Ps,Pr=(Ps=class extends Ue{constructor(){super();f(this,He,!0);f(this,me);f(this,ze);h(this,ze,e=>{if(typeof window<"u"&&window.addEventListener){const s=()=>e(!0),r=()=>e(!1);return window.addEventListener("online",s,!1),window.addEventListener("offline",r,!1),()=>{window.removeEventListener("online",s),window.removeEventListener("offline",r)}}})}onSubscribe(){i(this,me)||this.setEventListener(i(this,ze))}onUnsubscribe(){var e;this.hasListeners()||((e=i(this,me))==null||e.call(this),h(this,me,void 0))}setEventListener(e){var s;h(this,ze,e),(s=i(this,me))==null||s.call(this),h(this,me,e(this.setOnline.bind(this)))}setOnline(e){i(this,He)!==e&&(h(this,He,e),this.listeners.forEach(r=>{r(e)}))}isOnline(){return i(this,He)}},He=new WeakMap,me=new WeakMap,ze=new WeakMap,Ps),Rt=new Pr;function Er(t){return Math.min(1e3*2**t,3e4)}function Us(t){return(t??"online")==="online"?Rt.isOnline():!0}var Pt=class extends Error{constructor(t){super("CancelledError"),this.revert=t==null?void 0:t.revert,this.silent=t==null?void 0:t.silent}};function Br(t){return t instanceof Pt}function Ns(t){let e=!1,s=0,r;const n=kt(),a=()=>n.status!=="pending",o=g=>{var b;if(!a()){const O=new Pt(g);d(O),(b=t.onCancel)==null||b.call(t,O)}},c=()=>{e=!0},y=()=>{e=!1},m=()=>Xt.isFocused()&&(t.networkMode==="always"||Rt.isOnline())&&t.canRun(),v=()=>Us(t.networkMode)&&t.canRun(),l=g=>{a()||(r==null||r(),n.resolve(g))},d=g=>{a()||(r==null||r(),n.reject(g))},p=()=>new Promise(g=>{var b;r=O=>{(a()||m())&&g(O)},(b=t.onPause)==null||b.call(t)}).then(()=>{var g;r=void 0,a()||(g=t.onContinue)==null||g.call(t)}),P=()=>{if(a())return;let g;const b=s===0?t.initialPromise:void 0;try{g=b??t.fn()}catch(O){g=Promise.reject(O)}Promise.resolve(g).then(l).catch(O=>{var j;if(a())return;const M=t.retry??(ut.isServer()?0:3),R=t.retryDelay??Er,S=typeof R=="function"?R(s,O):R,D=M===!0||typeof M=="number"&&s<M||typeof M=="function"&&M(s,O);if(e||!D){d(O);return}s++,(j=t.onFail)==null||j.call(t,s,O),yr(S).then(()=>m()?void 0:p()).then(()=>{e?d(O):P()})})};return{promise:n,status:()=>n.status,cancel:o,continue:()=>(r==null||r(),n),cancelRetry:c,continueRetry:y,canStart:v,start:()=>(v()?P():p().then(P),n)}}var Te,Es,Ks=(Es=class{constructor(){f(this,Te)}destroy(){this.clearGcTimeout()}scheduleGc(){this.clearGcTimeout(),At(this.gcTime)&&h(this,Te,Ee.setTimeout(()=>{this.optionalRemove()},this.gcTime))}updateGcTime(t){this.gcTime=Math.max(this.gcTime||0,t??(ut.isServer()?1/0:300*1e3))}clearGcTimeout(){i(this,Te)&&(Ee.clearTimeout(i(this,Te)),h(this,Te,void 0))}},Te=new WeakMap,Es),Fe,$e,J,Me,K,ct,Ae,W,Ls,ne,Cs,Cr=(Cs=class extends Ks{constructor(e){super();f(this,W);f(this,Fe);f(this,$e);f(this,J);f(this,Me);f(this,K);f(this,ct);f(this,Ae);h(this,Ae,!1),h(this,ct,e.defaultOptions),this.setOptions(e.options),this.observers=[],h(this,Me,e.client),h(this,J,i(this,Me).getQueryCache()),this.queryKey=e.queryKey,this.queryHash=e.queryHash,h(this,Fe,ps(this.options)),this.state=e.state??i(this,Fe),this.scheduleGc()}get meta(){return this.options.meta}get promise(){var e;return(e=i(this,K))==null?void 0:e.promise}setOptions(e){if(this.options={...i(this,ct),...e},this.updateGcTime(this.options.gcTime),this.state&&this.state.data===void 0){const s=ps(this.options);s.data!==void 0&&(this.setState(ys(s.data,s.dataUpdatedAt)),h(this,Fe,s))}}optionalRemove(){!this.observers.length&&this.state.fetchStatus==="idle"&&i(this,J).remove(this)}setData(e,s){const r=Dt(this.state.data,e,this.options);return w(this,W,ne).call(this,{data:r,type:"success",dataUpdatedAt:s==null?void 0:s.updatedAt,manual:s==null?void 0:s.manual}),r}setState(e,s){w(this,W,ne).call(this,{type:"setState",state:e,setStateOptions:s})}cancel(e){var r,n;const s=(r=i(this,K))==null?void 0:r.promise;return(n=i(this,K))==null||n.cancel(e),s?s.then(_).catch(_):Promise.resolve()}destroy(){super.destroy(),this.cancel({silent:!0})}get resetState(){return i(this,Fe)}reset(){this.destroy(),this.setState(this.resetState)}isActive(){return this.observers.some(e=>X(e.options.enabled,this)!==!1)}isDisabled(){return this.getObserversCount()>0?!this.isActive():this.options.queryFn===qe||!this.isFetched()}isFetched(){return this.state.dataUpdateCount+this.state.errorUpdateCount>0}isStatic(){return this.getObserversCount()>0?this.observers.some(e=>Pe(e.options.staleTime,this)==="static"):!1}isStale(){return this.getObserversCount()>0?this.observers.some(e=>e.getCurrentResult().isStale):this.state.data===void 0||this.state.isInvalidated}isStaleByTime(e=0){return this.state.data===void 0?!0:e==="static"?!1:this.state.isInvalidated?!0:!ks(this.state.dataUpdatedAt,e)}onFocus(){var s;const e=this.observers.find(r=>r.shouldFetchOnWindowFocus());e==null||e.refetch({cancelRefetch:!1}),(s=i(this,K))==null||s.continue()}onOnline(){var s;const e=this.observers.find(r=>r.shouldFetchOnReconnect());e==null||e.refetch({cancelRefetch:!1}),(s=i(this,K))==null||s.continue()}addObserver(e){this.observers.includes(e)||(this.observers.push(e),this.clearGcTimeout(),i(this,J).notify({type:"observerAdded",query:this,observer:e}))}removeObserver(e){this.observers.includes(e)&&(this.observers=this.observers.filter(s=>s!==e),this.observers.length||(i(this,K)&&(i(this,Ae)||w(this,W,Ls).call(this)?i(this,K).cancel({revert:!0}):i(this,K).cancelRetry()),this.scheduleGc()),i(this,J).notify({type:"observerRemoved",query:this,observer:e}))}getObserversCount(){return this.observers.length}invalidate(){this.state.isInvalidated||w(this,W,ne).call(this,{type:"invalidate"})}async fetch(e,s){var y,m,v,l,d,p,P,g,b,O,M,R;if(this.state.fetchStatus!=="idle"&&((y=i(this,K))==null?void 0:y.status())!=="rejected"){if(this.state.data!==void 0&&(s!=null&&s.cancelRefetch))this.cancel({silent:!0});else if(i(this,K))return i(this,K).continueRetry(),i(this,K).promise}if(e&&this.setOptions(e),!this.options.queryFn){const S=this.observers.find(D=>D.options.queryFn);S&&this.setOptions(S.options)}Array.isArray(this.options.queryKey)||console.error("As of v4, queryKey needs to be an Array. If you are using a string like 'repoData', please change it to an Array, e.g. ['repoData']");const r=new AbortController,n=S=>{Object.defineProperty(S,"signal",{enumerable:!0,get:()=>(h(this,Ae,!0),r.signal)})},a=()=>{const S=_s(this.options,s),j=(()=>{const B={client:i(this,Me),queryKey:this.queryKey,meta:this.meta};return n(B),B})();return h(this,Ae,!1),this.options.persister?this.options.persister(S,j,this):S(j)},c=(()=>{const S={fetchOptions:s,options:this.options,queryKey:this.queryKey,client:i(this,Me),state:this.state,fetchFn:a};return n(S),S})();(m=this.options.behavior)==null||m.onFetch(c,this),h(this,$e,this.state),(this.state.fetchStatus==="idle"||this.state.fetchMeta!==((v=c.fetchOptions)==null?void 0:v.meta))&&w(this,W,ne).call(this,{type:"fetch",meta:(l=c.fetchOptions)==null?void 0:l.meta}),h(this,K,Ns({initialPromise:s==null?void 0:s.initialPromise,fn:c.fetchFn,onCancel:S=>{S instanceof Pt&&S.revert&&this.setState({...i(this,$e),fetchStatus:"idle"}),r.abort()},onFail:(S,D)=>{w(this,W,ne).call(this,{type:"failed",failureCount:S,error:D})},onPause:()=>{w(this,W,ne).call(this,{type:"pause"})},onContinue:()=>{w(this,W,ne).call(this,{type:"continue"})},retry:c.options.retry,retryDelay:c.options.retryDelay,networkMode:c.options.networkMode,canRun:()=>!0}));try{const S=await i(this,K).start();if(S===void 0)throw console.error(`Query data cannot be undefined. Please make sure to return a value other than undefined from your query function. Affected query key: ${this.queryHash}`),new Error(`${this.queryHash} data is undefined`);return this.setData(S),(p=(d=i(this,J).config).onSuccess)==null||p.call(d,S,this),(g=(P=i(this,J).config).onSettled)==null||g.call(P,S,this.state.error,this),S}catch(S){if(S instanceof Pt){if(S.silent)return i(this,K).promise;if(S.revert){if(this.state.data===void 0)throw S;return this.state.data}}throw w(this,W,ne).call(this,{type:"error",error:S}),(O=(b=i(this,J).config).onError)==null||O.call(b,S,this),(R=(M=i(this,J).config).onSettled)==null||R.call(M,this.state.data,S,this),S}finally{this.scheduleGc()}}},Fe=new WeakMap,$e=new WeakMap,J=new WeakMap,Me=new WeakMap,K=new WeakMap,ct=new WeakMap,Ae=new WeakMap,W=new WeakSet,Ls=function(){return this.state.fetchStatus==="paused"&&this.state.status==="pending"},ne=function(e){const s=r=>{switch(e.type){case"failed":return{...r,fetchFailureCount:e.failureCount,fetchFailureReason:e.error};case"pause":return{...r,fetchStatus:"paused"};case"continue":return{...r,fetchStatus:"fetching"};case"fetch":return{...r,...Hs(r.data,this.options),fetchMeta:e.meta??null};case"success":const n={...r,...ys(e.data,e.dataUpdatedAt),dataUpdateCount:r.dataUpdateCount+1,...!e.manual&&{fetchStatus:"idle",fetchFailureCount:0,fetchFailureReason:null}};return h(this,$e,e.manual?n:void 0),n;case"error":const a=e.error;return{...r,error:a,errorUpdateCount:r.errorUpdateCount+1,errorUpdatedAt:Date.now(),fetchFailureCount:r.fetchFailureCount+1,fetchFailureReason:a,fetchStatus:"idle",status:"error",isInvalidated:!0};case"invalidate":return{...r,isInvalidated:!0};case"setState":return{...r,...e.state}}};this.state=s(this.state),A.batch(()=>{this.observers.forEach(r=>{r.onQueryUpdate()}),i(this,J).notify({query:this,type:"updated",action:e})})},Cs);function Hs(t,e){return{fetchFailureCount:0,fetchFailureReason:null,fetchStatus:Us(e.networkMode)?"fetching":"paused",...t===void 0&&{error:null,status:"pending"}}}function ys(t,e){return{data:t,dataUpdatedAt:e??Date.now(),error:null,isInvalidated:!1,status:"success"}}function ps(t){const e=typeof t.initialData=="function"?t.initialData():t.initialData,s=e!==void 0,r=s?typeof t.initialDataUpdatedAt=="function"?t.initialDataUpdatedAt():t.initialDataUpdatedAt:0;return{data:e,dataUpdateCount:0,dataUpdatedAt:s?r??Date.now():0,error:null,errorUpdateCount:0,errorUpdatedAt:0,fetchFailureCount:0,fetchFailureReason:null,fetchMeta:null,isInvalidated:!1,status:s?"success":"pending",fetchStatus:"idle"}}var $,C,ht,z,xe,Ge,ae,ve,lt,Be,Ye,De,ke,ge,We,F,it,It,_t,jt,qt,Ut,Nt,Kt,zs,Qs,gt=(Qs=class extends Ue{constructor(e,s){super();f(this,F);f(this,$);f(this,C);f(this,ht);f(this,z);f(this,xe);f(this,Ge);f(this,ae);f(this,ve);f(this,lt);f(this,Be);f(this,Ye);f(this,De);f(this,ke);f(this,ge);f(this,We,new Set);this.options=s,h(this,$,e),h(this,ve,null),h(this,ae,kt()),this.bindMethods(),this.setOptions(s)}bindMethods(){this.refetch=this.refetch.bind(this)}onSubscribe(){this.listeners.size===1&&(i(this,C).addObserver(this),ms(i(this,C),this.options)?w(this,F,it).call(this):this.updateResult(),w(this,F,qt).call(this))}onUnsubscribe(){this.hasListeners()||this.destroy()}shouldFetchOnReconnect(){return Lt(i(this,C),this.options,this.options.refetchOnReconnect)}shouldFetchOnWindowFocus(){return Lt(i(this,C),this.options,this.options.refetchOnWindowFocus)}destroy(){this.listeners=new Set,w(this,F,Ut).call(this),w(this,F,Nt).call(this),i(this,C).removeObserver(this)}setOptions(e){const s=this.options,r=i(this,C);if(this.options=i(this,$).defaultQueryOptions(e),this.options.enabled!==void 0&&typeof this.options.enabled!="boolean"&&typeof this.options.enabled!="function"&&typeof X(this.options.enabled,i(this,C))!="boolean")throw new Error("Expected enabled to be a boolean or a callback that returns a boolean");w(this,F,Kt).call(this),i(this,C).setOptions(this.options),s._defaulted&&!ot(this.options,s)&&i(this,$).getQueryCache().notify({type:"observerOptionsUpdated",query:i(this,C),observer:this});const n=this.hasListeners();n&&vs(i(this,C),r,this.options,s)&&w(this,F,it).call(this),this.updateResult(),n&&(i(this,C)!==r||X(this.options.enabled,i(this,C))!==X(s.enabled,i(this,C))||Pe(this.options.staleTime,i(this,C))!==Pe(s.staleTime,i(this,C)))&&w(this,F,It).call(this);const a=w(this,F,_t).call(this);n&&(i(this,C)!==r||X(this.options.enabled,i(this,C))!==X(s.enabled,i(this,C))||a!==i(this,ge))&&w(this,F,jt).call(this,a)}getOptimisticResult(e){const s=i(this,$).getQueryCache().build(i(this,$),e),r=this.createResult(s,e);return Tr(this,r)&&(h(this,z,r),h(this,Ge,this.options),h(this,xe,i(this,C).state)),r}getCurrentResult(){return i(this,z)}trackResult(e,s){return new Proxy(e,{get:(r,n)=>(this.trackProp(n),s==null||s(n),n==="promise"&&(this.trackProp("data"),!this.options.experimental_prefetchInRender&&i(this,ae).status==="pending"&&i(this,ae).reject(new Error("experimental_prefetchInRender feature flag is not enabled"))),Reflect.get(r,n))})}trackProp(e){i(this,We).add(e)}getCurrentQuery(){return i(this,C)}refetch({...e}={}){return this.fetch({...e})}fetchOptimistic(e){const s=i(this,$).defaultQueryOptions(e),r=i(this,$).getQueryCache().build(i(this,$),s);return r.fetch().then(()=>this.createResult(r,s))}fetch(e){return w(this,F,it).call(this,{...e,cancelRefetch:e.cancelRefetch??!0}).then(()=>(this.updateResult(),i(this,z)))}createResult(e,s){var x;const r=i(this,C),n=this.options,a=i(this,z),o=i(this,xe),c=i(this,Ge),m=e!==r?e.state:i(this,ht),{state:v}=e;let l={...v},d=!1,p;if(s._optimisticResults){const q=this.hasListeners(),ee=!q&&ms(e,s),fe=q&&vs(e,r,s,n);(ee||fe)&&(l={...l,...Hs(v.data,e.options)}),s._optimisticResults==="isRestoring"&&(l.fetchStatus="idle")}let{error:P,errorUpdatedAt:g,status:b}=l;p=l.data;let O=!1;if(s.placeholderData!==void 0&&p===void 0&&b==="pending"){let q;a!=null&&a.isPlaceholderData&&s.placeholderData===(c==null?void 0:c.placeholderData)?(q=a.data,O=!0):q=typeof s.placeholderData=="function"?s.placeholderData((x=i(this,Ye))==null?void 0:x.state.data,i(this,Ye)):s.placeholderData,q!==void 0&&(b="success",p=Dt(a==null?void 0:a.data,q,s),d=!0)}if(s.select&&p!==void 0&&!O)if(a&&p===(o==null?void 0:o.data)&&s.select===i(this,lt))p=i(this,Be);else try{h(this,lt,s.select),p=s.select(p),p=Dt(a==null?void 0:a.data,p,s),h(this,Be,p),h(this,ve,null)}catch(q){h(this,ve,q)}i(this,ve)&&(P=i(this,ve),p=i(this,Be),g=Date.now(),b="error");const M=l.fetchStatus==="fetching",R=b==="pending",S=b==="error",D=R&&M,j=p!==void 0,T={status:b,fetchStatus:l.fetchStatus,isPending:R,isSuccess:b==="success",isError:S,isInitialLoading:D,isLoading:D,data:p,dataUpdatedAt:l.dataUpdatedAt,error:P,errorUpdatedAt:g,failureCount:l.fetchFailureCount,failureReason:l.fetchFailureReason,errorUpdateCount:l.errorUpdateCount,isFetched:e.isFetched(),isFetchedAfterMount:l.dataUpdateCount>m.dataUpdateCount||l.errorUpdateCount>m.errorUpdateCount,isFetching:M,isRefetching:M&&!R,isLoadingError:S&&!j,isPaused:l.fetchStatus==="paused",isPlaceholderData:d,isRefetchError:S&&j,isStale:ts(e,s),refetch:this.refetch,promise:i(this,ae),isEnabled:X(s.enabled,e)!==!1};if(this.options.experimental_prefetchInRender){const q=T.data!==void 0,ee=T.status==="error"&&!q,fe=de=>{ee?de.reject(T.error):q&&de.resolve(T.data)},st=()=>{const de=h(this,ae,T.promise=kt());fe(de)},Ne=i(this,ae);switch(Ne.status){case"pending":e.queryHash===r.queryHash&&fe(Ne);break;case"fulfilled":(ee||T.data!==Ne.value)&&st();break;case"rejected":(!ee||T.error!==Ne.reason)&&st();break}}return T}updateResult(){const e=i(this,z),s=this.createResult(i(this,C),this.options);if(h(this,xe,i(this,C).state),h(this,Ge,this.options),i(this,xe).data!==void 0&&h(this,Ye,i(this,C)),ot(s,e))return;h(this,z,s);const r=()=>{if(!e)return!0;const{notifyOnChangeProps:n}=this.options,a=typeof n=="function"?n():n;if(a==="all"||!a&&!i(this,We).size)return!0;const o=new Set(a??i(this,We));return this.options.throwOnError&&o.add("error"),Object.keys(i(this,z)).some(c=>{const y=c;return i(this,z)[y]!==e[y]&&o.has(y)})};w(this,F,zs).call(this,{listeners:r()})}onQueryUpdate(){this.updateResult(),this.hasListeners()&&w(this,F,qt).call(this)}},$=new WeakMap,C=new WeakMap,ht=new WeakMap,z=new WeakMap,xe=new WeakMap,Ge=new WeakMap,ae=new WeakMap,ve=new WeakMap,lt=new WeakMap,Be=new WeakMap,Ye=new WeakMap,De=new WeakMap,ke=new WeakMap,ge=new WeakMap,We=new WeakMap,F=new WeakSet,it=function(e){w(this,F,Kt).call(this);let s=i(this,C).fetch(this.options,e);return e!=null&&e.throwOnError||(s=s.catch(_)),s},It=function(){w(this,F,Ut).call(this);const e=Pe(this.options.staleTime,i(this,C));if(ut.isServer()||i(this,z).isStale||!At(e))return;const r=ks(i(this,z).dataUpdatedAt,e)+1;h(this,De,Ee.setTimeout(()=>{i(this,z).isStale||this.updateResult()},r))},_t=function(){return(typeof this.options.refetchInterval=="function"?this.options.refetchInterval(i(this,C)):this.options.refetchInterval)??!1},jt=function(e){w(this,F,Nt).call(this),h(this,ge,e),!(ut.isServer()||X(this.options.enabled,i(this,C))===!1||!At(i(this,ge))||i(this,ge)===0)&&h(this,ke,Ee.setInterval(()=>{(this.options.refetchIntervalInBackground||Xt.isFocused())&&w(this,F,it).call(this)},i(this,ge)))},qt=function(){w(this,F,It).call(this),w(this,F,jt).call(this,w(this,F,_t).call(this))},Ut=function(){i(this,De)&&(Ee.clearTimeout(i(this,De)),h(this,De,void 0))},Nt=function(){i(this,ke)&&(Ee.clearInterval(i(this,ke)),h(this,ke,void 0))},Kt=function(){const e=i(this,$).getQueryCache().build(i(this,$),this.options);if(e===i(this,C))return;const s=i(this,C);h(this,C,e),h(this,ht,e.state),this.hasListeners()&&(s==null||s.removeObserver(this),e.addObserver(this))},zs=function(e){A.batch(()=>{e.listeners&&this.listeners.forEach(s=>{s(i(this,z))}),i(this,$).getQueryCache().notify({query:i(this,C),type:"observerResultsUpdated"})})},Qs);function Qr(t,e){return X(e.enabled,t)!==!1&&t.state.data===void 0&&!(t.state.status==="error"&&e.retryOnMount===!1)}function ms(t,e){return Qr(t,e)||t.state.data!==void 0&&Lt(t,e,e.refetchOnMount)}function Lt(t,e,s){if(X(e.enabled,t)!==!1&&Pe(e.staleTime,t)!=="static"){const r=typeof s=="function"?s(t):s;return r==="always"||r!==!1&&ts(t,e)}return!1}function vs(t,e,s,r){return(t!==e||X(r.enabled,t)===!1)&&(!s.suspense||t.state.status!=="error")&&ts(t,s)}function ts(t,e){return X(e.enabled,t)!==!1&&t.isStaleByTime(Pe(e.staleTime,t))}function Tr(t,e){return!ot(t.getCurrentResult(),e)}function Et(t){return{onFetch:(e,s)=>{var v,l,d,p,P;const r=e.options,n=(d=(l=(v=e.fetchOptions)==null?void 0:v.meta)==null?void 0:l.fetchMore)==null?void 0:d.direction,a=((p=e.state.data)==null?void 0:p.pages)||[],o=((P=e.state.data)==null?void 0:P.pageParams)||[];let c={pages:[],pageParams:[]},y=0;const m=async()=>{let g=!1;const b=R=>{js(R,()=>e.signal,()=>g=!0)},O=_s(e.options,e.fetchOptions),M=async(R,S,D)=>{if(g)return Promise.reject();if(S==null&&R.pages.length)return Promise.resolve(R);const B=(()=>{const ee={client:e.client,queryKey:e.queryKey,pageParam:S,direction:D?"backward":"forward",meta:e.options.meta};return b(ee),ee})(),T=await O(B),{maxPages:x}=e.options,q=D?pr:Is;return{pages:q(R.pages,T,x),pageParams:q(R.pageParams,S,x)}};if(n&&a.length){const R=n==="backward",S=R?$s:Ht,D={pages:a,pageParams:o},j=S(r,D);c=await M(D,j,R)}else{const R=t??a.length;do{const S=y===0?o[0]??r.initialPageParam:Ht(r,c);if(y>0&&S==null)break;c=await M(c,S),y++}while(y<R)}return c};e.options.persister?e.fetchFn=()=>{var g,b;return(b=(g=e.options).persister)==null?void 0:b.call(g,m,{client:e.client,queryKey:e.queryKey,meta:e.options.meta,signal:e.signal},s)}:e.fetchFn=m}}}function Ht(t,{pages:e,pageParams:s}){const r=e.length-1;return e.length>0?t.getNextPageParam(e[r],e,s[r],s):void 0}function $s(t,{pages:e,pageParams:s}){var r;return e.length>0?(r=t.getPreviousPageParam)==null?void 0:r.call(t,e[0],e,s[0],s):void 0}function Fr(t,e){return e?Ht(t,e)!=null:!1}function Mr(t,e){return!e||!t.getPreviousPageParam?!1:$s(t,e)!=null}var Gs=class extends gt{constructor(t,e){super(t,e)}bindMethods(){super.bindMethods(),this.fetchNextPage=this.fetchNextPage.bind(this),this.fetchPreviousPage=this.fetchPreviousPage.bind(this)}setOptions(t){super.setOptions({...t,behavior:Et()})}getOptimisticResult(t){return t.behavior=Et(),super.getOptimisticResult(t)}fetchNextPage(t){return this.fetch({...t,meta:{fetchMore:{direction:"forward"}}})}fetchPreviousPage(t){return this.fetch({...t,meta:{fetchMore:{direction:"backward"}}})}createResult(t,e){var P,g;const{state:s}=t,r=super.createResult(t,e),{isFetching:n,isRefetching:a,isError:o,isRefetchError:c}=r,y=(g=(P=s.fetchMeta)==null?void 0:P.fetchMore)==null?void 0:g.direction,m=o&&y==="forward",v=n&&y==="forward",l=o&&y==="backward",d=n&&y==="backward";return{...r,fetchNextPage:this.fetchNextPage,fetchPreviousPage:this.fetchPreviousPage,hasNextPage:Fr(e,s.data),hasPreviousPage:Mr(e,s.data),isFetchNextPageError:m,isFetchingNextPage:v,isFetchPreviousPageError:l,isFetchingPreviousPage:d,isRefetchError:c&&!m&&!l,isRefetching:a&&!v&&!d}}},ft,se,H,Ie,re,ye,Ts,Ar=(Ts=class extends Ks{constructor(e){super();f(this,re);f(this,ft);f(this,se);f(this,H);f(this,Ie);h(this,ft,e.client),this.mutationId=e.mutationId,h(this,H,e.mutationCache),h(this,se,[]),this.state=e.state||Bs(),this.setOptions(e.options),this.scheduleGc()}setOptions(e){this.options=e,this.updateGcTime(this.options.gcTime)}get meta(){return this.options.meta}addObserver(e){i(this,se).includes(e)||(i(this,se).push(e),this.clearGcTimeout(),i(this,H).notify({type:"observerAdded",mutation:this,observer:e}))}removeObserver(e){h(this,se,i(this,se).filter(s=>s!==e)),this.scheduleGc(),i(this,H).notify({type:"observerRemoved",mutation:this,observer:e})}optionalRemove(){i(this,se).length||(this.state.status==="pending"?this.scheduleGc():i(this,H).remove(this))}continue(){var e;return((e=i(this,Ie))==null?void 0:e.continue())??this.execute(this.state.variables)}async execute(e){var o,c,y,m,v,l,d,p,P,g,b,O,M,R,S,D,j,B;const s=()=>{w(this,re,ye).call(this,{type:"continue"})},r={client:i(this,ft),meta:this.options.meta,mutationKey:this.options.mutationKey};h(this,Ie,Ns({fn:()=>this.options.mutationFn?this.options.mutationFn(e,r):Promise.reject(new Error("No mutationFn found")),onFail:(T,x)=>{w(this,re,ye).call(this,{type:"failed",failureCount:T,error:x})},onPause:()=>{w(this,re,ye).call(this,{type:"pause"})},onContinue:s,retry:this.options.retry??0,retryDelay:this.options.retryDelay,networkMode:this.options.networkMode,canRun:()=>i(this,H).canRun(this)}));const n=this.state.status==="pending",a=!i(this,Ie).canStart();try{if(n)s();else{w(this,re,ye).call(this,{type:"pending",variables:e,isPaused:a}),i(this,H).config.onMutate&&await i(this,H).config.onMutate(e,this,r);const x=await((c=(o=this.options).onMutate)==null?void 0:c.call(o,e,r));x!==this.state.context&&w(this,re,ye).call(this,{type:"pending",context:x,variables:e,isPaused:a})}const T=await i(this,Ie).start();return await((m=(y=i(this,H).config).onSuccess)==null?void 0:m.call(y,T,e,this.state.context,this,r)),await((l=(v=this.options).onSuccess)==null?void 0:l.call(v,T,e,this.state.context,r)),await((p=(d=i(this,H).config).onSettled)==null?void 0:p.call(d,T,null,this.state.variables,this.state.context,this,r)),await((g=(P=this.options).onSettled)==null?void 0:g.call(P,T,null,e,this.state.context,r)),w(this,re,ye).call(this,{type:"success",data:T}),T}catch(T){try{await((O=(b=i(this,H).config).onError)==null?void 0:O.call(b,T,e,this.state.context,this,r))}catch(x){Promise.reject(x)}try{await((R=(M=this.options).onError)==null?void 0:R.call(M,T,e,this.state.context,r))}catch(x){Promise.reject(x)}try{await((D=(S=i(this,H).config).onSettled)==null?void 0:D.call(S,void 0,T,this.state.variables,this.state.context,this,r))}catch(x){Promise.reject(x)}try{await((B=(j=this.options).onSettled)==null?void 0:B.call(j,void 0,T,e,this.state.context,r))}catch(x){Promise.reject(x)}throw w(this,re,ye).call(this,{type:"error",error:T}),T}finally{i(this,H).runNext(this)}}},ft=new WeakMap,se=new WeakMap,H=new WeakMap,Ie=new WeakMap,re=new WeakSet,ye=function(e){const s=r=>{switch(e.type){case"failed":return{...r,failureCount:e.failureCount,failureReason:e.error};case"pause":return{...r,isPaused:!0};case"continue":return{...r,isPaused:!1};case"pending":return{...r,context:e.context,data:void 0,failureCount:0,failureReason:null,error:null,isPaused:e.isPaused,status:"pending",variables:e.variables,submittedAt:Date.now()};case"success":return{...r,data:e.data,failureCount:0,failureReason:null,error:null,status:"success",isPaused:!1};case"error":return{...r,data:void 0,error:e.error,failureCount:r.failureCount+1,failureReason:e.error,isPaused:!1,status:"error"}}};this.state=s(this.state),A.batch(()=>{i(this,se).forEach(r=>{r.onMutationUpdate(e)}),i(this,H).notify({mutation:this,type:"updated",action:e})})},Ts);function Bs(){return{context:void 0,data:void 0,error:null,failureCount:0,failureReason:null,isPaused:!1,status:"idle",variables:void 0,submittedAt:0}}var oe,Z,dt,Fs,xr=(Fs=class extends Ue{constructor(e={}){super();f(this,oe);f(this,Z);f(this,dt);this.config=e,h(this,oe,new Set),h(this,Z,new Map),h(this,dt,0)}build(e,s,r){const n=new Ar({client:e,mutationCache:this,mutationId:++St(this,dt)._,options:e.defaultMutationOptions(s),state:r});return this.add(n),n}add(e){i(this,oe).add(e);const s=wt(e);if(typeof s=="string"){const r=i(this,Z).get(s);r?r.push(e):i(this,Z).set(s,[e])}this.notify({type:"added",mutation:e})}remove(e){if(i(this,oe).delete(e)){const s=wt(e);if(typeof s=="string"){const r=i(this,Z).get(s);if(r)if(r.length>1){const n=r.indexOf(e);n!==-1&&r.splice(n,1)}else r[0]===e&&i(this,Z).delete(s)}}this.notify({type:"removed",mutation:e})}canRun(e){const s=wt(e);if(typeof s=="string"){const r=i(this,Z).get(s),n=r==null?void 0:r.find(a=>a.state.status==="pending");return!n||n===e}else return!0}runNext(e){var r;const s=wt(e);if(typeof s=="string"){const n=(r=i(this,Z).get(s))==null?void 0:r.find(a=>a!==e&&a.state.isPaused);return(n==null?void 0:n.continue())??Promise.resolve()}else return Promise.resolve()}clear(){A.batch(()=>{i(this,oe).forEach(e=>{this.notify({type:"removed",mutation:e})}),i(this,oe).clear(),i(this,Z).clear()})}getAll(){return Array.from(i(this,oe))}find(e){const s={exact:!0,...e};return this.getAll().find(r=>hs(s,r))}findAll(e={}){return this.getAll().filter(s=>hs(e,s))}notify(e){A.batch(()=>{this.listeners.forEach(s=>{s(e)})})}resumePausedMutations(){const e=this.getAll().filter(s=>s.state.isPaused);return A.batch(()=>Promise.all(e.map(s=>s.continue().catch(_))))}},oe=new WeakMap,Z=new WeakMap,dt=new WeakMap,Fs);function wt(t){var e;return(e=t.options.scope)==null?void 0:e.id}var ue,be,G,ce,he,Ot,zt,Ms,Dr=(Ms=class extends Ue{constructor(e,s){super();f(this,he);f(this,ue);f(this,be);f(this,G);f(this,ce);h(this,ue,e),this.setOptions(s),this.bindMethods(),w(this,he,Ot).call(this)}bindMethods(){this.mutate=this.mutate.bind(this),this.reset=this.reset.bind(this)}setOptions(e){var r;const s=this.options;this.options=i(this,ue).defaultMutationOptions(e),ot(this.options,s)||i(this,ue).getMutationCache().notify({type:"observerOptionsUpdated",mutation:i(this,G),observer:this}),s!=null&&s.mutationKey&&this.options.mutationKey&&je(s.mutationKey)!==je(this.options.mutationKey)?this.reset():((r=i(this,G))==null?void 0:r.state.status)==="pending"&&i(this,G).setOptions(this.options)}onUnsubscribe(){var e;this.hasListeners()||(e=i(this,G))==null||e.removeObserver(this)}onMutationUpdate(e){w(this,he,Ot).call(this),w(this,he,zt).call(this,e)}getCurrentResult(){return i(this,be)}reset(){var e;(e=i(this,G))==null||e.removeObserver(this),h(this,G,void 0),w(this,he,Ot).call(this),w(this,he,zt).call(this)}mutate(e,s){var r;return h(this,ce,s),(r=i(this,G))==null||r.removeObserver(this),h(this,G,i(this,ue).getMutationCache().build(i(this,ue),this.options)),i(this,G).addObserver(this),i(this,G).execute(e)}},ue=new WeakMap,be=new WeakMap,G=new WeakMap,ce=new WeakMap,he=new WeakSet,Ot=function(){var s;const e=((s=i(this,G))==null?void 0:s.state)??Bs();h(this,be,{...e,isPending:e.status==="pending",isSuccess:e.status==="success",isError:e.status==="error",isIdle:e.status==="idle",mutate:this.mutate,reset:this.reset})},zt=function(e){A.batch(()=>{var s,r,n,a,o,c,y,m;if(i(this,ce)&&this.hasListeners()){const v=i(this,be).variables,l=i(this,be).context,d={client:i(this,ue),meta:this.options.meta,mutationKey:this.options.mutationKey};if((e==null?void 0:e.type)==="success"){try{(r=(s=i(this,ce)).onSuccess)==null||r.call(s,e.data,v,l,d)}catch(p){Promise.reject(p)}try{(a=(n=i(this,ce)).onSettled)==null||a.call(n,e.data,null,v,l,d)}catch(p){Promise.reject(p)}}else if((e==null?void 0:e.type)==="error"){try{(c=(o=i(this,ce)).onError)==null||c.call(o,e.error,v,l,d)}catch(p){Promise.reject(p)}try{(m=(y=i(this,ce)).onSettled)==null||m.call(y,void 0,e.error,v,l,d)}catch(p){Promise.reject(p)}}}this.listeners.forEach(v=>{v(i(this,be))})})},Ms);function gs(t,e){const s=new Set(e);return t.filter(r=>!s.has(r))}function kr(t,e,s){const r=t.slice(0);return r[e]=s,r}var _e,Y,Je,Ve,V,Se,yt,pt,mt,vt,L,$t,Gt,Bt,Yt,Wt,As,Ir=(As=class extends Ue{constructor(e,s,r){super();f(this,L);f(this,_e);f(this,Y);f(this,Je);f(this,Ve);f(this,V);f(this,Se);f(this,yt);f(this,pt);f(this,mt);f(this,vt,[]);h(this,_e,e),h(this,Ve,r),h(this,Je,[]),h(this,V,[]),h(this,Y,[]),this.setQueries(s)}onSubscribe(){this.listeners.size===1&&i(this,V).forEach(e=>{e.subscribe(s=>{w(this,L,Yt).call(this,e,s)})})}onUnsubscribe(){this.listeners.size||this.destroy()}destroy(){this.listeners=new Set,i(this,V).forEach(e=>{e.destroy()})}setQueries(e,s){h(this,Je,e),h(this,Ve,s);{const r=e.map(n=>i(this,_e).defaultQueryOptions(n).queryHash);new Set(r).size!==r.length&&console.warn("[QueriesObserver]: Duplicate Queries found. This might result in unexpected behavior.")}A.batch(()=>{const r=i(this,V),n=w(this,L,Bt).call(this,i(this,Je));n.forEach(l=>l.observer.setOptions(l.defaultedQueryOptions));const a=n.map(l=>l.observer),o=a.map(l=>l.getCurrentResult()),c=r.length!==a.length,y=a.some((l,d)=>l!==r[d]),m=c||y,v=m?!0:o.some((l,d)=>{const p=i(this,Y)[d];return!p||!ot(l,p)});!m&&!v||(m&&(h(this,vt,n),h(this,V,a)),h(this,Y,o),this.hasListeners()&&(m&&(gs(r,a).forEach(l=>{l.destroy()}),gs(a,r).forEach(l=>{l.subscribe(d=>{w(this,L,Yt).call(this,l,d)})})),w(this,L,Wt).call(this)))})}getCurrentResult(){return i(this,Y)}getQueries(){return i(this,V).map(e=>e.getCurrentQuery())}getObservers(){return i(this,V)}getOptimisticResult(e,s){const r=w(this,L,Bt).call(this,e),n=r.map(o=>o.observer.getOptimisticResult(o.defaultedQueryOptions)),a=r.map(o=>o.defaultedQueryOptions.queryHash);return[n,o=>w(this,L,Gt).call(this,o??n,s,a),()=>w(this,L,$t).call(this,n,r)]}},_e=new WeakMap,Y=new WeakMap,Je=new WeakMap,Ve=new WeakMap,V=new WeakMap,Se=new WeakMap,yt=new WeakMap,pt=new WeakMap,mt=new WeakMap,vt=new WeakMap,L=new WeakSet,$t=function(e,s){return s.map((r,n)=>{const a=e[n];return r.defaultedQueryOptions.notifyOnChangeProps?a:r.observer.trackResult(a,o=>{s.forEach(c=>{c.observer.trackProp(o)})})})},Gt=function(e,s,r){if(s){const n=i(this,mt),a=r!==void 0&&n!==void 0&&(n.length!==r.length||r.some((o,c)=>o!==n[c]));return(!i(this,Se)||i(this,Y)!==i(this,pt)||a||s!==i(this,yt))&&(h(this,yt,s),h(this,pt,i(this,Y)),r!==void 0&&h(this,mt,r),h(this,Se,at(i(this,Se),s(e)))),i(this,Se)}return e},Bt=function(e){const s=new Map;i(this,V).forEach(n=>{const a=n.options.queryHash;if(!a)return;const o=s.get(a);o?o.push(n):s.set(a,[n])});const r=[];return e.forEach(n=>{var y;const a=i(this,_e).defaultQueryOptions(n),c=((y=s.get(a.queryHash))==null?void 0:y.shift())??new gt(i(this,_e),a);r.push({defaultedQueryOptions:a,observer:c})}),r},Yt=function(e,s){const r=i(this,V).indexOf(e);r!==-1&&(h(this,Y,kr(i(this,Y),r,s)),w(this,L,Wt).call(this))},Wt=function(){var e;if(this.hasListeners()){const s=i(this,Se),r=w(this,L,$t).call(this,i(this,Y),i(this,vt)),n=w(this,L,Gt).call(this,r,(e=i(this,Ve))==null?void 0:e.combine);s!==n&&A.batch(()=>{this.listeners.forEach(a=>{a(i(this,Y))})})}},As),ie,xs,_r=(xs=class extends Ue{constructor(e={}){super();f(this,ie);this.config=e,h(this,ie,new Map)}build(e,s,r){const n=s.queryKey,a=s.queryHash??Zt(n,s);let o=this.get(a);return o||(o=new Cr({client:e,queryKey:n,queryHash:a,options:e.defaultQueryOptions(s),state:r,defaultOptions:e.getQueryDefaults(n)}),this.add(o)),o}add(e){i(this,ie).has(e.queryHash)||(i(this,ie).set(e.queryHash,e),this.notify({type:"added",query:e}))}remove(e){const s=i(this,ie).get(e.queryHash);s&&(e.destroy(),s===e&&i(this,ie).delete(e.queryHash),this.notify({type:"removed",query:e}))}clear(){A.batch(()=>{this.getAll().forEach(e=>{this.remove(e)})})}get(e){return i(this,ie).get(e)}getAll(){return[...i(this,ie).values()]}find(e){const s={exact:!0,...e};return this.getAll().find(r=>cs(s,r))}findAll(e={}){const s=this.getAll();return Object.keys(e).length>0?s.filter(r=>cs(e,r)):s}notify(e){A.batch(()=>{this.listeners.forEach(s=>{s(e)})})}onFocus(){A.batch(()=>{this.getAll().forEach(e=>{e.onFocus()})})}onOnline(){A.batch(()=>{this.getAll().forEach(e=>{e.onOnline()})})}},ie=new WeakMap,xs),I,we,Oe,Xe,Ze,Re,et,tt,Ds,Yr=(Ds=class{constructor(t={}){f(this,I);f(this,we);f(this,Oe);f(this,Xe);f(this,Ze);f(this,Re);f(this,et);f(this,tt);h(this,I,t.queryCache||new _r),h(this,we,t.mutationCache||new xr),h(this,Oe,t.defaultOptions||{}),h(this,Xe,new Map),h(this,Ze,new Map),h(this,Re,0)}mount(){St(this,Re)._++,i(this,Re)===1&&(h(this,et,Xt.subscribe(async t=>{t&&(await this.resumePausedMutations(),i(this,I).onFocus())})),h(this,tt,Rt.subscribe(async t=>{t&&(await this.resumePausedMutations(),i(this,I).onOnline())})))}unmount(){var t,e;St(this,Re)._--,i(this,Re)===0&&((t=i(this,et))==null||t.call(this),h(this,et,void 0),(e=i(this,tt))==null||e.call(this),h(this,tt,void 0))}isFetching(t){return i(this,I).findAll({...t,fetchStatus:"fetching"}).length}isMutating(t){return i(this,we).findAll({...t,status:"pending"}).length}getQueryData(t){var s;const e=this.defaultQueryOptions({queryKey:t});return(s=i(this,I).get(e.queryHash))==null?void 0:s.state.data}ensureQueryData(t){const e=this.defaultQueryOptions(t),s=i(this,I).build(this,e),r=s.state.data;return r===void 0?this.fetchQuery(t):(t.revalidateIfStale&&s.isStaleByTime(Pe(e.staleTime,s))&&this.prefetchQuery(e),Promise.resolve(r))}getQueriesData(t){return i(this,I).findAll(t).map(({queryKey:e,state:s})=>{const r=s.data;return[e,r]})}setQueryData(t,e,s){const r=this.defaultQueryOptions({queryKey:t}),n=i(this,I).get(r.queryHash),a=n==null?void 0:n.state.data,o=fr(e,a);if(o!==void 0)return i(this,I).build(this,r).setData(o,{...s,manual:!0})}setQueriesData(t,e,s){return A.batch(()=>i(this,I).findAll(t).map(({queryKey:r})=>[r,this.setQueryData(r,e,s)]))}getQueryState(t){var s;const e=this.defaultQueryOptions({queryKey:t});return(s=i(this,I).get(e.queryHash))==null?void 0:s.state}removeQueries(t){const e=i(this,I);A.batch(()=>{e.findAll(t).forEach(s=>{e.remove(s)})})}resetQueries(t,e){const s=i(this,I);return A.batch(()=>(s.findAll(t).forEach(r=>{r.reset()}),this.refetchQueries({type:"active",...t},e)))}cancelQueries(t,e={}){const s={revert:!0,...e},r=A.batch(()=>i(this,I).findAll(t).map(n=>n.cancel(s)));return Promise.all(r).then(_).catch(_)}invalidateQueries(t,e={}){return A.batch(()=>(i(this,I).findAll(t).forEach(s=>{s.invalidate()}),(t==null?void 0:t.refetchType)==="none"?Promise.resolve():this.refetchQueries({...t,type:(t==null?void 0:t.refetchType)??(t==null?void 0:t.type)??"active"},e)))}refetchQueries(t,e={}){const s={...e,cancelRefetch:e.cancelRefetch??!0},r=A.batch(()=>i(this,I).findAll(t).filter(n=>!n.isDisabled()&&!n.isStatic()).map(n=>{let a=n.fetch(void 0,s);return s.throwOnError||(a=a.catch(_)),n.state.fetchStatus==="paused"?Promise.resolve():a}));return Promise.all(r).then(_)}fetchQuery(t){const e=this.defaultQueryOptions(t);e.retry===void 0&&(e.retry=!1);const s=i(this,I).build(this,e);return s.isStaleByTime(Pe(e.staleTime,s))?s.fetch(e):Promise.resolve(s.state.data)}prefetchQuery(t){return this.fetchQuery(t).then(_).catch(_)}fetchInfiniteQuery(t){return t.behavior=Et(t.pages),this.fetchQuery(t)}prefetchInfiniteQuery(t){return this.fetchInfiniteQuery(t).then(_).catch(_)}ensureInfiniteQueryData(t){return t.behavior=Et(t.pages),this.ensureQueryData(t)}resumePausedMutations(){return Rt.isOnline()?i(this,we).resumePausedMutations():Promise.resolve()}getQueryCache(){return i(this,I)}getMutationCache(){return i(this,we)}getDefaultOptions(){return i(this,Oe)}setDefaultOptions(t){h(this,Oe,t)}setQueryDefaults(t,e){i(this,Xe).set(je(t),{queryKey:t,defaultOptions:e})}getQueryDefaults(t){const e=[...i(this,Xe).values()],s={};return e.forEach(r=>{nt(t,r.queryKey)&&Object.assign(s,r.defaultOptions)}),s}setMutationDefaults(t,e){i(this,Ze).set(je(t),{mutationKey:t,defaultOptions:e})}getMutationDefaults(t){const e=[...i(this,Ze).values()],s={};return e.forEach(r=>{nt(t,r.mutationKey)&&Object.assign(s,r.defaultOptions)}),s}defaultQueryOptions(t){if(t._defaulted)return t;const e={...i(this,Oe).queries,...this.getQueryDefaults(t.queryKey),...t,_defaulted:!0};return e.queryHash||(e.queryHash=Zt(e.queryKey,e)),e.refetchOnReconnect===void 0&&(e.refetchOnReconnect=e.networkMode!=="always"),e.throwOnError===void 0&&(e.throwOnError=!!e.suspense),!e.networkMode&&e.persister&&(e.networkMode="offlineFirst"),e.queryFn===qe&&(e.enabled=!1),e}defaultMutationOptions(t){return t!=null&&t._defaulted?t:{...i(this,Oe).mutations,...(t==null?void 0:t.mutationKey)&&this.getMutationDefaults(t.mutationKey),...t,_defaulted:!0}}clear(){i(this,I).clear(),i(this,we).clear()}},I=new WeakMap,we=new WeakMap,Oe=new WeakMap,Xe=new WeakMap,Ze=new WeakMap,Re=new WeakMap,et=new WeakMap,tt=new WeakMap,Ds);function Wr({streamFn:t,refetchMode:e="reset",reducer:s=(n,a)=>Is(n,a),initialValue:r=[]}){return async n=>{const a=n.client.getQueryCache().find({queryKey:n.queryKey,exact:!0}),o=!!a&&a.isFetched();o&&e==="reset"&&a.setState({...a.resetState,fetchStatus:"fetching"});let c=r,y=!1;const m=js({client:n.client,meta:n.meta,queryKey:n.queryKey,pageParam:n.pageParam,direction:n.direction},()=>n.signal,()=>y=!0),v=await t(m),l=o&&e==="replace";for await(const d of v){if(y)break;l?c=s(c,d):n.client.setQueryData(n.queryKey,p=>s(p===void 0?r:p,d))}return l&&!y&&n.client.setQueryData(n.queryKey,c),n.client.getQueryData(n.queryKey)??r}}var Jr=Symbol("dataTagSymbol"),Vr=Symbol("dataTagErrorSymbol"),Xr=Symbol("unsetMarker"),Mt={exports:{}},rt={},bs;function jr(){if(bs)return rt;bs=1;/**
2
+ * @license React
3
+ * react-jsx-runtime.development.js
4
+ *
5
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */return(function(){function t(u){if(u==null)return null;if(typeof u=="function")return u.$$typeof===ee?null:u.displayName||u.name||null;if(typeof u=="string")return u;switch(u){case b:return"Fragment";case M:return"Profiler";case O:return"StrictMode";case j:return"Suspense";case B:return"SuspenseList";case q:return"Activity"}if(typeof u=="object")switch(typeof u.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),u.$$typeof){case g:return"Portal";case S:return u.displayName||"Context";case R:return(u._context.displayName||"Context")+".Consumer";case D:var E=u.render;return u=u.displayName,u||(u=E.displayName||E.name||"",u=u!==""?"ForwardRef("+u+")":"ForwardRef"),u;case T:return E=u.displayName||null,E!==null?E:t(u.type)||"Memo";case x:E=u._payload,u=u._init;try{return t(u(E))}catch{}}return null}function e(u){return""+u}function s(u){try{e(u);var E=!1}catch{E=!0}if(E){E=console;var k=E.error,U=typeof Symbol=="function"&&Symbol.toStringTag&&u[Symbol.toStringTag]||u.constructor.name||"Object";return k.call(E,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",U),e(u)}}function r(u){if(u===b)return"<>";if(typeof u=="object"&&u!==null&&u.$$typeof===x)return"<...>";try{var E=t(u);return E?"<"+E+">":"<...>"}catch{return"<...>"}}function n(){var u=fe.A;return u===null?null:u.getOwner()}function a(){return Error("react-stack-top-frame")}function o(u){if(st.call(u,"key")){var E=Object.getOwnPropertyDescriptor(u,"key").get;if(E&&E.isReactWarning)return!1}return u.key!==void 0}function c(u,E){function k(){rs||(rs=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",E))}k.isReactWarning=!0,Object.defineProperty(u,"key",{get:k,configurable:!0})}function y(){var u=t(this.type);return is[u]||(is[u]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),u=this.props.ref,u!==void 0?u:null}function m(u,E,k,U,bt,Qt){var N=k.ref;return u={$$typeof:P,type:u,key:E,props:k,_owner:U},(N!==void 0?N:null)!==null?Object.defineProperty(u,"ref",{enumerable:!1,get:y}):Object.defineProperty(u,"ref",{enumerable:!1,value:null}),u._store={},Object.defineProperty(u._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(u,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(u,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:bt}),Object.defineProperty(u,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:Qt}),Object.freeze&&(Object.freeze(u.props),Object.freeze(u)),u}function v(u,E,k,U,bt,Qt){var N=E.children;if(N!==void 0)if(U)if(Ne(N)){for(U=0;U<N.length;U++)l(N[U]);Object.freeze&&Object.freeze(N)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else l(N);if(st.call(E,"key")){N=t(u);var Ke=Object.keys(E).filter(function(nr){return nr!=="key"});U=0<Ke.length?"{key: someKey, "+Ke.join(": ..., ")+": ...}":"{key: someKey}",os[N+U]||(Ke=0<Ke.length?"{"+Ke.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
10
+ let props = %s;
11
+ <%s {...props} />
12
+ React keys must be passed directly to JSX without using spread:
13
+ let props = %s;
14
+ <%s key={someKey} {...props} />`,U,N,Ke,N),os[N+U]=!0)}if(N=null,k!==void 0&&(s(k),N=""+k),o(E)&&(s(E.key),N=""+E.key),"key"in E){k={};for(var Tt in E)Tt!=="key"&&(k[Tt]=E[Tt])}else k=E;return N&&c(k,typeof u=="function"?u.displayName||u.name||"Unknown":u),m(u,N,k,n(),bt,Qt)}function l(u){d(u)?u._store&&(u._store.validated=1):typeof u=="object"&&u!==null&&u.$$typeof===x&&(u._payload.status==="fulfilled"?d(u._payload.value)&&u._payload.value._store&&(u._payload.value._store.validated=1):u._store&&(u._store.validated=1))}function d(u){return typeof u=="object"&&u!==null&&u.$$typeof===P}var p=ar(),P=Symbol.for("react.transitional.element"),g=Symbol.for("react.portal"),b=Symbol.for("react.fragment"),O=Symbol.for("react.strict_mode"),M=Symbol.for("react.profiler"),R=Symbol.for("react.consumer"),S=Symbol.for("react.context"),D=Symbol.for("react.forward_ref"),j=Symbol.for("react.suspense"),B=Symbol.for("react.suspense_list"),T=Symbol.for("react.memo"),x=Symbol.for("react.lazy"),q=Symbol.for("react.activity"),ee=Symbol.for("react.client.reference"),fe=p.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,st=Object.prototype.hasOwnProperty,Ne=Array.isArray,de=console.createTask?console.createTask:function(){return null};p={react_stack_bottom_frame:function(u){return u()}};var rs,is={},ns=p.react_stack_bottom_frame.bind(p,a)(),as=de(r(a)),os={};rt.Fragment=b,rt.jsx=function(u,E,k){var U=1e4>fe.recentlyCreatedOwnerStacks++;return v(u,E,k,!1,U?Error("react-stack-top-frame"):ns,U?de(r(u)):as)},rt.jsxs=function(u,E,k){var U=1e4>fe.recentlyCreatedOwnerStacks++;return v(u,E,k,!0,U?Error("react-stack-top-frame"):ns,U?de(r(u)):as)}})(),rt}var Ss;function qr(){return Ss||(Ss=1,Mt.exports=jr()),Mt.exports}var Ys=qr(),Ws=Q.createContext(void 0),le=t=>{const e=Q.useContext(Ws);if(t)return t;if(!e)throw new Error("No QueryClient set, use QueryClientProvider to set one");return e},Zr=({client:t,children:e})=>(Q.useEffect(()=>(t.mount(),()=>{t.unmount()}),[t]),Ys.jsx(Ws.Provider,{value:t,children:e})),Js=Q.createContext(!1),Vs=()=>Q.useContext(Js),ei=Js.Provider;function Xs(){let t=!1;return{clearReset:()=>{t=!1},reset:()=>{t=!0},isReset:()=>t}}var Zs=Q.createContext(Xs()),er=()=>Q.useContext(Zs),ti=({children:t})=>{const[e]=Q.useState(()=>Xs());return Ys.jsx(Zs.Provider,{value:e,children:typeof t=="function"?t(e):t})},tr=(t,e,s)=>{const r=s!=null&&s.state.error&&typeof t.throwOnError=="function"?es(t.throwOnError,[s.state.error,s]):t.throwOnError;(t.suspense||t.experimental_prefetchInRender||r)&&(e.isReset()||(t.retryOnMount=!1))},sr=t=>{Q.useEffect(()=>{t.clearReset()},[t])},rr=({result:t,errorResetBoundary:e,throwOnError:s,query:r,suspense:n})=>t.isError&&!e.isReset()&&!t.isFetching&&r&&(n&&t.data===void 0||es(s,[t.error,r])),ss=(t,e)=>e.state.data===void 0,ir=t=>{if(t.suspense){const s=n=>n==="static"?n:Math.max(n??1e3,1e3),r=t.staleTime;t.staleTime=typeof r=="function"?(...n)=>s(r(...n)):s(r),typeof t.gcTime=="number"&&(t.gcTime=Math.max(t.gcTime,1e3))}},Ur=(t,e)=>t.isLoading&&t.isFetching&&!e,Jt=(t,e)=>(t==null?void 0:t.suspense)&&e.isPending,Vt=(t,e,s)=>e.fetchOptimistic(t).catch(()=>{s.clearReset()});function Nr({queries:t,...e},s){const r=le(s),n=Vs(),a=er(),o=Q.useMemo(()=>t.map(g=>{const b=r.defaultQueryOptions(g);return b._optimisticResults=n?"isRestoring":"optimistic",b}),[t,r,n]);o.forEach(g=>{ir(g);const b=r.getQueryCache().get(g.queryHash);tr(g,a,b)}),sr(a);const[c]=Q.useState(()=>new Ir(r,o,e)),[y,m,v]=c.getOptimisticResult(o,e.combine),l=!n&&e.subscribed!==!1;Q.useSyncExternalStore(Q.useCallback(g=>l?c.subscribe(A.batchCalls(g)):_,[c,l]),()=>c.getCurrentResult(),()=>c.getCurrentResult()),Q.useEffect(()=>{c.setQueries(o,e)},[o,e,c]);const p=y.some((g,b)=>Jt(o[b],g))?y.flatMap((g,b)=>{const O=o[b];if(O&&Jt(O,g)){const M=new gt(r,O);return Vt(O,M,a)}return[]}):[];if(p.length>0)throw Promise.all(p);const P=y.find((g,b)=>{const O=o[b];return O&&rr({result:g,errorResetBoundary:a,throwOnError:O.throwOnError,query:r.getQueryCache().get(O.queryHash),suspense:O.suspense})});if(P!=null&&P.error)throw P.error;return m(v())}function Ct(t,e,s){var d,p,P,g;if(typeof t!="object"||Array.isArray(t))throw new Error('Bad argument type. Starting with v5, only the "Object" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object');const r=Vs(),n=er(),a=le(s),o=a.defaultQueryOptions(t);(p=(d=a.getDefaultOptions().queries)==null?void 0:d._experimental_beforeQuery)==null||p.call(d,o);const c=a.getQueryCache().get(o.queryHash);o.queryFn||console.error(`[${o.queryHash}]: No queryFn was passed as an option, and no default queryFn was found. The queryFn parameter is only optional when using a default queryFn. More info here: https://tanstack.com/query/latest/docs/framework/react/guides/default-query-function`),o._optimisticResults=r?"isRestoring":"optimistic",ir(o),tr(o,n,c),sr(n);const y=!a.getQueryCache().get(o.queryHash),[m]=Q.useState(()=>new e(a,o)),v=m.getOptimisticResult(o),l=!r&&t.subscribed!==!1;if(Q.useSyncExternalStore(Q.useCallback(b=>{const O=l?m.subscribe(A.batchCalls(b)):_;return m.updateResult(),O},[m,l]),()=>m.getCurrentResult(),()=>m.getCurrentResult()),Q.useEffect(()=>{m.setOptions(o)},[o,m]),Jt(o,v))throw Vt(o,m,n);if(rr({result:v,errorResetBoundary:n,throwOnError:o.throwOnError,query:c,suspense:o.suspense}))throw v.error;if((g=(P=a.getDefaultOptions().queries)==null?void 0:P._experimental_afterQuery)==null||g.call(P,o,v),o.experimental_prefetchInRender&&!ut.isServer()&&Ur(v,r)){const b=y?Vt(o,m,n):c==null?void 0:c.promise;b==null||b.catch(_).finally(()=>{m.updateResult()})}return o.notifyOnChangeProps?v:m.trackResult(v)}function si(t,e){return Ct(t,gt,e)}function ri(t,e){return t.queryFn===qe&&console.error("skipToken is not allowed for useSuspenseQuery"),Ct({...t,enabled:!0,suspense:!0,throwOnError:ss,placeholderData:void 0},gt,e)}function ii(t,e){return t.queryFn===qe&&console.error("skipToken is not allowed for useSuspenseInfiniteQuery"),Ct({...t,enabled:!0,suspense:!0,throwOnError:ss},Gs,e)}function ni(t,e){return Nr({...t,queries:t.queries.map(s=>(s.queryFn===qe&&console.error("skipToken is not allowed for useSuspenseQueries"),{...s,suspense:!0,throwOnError:ss,enabled:!0,placeholderData:void 0}))},e)}function ai(t,e){const s=le(e);s.getQueryState(t.queryKey)||s.prefetchQuery(t)}function oi(t,e){const s=le(e);s.getQueryState(t.queryKey)||s.prefetchInfiniteQuery(t)}function ui(t){return t}function ci(t){return t}var hi=({children:t,options:e={},state:s,queryClient:r})=>{const n=le(r),a=Q.useRef(e);Q.useEffect(()=>{a.current=e});const o=Q.useMemo(()=>{if(s){if(typeof s!="object")return;const c=n.getQueryCache(),y=s.queries||[],m=[],v=[];for(const l of y){const d=c.get(l.queryHash);d?(l.state.dataUpdatedAt>d.state.dataUpdatedAt||l.promise&&d.state.status!=="pending"&&d.state.fetchStatus!=="fetching"&&l.dehydratedAt!==void 0&&l.dehydratedAt>d.state.dataUpdatedAt)&&v.push(l):m.push(l)}if(m.length>0&&ds(n,{queries:m},a.current),v.length>0)return v}},[n,s]);return Q.useEffect(()=>{o&&ds(n,{queries:o},a.current)},[n,o]),t};function li(t,e){const s=le(e),r=s.getQueryCache();return Q.useSyncExternalStore(Q.useCallback(n=>r.subscribe(A.batchCalls(n)),[r]),()=>s.isFetching(t),()=>s.isFetching(t))}function fi(t,e){const s=le(e);return Kr({filters:{...t,status:"pending"}},s).length}function ws(t,e){return t.findAll(e.filters).map(s=>e.select?e.select(s):s.state)}function Kr(t={},e){const s=le(e).getMutationCache(),r=Q.useRef(t),n=Q.useRef(null);return n.current===null&&(n.current=ws(s,t)),Q.useEffect(()=>{r.current=t}),Q.useSyncExternalStore(Q.useCallback(a=>s.subscribe(()=>{const o=at(n.current,ws(s,r.current));n.current!==o&&(n.current=o,A.schedule(a))}),[s]),()=>n.current,()=>n.current)}function di(t,e){const s=le(e),[r]=Q.useState(()=>new Dr(s,t));Q.useEffect(()=>{r.setOptions(t)},[r,t]);const n=Q.useSyncExternalStore(Q.useCallback(o=>r.subscribe(A.batchCalls(o)),[r]),()=>r.getCurrentResult(),()=>r.getCurrentResult()),a=Q.useCallback((o,c)=>{r.mutate(o,c).catch(_)},[r]);if(n.error&&es(r.options.throwOnError,[n.error]))throw n.error;return{...n,mutate:a,mutateAsync:n.mutate}}function yi(t){return t}function pi(t,e){return Ct(t,Gs,e)}export{Pt as CancelledError,hi as HydrationBoundary,Gs as InfiniteQueryObserver,ei as IsRestoringProvider,Ar as Mutation,xr as MutationCache,Dr as MutationObserver,Ir as QueriesObserver,Cr as Query,_r as QueryCache,Yr as QueryClient,Ws as QueryClientContext,Zr as QueryClientProvider,ti as QueryErrorResetBoundary,gt as QueryObserver,Vr as dataTagErrorSymbol,Jr as dataTagSymbol,Or as defaultScheduler,br as defaultShouldDehydrateMutation,Sr as defaultShouldDehydrateQuery,Gr as dehydrate,ut as environmentManager,Wr as experimental_streamedQuery,Xt as focusManager,je as hashKey,ds as hydrate,ci as infiniteQueryOptions,Br as isCancelledError,lr as isServer,$r as keepPreviousData,hs as matchMutation,cs as matchQuery,yi as mutationOptions,_ as noop,A as notifyManager,Rt as onlineManager,nt as partialMatchKey,ui as queryOptions,at as replaceEqualDeep,es as shouldThrowError,qe as skipToken,Ee as timeoutManager,Xr as unsetMarker,pi as useInfiniteQuery,li as useIsFetching,fi as useIsMutating,Vs as useIsRestoring,di as useMutation,Kr as useMutationState,oi as usePrefetchInfiniteQuery,ai as usePrefetchQuery,Nr as useQueries,si as useQuery,le as useQueryClient,er as useQueryErrorResetBoundary,ii as useSuspenseInfiniteQuery,ni as useSuspenseQueries,ri as useSuspenseQuery};
assets/jsx-dev-runtime-Czb3f8pQ.js ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r as H}from"./index-BlGQAcOD.js";var b={exports:{}},c={},w;function Z(){if(w)return c;w=1;/**
2
+ * @license React
3
+ * react-jsx-dev-runtime.development.js
4
+ *
5
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */return(function(){function s(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===G?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case i:return"Fragment";case F:return"Profiler";case $:return"StrictMode";case M:return"Suspense";case z:return"SuspenseList";case q:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case I:return"Portal";case L:return e.displayName||"Context";case W:return(e._context.displayName||"Context")+".Consumer";case U:var r=e.render;return e=e.displayName,e||(e=r.displayName||r.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case V:return r=e.displayName||null,r!==null?r:s(e.type)||"Memo";case f:r=e._payload,e=e._init;try{return s(e(r))}catch{}}return null}function _(e){return""+e}function E(e){try{_(e);var r=!1}catch{r=!0}if(r){r=console;var t=r.error,n=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return t.call(r,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",n),_(e)}}function v(e){if(e===i)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===f)return"<...>";try{var r=s(e);return r?"<"+r+">":"<...>"}catch{return"<...>"}}function j(){var e=O.A;return e===null?null:e.getOwner()}function R(){return Error("react-stack-top-frame")}function x(e){if(k.call(e,"key")){var r=Object.getOwnPropertyDescriptor(e,"key").get;if(r&&r.isReactWarning)return!1}return e.key!==void 0}function N(e,r){function t(){A||(A=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",r))}t.isReactWarning=!0,Object.defineProperty(e,"key",{get:t,configurable:!0})}function C(){var e=s(this.type);return S[e]||(S[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function D(e,r,t,n,o,m){var a=t.ref;return e={$$typeof:g,type:e,key:r,props:t,_owner:n},(a!==void 0?a:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:C}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:o}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:m}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function Y(e,r,t,n,o,m){var a=r.children;if(a!==void 0)if(n)if(J(a)){for(n=0;n<a.length;n++)T(a[n]);Object.freeze&&Object.freeze(a)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else T(a);if(k.call(r,"key")){a=s(e);var l=Object.keys(r).filter(function(B){return B!=="key"});n=0<l.length?"{key: someKey, "+l.join(": ..., ")+": ...}":"{key: someKey}",P[a+n]||(l=0<l.length?"{"+l.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
10
+ let props = %s;
11
+ <%s {...props} />
12
+ React keys must be passed directly to JSX without using spread:
13
+ let props = %s;
14
+ <%s key={someKey} {...props} />`,n,a,l,a),P[a+n]=!0)}if(a=null,t!==void 0&&(E(t),a=""+t),x(r)&&(E(r.key),a=""+r.key),"key"in r){t={};for(var d in r)d!=="key"&&(t[d]=r[d])}else t=r;return a&&N(t,typeof e=="function"?e.displayName||e.name||"Unknown":e),D(e,a,t,j(),o,m)}function T(e){p(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===f&&(e._payload.status==="fulfilled"?p(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function p(e){return typeof e=="object"&&e!==null&&e.$$typeof===g}var u=H(),g=Symbol.for("react.transitional.element"),I=Symbol.for("react.portal"),i=Symbol.for("react.fragment"),$=Symbol.for("react.strict_mode"),F=Symbol.for("react.profiler"),W=Symbol.for("react.consumer"),L=Symbol.for("react.context"),U=Symbol.for("react.forward_ref"),M=Symbol.for("react.suspense"),z=Symbol.for("react.suspense_list"),V=Symbol.for("react.memo"),f=Symbol.for("react.lazy"),q=Symbol.for("react.activity"),G=Symbol.for("react.client.reference"),O=u.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,k=Object.prototype.hasOwnProperty,J=Array.isArray,y=console.createTask?console.createTask:function(){return null};u={react_stack_bottom_frame:function(e){return e()}};var A,S={},X=u.react_stack_bottom_frame.bind(u,R)(),K=y(v(R)),P={};c.Fragment=i,c.jsxDEV=function(e,r,t,n){var o=1e4>O.recentlyCreatedOwnerStacks++;return Y(e,r,t,n,o?Error("react-stack-top-frame"):X,o?y(v(e)):K)}})(),c}var h;function Q(){return h||(h=1,b.exports=Z()),b.exports}var re=Q();export{re as j};
assets/scenes-oUf6rtD_.js ADDED
@@ -0,0 +1 @@
 
 
1
+ import{P as M,o as q,b as L}from"./state-B_bTBsCz.js";const t0={total:88.234,shots:[{index:0,title:"疼痛开始",start:0,end:6.237},{index:1,title:"腱鞘炎到底发生了什么",start:6.237,end:15.339},{index:2,title:"为什么一动就疼",start:15.339,end:20.421},{index:3,title:"哪些人更容易出现",start:20.421,end:26.929},{index:4,title:"不要一上来就直接治疗",start:26.929,end:34.295},{index:5,title:"常见治疗方法",start:34.295,end:44.102},{index:6,title:"重点进入小针刀",start:44.102,end:51.138},{index:7,title:"小针刀治疗过程",start:51.138,end:61.586},{index:8,title:"松解前后对比",start:61.586,end:67.382},{index:9,title:"从疼痛到恢复",start:67.382,end:74.663},{index:10,title:"最后的记忆点",start:74.663,end:83.494},{index:11,title:"评论区互动",start:83.494,end:88.234}],lines:[{shot:0,text:"手指一弯,手腕一动,",file:"s01_01.mp3",start:2.3,off:.128,dur:1.186},{shot:0,text:"这里为什么突然疼?",file:"s01_02.mp3",start:3.586,off:.155,dur:.952},{shot:1,text:"腱鞘,本来像一条小通道,",file:"s02_01.mp3",start:6.387,off:.136,dur:1.386},{shot:1,text:"让肌腱顺畅滑动。",file:"s02_02.mp3",start:7.873,off:.156,dur:1.098},{shot:1,text:"但长期反复摩擦,",file:"s02_03.mp3",start:9.272,off:.135,dur:1.079},{shot:1,text:"腱鞘可能出现肿胀、增厚。",file:"s02_04.mp3",start:10.451,off:.143,dur:1.61},{shot:1,text:"通道变得更紧。",file:"s02_05.mp3",start:12.161,off:.172,dur:.914},{shot:1,text:"肌腱经过这里,就会越来越不顺。",file:"s02_06.mp3",start:13.174,off:.159,dur:1.765},{shot:2,text:"这时候,你越抓、越捏、越拧,",file:"s03_01.mp3",start:15.489,off:.153,dur:1.82},{shot:2,text:"肌腱移动越明显。",file:"s03_02.mp3",start:17.409,off:.135,dur:1.013},{shot:2,text:"疼痛,也可能越来越明显。",file:"s03_03.mp3",start:18.522,off:.155,dur:1.4},{shot:3,text:"哪些人更容易出现?",file:"s04_01.mp3",start:20.571,off:.168,dur:.993},{shot:3,text:"长期重复用手的人。",file:"s04_02.mp3",start:21.664,off:.147,dur:1.19},{shot:3,text:"经常抓握、捏、拧的人。",file:"s04_03.mp3",start:22.954,off:.144,dur:1.53},{shot:3,text:"还有部分需要频繁抱孩子的新手妈妈。",file:"s04_04.mp3",start:24.584,off:.141,dur:2.046},{shot:4,text:"出现疼痛,不是马上做一种治疗。",file:"s05_01.mp3",start:27.079,off:.142,dur:1.873},{shot:4,text:"先判断位置。",file:"s05_02.mp3",start:29.052,off:.133,dur:.747},{shot:4,text:"看活动时哪里疼。",file:"s05_03.mp3",start:29.899,off:.144,dur:1.053},{shot:4,text:"必要时结合检查,",file:"s05_04.mp3",start:31.052,off:.145,dur:.988},{shot:4,text:"判断到底是哪一种腱鞘问题。",file:"s05_05.mp3",start:32.14,off:.163,dur:1.754},{shot:5,text:"症状比较轻,可以先减少诱发动作。",file:"s06_01.mp3",start:34.445,off:.155,dur:1.964},{shot:5,text:"必要时使用支具,配合止痛、抗炎等处理。",file:"s06_02.mp3",start:36.509,off:.146,dur:2.465},{shot:5,text:"症状持续,还可以考虑局部注射等方法。",file:"s06_03.mp3",start:39.073,off:.155,dur:2.213},{shot:5,text:"少数长期不缓解的情况,可能需要手术松解。",file:"s06_04.mp3",start:41.386,off:.141,dur:2.415},{shot:6,text:"那小针刀,到底是在做什么?",file:"s07_01.mp3",start:44.252,off:.163,dur:1.581},{shot:6,text:"不是“扎一下就结束”。",file:"s07_02.mp3",start:45.933,off:.148,dur:1.022},{shot:6,text:"核心是:找到狭窄的位置,",file:"s07_03.mp3",start:47.055,off:.168,dur:1.418},{shot:6,text:"对增厚、卡压的区域进行精准松解。",file:"s07_04.mp3",start:48.573,off:.153,dur:2.165},{shot:7,text:"先定位。",file:"s08_01.mp3",start:51.238,off:.132,dur:.427},{shot:7,text:"再进行消毒。",file:"s08_02.mp3",start:52.465,off:.141,dur:.764},{shot:7,text:"必要时进行局部麻醉。",file:"s08_03.mp3",start:54.129,off:.147,dur:1.419},{shot:7,text:"随后在影像或规范定位辅助下,",file:"s08_04.mp3",start:56.248,off:.134,dur:1.828},{shot:7,text:"让器械到达目标区域。",file:"s08_05.mp3",start:58.176,off:.152,dur:1.206},{shot:7,text:"进行松解。",file:"s08_06.mp3",start:59.882,off:.142,dur:.604},{shot:8,text:"松解前,肌腱经过狭窄区域时,明显受限。",file:"s09_01.mp3",start:61.736,off:.136,dur:2.51},{shot:8,text:"松解后,通道空间改善。",file:"s09_02.mp3",start:64.346,off:.145,dur:1.359},{shot:8,text:"肌腱活动更顺畅。",file:"s09_03.mp3",start:65.805,off:.139,dur:1.077},{shot:9,text:"疼痛改善,不代表马上就能过度使用。",file:"s10_01.mp3",start:67.532,off:.146,dur:2.072},{shot:9,text:"治疗之后,还要根据情况逐步恢复活动。",file:"s10_02.mp3",start:69.703,off:.146,dur:2.27},{shot:9,text:"减少再次刺激。",file:"s10_03.mp3",start:72.074,off:.129,dur:.928},{shot:9,text:"让手部功能慢慢回来。",file:"s10_04.mp3",start:73.102,off:.139,dur:1.261},{shot:10,text:"所以腱鞘炎,真正要解决的不是“忍住疼”。",file:"s11_01.mp3",start:74.813,off:.151,dur:2.365},{shot:10,text:"而是找到疼痛的原因,选择合适的治疗方式。",file:"s11_02.mp3",start:77.278,off:.268,dur:2.484},{shot:10,text:"记住一句话:",file:"s11_03.mp3",start:79.862,off:.147,dur:.576},{shot:10,text:"手越疼,越不能只靠硬扛。",file:"s11_04.mp3",start:80.788,off:.148,dur:1.606},{shot:11,text:"你是哪个动作一做,手腕或者手指就开始疼?",file:"s12_01.mp3",start:83.644,off:.147,dur:2.29}]},O=(e,a=0,n=1)=>Math.min(n,Math.max(a,e)),w=(e,a,n)=>e+(a-e)*n,b=e=>(e=O(e),e*e*(3-2*e)),J=e=>1-Math.pow(1-O(e),3),g0=e=>{e=O(e);const a=1.70158;return 1+(a+1)*Math.pow(e-1,3)+a*Math.pow(e-1,2)},f=(e,a,n)=>O((e-a)/(n-a)),_=(e,a,n,o=.3,s=.3)=>Math.min(b(f(e,a,a+o)),1-b(f(e,n-s,n))),i0=(e,a,n)=>e.map((o,s)=>w(o,a[s],n)),c=e=>{const a=Math.sin(e*127.1+311.7)*43758.5453;return a-Math.floor(a)},s0=e=>{const a=Math.floor(e),n=e-a,o=n*n*(3-2*n);return w(c(a),c(a+1),o)*2-1},$='"PingFang SC","Noto Sans SC","Source Han Sans SC","Microsoft YaHei","Hiragino Sans GB",sans-serif',y={cyan:"#5fd4ff",teal:"#2fe0c0",red:"#ff3b3b",yellow:"#ffd23f",white:"#ffffff",green:"#3ee08f"};function G(e,a,n,o,s,t){e.beginPath(),e.moveTo(a+t,n),e.arcTo(a+o,n,a+o,n+s,t),e.arcTo(a+o,n+s,a,n+s,t),e.arcTo(a,n+s,a,n,t),e.arcTo(a,n,a+o,n,t),e.closePath()}function b0(e,a,n,o=1555){if(n<=.01||!a)return;e.save(),e.globalAlpha=n,e.font=`800 58px ${$}`,e.textAlign="center",e.textBaseline="middle";const s=m0(e,a,940),t=80;s.forEach((r,l)=>{const i=o+(l-(s.length-1)/2)*t+(1-n)*10;e.lineJoin="round",e.lineWidth=12,e.strokeStyle="rgba(0,8,20,0.85)",e.strokeText(r,540,i),e.fillStyle="#ffffff",e.fillText(r,540,i)}),e.restore()}function m0(e,a,n){if(e.measureText(a).width<=n)return[a];const o=[...a],s=[];let t="";for(const r of o)e.measureText(t+r).width>n?(s.push(t),t=r):t+=r;if(t&&s.push(t),s.length===2){const r=Math.floor(o.length/2);let l=-1;for(let i=0;i<6;i++)for(const h of[r+i,r-i])l<0&&",、:;".includes(o[h]??"")&&(l=h);if(l>0)return[o.slice(0,l+1).join(""),o.slice(l+1).join("")]}return s}function C(e,a,n,o,s={}){const t=s.alpha??1;if(t<=.01)return;const r=s.size??46,l=s.color??y.cyan;e.save(),e.globalAlpha=t,e.translate(a,n);const i=s.scale??1;e.scale(i,i),e.font=`800 ${r}px ${$}`;const h=e.measureText(o).width,d=s.icon?r*1.05:0,k=h+d+r*1.1,g=r*1.7;e.shadowColor=l,e.shadowBlur=24,G(e,-k/2,-g/2,k,g,g/2),e.fillStyle=s.fill?l:"rgba(6,18,36,0.78)",e.fill(),e.shadowBlur=0,e.lineWidth=3,e.strokeStyle=l,e.stroke();const p=-k/2+r*.55+d;s.icon&&f0(e,s.icon,-k/2+r*.55+r*.42,0,r*.8,s.fill?"#061224":l,s.num),e.fillStyle=s.fill?"#061224":"#fff",e.textBaseline="middle",e.textAlign="left",e.fillText(o,p,2),s.strike&&(e.strokeStyle=y.red,e.lineWidth=7,e.lineCap="round",e.beginPath(),e.moveTo(-k/2+10,0),e.lineTo(-k/2+10+(k-20)*O(s.strike),0),e.stroke()),e.restore()}function f0(e,a,n,o,s,t,r){e.save(),e.translate(n,o),e.strokeStyle=t,e.fillStyle=t,e.lineWidth=s*.13,e.lineCap="round",e.lineJoin="round",a==="check"?(e.beginPath(),e.moveTo(-s*.35,0),e.lineTo(-s*.08,s*.28),e.lineTo(s*.4,-s*.3),e.stroke()):a==="cross"?(e.beginPath(),e.moveTo(-s*.3,-s*.3),e.lineTo(s*.3,s*.3),e.moveTo(s*.3,-s*.3),e.lineTo(-s*.3,s*.3),e.stroke()):a==="warn"?(e.beginPath(),e.moveTo(0,-s*.42),e.lineTo(s*.45,s*.38),e.lineTo(-s*.45,s*.38),e.closePath(),e.stroke(),e.beginPath(),e.moveTo(0,-s*.1),e.lineTo(0,s*.12),e.stroke(),e.beginPath(),e.arc(0,s*.25,s*.04,0,7),e.fill()):a==="dot"?(e.beginPath(),e.arc(0,0,s*.22,0,7),e.fill()):a==="num"&&(e.beginPath(),e.arc(0,0,s*.45,0,7),e.fill(),e.fillStyle="#061224",e.font=`900 ${s*.6}px ${$}`,e.textAlign="center",e.textBaseline="middle",e.fillText(String(r??1),0,s*.03)),e.restore()}function Q(e,a,n,o,s,t=y.red,r=92){if(s<=.01)return;e.save();const l=.6+.4*g0(Math.min(1,s*1.6));e.globalAlpha=O(s*2),e.translate(n,o),e.scale(l,l),e.font=`900 ${r}px ${$}`,e.textAlign="center",e.textBaseline="middle",e.shadowColor=t,e.shadowBlur=40,e.lineWidth=14,e.strokeStyle="rgba(0,6,16,0.9)",e.lineJoin="round",e.strokeText(a,0,0),e.fillStyle=t,e.fillText(a,0,0),e.shadowBlur=0,e.fillStyle="#fff",e.globalAlpha*=.25,e.fillText(a,0,-3),e.restore()}function H(e,a,n,o,s,t,r,l=y.cyan,i=40){if(r<=.01)return;e.save(),e.globalAlpha=r;const h=b(r),d=a+(o-a)*h,k=n+(s-n)*h;e.strokeStyle=l,e.lineWidth=3,e.shadowColor=l,e.shadowBlur=10,e.beginPath(),e.moveTo(a,n),e.lineTo(d,k),e.stroke(),e.fillStyle=l,e.beginPath(),e.arc(a,n,8,0,7),e.fill(),e.strokeStyle="#fff",e.lineWidth=2,e.beginPath(),e.arc(a,n,14+Math.sin(r*6)*2,0,7),e.stroke(),e.shadowBlur=0,e.font=`800 ${i}px ${$}`;const g=e.measureText(t).width+36,p=i*1.5,v=o<a?d-g:d;G(e,v,k-p/2,g,p,12),e.fillStyle="rgba(4,14,30,0.85)",e.fill(),e.strokeStyle=l,e.lineWidth=2.5,e.stroke(),e.fillStyle="#fff",e.textAlign="left",e.textBaseline="middle",e.fillText(t,v+18,k+2),e.restore()}function a0(e,a,n,o,s,t,r=y.red,l=1){if(s<=.01)return;e.save(),e.globalAlpha=s,e.translate(a,n);const i=o*(1+(1-l)*1.4);e.rotate((1-l)*1.2+t*.3),e.strokeStyle=r,e.lineWidth=5,e.shadowColor=r,e.shadowBlur=16;for(let h=0;h<4;h++)e.rotate(Math.PI/2),e.beginPath(),e.moveTo(i,i*.45),e.lineTo(i,i),e.lineTo(i*.45,i),e.stroke();e.rotate(-t*.3-(1-l)*1.2),e.lineWidth=2,e.setLineDash([8,10]),e.beginPath(),e.arc(0,0,i*.72,t,t+Math.PI*2),e.stroke(),e.setLineDash([]),e.lineWidth=2.5,e.beginPath(),e.moveTo(-14,0),e.lineTo(14,0),e.moveTo(0,-14),e.lineTo(0,14),e.stroke(),e.restore()}function x(e,a,n,o,s){if(!(o<=.01)){e.save(),e.translate(a,n),e.globalCompositeOperation="lighter";for(let t=0;t<3;t++){const r=(s*1.3+t/3)%1;e.strokeStyle=`rgba(255,60,50,${(1-r)*.6*o})`,e.lineWidth=6*(1-r)+1,e.beginPath(),e.arc(0,0,40+r*170,0,Math.PI*2),e.stroke()}e.strokeStyle=`rgba(255,90,70,${.9*o})`,e.lineWidth=7,e.lineCap="round";for(let t=0;t<9;t++){const r=t/9*Math.PI*2+.3,l=.6+.4*Math.sin(s*20+t*3),i=70+20*l,h=i+50*o*l;e.beginPath(),e.moveTo(Math.cos(r)*i,Math.sin(r)*i),e.lineTo(Math.cos(r)*h,Math.sin(r)*h),e.stroke()}e.restore()}}function l0(e,a,n,o,s,t,r,l,i="横截面示意"){if(r<=.01)return;e.save(),e.globalAlpha=r,e.translate(a,n);const h=o*1.5;G(e,-h,-h-50,h*2,h*2+70,26),e.fillStyle="rgba(4,14,30,0.82)",e.fill(),e.strokeStyle="rgba(95,212,255,0.7)",e.lineWidth=2.5,e.stroke(),e.font=`800 30px ${$}`,e.fillStyle=y.cyan,e.textAlign="center",e.fillText(i,0,-h-12);const d=o*(1+s*.22),k=o*(.82-s*.3),g=`rgb(${Math.round(140+115*s)},${Math.round(200-120*s)},${Math.round(255-170*s)})`;e.fillStyle=g,e.globalAlpha=r*.85,e.beginPath(),e.arc(0,10,d,0,Math.PI*2),e.arc(0,10,k,0,Math.PI*2,!0),e.fill("evenodd"),e.globalAlpha=r,e.strokeStyle="#fff",e.lineWidth=2,e.beginPath(),e.arc(0,10,k,0,7),e.stroke(),e.fillStyle="rgba(70,170,255,0.25)",e.beginPath(),e.arc(0,10,k-2,0,7),e.fill();const p=o*.3,m=Math.sin(l*5)*2,v=t;for(const u of[-p*1.05,p*1.05]){const A=e.createRadialGradient(u-6,4+m,2,u,10+m,p);A.addColorStop(0,"#ffffff"),A.addColorStop(1,v>.1?`rgb(255,${Math.round(230-170*v)},${Math.round(200-170*v)})`:"#e6dfcf"),e.fillStyle=A,e.beginPath(),e.arc(u,10+m,p,0,7),e.fill(),e.strokeStyle="rgba(0,0,0,0.25)",e.lineWidth=1.5;for(let P=-2;P<=2;P++)e.beginPath(),e.arc(u+P*6,10+m,p*.18,0,7),e.stroke()}if(v>.05){e.globalCompositeOperation="lighter";const u=e.createRadialGradient(0,10,k*.5,0,10,d);u.addColorStop(0,"rgba(255,40,30,0)"),u.addColorStop(.7,`rgba(255,60,40,${.5*v})`),u.addColorStop(1,"rgba(255,40,30,0)"),e.fillStyle=u,e.beginPath(),e.arc(0,10,d*1.1,0,7),e.fill(),e.globalCompositeOperation="source-over"}const S=k-p*2.05;e.font=`700 24px ${$}`,e.fillStyle="#cfefff",e.textAlign="center",e.fillText(S>o*.12?"间隙充足":"间隙变窄",0,o*1.45),e.restore()}let o0=null;function y0(){if(o0)return o0;const e=document.createElement("canvas");e.width=360,e.height=300;const a=e.getContext("2d"),n=a.createImageData(360,300);for(let o=0;o<360*300;o++){const s=Math.pow(c(o*1.37+.5),2.2)*120;n.data[o*4]=n.data[o*4+1]=n.data[o*4+2]=s,n.data[o*4+3]=255}return a.putImageData(n,0,0),o0=e,e}function n0(e,a,n,o,s,t,r){if(r.alpha<=.01)return;e.save(),e.globalAlpha=r.alpha,G(e,a-14,n-64,o+28,s+84,24),e.fillStyle="rgba(2,8,16,0.94)",e.fill(),e.strokeStyle="rgba(95,212,255,0.6)",e.lineWidth=2.5,e.stroke(),e.font=`800 30px ${$}`,e.fillStyle=y.cyan,e.textAlign="left",e.textBaseline="middle",e.fillText(r.title??"超声检查 · 示意",a+6,n-32),e.fillStyle="rgba(255,255,255,0.5)",e.font=`600 22px ${$}`,e.textAlign="right",e.fillText(`B-MODE 12MHz ${(t%60).toFixed(1)}s`,a+o-6,n-32),e.save(),G(e,a,n,o,s,10),e.clip(),e.fillStyle="#000",e.fillRect(a,n,o,s);const l=y0();e.globalAlpha=r.alpha*.9,e.drawImage(l,t*7%40,0,320,300,a,n,o,s),e.globalAlpha=r.alpha;const i=n+s*.48,h=a+o*.5;e.fillStyle="rgba(230,230,230,0.55)",e.fillRect(a,n+s*.06,o,5);const d=s*(.12+r.thick*.1),k=o*.32;e.fillStyle="rgba(0,0,0,0.75)",e.beginPath(),e.ellipse(h,i,o*.46,s*.1+d*.6,0,0,7),e.fill();for(let m=0;m<9;m++){const v=i-s*.07+m*s*.0175;e.strokeStyle=`rgba(240,240,240,${.35+.35*c(m)})`,e.lineWidth=2.2,e.beginPath();for(let S=0;S<=40;S++){const u=a+o*.06+o*.88*S/40,A=Math.exp(-Math.pow((u-h)/(k*.5),2))*r.thick*(r.release?1-r.release*.7:1),P=i+(v-i)*(1-A*.35)+Math.sin(S*1.7+m)*1.2;S===0?e.moveTo(u,P):e.lineTo(u,P)}e.stroke()}e.strokeStyle="rgba(255,255,255,0.9)",e.lineWidth=8,e.beginPath(),e.moveTo(a,n+s*.8),e.quadraticCurveTo(h,n+s*.7,a+o,n+s*.82),e.stroke();const g=e.createLinearGradient(0,n+s*.8,0,n+s);if(g.addColorStop(0,"rgba(0,0,0,0.6)"),g.addColorStop(1,"rgba(0,0,0,0.95)"),e.fillStyle=g,e.fillRect(a,n+s*.8,o,s*.2),r.knife&&r.knife>0){const m=a+o*.1,v=n+s*.04,S=m+(h-m)*r.knife,u=v+(i-s*.05-v)*r.knife;e.strokeStyle="rgba(255,255,255,0.95)",e.lineWidth=5,e.shadowColor="#fff",e.shadowBlur=12,e.beginPath(),e.moveTo(m,v),e.lineTo(S,u),e.stroke(),e.shadowBlur=0}if(r.narrowMark&&r.narrowMark>0&&(e.globalAlpha=r.alpha*r.narrowMark,e.strokeStyle=y.red,e.lineWidth=4,e.setLineDash([12,8]),e.beginPath(),e.ellipse(h,i,k*.62,s*.2,0,0,7),e.stroke(),e.setLineDash([]),e.globalAlpha=r.alpha),r.locator&&r.locator>0){e.globalAlpha=r.alpha*r.locator;const m=10+Math.sin(t*8)*3;e.fillStyle="#fff",e.shadowColor="#fff",e.shadowBlur=25,e.beginPath(),e.arc(h,i-s*.05,m,0,7),e.fill(),e.shadowBlur=0,e.strokeStyle="#fff",e.lineWidth=2,e.beginPath(),e.arc(h,i-s*.05,m+18,0,7),e.stroke(),e.globalAlpha=r.alpha}e.fillStyle="rgba(255,255,255,0.6)";for(let m=0;m<8;m++)e.fillRect(a+o-16,n+10+m*(s-20)/7,m%2?6:12,2);e.restore();const p=r.labels??0;if(p>0){const m=[{t:"肌腱",ax:a+o*.2,ay:i,tx:a+o*.08,ty:n+s+50,c:y.white,d:0},{t:"腱鞘",ax:a+o*.78,ay:i-s*.13,tx:a+o*.66,ty:n+s+50,c:y.cyan,d:.25},{t:"狭窄位置",ax:h,ay:i+s*.08,tx:a+o*.36,ty:n+s+50,c:y.red,d:.5}];for(const v of m){const S=O((p-v.d)*2.5);S<=0||(e.save(),e.globalAlpha=r.alpha*S,e.strokeStyle=v.c,e.lineWidth=3,e.beginPath(),e.moveTo(v.ax,v.ay),e.lineTo(v.ax,v.ty-26),e.stroke(),e.fillStyle=v.c,e.beginPath(),e.arc(v.ax,v.ay,7,0,7),e.fill(),e.font=`800 34px ${$}`,e.textAlign="center",e.fillStyle=v.c,e.fillText(v.t,v.ax,v.ty),e.restore())}}e.restore()}function k0(e,a,n,o,s=260){e.save(),e.globalAlpha=o;const t=a.length,r=230,l=540-r*(t-1)/2;e.strokeStyle="rgba(95,212,255,0.35)",e.lineWidth=4,e.beginPath(),e.moveTo(l,s),e.lineTo(l+r*(t-1),s),e.stroke();const i=O(n/(t-1));e.strokeStyle=y.teal,e.beginPath(),e.moveTo(l,s),e.lineTo(l+r*(t-1)*i,s),e.stroke(),a.forEach((h,d)=>{const k=l+d*r,g=n>=d-.01,p=Math.abs(n-d)<.5;e.fillStyle=g?y.teal:"#0b2238",e.strokeStyle=g?y.teal:"rgba(95,212,255,0.5)",e.lineWidth=3,e.beginPath(),e.arc(k,s,p?30:24,0,7),e.fill(),e.stroke(),e.fillStyle=g?"#04121f":"#9fd8ff",e.font=`900 28px ${$}`,e.textAlign="center",e.textBaseline="middle",e.fillText(String(d+1),k,s+1),e.fillStyle=p?"#fff":"rgba(255,255,255,0.65)",e.font=`800 ${p?36:30}px ${$}`,e.fillText(h,k,s+62)}),e.restore()}function v0(e,a,n,o){if(e.save(),e.globalAlpha=.9,e.font=`800 30px ${$}`,e.textBaseline="middle",e.textAlign="left",G(e,48,120,300,54,27),e.fillStyle="rgba(4,14,30,0.6)",e.fill(),e.strokeStyle="rgba(95,212,255,0.45)",e.lineWidth=2,e.stroke(),e.fillStyle=y.red,e.beginPath(),e.arc(76,147,8,0,7),e.fill(),e.fillStyle="#dff4ff",e.fillText("腱鞘炎 · 3D 解剖",96,148),o>.01){e.globalAlpha=o,e.font=`900 40px ${$}`;const s=e.measureText(n).width,t=48-(1-o)*40;G(e,t,190,s+120,66,14),e.fillStyle="rgba(95,212,255,0.14)",e.fill(),e.fillStyle=y.cyan,e.fillRect(t,190,8,66),e.fillStyle=y.cyan,e.font=`900 34px ${$}`,e.fillText(String(a).padStart(2,"0"),t+26,224),e.fillStyle="#fff",e.font=`900 40px ${$}`,e.fillText(n,t+84,224)}e.restore()}function S0(e){e.save(),e.globalAlpha=.55,e.font=`600 24px ${$}`,e.fillStyle="#cfe6ff",e.textAlign="center",e.fillText("原创3D医学示意动画 · 仅供科普,不替代面诊",540,1870),e.restore()}function T0(e,a,n,o,s,t,r,l,i){e.save(),i>.01&&(e.fillStyle=`rgba(2,6,14,${i*.6})`,e.fillRect(a,n,o,s));const h=l>.5?y.teal:"rgba(95,212,255,0.4)";e.strokeStyle=h,e.lineWidth=l>.5?6:2,l>.5&&(e.shadowColor=y.teal,e.shadowBlur=20),G(e,a+6,n+6,o-12,s-12,22),e.stroke(),e.shadowBlur=0,e.font=`900 40px ${$}`;const d=e.measureText(t).width;G(e,a+22,n+s-100,d+100,70,35),e.fillStyle=l>.5?y.teal:"rgba(4,14,30,0.85)",e.fill(),f0(e,"num",a+62,n+s-65,46,l>.5?"#04121f":y.cyan,r),e.fillStyle=l>.5?"#04121f":"#fff",e.textBaseline="middle",e.textAlign="left",e.fillText(t,a+98,n+s-63),e.restore()}function e0(e,a,n="255,255,255"){a<=.01||(e.save(),e.fillStyle=`rgba(${n},${a})`,e.fillRect(0,0,1080,1920),e.restore())}function U(e,a,n,o,s,t,r=1){if(r<=.01)return;e.save(),e.globalAlpha=r,e.translate(n,o),e.strokeStyle=t,e.fillStyle=t,e.lineWidth=s*.07,e.lineCap="round",e.lineJoin="round";const l=s/2;if(a==="grab"){e.beginPath(),e.arc(0,0,l*.55,0,7),e.stroke();for(let i=0;i<4;i++){const h=-2.4+i*.45;e.beginPath(),e.arc(Math.cos(h)*l*.55,Math.sin(h)*l*.55,l*.16,0,7),e.fill()}}else if(a==="pinch")e.beginPath(),e.moveTo(-l*.7,-l*.5),e.quadraticCurveTo(0,-l*.2,-l*.05,-l*.05),e.moveTo(-l*.7,l*.5),e.quadraticCurveTo(0,l*.2,-l*.05,l*.05),e.stroke(),e.beginPath(),e.arc(l*.15,0,l*.15,0,7),e.fill();else if(a==="twist")e.beginPath(),e.arc(0,0,l*.6,-2.6,1.2),e.stroke(),e.beginPath(),e.moveTo(l*.21,l*.56),e.lineTo(l*.5,l*.75),e.lineTo(l*.4,l*.4),e.stroke(),e.strokeRect(-l*.25,-l*.25,l*.5,l*.5);else if(a==="baby")e.beginPath(),e.arc(-l*.35,-l*.15,l*.28,0,7),e.stroke(),e.beginPath(),e.ellipse(l*.2,l*.15,l*.55,l*.32,-.3,0,7),e.stroke();else if(a==="keyboard"){e.strokeRect(-l*.75,-l*.35,l*1.5,l*.7);for(let i=0;i<5;i++)e.fillRect(-l*.6+i*l*.27,-l*.15,l*.12,l*.1)}else if(a==="tool")e.beginPath(),e.moveTo(-l*.6,l*.6),e.lineTo(l*.25,-l*.25),e.stroke(),e.fillRect(l*.05,-l*.7,l*.6,l*.35);else if(a==="home")e.beginPath(),e.moveTo(-l*.6,0),e.lineTo(0,-l*.6),e.lineTo(l*.6,0),e.moveTo(-l*.45,-l*.1),e.lineTo(-l*.45,l*.55),e.lineTo(l*.45,l*.55),e.lineTo(l*.45,-l*.1),e.stroke();else if(a==="comment"){G(e,-l*.7,-l*.55,l*1.4,l*.95,l*.25),e.stroke(),e.beginPath(),e.moveTo(-l*.3,l*.4),e.lineTo(-l*.45,l*.75),e.lineTo(0,l*.4),e.stroke();for(let i=-1;i<=1;i++)e.beginPath(),e.arc(i*l*.32,-l*.08,l*.08,0,7),e.fill()}e.restore()}const u0=t0.total,E=t0.shots,Z=t0.lines,M0=e=>Z.filter(a=>a.shot===e).map(a=>({...a,s:a.start-E[e].start,e:a.start-E[e].start+a.dur})),F=E.map((e,a)=>M0(a)),r0=(e,a)=>{const n=[...e];for(let o=0;o<5;o++)n[16+o]=a[o];return n},w0=[-.08,.75,.1,.9,.65],P0=[.35,-.1,0,-.05,-.05];function N(e,a,n,o,s=0){let t=.5-.5*Math.cos(a*n*Math.PI*2);if(s>0){const i=Math.round(t*4)/4;t=w(t,i,s)+s0(a*13)*.04*s}const r=r0(e,P0),l=r0(e,w0);return i0(r,l,O(t*o+(1-o)*.35))}const D=(e,a,n)=>i0(e,a,O(n)),V=(e,a,n,o=e[2])=>{const s=[...e];return s[0]=a,s[1]=n,s[2]=o,s},j=(e,a="lab")=>[{rect:[0,0,1,1],state:e,bg:a}],K=(e,a,n,o=35)=>({pos:q([0,0,0],e,a,n),target:[0,0,0],fov:o,follow:1});function A0(e,a,n){const o=F[0],s=o[0].s,t=o[1].s;let r;e<s-.2?r=N(M.rest,e,.85,.9):r=D(D(M.rest,M.fist,b(f(e,s-.2,s+.6))),M.tuck,b(f(e,s+.55,s+1.15)));const l=s+1.05,i=b(f(e,l,l+.35));r=D(r,D(M.rest,M.tuck,.25),b(f(e,t+.9,t+1.6)));const h=Math.max(0,1-Math.abs(e-l-.15)/.35)*.035,d=[s0(e*40)*h,s0(e*37+5)*h,0],k=b(f(e,t-.25,t+1)),g=b(f(e,t+.7,t+1.3)),p={pos:q([0,.45,0],w(5.6,4.8,b(e/s)),.25-.15*b(e/a),.08),target:[0,.45,0],fov:35},m=L({time:n,pose:r,shake:d,arm:{pos:[0,0,0],rot:[0,w(.45,.95,k),.04]},cam:k<.001?p:(()=>{const v=K(w(4.8,1.75,k),w(.1,.05,k),w(.08,.12,k));return{...v,follow:k,pos:X(p.pos,v.pos,k),target:X(p.target,v.target,k)}})(),pain:i*(1-.2*g),xray:g,skin:1,bone:b(f(e,t+1,t+1.7)),tendon:b(f(e,t+1.25,t+1.95)),sheath:b(f(e,t+1.5,a+.4)),friction:0});return{views:j(m),fade:1-b(e/.8),overlay:(v,S)=>{const u=S.anchor("pain");x(v,u.x,u.y,Math.max(0,1-Math.abs(e-l-.4)/1.2)*i,n),a0(v,u.x,u.y,70,_(e,t,a,.3,.4)*(1-g*.5),n,y.red,b(f(e,t,t+.6))),Q(v,"?",u.x+150,u.y-150,f(e,t+.2,t+.6)*(1-f(e,t+1.3,t+1.6)),y.red,150);const A=S.anchor("bone"),P=S.anchor("tendon"),W=S.anchor("sheath");H(v,A.x,A.y,A.x+230,A.y+120,"骨骼",f(e,t+1.2,t+1.5),"#f2e7cf"),H(v,P.x,P.y,P.x+260,P.y-60,"肌腱",f(e,t+1.45,t+1.75),y.white),H(v,W.x,W.y,W.x-230,W.y-170,"腱鞘",f(e,t+1.7,t+2),y.cyan)}}}const X=(e,a,n)=>[w(e[0],a[0],n),w(e[1],a[1],n),w(e[2],a[2],n)];function _0(e,a,n){const o=F[1],s=b(f(e,o[2].s,o[3].e)),t=Math.max(.45*b(f(e,o[2].s,o[3].s)),.95*b(f(e,o[4].s,o[5].s+.6))),r=b(f(e,o[3].s,o[5].s)),l=N(M.rest,e,w(.9,1.1,r),w(1,.7,r),r),i=L({time:n,pose:l,arm:{pos:[0,0,0],rot:[0,w(.95,.75,b(e/a)),.04]},cam:K(w(1.75,1.08,J(e/3)),w(.05,-.12,b(e/a)),.12),skin:.75,xray:1,bone:1,tendon:1,sheath:1,focus:b(f(e,0,1)),thick:s,friction:t,pain:.85*b(f(e,o[5].s,o[5].s+.6))});return{views:j(i),overlay:(h,d)=>{const k=d.anchor("sheath"),g=d.anchor("tendon");H(h,k.x,k.y,k.x-200,k.y-260,"腱鞘 = 小通道",_(e,o[0].s,o[2].s+.3),y.cyan),H(h,g.x,g.y,g.x+150,g.y+200,"肌腱",_(e,o[0].s+.4,o[2].s+.3),y.white),C(h,540,1300,"正常:顺畅滑动",{icon:"check",color:y.green,alpha:_(e,o[1].s,o[2].s+.2)}),l0(h,830,560,105,s,t,b(f(e,.5,1)),n);const p=m=>f(e,o[m].s+.1,o[m].s+.5);C(h,540,1150,"腱鞘增厚",{icon:"warn",color:y.yellow,alpha:p(3),scale:.8+.2*J(p(3))}),C(h,540,1268,"空间变窄",{icon:"warn",color:"#ff9a3c",alpha:p(4),scale:.8+.2*J(p(4))}),C(h,540,1386,"活动疼痛",{icon:"warn",color:y.red,alpha:p(5),scale:.8+.2*J(p(5))})}}}function C0(e,a,n){const o=a/3,s=Math.min(2,Math.floor(e/o)),t=e-s*o,r=.5-.5*Math.cos(t*Math.PI*2*1.3);let l,i={},h;if(s===0)l=D(M.open,M.gripBall,b(f(t,0,.35))*(.8+.2*r)),i={ball:{vis:b(f(t,0,.2))}};else if(s===1)l=D(M.open,M.pinch,b(f(t,0,.35))*(.9+.1*r)),i={bead:{vis:b(f(t,.25,.4))}};else{l=D(M.open,M.gripBall,b(f(t,0,.3))),l=V(l,l[0],l[1]+.25*r);const g=-.8*r;h={pivot:[-.02,.6,-.3],axis:[0,0,1],angle:g},i={bottle:{vis:b(f(t,0,.2)),twist:g}}}const d=[.4,.7,1][s],k=L({time:n,pose:l,props:i,arm:{pos:[0,0,0],rot:[.05,.85,.05],twist:h},cam:{...K(2.5,.25,.18),pos:q([0,0,0],2.5,.25,.18)},skin:1,xray:.62,bone:1,tendon:1,sheath:1,focus:.25,thick:1,friction:d*(.7+.3*r),pain:d*(.75+.25*r)});return k.cam.target=[0,.35,0],k.cam.pos=[k.cam.pos[0],k.cam.pos[1]+.35,k.cam.pos[2]],{views:j(k),overlay:(g,p)=>{const m=["抓","捏","拧"],v=["grab","pinch","twist"];m.forEach((B,R)=>{const I=R===s?1:R<s?.55:.3,z=250+R*290,Y=1230;g.save(),g.globalAlpha=I,g.fillStyle=R===s?"rgba(255,59,59,0.22)":"rgba(4,14,30,0.7)",g.strokeStyle=R===s?y.red:"rgba(95,212,255,0.5)",g.lineWidth=R===s?5:2,g.beginPath(),g.arc(z,Y,92*(R===s?1+.06*r:1),0,7),g.fill(),g.stroke(),g.restore(),U(g,v[R],z,Y-22,90,R===s?"#fff":y.cyan,I),g.save(),g.globalAlpha=I,g.font=`900 46px ${$}`,g.fillStyle="#fff",g.textAlign="center",g.textBaseline="middle",g.fillText(B,z,Y+48),g.restore()});const S=p.anchor("pain");x(g,S.x,S.y,d*.5*r,n);const u=975,A=520,P=480;g.save(),g.fillStyle="rgba(4,14,30,0.75)",g.fillRect(u-20,A,40,P);const W=P*d*(.85+.15*r),T=g.createLinearGradient(0,A+P,0,A);T.addColorStop(0,y.yellow),T.addColorStop(1,y.red),g.fillStyle=T,g.fillRect(u-20,A+P-W,40,W),g.strokeStyle="rgba(255,255,255,0.6)",g.lineWidth=2,g.strokeRect(u-20,A,40,P),g.font=`800 30px ${$}`,g.fillStyle="#fff",g.textAlign="center",g.fillText("疼痛",u,A+P+40),g.restore()}}}function $0(e,a,n){const s=F[3][1].s-.05,t=(a-s)/4,r=e<s,l=r?-1:Math.min(3,Math.floor((e-s)/t)),i=r?e:e-s-l*t,h=["重复用手","长期抓握","频繁捏拧","抱孩子"],d=["keyboard","tool","home","baby"];let k;const g=r?0:b(f(i,.35,.6))*(.75+.25*Math.sin(n*9));if(r)k=L({time:n,pose:D(M.rest,M.open,.5+.5*Math.sin(e*3)),arm:{pos:[0,0,0],rot:[0,-.4+e*.9,0]},cam:{pos:q([0,.4,0],5.4,0,.1),target:[0,.4,0],fov:35}});else if(l===0){const p=Math.max(0,Math.sin(i*18)),m=V(M.mouse,-.25,.1+.18*Math.sin(i*5));m[4]+=p*.18,k=L({time:n,pose:m,arm:{pos:[0,0,0],rot:[-1.25,0,0]},props:{keyboard:{vis:1,x:-1.75,y:.7,z:-.38,rx:Math.PI/2}},cam:{pos:[-1,2.4,2.6],target:[-.35,.15,-.6],fov:38},pain:g})}else if(l===1){const p=Math.pow(.5+.5*Math.sin(i*9),2);k=L({time:n,pose:V(M.grip,.05,-.15+.5*p),arm:{pos:[0,0,0],rot:[0,.85,.15]},props:{hammer:{vis:1}},cam:{pos:q([-.2,.55,0],4.2,.05,.12),target:[-.2,.55,0],fov:35},pain:g})}else if(l===2){const p=Math.sin(i*6);k=L({time:n,pose:V(M.grip,.1,.15+.15*p,.55*p),arm:{pos:[0,0,0],rot:[0,.75,-.2]},props:{towel:{vis:1}},cam:{pos:q([.1,.5,0],4.4,.1,.15),target:[.1,.5,0],fov:35},pain:g})}else k=L({time:n,pose:V(M.baby,-.25,.05*Math.sin(i*4)),arm:{pos:[0,-.1*Math.sin(i*3),0],rot:[1.25,.7,0]},props:{baby:{vis:1}},cam:{pos:[1.6,3,3.6],target:[0,.35,.3],fov:38},pain:g});return{views:j(k,r?"lab":"warm"),overlay:(p,m)=>{if(!r&&i<.14&&e0(p,.35*(1-i/.14)),r){d.forEach((S,u)=>{const A=f(e,.2+u*.12,.45+u*.12),P=195+u*230,W=1230;p.save(),p.globalAlpha=A,p.fillStyle="rgba(4,14,30,0.75)",p.strokeStyle=y.cyan,p.lineWidth=3,p.beginPath(),p.arc(P,W,80,0,7),p.fill(),p.stroke(),p.restore(),U(p,S,P,W,80,y.cyan,A)}),Q(p,"哪些人更容易出现?",540,1050,f(e,.1,.5),"#ffffff",74);return}const v=m.anchor("pain");x(p,v.x,v.y,g*.6,n),p.save(),p.font=`900 34px ${$}`,p.fillStyle="rgba(255,255,255,0.75)",p.textAlign="right",p.fillText(`0${l+1} / 04`,1030,330),p.restore(),C(p,540,1290,h[l],{color:y.red,size:60,alpha:f(i,.05,.25),scale:.85+.15*J(f(i,.05,.35)),icon:"dot"}),U(p,d[l],120,330,90,y.yellow,.9)}}}function W0(e,a,n){const o=F[4],s=b(f(e,o[1].s-.2,o[1].s+.6)),t=f(e,o[2].s,o[2].s+.2),r=b(f(e,o[3].s-.1,o[3].s+.4)),l=b(f(e,o[3].s+.5,o[3].s+1)),i=t>0?N(M.rest,e,1.1,.9):M.rest,h=w(-.7,.9,b(f(e,0,o[1].s))),d={pos:q([0,.35,0],4.9,0,.1),target:[0,.35,0]},k=K(w(4.9,1.6,s),.05,.12),g=L({time:n,pose:i,arm:{pos:[0,0,0],rot:[.03,h,.04]},cam:{...k,follow:s,pos:X(d.pos,k.pos,s),target:X(d.target,k.target,s)},skin:1,xray:.75,bone:1,tendon:1,sheath:1,thick:.8,focus:b(f(e,o[2].s,o[2].s+.5))*.9,friction:.6*t,pain:.55+.3*s,props:{probe:{vis:r,lift:(1-r)*.6}}});return{views:j(g),overlay:(p,m)=>{C(p,540,1180,"直接治疗",{icon:"cross",color:y.red,alpha:_(e,.2,o[1].s+.2),strike:f(e,.9,1.5)}),C(p,540,1300,"先判断,再治疗",{icon:"check",color:y.teal,alpha:_(e,1.2,o[2].s+.1)});const v=m.anchor("pain");a0(p,v.x,v.y,90,_(e,o[1].s-.1,o[3].s+.4),n,y.red,s),H(p,v.x,v.y,v.x-240,v.y-250,"疼痛位置",_(e,o[1].s+.4,o[3].s+.4),y.red);const S=_(e,o[2].s,o[3].s+.5);if(S>.01){const u=m.anchor("tendon"),A=m.anchor("pain"),P=m.anchor("thumbBase");p.save(),p.globalAlpha=S,p.strokeStyle=y.yellow,p.lineWidth=7,p.setLineDash([22,18]),p.lineDashOffset=-n*120,p.shadowColor=y.yellow,p.shadowBlur=14,p.beginPath(),p.moveTo(u.x,u.y),p.quadraticCurveTo(A.x,A.y,P.x,P.y),p.stroke(),p.restore(),C(p,540,1300,"肌腱活动轨迹",{color:y.yellow,alpha:S,icon:"dot"})}n0(p,110,470,860,620,n,{alpha:l,thick:.85,labels:f(e,o[4].s,o[4].s+1.2),narrowMark:f(e,o[4].s+.6,o[4].s+1)})}}}function B0(e,a,n){const o=F[5],s=T=>e>=o[T].s-.1&&(T===3||e<o[T+1].s-.1)?1:0,t=T=>O((e-o[T].s)/(T===3?a-o[T].s:o[T+1].s-o[T].s)),r=.16,l=.3,i=[[0,r,.5,l],[.5,r,.5,l],[0,r+l,.5,l],[.5,r+l,.5,l]],h=(T,B,R=0,I=.1)=>({pos:q(B,T,R,I),target:B,fov:35}),d=t(0),k=L({time:n,pose:D(M.grip,M.open,b(f(d,.1,.5))),arm:{pos:[0,0,0],rot:[0,.5,0]},cam:h(3.3,[0,.55,0]),pain:.5*(1-d)}),g=t(1),p=L({time:n,pose:M.rest,arm:{pos:[0,0,0],rot:[0,.75+.2*Math.sin(n*.8),0]},cam:h(3.5,[0,.2,0]),props:{splint:{vis:b(f(g,.05,.3))},splintThumb:{vis:b(f(g,.05,.3))},splintPalm:{vis:b(f(g,.05,.3))}},pain:.4}),m=t(2),v=L({time:n,pose:M.rest,arm:{pos:[0,0,0],rot:[0,-.35,0]},cam:K(1.5,0,.1),skin:1,xray:.9,bone:1,tendon:1,sheath:1,thick:.9,focus:.7,pain:.8*(1-b(f(m,.6,1))*.6),props:{syringe:{vis:b(f(m,0,.15)),depth:w(.8,.12,b(f(m,.05,.45))),push:b(f(m,.5,.85))},cloud:{vis:b(f(m,.5,.7))*.8,r:.04+.1*b(f(m,.5,.9))}}}),S=t(3),u=b(f(S,.35,.75)),A=L({time:n,pose:N(M.rest,n,.8,w(.3,1,u)),arm:{pos:[0,0,0],rot:[0,.85,0]},cam:K(1.25,.05,.1),skin:.7,xray:1,bone:1,tendon:1,sheath:1,thick:1-.8*u,friction:.8*(1-u),focus:1,pain:.9*(1-u*.8),props:{ring:{vis:_(S,.35,.8,.05,.2),r:u}}}),P=[k,p,v,A],W=["减少抓握","支具固定","局部治疗示意","手术松解示意"];return{views:P.map((T,B)=>({rect:i[B],state:T,bg:"lab"})),overlay:(T,B)=>{T.save(),T.fillStyle="#02060d",T.fillRect(0,0,1080,r*1920),T.fillRect(0,(r+2*l)*1920,1080,1920-(r+2*l)*1920),T.restore(),P.forEach((I,z)=>{const[Y,h0,p0,d0]=i[z];T0(T,Y*1080,h0*1920,p0*1080,d0*1920,W[z],z+1,s(z),s(z)?0:e>=o[z].s?.35:.7)});const R=s(0)?1:.5;if(T.save(),T.globalAlpha=R,T.translate(430,420),T.strokeStyle=y.red,T.lineWidth=7,T.beginPath(),T.arc(0,0,52,0,7),T.stroke(),T.beginPath(),T.moveTo(-36,-36),T.lineTo(36,36),T.stroke(),T.restore(),U(T,"grab",430,420,60,"#fff",R),s(3)){const I=B.anchor("pain",3);T.save(),T.strokeStyle="#fff",T.globalAlpha=_(S,.15,.6,.1,.1),T.lineWidth=4,T.setLineDash([12,10]),T.beginPath(),T.moveTo(I.x-10,I.y-120),T.lineTo(I.x+10,I.y+120),T.stroke(),T.restore()}C(T,540,245,"常见处理方式 · 需医生评估",{size:36,color:y.cyan,alpha:f(e,0,.4)})}}}function L0(e,a,n){const o=F[6],s=e<o[3].s?w(1.7,.72,b(f(e,.2,o[1].e))):w(.72,.1,b(f(e,o[3].s,a-.2))),t=L({time:n,pose:M.rest,arm:{pos:[0,0,0],rot:[.12,-.3,0]},cam:K(w(2.6,1.35,b(f(e,0,o[2].s))),.1,.06),skin:1,xray:w(.55,1,b(f(e,o[2].s-.4,o[2].s+.3))),bone:1,tendon:1,sheath:1,thick:1,friction:.5,pain:.85,focus:w(.2,.8,b(f(e,o[2].s,o[2].s+.5))),props:{knife:{vis:b(f(e,.1,.5)),depth:s}}});return{views:j(t),overlay:(r,l)=>{Q(r,"小针刀在做什么?",540,380,_(e,.2,o[1].s,.3,.3),"#ffffff",70),C(r,540,1250,"扎一下就结束",{icon:"cross",color:y.red,alpha:_(e,o[1].s,o[2].s+.2),strike:f(e,o[1].s+.4,o[1].e)});const i=l.anchor("narrow");a0(r,i.x,i.y,80,_(e,o[2].s,a+1,.3,.3),n,y.red,b(f(e,o[2].s,o[2].s+.6))),H(r,i.x,i.y,i.x+210,i.y+230,"狭窄位置",f(e,o[2].s+.6,o[2].s+1),y.red);const h=l.anchor("knife");H(r,h.x,h.y,h.x-40,h.y-170,"原创器械示意",_(e,.8,o[2].s),y.teal,34),C(r,540,1300,"精准松解",{icon:"check",color:y.teal,alpha:f(e,o[3].s+.8,o[3].s+1.2),size:52})}}}function R0(e,a,n){const o=F[7],s=e<o[1].s-.1?0:e<o[2].s-.1?1:e<o[3].s-.1?2:3,t=[o[0].s,o[1].s,o[2].s,o[3].s],r=_(e,0,o[1].s-.05,.2,.25),l=_(e,o[1].s-.1,o[2].s,.2,.25),i=_(e,o[2].s-.1,o[3].s,.2,.3),h=b(f(e,o[3].s-.2,o[3].s+.4)),d=b(f(e,o[5].s,o[5].s+.9)),k=s===0?.6:s===1?w(.6,.12,b(f(e,o[1].s-.1,o[1].s+.3))):s===2?w(.12,.5,b(f(e,o[2].s,o[2].s+.4))):w(.5,1,h),g=w(.9,0,b(f(e,o[3].s+.3,o[4].e))),p=L({time:n,pose:M.rest,arm:{pos:[0,0,0],rot:[.12,-.3,0]},cam:K(s===3?w(1.6,1.2,h):1.6,.1,.06),skin:1,xray:k,bone:1,tendon:1,sheath:1,thick:1-.7*d,friction:.5*(1-d),pain:.85-.6*d,focus:.75,slide:d*Math.sin(n*5)*.03,props:{probe:{vis:Math.max(r,0),lift:0},locator:{vis:Math.max(r,s===3?_(e,o[3].s,o[4].e,.2,.3)*.8:0)},swab:{vis:l,r:.03+.12*b(f(e,o[1].s,o[2].s-.2))},iodine:{vis:Math.max(l,s>=2?.55*(1-h):0),r:.04+.26*b(f(e,o[1].s,o[2].s-.2))},syringe:{vis:i,depth:w(.7,.13,b(f(e,o[2].s,o[2].s+.7))),push:b(f(e,o[2].s+.7,o[3].s-.3))},cloud:{vis:i*b(f(e,o[2].s+.7,o[2].s+1.1))*.8,r:.03+.1*b(f(e,o[2].s+.7,o[3].s-.2))},knife:{vis:h,depth:g,release:d*(1-f(e,a-.3,a))},ring:{vis:d>.01?(.5+.5*Math.sin(n*14))*_(e,o[5].s,a,.1,.3):0,r:d}}});return{views:j(p),overlay:(m,v)=>{const S=s+(s<3?b(f(e,t[s+1]-.4,t[s+1]))*0:0);k0(m,["定位","消毒","麻醉","松解"],S,1,330),n0(m,190,520,700,400,n,{alpha:r,thick:1,locator:f(e,.2,.5),title:"超声定位 · 示意"});const u=_(e,o[3].s+.3,a,.3,.3);n0(m,620,520,400,240,n,{alpha:u,thick:1-.7*d,knife:b(f(e,o[3].s+.3,o[4].e)),release:d,title:"影像引导"});const A=v.anchor("pain");if(s===0&&H(m,A.x,A.y,A.x-250,A.y+230,"目标区域",f(e,.4,.8),"#ffffff"),s===1&&C(m,540,1300,"皮肤消毒",{icon:"check",color:"#e0a050",alpha:l}),s===2&&C(m,540,1300,"局部麻醉(必要时)",{icon:"dot",color:"#59c8ff",alpha:i}),s===3){const P=v.anchor("knife"),W=v.anchor("tendon"),T=v.anchor("sheath"),B=_(e,o[3].s+.6,o[5].s+.2,.3,.3);H(m,P.x,P.y,P.x-60,P.y-150,"器械位置",B,y.teal,36),H(m,W.x,W.y,W.x+200,W.y+150,"肌腱位置",B,"#ffffff",36),H(m,T.x,T.y,T.x-200,T.y+300,"腱鞘位置",B,y.cyan,36),["精准","有限","局部"].forEach((I,z)=>C(m,290+z*250,1330,I,{color:y.teal,fill:!0,size:50,alpha:f(e,o[5].s+.1+z*.25,o[5].s+.35+z*.25),scale:.8+.2*J(f(e,o[5].s+z*.25,o[5].s+.4+z*.25))})),d>0&&e0(m,.25*_(e,o[5].s,o[5].s+.3,.05,.25),"200,255,240")}}}}function z0(e,a,n){const o=F[8],s=b(f(e,o[1].s,o[2].e)),t={arm:{pos:[0,0,0],rot:[0,.85,.04]},cam:K(1.35,.05,.1,40),skin:.7,xray:1,bone:1,tendon:1,sheath:1,focus:1,time:n},r=L({...t,pose:N(M.rest,e,1,.45,1),thick:1,friction:.95,pain:.95}),l=L({...t,pose:N(M.rest,e,1,w(.45,1,s),1-s),thick:w(1,.12,s),friction:w(.95,0,s),pain:w(.95,.08,s)}),i=.15,h=.62;return{views:[{rect:[0,i,.5,h],state:r,bg:"red"},{rect:[.5,i,.5,h],state:l,bg:s>.5?"clean":"lab"}],overlay:d=>{d.save(),d.fillStyle="#02060d",d.fillRect(0,0,1080,i*1920),d.fillRect(0,(i+h)*1920,1080,1920),d.restore();const k=i*1920+60,g=e<o[1].s?1:.55,p=e>=o[1].s-.1?1:.5;C(d,270,k,"治疗前",{color:y.red,size:48,alpha:g,fill:g>.9}),C(d,810,k,"治疗后示意",{color:y.teal,size:48,alpha:p,fill:p>.9}),d.save();const m=d.createLinearGradient(0,i*1920,0,(i+h)*1920);m.addColorStop(0,"rgba(95,212,255,0)"),m.addColorStop(.5,"rgba(95,212,255,0.9)"),m.addColorStop(1,"rgba(95,212,255,0)"),d.fillStyle=m,d.fillRect(538,i*1920,4,h*1920),d.restore();const v=(i+h)*1920-70;C(d,160,v,"受限",{color:y.red,size:38,icon:"cross",alpha:f(e,.6,1)}),C(d,390,v,"摩擦",{color:y.red,size:38,icon:"warn",alpha:f(e,1,1.4)}),C(d,690,v,"空间改善",{color:y.teal,size:38,icon:"check",alpha:f(e,o[1].s+.3,o[1].s+.7)}),C(d,940,v,"更顺畅",{color:y.teal,size:38,icon:"check",alpha:f(e,o[2].s,o[2].s+.4)}),l0(d,270,1330,80,1,.95,.9,n,"狭窄"),l0(d,810,1330,80,w(1,.12,s),w(.95,0,s),.9,n,"改善")}}}function D0(e,a,n){const s=a/6,t=Math.min(5,Math.floor(e/s)),r=e-t*s,l=["治疗前:活动困难","早期:轻微活动","正常抓握","正常拿杯子","正常使用手机","自然活动"],i=[1,.7,.45,.25,.1,0],h=w(i[t],i[Math.min(5,t+1)],b(f(r,s*.6,s)));let d,k={},g=[0,.6,.04],p={pos:q([0,.5,0],4.3,.05,.1),target:[0,.5,0],fov:35};const m=b(f(r,0,.35));t===0?d=N(M.rest,r,1.4,.3,1):t===1?d=N(M.rest,r,.7,.6):t===2?(d=D(M.open,M.gripBall,m*(.85+.15*Math.sin(r*6))),k={ball:{vis:m}}):t===3?(d=D(M.open,M.cup,m),k={cup:{vis:m}},g=[0,.5,.04+.15*b(f(r,.4,1))]):t===4?(d=D(M.open,M.phone,m),d[17]+=.25*Math.max(0,Math.sin(r*12)),d[19]+=.15*Math.max(0,Math.sin(r*12)),k={phone:{vis:m}},g=[.1,-.25,0],p={pos:q([0,.6,0],4.1,0,.12),target:[0,.6,0],fov:35}):(d=D(M.open,M.rest,.5+.5*Math.sin(r*5)),g=[0,.4+.3*Math.sin(r*2),.04]);const v=L({time:n,pose:d,props:k,arm:{pos:[0,0,0],rot:g},cam:p,pain:h,skin:1});return{views:j(v,t>=3?"clean":"lab"),overlay:(S,u)=>{r<.12&&t>0&&e0(S,.18*(1-r/.12));const A=1300,P=140,W=940;S.save();const T=S.createLinearGradient(P,0,W,0);T.addColorStop(0,y.red),T.addColorStop(.5,y.yellow),T.addColorStop(1,y.green),S.strokeStyle="rgba(255,255,255,0.18)",S.lineWidth=10,S.lineCap="round",S.beginPath(),S.moveTo(P,A),S.lineTo(W,A),S.stroke(),S.strokeStyle=T,S.beginPath(),S.moveTo(P,A),S.lineTo(P+(W-P)*O(e/a),A),S.stroke();for(let B=0;B<6;B++){const R=P+(W-P)*B/5;S.fillStyle=B<=t?"#fff":"rgba(255,255,255,0.3)",S.beginPath(),S.arc(R,A,B===t?16:10,0,7),S.fill()}if(S.restore(),C(S,540,1200,l[t],{color:t===0?y.red:t<2?y.yellow:y.green,size:50,alpha:b(f(r,0,.2)),icon:t===0?"warn":"check"}),h>.3){const B=u.anchor("pain");x(S,B.x,B.y,(h-.3)*.6,n)}S.save(),S.font=`800 30px ${$}`,S.fillStyle="rgba(255,255,255,0.7)",S.textAlign="left",S.fillText("疼痛",P-10,A-34),S.textAlign="right",S.fillText("功能恢复",W+10,A-34),S.restore()}}}function I0(e,a,n){const o=F[10],s=b(f(e,o[1].s+.6,a-.3)),t=K(w(1.4,5.4,s),w(.05,0,s),.1),r={pos:q([0,.45,0],5.4,0,.1),target:[0,.45,0]},l=1-s,i=L({time:n,pose:D(M.rest,M.open,s*.5),arm:{pos:[0,0,0],rot:[0,w(.85,.35,s),.04]},cam:{...t,follow:l,pos:X(r.pos,t.pos,l),target:X(r.target,t.target,l)},skin:1,xray:1-b(f(e,o[2].s,a-.5)),bone:1,tendon:1,sheath:1,thick:w(.7,.1,b(f(e,o[1].s,o[2].s))),pain:.75*(1-b(f(e,o[1].s,o[3].s))),focus:.4*(1-s)});return{views:j(i,e>o[2].s?"clean":"lab"),overlay:h=>{C(h,540,1180,"忍住疼",{icon:"cross",color:y.red,size:54,alpha:_(e,.3,o[1].s+.1),strike:f(e,o[0].s+1.4,o[0].e)}),C(h,540,1110,"找到疼痛原因",{icon:"check",color:y.teal,size:50,alpha:_(e,o[1].s+.1,o[2].s+.1)}),C(h,540,1240,"选择合适方式",{icon:"check",color:y.teal,size:50,alpha:_(e,o[1].s+1.1,o[2].s+.1)});const d=f(e,o[3].s-.1,o[3].s+.4);d>0&&(h.save(),h.globalAlpha=d*.75,h.fillStyle="rgba(2,8,18,0.7)",h.fillRect(0,1e3,1080,330),h.restore(),Q(h,"手越疼,",540,1090,d,"#ffffff",96),Q(h,"越不能只靠硬扛。",540,1230,f(e,o[3].s+.35,o[3].s+.8),y.yellow,96)),C(h,540,960,"记住一句话",{size:40,color:y.cyan,alpha:_(e,o[2].s,a+1,.2,.2)})}}}function O0(e,a,n){const o=L({time:n,pose:D(M.open,M.rest,.5+.5*Math.sin(e*2.4)),arm:{pos:[0,.15,0],rot:[0,.35+.2*Math.sin(e*1.5),.04+.08*Math.sin(e*3)]},cam:{pos:q([0,.7,0],6.2,0,.1),target:[0,.2,0],fov:35}}),s=[["grab","抓"],["pinch","捏"],["twist","拧"],["baby","抱孩子"]];return{views:j(o,"clean"),fade:b(f(e,a-.5,a)),overlay:t=>{const r=b(f(e,.1,.5));t.save(),t.globalAlpha=r,t.fillStyle="rgba(3,12,26,0.86)",t.strokeStyle=y.cyan,t.lineWidth=3,t.beginPath(),t.roundRect(70,980,940,430,36),t.fill(),t.stroke(),t.font=`900 50px ${$}`,t.fillStyle="#fff",t.textAlign="center",t.fillText("评论区告诉我",540,1060),t.font=`800 40px ${$}`,t.fillStyle="#bfe9ff",t.fillText("是抓、捏、拧,还是抱孩子?",540,1125),t.restore(),s.forEach(([l,i],h)=>{const d=f(e,.6+h*.25,1+h*.25),k=200+h*227,g=1265,p=Math.sin(n*4+h)*6;t.save(),t.globalAlpha=d,t.translate(k,g+p);const m=.6+.4*J(d);t.scale(m,m),t.fillStyle="rgba(95,212,255,0.12)",t.strokeStyle=y.cyan,t.lineWidth=3,t.beginPath(),t.arc(0,0,82,0,7),t.fill(),t.stroke(),t.restore(),U(t,l,k,g-16+p,70,"#fff",d),t.save(),t.globalAlpha=d,t.font=`900 34px ${$}`,t.fillStyle="#fff",t.textAlign="center",t.fillText(i,k,g+50+p),t.restore()}),U(t,"comment",540,880,120*(1+.06*Math.sin(n*6)),y.yellow,r)}}}const E0=[A0,_0,C0,$0,W0,B0,L0,R0,z0,D0,I0,O0];function H0(e){let a=E.length-1;for(let n=0;n<E.length;n++)if(e<E[n].end){a=n;break}return a}function q0(e){let a=null;for(let n=0;n<Z.length;n++){const o=Z[n],s=Z[n+1],t=s?Math.min(s.start,o.start+o.dur+.5):o.start+o.dur+.8;e>=o.start-.05&&e<t&&(a=o)}return a}function G0(e){e=O(e,0,u0-1e-4);const a=H0(e),n=E[a],o=e-n.start,s=n.end-n.start,t=E0[a](o,s,e),r=t.overlay,l=q0(e);return t.overlay=(i,h)=>{if(r==null||r(i,h),a>0&&o<.2&&e0(i,.22*(1-o/.2),"180,230,255"),v0(i,a+1,n.title,a===0?_(o,.8,3.2,.4,.5):_(o,.05,2.4,.3,.5)),l){const d=Math.min(b(f(e,l.start-.05,l.start+.12)),1);b0(i,l.text,d)}S0(i)},t}function K0(){const e=[],a=l=>E[l].start,n=(l,i)=>a(l)+F[l][i].s;E.forEach((l,i)=>{i>0&&e.push({t:l.start-.15,k:"whoosh",v:.6})}),e.push({t:n(0,0)+1.05,k:"pain",v:1},{t:n(0,1)-.2,k:"whoosh",v:.5},{t:n(0,1)+.7,k:"scan",v:.6}),e.push({t:n(0,1)+1.2,k:"tick"},{t:n(0,1)+1.45,k:"tick"},{t:n(0,1)+1.7,k:"tick"});for(const l of[3,4,5])e.push({t:n(1,l)+.1,k:"pop",v:.7});e.push({t:n(1,5)+.1,k:"pain",v:.6});const o=E[2].end-a(2);for(let l=0;l<3;l++)e.push({t:a(2)+l*o/3+.05,k:"thud",v:.6+l*.2}),e.push({t:a(2)+l*o/3+.35,k:"pain",v:.4+l*.25});const s=a(3)+F[3][1].s-.05,t=(E[3].end-s)/4;for(let l=0;l<4;l++)e.push({t:s+l*t,k:"swipe",v:.7}),e.push({t:s+l*t+.45,k:"pain",v:.35});e.push({t:n(4,1),k:"click",v:.8},{t:n(4,3)+.5,k:"scan",v:.8},{t:n(4,4),k:"tick"},{t:n(4,4)+.3,k:"tick"},{t:n(4,4)+.6,k:"tick"});for(let l=0;l<4;l++)e.push({t:n(5,l)-.1,k:"click",v:.7});e.push({t:n(6,1)+.4,k:"pop",v:.6},{t:n(6,2),k:"click",v:.8},{t:n(6,3)+.9,k:"chime",v:.5});for(let l=0;l<4;l++)e.push({t:a(7)+F[7][[0,1,2,3][l]].s,k:"click",v:.9});e.push({t:n(7,0)+.2,k:"scan",v:.7},{t:n(7,5),k:"release",v:1}),e.push({t:n(8,1)+.3,k:"release",v:.6});const r=E[9].end-a(9);for(let l=1;l<6;l++)e.push({t:a(9)+l*r/6,k:"tick",v:.8});e.push({t:n(10,0)+1.4,k:"pop",v:.6},{t:n(10,3),k:"chime",v:1});for(let l=0;l<4;l++)e.push({t:a(11)+.6+l*.25,k:"pop",v:.5});return e.sort((l,i)=>l.t-i.t)}export{y as C,u0 as D,$ as F,Z as L,E as S,K0 as a,G0 as f,H as l,a0 as r,H0 as s};
assets/state-B_bTBsCz.js ADDED
The diff for this file is too large to render. See raw diff
 
index.html CHANGED
@@ -1 +1,19 @@
1
- <!doctype html><html lang="zh"><meta charset="utf-8"><title>腱鞘炎 3D 科普动画 · 制作中</title><body style="background:#06101f;color:#cfe;font-family:sans-serif;display:grid;place-items:center;height:100vh"><div><h2>腱鞘炎 3D 医学科普动画</h2><p>项目制作中,进度见 README。</p></div></body></html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
6
+
7
+ <title>腱鞘炎 · 3D 医学科普动画</title>
8
+ <meta name="theme-color" content="#04080f" />
9
+ <meta name="description" content="原创 3D 解剖动画:腱鞘炎从疼痛到恢复。浏览器实时渲染,可本地导出 MP4。" />
10
+ <script>
11
+ document.documentElement.classList.add('dark');
12
+ </script>
13
+ <script type="module" crossorigin src="./assets/index-CXVdwQTy.js"></script>
14
+ <link rel="stylesheet" crossorigin href="./assets/index-D8uigG9a.css">
15
+ </head>
16
+ <body>
17
+ <div id="root"></div>
18
+ </body>
19
+ </html>
scripts/build_static.sh ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+ # Static build for the HF Space (relative base, no platform scripts)
3
+ set -e
4
+ cd "$(dirname "$0")/../frontend"
5
+ rm -rf ../dist_static
6
+ BASE_PATH=./ npx vite build --base ./ --outDir ../dist_static
7
+ python3 - <<'P'
8
+ import re
9
+ p='../dist_static/index.html'; s=open(p).read()
10
+ s=re.sub(r'<script type="module">\s*\(function\(\) \{\s*const errors = \[\];.*?</script>\s*','',s,flags=re.S)
11
+ s=re.sub(r'<script>\s*// Fallback: if React fails.*?</script>\s*','',s,flags=re.S)
12
+ s=re.sub(r'<!-- Made by Surf badge -->.*?</a>\s*','',s,flags=re.S)
13
+ s=re.sub(r'<!-- Plaza badge.*?</script>\s*','',s,flags=re.S)
14
+ s=s.replace('<html lang="en">','<html lang="zh-CN">').replace('<title>App</title>','<title>腱鞘炎 · 3D 医学科普动画</title>\n <meta name="theme-color" content="#04080f" />\n <meta name="description" content="原创 3D 解剖动画:腱鞘炎从疼痛到恢复。浏览器实时渲染,可本地导出 MP4。" />')
15
+ s=s.replace('initial-scale=1.0"','initial-scale=1.0, viewport-fit=cover"').replace('<link rel="icon" href="/favicon.ico" />','')
16
+ s=s.replace('<!--ssr-outlet-->','')
17
+ open(p,'w').write(s)
18
+ P
19
+ echo built
scripts/e2e.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio, sys, time
2
+ from playwright.async_api import async_playwright
3
+ URL = "http://localhost:5173/preview/production/ed5ba841-ed53-4eec-a8c5-93237d26b7ab/"
4
+ async def main():
5
+ async with async_playwright() as p:
6
+ b = await p.chromium.launch(args=["--use-gl=angle","--use-angle=swiftshader","--enable-unsafe-swiftshader","--autoplay-policy=no-user-gesture-required"])
7
+ pg = await b.new_page(viewport={"width": 1280, "height": 860}, accept_downloads=True)
8
+ logs=[]
9
+ pg.on("console", lambda m: logs.append(m.type+": "+m.text) if m.type in ("error","warning") else None)
10
+ pg.on("pageerror", lambda e: logs.append("PAGEERROR: "+str(e)))
11
+ await pg.goto(URL); await pg.wait_for_timeout(6000)
12
+ print("play visible", await pg.locator("text=点击播放").count())
13
+ await pg.locator("text=点击播放").click(); await pg.wait_for_timeout(4000)
14
+ print("time", await pg.locator("span.tabular-nums").first.inner_text())
15
+ await pg.screenshot(path="/tmp/e2e_play.png")
16
+ await pg.locator("button:has-text('平台文案')").click(); await pg.wait_for_timeout(500)
17
+ print("copy cards", await pg.locator("text=复制全部").count())
18
+ await pg.locator("button:has-text('封面')").click(); await pg.wait_for_timeout(15000)
19
+ print("covers", await pg.locator("text=PNG").count())
20
+ await pg.screenshot(path="/tmp/e2e_cover.png", full_page=True)
21
+ if len(sys.argv) > 1:
22
+ await pg.locator("button:has-text('导出视频')").click()
23
+ await pg.locator("button:has-text('24')").first.click()
24
+ t0=time.time()
25
+ async with pg.expect_download(timeout=1500000) as dl:
26
+ await pg.locator("button:has-text('导出 MP4')").click()
27
+ while True:
28
+ await pg.wait_for_timeout(20000)
29
+ try: print("prog", (await pg.locator("text=/第 \\d+/").inner_text(timeout=1000)), int(time.time()-t0), flush=True)
30
+ except Exception: break
31
+ d = await dl.value
32
+ await d.save_as("/tmp/out.mp4"); print("saved", int(time.time()-t0))
33
+ fails = await pg.locator("text=导出失败").count(); print("fail", fails)
34
+ for l in logs[:20]: print(l[:400])
35
+ await b.close()
36
+ asyncio.run(main())
scripts/xtest.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Short (3s) MP4 export smoke test in headless Chromium -> /tmp/x.mp4"""
2
+ import asyncio, base64
3
+ from playwright.async_api import async_playwright
4
+ async def main():
5
+ async with async_playwright() as p:
6
+ b = await p.chromium.launch(args=["--use-gl=angle","--use-angle=swiftshader","--enable-unsafe-swiftshader"])
7
+ pg = await b.new_page()
8
+ pg.on("console", lambda m: print(m.text[:300]) if "INFO" in m.text or m.type=="error" else None)
9
+ await pg.goto("http://localhost:5173/preview/production/ed5ba841-ed53-4eec-a8c5-93237d26b7ab/?xdebug=1")
10
+ await pg.wait_for_function("window.__done === true", timeout=400000)
11
+ d = await pg.evaluate("window.__mp4 || ''")
12
+ if d: open("/tmp/x.mp4","wb").write(base64.b64decode(d))
13
+ await b.close()
14
+ asyncio.run(main())
src/App.tsx CHANGED
@@ -1,13 +1,26 @@
1
- import { lazy, Suspense } from 'react'
2
 
3
  const Debug = lazy(() => import('./video/Debug'))
4
  const TDebug = lazy(() => import('./video/TDebug'))
5
  const ADebug = lazy(() => import('./video/ADebug'))
 
 
 
 
 
 
 
 
 
 
6
 
7
  export default function App() {
8
- const q = typeof window !== 'undefined' ? new URLSearchParams(window.location.search) : null
9
- if (q?.has('debug')) return <Suspense fallback={null}><Debug /></Suspense>
10
- if (q?.has('tdebug')) return <Suspense fallback={null}><TDebug /></Suspense>
11
- if (q?.has('adebug')) return <Suspense fallback={null}><ADebug /></Suspense>
12
- return <div style={{ color: '#fff' }}>loading</div>
 
 
 
13
  }
 
1
+ import { lazy, Suspense, useEffect, useState } from 'react'
2
 
3
  const Debug = lazy(() => import('./video/Debug'))
4
  const TDebug = lazy(() => import('./video/TDebug'))
5
  const ADebug = lazy(() => import('./video/ADebug'))
6
+ const XDebug = lazy(() => import('./video/XDebug'))
7
+ const Studio = lazy(() => import('./video/Studio'))
8
+
9
+ function Splash() {
10
+ return (
11
+ <div className="min-h-screen bg-[#04080f] flex items-center justify-center text-cyan-200 text-sm tracking-widest">
12
+ 腱鞘炎 · 3D 医学科普动画 加载中…
13
+ </div>
14
+ )
15
+ }
16
 
17
  export default function App() {
18
+ const [q, setQ] = useState<URLSearchParams | null>(null)
19
+ useEffect(() => { setQ(new URLSearchParams(window.location.search)); document.title = '腱鞘炎 · 3D 医学科普动画'; document.documentElement.lang = 'zh-CN' }, [])
20
+ if (!q) return <Splash />
21
+ if (q.has('debug')) return <Suspense fallback={null}><Debug /></Suspense>
22
+ if (q.has('tdebug')) return <Suspense fallback={null}><TDebug /></Suspense>
23
+ if (q.has('adebug')) return <Suspense fallback={null}><ADebug /></Suspense>
24
+ if (q.has('xdebug')) return <Suspense fallback={null}><XDebug /></Suspense>
25
+ return <Suspense fallback={<Splash />}><Studio /></Suspense>
26
  }
src/video/Studio.tsx ADDED
@@ -0,0 +1,382 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useCallback, useEffect, useRef, useState } from 'react'
2
+ import { Engine } from './engine'
3
+ import { frameAt, DURATION, SHOTS, shotAt } from './scenes'
4
+ import { getSoundtrack } from './audio'
5
+ import { exportMp4, type Fps, type ExportProgress } from './exporter'
6
+ import { COPY, charLen, bodyCount, bodyWithTopics, topicText, type PlatformCopy } from './copy'
7
+ import { COVERS, drawCover, coverBlob } from './covers'
8
+ import { Play, Pause, Maximize, Minimize, Volume2, VolumeX, Download, Copy, Check, Film, FileText, Image as ImageIcon, X, RotateCcw } from 'lucide-react'
9
+
10
+ const fmt = (s: number) => `${Math.floor(s / 60)}:${String(Math.floor(s % 60)).padStart(2, '0')}`
11
+
12
+ function download(blob: Blob, name: string) {
13
+ const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = name
14
+ document.body.appendChild(a); a.click(); a.remove()
15
+ setTimeout(() => URL.revokeObjectURL(a.href), 60000)
16
+ }
17
+
18
+ /* ============================== Player ============================== */
19
+ function Player() {
20
+ const wrapRef = useRef<HTMLDivElement>(null)
21
+ const canvasRef = useRef<HTMLCanvasElement>(null)
22
+ const engRef = useRef<Engine | null>(null)
23
+ const st = useRef({ t: 0, playing: false, startAt: 0, startT: 0, dirty: true })
24
+ const audio = useRef<{ ctx: AudioContext | null; buf: AudioBuffer | null; src: AudioBufferSourceNode | null; gain: GainNode | null }>({ ctx: null, buf: null, src: null, gain: null })
25
+ const [t, setT] = useState(0)
26
+ const [playing, setPlaying] = useState(false)
27
+ const [muted, setMuted] = useState(false)
28
+ const [full, setFull] = useState(false)
29
+ const [load, setLoad] = useState<{ p: number; label: string } | null>({ p: 0, label: '加载音频' })
30
+ const [err, setErr] = useState<string | null>(null)
31
+ const [started, setStarted] = useState(false)
32
+
33
+ useEffect(() => {
34
+ getSoundtrack((p, label) => setLoad({ p, label }))
35
+ .then(b => { audio.current.buf = b; setLoad(null) })
36
+ .catch(e => { setErr('音频加载失败:' + (e as Error).message); setLoad(null) })
37
+ }, [])
38
+
39
+ // render loop
40
+ useEffect(() => {
41
+ const c = canvasRef.current!
42
+ const small = Math.min(window.innerWidth, window.innerHeight) < 600
43
+ const W = small ? 540 : 720, H = small ? 960 : 1280
44
+ c.width = W; c.height = H
45
+ let eng: Engine
46
+ try { eng = new Engine(); eng.setSize(W, H); engRef.current = eng } catch (e) { setErr('当前浏览器不支持 WebGL:' + (e as Error).message); return }
47
+ const ctx = c.getContext('2d', { alpha: false })!
48
+ let raf = 0, lastUi = 0
49
+ const loop = () => {
50
+ raf = requestAnimationFrame(loop)
51
+ const s = st.current
52
+ if (s.playing) {
53
+ const a = audio.current.ctx
54
+ s.t = s.startT + (a ? a.currentTime - s.startAt : (performance.now() / 1000 - s.startAt))
55
+ if (s.t >= DURATION) { s.t = DURATION; stopInternal(); setPlaying(false) }
56
+ s.dirty = true
57
+ }
58
+ if (s.dirty) {
59
+ s.dirty = false
60
+ eng.render(frameAt(s.t), ctx, s.t)
61
+ const now = performance.now()
62
+ if (now - lastUi > 100 || !s.playing) { lastUi = now; setT(s.t) }
63
+ }
64
+ }
65
+ loop()
66
+ return () => { cancelAnimationFrame(raf); eng.renderer.dispose() }
67
+ // eslint-disable-next-line react-hooks/exhaustive-deps
68
+ }, [])
69
+
70
+ const stopInternal = () => {
71
+ const a = audio.current
72
+ try { a.src?.stop() } catch { /* already stopped */ }
73
+ a.src = null
74
+ st.current.playing = false
75
+ }
76
+
77
+ const play = useCallback(async () => {
78
+ const a = audio.current, s = st.current
79
+ if (s.t >= DURATION - 0.05) s.t = 0
80
+ if (!a.ctx) {
81
+ a.ctx = new AudioContext({ sampleRate: 48000 })
82
+ a.gain = a.ctx.createGain(); a.gain.connect(a.ctx.destination)
83
+ }
84
+ await a.ctx.resume()
85
+ a.gain!.gain.value = muted ? 0 : 1
86
+ if (a.buf) {
87
+ const src = a.ctx.createBufferSource(); src.buffer = a.buf; src.connect(a.gain!)
88
+ src.start(a.ctx.currentTime + 0.03, Math.min(s.t, a.buf.duration - 0.01))
89
+ a.src = src
90
+ s.startAt = a.ctx.currentTime + 0.03
91
+ } else s.startAt = a.ctx.currentTime
92
+ s.startT = s.t; s.playing = true
93
+ setPlaying(true); setStarted(true)
94
+ }, [muted])
95
+
96
+ const pause = useCallback(() => { stopInternal(); setPlaying(false) }, [])
97
+ const toggle = () => (st.current.playing ? pause() : play())
98
+
99
+ const seek = (v: number) => {
100
+ const was = st.current.playing
101
+ if (was) stopInternal()
102
+ st.current.t = v; st.current.dirty = true; setT(v)
103
+ if (was) play()
104
+ }
105
+
106
+ useEffect(() => { if (audio.current.gain) audio.current.gain.gain.value = muted ? 0 : 1 }, [muted])
107
+
108
+ const toggleFull = async () => {
109
+ const el = wrapRef.current!
110
+ if (document.fullscreenElement) { await document.exitFullscreen(); return }
111
+ if (full) { setFull(false); return }
112
+ if (el.requestFullscreen) { try { await el.requestFullscreen(); return } catch { /* fall through */ } }
113
+ setFull(true) // iOS fallback: CSS theater
114
+ }
115
+ useEffect(() => {
116
+ const h = () => setFull(!!document.fullscreenElement)
117
+ document.addEventListener('fullscreenchange', h)
118
+ return () => document.removeEventListener('fullscreenchange', h)
119
+ }, [])
120
+
121
+ useEffect(() => {
122
+ const k = (e: KeyboardEvent) => {
123
+ if ((e.target as HTMLElement)?.tagName === 'TEXTAREA' || (e.target as HTMLElement)?.tagName === 'INPUT') return
124
+ if (e.code === 'Space') { e.preventDefault(); toggle() }
125
+ if (e.code === 'ArrowRight') seek(Math.min(DURATION, st.current.t + 5))
126
+ if (e.code === 'ArrowLeft') seek(Math.max(0, st.current.t - 5))
127
+ }
128
+ window.addEventListener('keydown', k); return () => window.removeEventListener('keydown', k)
129
+ })
130
+
131
+ const cur = shotAt(t)
132
+ return (
133
+ <div ref={wrapRef}
134
+ className={full ? 'fixed inset-0 z-50 bg-black flex items-center justify-center' : 'relative w-full flex items-center justify-center'}>
135
+ <div className="relative bg-black overflow-hidden shadow-[0_0_80px_rgba(60,180,255,0.15)] sm:rounded-2xl"
136
+ style={{ aspectRatio: '9 / 16', height: full ? '100%' : 'min(100svh - 24px, calc(100vw * 16 / 9))', maxWidth: '100%' }}>
137
+ <canvas ref={canvasRef} className="w-full h-full block cursor-pointer" onClick={toggle} />
138
+ {!playing && (
139
+ <button onClick={toggle} className="absolute inset-0 flex flex-col items-center justify-center gap-4 bg-black/25 hover:bg-black/15 transition">
140
+ <span className="w-20 h-20 rounded-full bg-white/90 flex items-center justify-center shadow-2xl">
141
+ <Play className="w-9 h-9 text-slate-900 ml-1" fill="currentColor" />
142
+ </span>
143
+ {!started && <span className="text-white/90 text-sm font-semibold tracking-wide px-3 py-1 rounded-full bg-black/40">点击播放 · 有声音</span>}
144
+ {load && <span className="text-cyan-200 text-xs">{load.label} {Math.round(load.p * 100)}%</span>}
145
+ </button>
146
+ )}
147
+ {err && <div className="absolute top-3 left-3 right-3 text-xs bg-red-900/80 text-red-100 rounded px-3 py-2">{err}</div>}
148
+ {/* controls */}
149
+ <div className={`absolute left-0 right-0 bottom-0 px-3 ${full ? 'pb-3' : 'pb-12 sm:pb-3'} pt-8 bg-gradient-to-t from-black/80 to-transparent`}
150
+ onClick={e => e.stopPropagation()}>
151
+ <div className="relative h-5 flex items-center group">
152
+ <div className="absolute inset-x-0 h-1 rounded bg-white/20 top-1/2 -translate-y-1/2" />
153
+ {SHOTS.map(s => <div key={s.index} className="absolute w-px h-2 bg-white/50 top-1/2 -translate-y-1/2" style={{ left: `${(s.start / DURATION) * 100}%` }} />)}
154
+ <div className="absolute h-1 rounded bg-cyan-400 top-1/2 -translate-y-1/2 left-0" style={{ width: `${(t / DURATION) * 100}%` }} />
155
+ <input type="range" min={0} max={DURATION} step={0.01} value={t} onChange={e => seek(+e.target.value)}
156
+ className="absolute inset-0 w-full opacity-0 cursor-pointer" aria-label="进度" />
157
+ </div>
158
+ <div className="flex items-center gap-3 text-white text-xs mt-1">
159
+ <button onClick={toggle} aria-label="播放/暂停">{playing ? <Pause className="w-5 h-5" /> : <Play className="w-5 h-5" />}</button>
160
+ <span className="tabular-nums opacity-80">{fmt(t)} / {fmt(DURATION)}</span>
161
+ <span className="truncate opacity-70 flex-1">{String(cur + 1).padStart(2, '0')} · {SHOTS[cur].title}</span>
162
+ <button onClick={() => setMuted(m => !m)} aria-label="静音">{muted ? <VolumeX className="w-5 h-5" /> : <Volume2 className="w-5 h-5" />}</button>
163
+ <button onClick={toggleFull} aria-label="全屏">{full ? <Minimize className="w-5 h-5" /> : <Maximize className="w-5 h-5" />}</button>
164
+ </div>
165
+ </div>
166
+ </div>
167
+ </div>
168
+ )
169
+ }
170
+
171
+ /* ============================== Export ============================== */
172
+ function ExportPanel() {
173
+ const [fps, setFps] = useState<Fps>(30)
174
+ const [prog, setProg] = useState<ExportProgress | null>(null)
175
+ const [busy, setBusy] = useState(false)
176
+ const [result, setResult] = useState<{ blob: Blob; fps: number; sec: number } | null>(null)
177
+ const [err, setErr] = useState<string | null>(null)
178
+ const ab = useRef<AbortController | null>(null)
179
+ const supported = typeof window !== 'undefined' && 'VideoEncoder' in window
180
+
181
+ const start = async () => {
182
+ setErr(null); setResult(null); setBusy(true)
183
+ ab.current = new AbortController()
184
+ const t0 = performance.now()
185
+ try {
186
+ const blob = await exportMp4(fps, setProg, ab.current.signal)
187
+ setResult({ blob, fps, sec: (performance.now() - t0) / 1000 })
188
+ download(blob, `腱鞘炎3D科普_1080x1920_${fps}fps.mp4`)
189
+ } catch (e) {
190
+ if ((e as Error).name !== 'AbortError') setErr((e as Error).message)
191
+ } finally { setBusy(false); setProg(null) }
192
+ }
193
+
194
+ const sizeMb = (fps === 60 ? 16 : fps === 30 ? 12 : 10) * DURATION / 8 + 2
195
+ return (
196
+ <div className="space-y-5">
197
+ <div>
198
+ <div className="text-sm text-slate-400 mb-2">帧率</div>
199
+ <div className="grid grid-cols-3 gap-2">
200
+ {([24, 30, 60] as Fps[]).map(f => (
201
+ <button key={f} disabled={busy} onClick={() => setFps(f)}
202
+ className={`rounded-xl py-3 border text-center transition ${fps === f ? 'border-cyan-400 bg-cyan-400/10 text-white' : 'border-white/10 text-slate-300 hover:border-white/30'}`}>
203
+ <div className="text-xl font-black">{f}<span className="text-xs font-semibold ml-0.5">fps</span></div>
204
+ <div className="text-[11px] opacity-60">{f === 24 ? '电影感 · 体积小' : f === 30 ? '平台推荐' : '最流畅'}</div>
205
+ </button>
206
+ ))}
207
+ </div>
208
+ </div>
209
+ <div className="text-xs text-slate-400 leading-relaxed bg-white/5 rounded-xl p-3">
210
+ 输出:1080×1920 竖屏 MP4 · H.264 + AAC 立体声 · 时长 {DURATION.toFixed(1)} 秒 · 预计约 {Math.round(sizeMb)} MB<br />
211
+ 全程在你的浏览器本地逐帧渲染,不上传任何数据。导出时请保持此页面在前台。
212
+ </div>
213
+ {!supported && <div className="text-xs text-amber-300">当前浏览器不支持本地视频编码,请使用电脑版 Chrome / Edge 最新版。</div>}
214
+ {busy ? (
215
+ <div className="space-y-2">
216
+ <div className="flex justify-between text-sm"><span className="text-cyan-300">{prog?.phase ?? '准备中'}</span><span className="tabular-nums">{Math.round((prog?.p ?? 0) * 100)}%</span></div>
217
+ <div className="h-2 rounded bg-white/10 overflow-hidden"><div className="h-full bg-gradient-to-r from-cyan-400 to-emerald-400 transition-[width]" style={{ width: `${(prog?.p ?? 0) * 100}%` }} /></div>
218
+ <div className="flex justify-between text-xs text-slate-400">
219
+ <span>{prog?.frame ? `第 ${prog.frame} / ${prog.total} 帧` : ''}</span>
220
+ <span>{prog?.eta != null ? `剩余约 ${fmt(prog.eta)}` : ''}</span>
221
+ </div>
222
+ <button onClick={() => ab.current?.abort()} className="w-full mt-2 rounded-xl py-2.5 border border-white/15 text-slate-200 flex items-center justify-center gap-2 hover:bg-white/5"><X className="w-4 h-4" />取消导出</button>
223
+ </div>
224
+ ) : (
225
+ <button onClick={start} disabled={!supported}
226
+ className="w-full rounded-xl py-3.5 font-bold text-slate-950 bg-gradient-to-r from-cyan-300 to-emerald-300 hover:brightness-110 disabled:opacity-40 flex items-center justify-center gap-2">
227
+ <Download className="w-5 h-5" />导出 MP4({fps}fps)
228
+ </button>
229
+ )}
230
+ {result && (
231
+ <div className="rounded-xl bg-emerald-500/10 border border-emerald-400/30 p-3 text-sm flex items-center gap-3">
232
+ <Check className="w-5 h-5 text-emerald-300 shrink-0" />
233
+ <div className="flex-1">已导出 {result.fps}fps · {(result.blob.size / 1048576).toFixed(1)} MB · 用时 {fmt(result.sec)}</div>
234
+ <button onClick={() => download(result.blob, `腱鞘炎3D科普_1080x1920_${result.fps}fps.mp4`)} className="text-emerald-300 underline">再次下载</button>
235
+ </div>
236
+ )}
237
+ {err && <div className="text-sm text-red-300 bg-red-500/10 rounded-xl p-3">导出失败:{err}</div>}
238
+ </div>
239
+ )
240
+ }
241
+
242
+ /* ============================== Copy ============================== */
243
+ function CopyBtn({ text, label = '复制' }: { text: string; label?: string }) {
244
+ const [ok, setOk] = useState(false)
245
+ const go = async () => {
246
+ try { await navigator.clipboard.writeText(text) } catch {
247
+ const ta = document.createElement('textarea'); ta.value = text; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); ta.remove()
248
+ }
249
+ setOk(true); setTimeout(() => setOk(false), 1400)
250
+ }
251
+ return (
252
+ <button onClick={go} className={`shrink-0 text-xs px-2.5 py-1 rounded-lg border flex items-center gap-1 transition ${ok ? 'border-emerald-400 text-emerald-300' : 'border-white/15 text-slate-300 hover:border-white/40'}`}>
253
+ {ok ? <Check className="w-3.5 h-3.5" /> : <Copy className="w-3.5 h-3.5" />}{ok ? '已复制' : label}
254
+ </button>
255
+ )
256
+ }
257
+
258
+ function Count({ n, max }: { n: number; max: number | null }) {
259
+ const ok = max == null || n <= max
260
+ return <span className={`text-[11px] tabular-nums px-1.5 py-0.5 rounded ${ok ? 'bg-emerald-500/15 text-emerald-300' : 'bg-red-500/20 text-red-300'}`}>{n}{max != null ? ` / ${max}` : ' 字'}</span>
261
+ }
262
+
263
+ function CopyCard({ p }: { p: PlatformCopy }) {
264
+ const all = `${p.title}\n\n${bodyWithTopics(p)}`
265
+ return (
266
+ <div className="rounded-2xl border border-white/10 bg-white/[0.03] overflow-hidden">
267
+ <div className="flex items-center gap-2 px-4 py-3 border-b border-white/10">
268
+ <span className="w-2.5 h-2.5 rounded-full" style={{ background: p.color }} />
269
+ <span className="font-bold">{p.name}</span>
270
+ <span className="text-[11px] text-slate-500 flex-1 truncate">{p.tips}</span>
271
+ <CopyBtn text={all} label="复制全部" />
272
+ </div>
273
+ <div className="p-4 space-y-4 text-sm">
274
+ <div>
275
+ <div className="flex items-center gap-2 mb-1.5"><span className="text-slate-400 text-xs">标题</span><Count n={charLen(p.title)} max={p.limits.title} /><span className="flex-1" /><CopyBtn text={p.title} /></div>
276
+ <div className="font-bold text-white text-base leading-snug">{p.title}</div>
277
+ </div>
278
+ <div>
279
+ <div className="flex items-center gap-2 mb-1.5"><span className="text-slate-400 text-xs">话题</span><Count n={p.topics.length} max={p.limits.topics} /><span className="text-[11px] text-slate-500">个</span><span className="flex-1" /><CopyBtn text={topicText(p)} /></div>
280
+ <div className="flex flex-wrap gap-1.5">{p.topics.map(tp => <span key={tp} className="text-xs px-2 py-0.5 rounded-full bg-cyan-400/10 text-cyan-200">#{tp}</span>)}</div>
281
+ </div>
282
+ <div>
283
+ <div className="flex items-center gap-2 mb-1.5">
284
+ <span className="text-slate-400 text-xs">正文{p.limits.bodyIncludesTopics && p.limits.body ? '(含话题)' : ''}</span>
285
+ <Count n={bodyCount(p)} max={p.limits.body} /><span className="flex-1" />
286
+ <CopyBtn text={p.limits.bodyIncludesTopics ? bodyWithTopics(p) : p.body} />
287
+ </div>
288
+ <pre className="whitespace-pre-wrap font-sans text-slate-300 text-[13px] leading-relaxed max-h-64 overflow-auto bg-black/30 rounded-xl p-3">{p.limits.bodyIncludesTopics ? bodyWithTopics(p) : p.body}</pre>
289
+ </div>
290
+ </div>
291
+ </div>
292
+ )
293
+ }
294
+
295
+ /* ============================== Covers ============================== */
296
+ function CoverPanel() {
297
+ const refs = useRef<Record<string, HTMLCanvasElement | null>>({})
298
+ const [ready, setReady] = useState(0)
299
+ useEffect(() => {
300
+ let alive = true, i = 0
301
+ const next = () => {
302
+ if (!alive || i >= COVERS.length) return
303
+ const s = COVERS[i]; const c = refs.current[s.key]
304
+ if (c) { try { drawCover(s, c) } catch (e) { console.error(e) } }
305
+ i++; setReady(i); setTimeout(next, 30)
306
+ }
307
+ setTimeout(next, 50)
308
+ return () => { alive = false }
309
+ }, [])
310
+ const dl = async (k: string) => { const s = COVERS.find(c => c.key === k)!; download(await coverBlob(s), `封面_${s.platform}_${s.label.split(' ')[0].replace(':', 'x')}_${s.w}x${s.h}.png`) }
311
+ const dlAll = async () => { for (const s of COVERS) { await dl(s.key); await new Promise(r => setTimeout(r, 350)) } }
312
+ const groups = [...new Set(COVERS.map(c => c.platform))]
313
+ return (
314
+ <div className="space-y-5">
315
+ <div className="flex items-center gap-3">
316
+ <div className="text-xs text-slate-400 flex-1">由动画真实画面实时渲染,PNG 原尺寸下载。{ready < COVERS.length ? `生成中 ${ready}/${COVERS.length}…` : ''}</div>
317
+ <button onClick={dlAll} className="text-xs px-3 py-1.5 rounded-lg bg-cyan-400/15 text-cyan-200 border border-cyan-400/30 flex items-center gap-1"><Download className="w-3.5 h-3.5" />全部下载</button>
318
+ </div>
319
+ {groups.map(g => (
320
+ <div key={g}>
321
+ <div className="text-sm font-bold mb-2">{g}</div>
322
+ <div className="grid grid-cols-2 gap-3 items-start">
323
+ {COVERS.filter(c => c.platform === g).map(s => (
324
+ <div key={s.key} className="rounded-xl overflow-hidden border border-white/10 bg-black/40">
325
+ <canvas ref={el => { refs.current[s.key] = el }} className="w-full block" style={{ aspectRatio: `${s.w} / ${s.h}` }} />
326
+ <div className="flex items-center justify-between px-2.5 py-2 text-xs">
327
+ <span className="text-slate-300">{s.label} <span className="text-slate-500">{s.w}×{s.h}</span></span>
328
+ <button onClick={() => dl(s.key)} className="text-cyan-300 flex items-center gap-1"><Download className="w-3.5 h-3.5" />PNG</button>
329
+ </div>
330
+ </div>
331
+ ))}
332
+ </div>
333
+ </div>
334
+ ))}
335
+ </div>
336
+ )
337
+ }
338
+
339
+ /* ============================== Studio ============================== */
340
+ export default function Studio() {
341
+ const [tab, setTab] = useState<'export' | 'copy' | 'cover'>('export')
342
+ const tabs = [
343
+ { k: 'export' as const, n: '导出视频', i: Film },
344
+ { k: 'copy' as const, n: '平台文案', i: FileText },
345
+ { k: 'cover' as const, n: '封面', i: ImageIcon },
346
+ ]
347
+ return (
348
+ <div className="min-h-screen bg-[#04080f] text-slate-100" style={{ backgroundImage: 'radial-gradient(1200px 600px at 20% -10%, rgba(40,140,255,0.12), transparent), radial-gradient(800px 500px at 100% 100%, rgba(255,60,60,0.06), transparent)' }}>
349
+ <div className="mx-auto max-w-6xl lg:flex lg:gap-8 lg:p-6 lg:items-start">
350
+ <div className="lg:sticky lg:top-6 sm:pt-3 lg:pt-0 lg:w-auto">
351
+ <Player />
352
+ </div>
353
+ <div className="flex-1 min-w-0 px-4 py-6 lg:px-0 lg:py-0">
354
+ <div className="mb-5">
355
+ <div className="text-[11px] tracking-[0.25em] text-cyan-300/80 font-bold">ORIGINAL 3D MEDICAL ANIMATION</div>
356
+ <h1 className="text-2xl lg:text-3xl font-black mt-1">腱鞘炎 · 从疼痛到恢复</h1>
357
+ <p className="text-sm text-slate-400 mt-1.5">实时 3D 解剖动画 · 竖屏 9:16 · {DURATION.toFixed(0)} 秒 · 旁白 + 配乐 + 音效</p>
358
+ <div className="flex flex-wrap gap-1.5 mt-3">
359
+ {['疼痛', '定位', '处理', '松解', '恢复'].map((s, i) => (
360
+ <span key={s} className={`text-xs px-2.5 py-1 rounded-full ${i === 0 ? 'bg-red-500/20 text-red-200' : i === 4 ? 'bg-emerald-500/20 text-emerald-200' : 'bg-white/5 text-slate-300'}`}>{s}</span>
361
+ ))}
362
+ </div>
363
+ </div>
364
+ <div className="flex gap-1 p-1 rounded-xl bg-white/5 mb-5 sticky top-0 z-10 backdrop-blur">
365
+ {tabs.map(({ k, n, i: I }) => (
366
+ <button key={k} onClick={() => setTab(k)} className={`flex-1 py-2 rounded-lg text-sm font-semibold flex items-center justify-center gap-1.5 transition ${tab === k ? 'bg-white/10 text-white' : 'text-slate-400 hover:text-slate-200'}`}>
367
+ <I className="w-4 h-4" />{n}
368
+ </button>
369
+ ))}
370
+ </div>
371
+ {tab === 'export' && <ExportPanel />}
372
+ {tab === 'copy' && <div className="space-y-4">{COPY.map(p => <CopyCard key={p.key} p={p} />)}</div>}
373
+ {tab === 'cover' && <CoverPanel />}
374
+ <div className="text-[11px] text-slate-500 mt-8 leading-relaxed flex gap-2">
375
+ <RotateCcw className="w-3.5 h-3.5 shrink-0 mt-0.5" />
376
+ 所有模型、器械、动画、配乐与音效均为原创程序化生成;内容仅供健康科普,不替代医生面诊。
377
+ </div>
378
+ </div>
379
+ </div>
380
+ </div>
381
+ )
382
+ }
src/video/XDebug.tsx ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useEffect } from 'react'
2
+ import { exportMp4 } from './exporter'
3
+
4
+ export default function XDebug() {
5
+ useEffect(() => {
6
+ const w = window as unknown as { __done: boolean; __mp4: string }
7
+ exportMp4(24, () => {}, new AbortController().signal, 3).then(async b => {
8
+ const u8 = new Uint8Array(await b.arrayBuffer()); let bin = ''
9
+ for (let i = 0; i < u8.length; i += 0x8000) bin += String.fromCharCode(...u8.subarray(i, i + 0x8000))
10
+ w.__mp4 = btoa(bin); console.log('INFO mp4 bytes ' + b.size)
11
+ }).catch(e => console.log('INFO ERROR ' + e)).finally(() => { w.__done = true })
12
+ }, [])
13
+ return null
14
+ }
src/video/copy.ts ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** Platform publishing copy. Limits checked live in the UI (and by scripts). */
2
+ export interface PlatformCopy {
3
+ key: string
4
+ name: string
5
+ color: string
6
+ limits: { title: number; topics: number | null; body: number | null; bodyIncludesTopics: boolean }
7
+ title: string
8
+ body: string
9
+ topics: string[]
10
+ tips: string
11
+ }
12
+
13
+ /** Character count as platforms see it: every code point = 1 (emoji/汉字/字母 all 1). */
14
+ export const charLen = (s: string) => Array.from(s).length
15
+
16
+ export const topicText = (p: PlatformCopy) => p.topics.map(t => '#' + t).join(' ')
17
+
18
+ export function bodyWithTopics(p: PlatformCopy) {
19
+ return p.topics.length ? p.body + '\n\n' + topicText(p) : p.body
20
+ }
21
+ export function bodyCount(p: PlatformCopy) {
22
+ return charLen(p.limits.bodyIncludesTopics ? bodyWithTopics(p) : p.body)
23
+ }
24
+
25
+ export const COPY: PlatformCopy[] = [
26
+ {
27
+ key: 'xhs', name: '小红书', color: '#ff2442',
28
+ limits: { title: 20, topics: 10, body: 1000, bodyIncludesTopics: true },
29
+ title: '拇指一动就疼?3D看懂腱鞘炎',
30
+ body: `抱娃、刷手机、拧瓶盖……
31
+ 手腕靠拇指这一侧,一用力就像被“卡住”一样疼?
32
+
33
+ 做了一条 3D 解剖动画,把皮肤“变透明”,直接看里面发生了什么👇
34
+
35
+ 🔹 腱鞘=包住肌腱的“小通道”
36
+ 正常时肌腱在里面顺畅滑动;反复用力后,腱鞘增厚、通道变窄,肌腱一滑就摩擦 → 疼
37
+
38
+ 🔹 为什么一动就疼
39
+ 抓、捏、拧这些动作,都会让肌腱在狭窄处来回拉扯
40
+
41
+ 🔹 谁更容易中招
42
+ 宝妈抱娃|长时间用手机|键盘鼠标党|经常用力的手工活
43
+
44
+ 🔹 处理顺序很重要
45
+ 先判断:疼在哪、哪个动作最明显、是否反复发作
46
+ 再选择:休息制动、护具、理疗、药物、局部注射等
47
+ 反复发作、保守效果不好时,部分情况会考虑小针刀等微创松解
48
+
49
+ 🔹 小针刀到底在干什么
50
+ 不是“切开手腕”,而是:定位 → 消毒 → 局部麻醉 → 在影像引导下对狭窄处做“精准、有限、局部”的松解
51
+ 目标只有一个:让肌腱重新顺畅滑动
52
+
53
+ 🔹 恢复期
54
+ 疼痛减轻 → 活动改善 → 逐步回到抱娃、打字、拿东西
55
+ 别一好就猛用手,循序渐进最重要
56
+
57
+ 📌 一句话记住:腱鞘炎的核心不是“手腕疼”,而是肌腱在狭窄的腱鞘里滑不动。
58
+
59
+ 你是抱娃疼、手机疼,还是打字疼?评论区说说你最疼的那个动作👇
60
+
61
+ ⚠️ 原创 3D 示意动画,仅作健康科普,不能替代面诊。具体是否适合某种治疗,请由专业医生评估。`,
62
+ topics: ['腱鞘炎', '妈妈手', '手腕疼', '拇指疼', '健康科普', '3D动画', '医学科普', '小针刀', '打工人', '护手'],
63
+ tips: '建议封面用 3:4 竖版;标题≤20字,话题已计入正文 1000 字。',
64
+ },
65
+ {
66
+ key: 'douyin', name: '抖音', color: '#25f4ee',
67
+ limits: { title: 30, topics: 5, body: 1000, bodyIncludesTopics: true },
68
+ title: '手腕拇指侧一用力就疼?3D动画带你看清腱鞘炎',
69
+ body: `抱娃、刷手机、拧瓶盖,拇指一侧一用力就疼?
70
+ 90 秒 3D 解剖动画,把皮肤变透明:
71
+ ✅ 腱鞘增厚 → 空间变窄 → 肌腱一滑就摩擦
72
+ ✅ 先判断,再处理:休息、护具、理疗、药物、注射……
73
+ ✅ 反复发作时,小针刀做的是“精准、有限、局部”的松解
74
+ ✅ 目标只有一个:让肌腱重新顺畅滑动
75
+ 记住:腱鞘炎不是简单的手腕疼,而是肌腱在狭窄的腱鞘里滑不动。
76
+ 你最疼的是哪个动作?评论区告诉我👇
77
+ (原创3D示意动画,仅供科普,不替代面诊)`,
78
+ topics: ['腱鞘炎', '妈妈手', '手腕疼', '健康科普', '3D医学动画'],
79
+ tips: '竖屏 9:16 原生发布;封面准备 3:4 与 4:3 两版。',
80
+ },
81
+ {
82
+ key: 'bili', name: 'B站', color: '#00aeec',
83
+ limits: { title: 80, topics: 10, body: 2000, bodyIncludesTopics: false },
84
+ title: '【3D解剖动画】拇指一动就疼?90秒看懂腱鞘炎:为什么疼、怎么判断、小针刀如何精准松解',
85
+ body: `这是一条原创 3D 医学科普动画,用一只“可以透视”的手,把腱鞘炎从疼痛到恢复的完整过程讲清楚。
86
+
87
+ 【时间轴】
88
+ 00:00 疼痛开始:拇指一侧,一用力就疼
89
+ 00:06 腱鞘炎到底发生了什么:腱鞘=肌腱的“小通道”,增厚 → 变窄 → 摩擦
90
+ 00:15 为什么一动就疼:抓、捏、拧
91
+ 00:20 哪些人更容易出现:抱娃、手机、键盘鼠标、反复用力
92
+ 00:26 不要一上来就直接治疗:先定位、先判断
93
+ 00:34 常见治疗方法:休息制动、护具、理疗、药物、注射
94
+ 00:44 重点进入小针刀:适合什么情况、解决什么问题
95
+ 00:51 小针刀治疗过程:定位 → 消毒 → 麻醉 → 精准松解
96
+ 01:01 松解前后对比:狭窄 vs 顺畅
97
+ 01:07 从疼痛到恢复:疼痛减轻、活动改善、回归日常
98
+ 01:14 最后的记忆点
99
+
100
+ 【一句话总结】
101
+ 腱鞘炎的核心不是“手腕疼”,而是肌腱���狭窄的腱鞘里滑不动。处理的思路是:先判断,再选择;即使做松解,也强调精准、有限、局部,目标是让肌腱重新顺畅滑动。
102
+
103
+ 【制作说明】
104
+ · 全部 3D 模型、器械、动画、配乐与音效均为原创程序化生成;
105
+ · 片中器械为示意模型,不代表任何品牌产品;
106
+ · 动画为原理示意,比例与操作细节经过简化,不能作为操作指导。
107
+
108
+ ⚠️ 本视频仅作健康科普,不替代面诊。是否适合任何一种治疗,请由专业医生面诊评估。
109
+
110
+ 你最疼的是哪个动作?抱娃、刷手机、拧瓶盖还是打字?弹幕/评论区告诉我~`,
111
+ topics: ['腱鞘炎', '妈妈手', '医学科普', '3D动画', '人体解剖', '健康', '手腕疼', '科普', '小针刀', '原创动画'],
112
+ tips: '建议投稿分区:知识 › 医学健康;个人空间封面使用 16:9,投稿封面使用 4:3。',
113
+ },
114
+ {
115
+ key: 'sph', name: '视频号', color: '#fa9d3b',
116
+ limits: { title: 16, topics: null, body: null, bodyIncludesTopics: true },
117
+ title: '拇指一动就疼?看懂腱鞘炎',
118
+ body: `抱娃、刷手机、拧瓶盖,拇指一侧一用力就疼?
119
+ 这条 3D 解剖动画,带你看清腱鞘炎从疼痛到恢复的全过程:
120
+
121
+ 1️⃣ 腱鞘增厚、通道变窄,肌腱一滑就摩擦
122
+ 2️⃣ 抓、捏、拧,都会加重拉扯
123
+ 3️⃣ 先判断,再处理:休息、护具、理疗、药物、注射
124
+ 4️⃣ 反复发作时,小针刀强调“精准、有限、局部”的松解
125
+ 5️⃣ 目标:让肌腱重新顺畅滑动,慢慢回归日常
126
+
127
+ 记住一句话:腱鞘炎的核心,是肌腱在狭窄的腱鞘里滑不动。
128
+
129
+ 转给家里经常抱娃、天天看手机的人👇
130
+ (原创3D示意动画,仅供科普,不替代面诊)`,
131
+ topics: ['腱鞘炎', '妈妈手', '手腕疼', '拇指疼', '健康科普', '医学科普', '3D动画', '中老年健康', '宝妈'],
132
+ tips: '主页卡片用 3:4,转发分享卡片用 4:3。',
133
+ },
134
+ ]
src/video/covers.ts ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Engine } from './engine'
2
+ import { frameAt, SHOTS } from './scenes'
3
+ import * as O from './overlay'
4
+ import { orbit } from './state'
5
+ import type { SceneState } from './model'
6
+
7
+ export interface CoverSpec { key: string; platform: string; label: string; w: number; h: number; l1: string; l2: string; hot: string; color: string }
8
+
9
+ export const COVERS: CoverSpec[] = [
10
+ { key: 'xhs-34', platform: '小红书', label: '3:4 竖版', w: 1080, h: 1440, l1: '拇指一动就疼?', l2: '3D看懂腱鞘炎', hot: '腱鞘炎', color: '#ff2442' },
11
+ { key: 'xhs-43', platform: '小红书', label: '4:3 横版', w: 1440, h: 1080, l1: '拇指一动就疼?', l2: '3D看懂腱鞘炎', hot: '腱鞘炎', color: '#ff2442' },
12
+ { key: 'dy-34', platform: '抖音', label: '3:4 竖版', w: 1080, h: 1440, l1: '一用力就疼?', l2: '透视腱鞘炎', hot: '腱鞘炎', color: '#25f4ee' },
13
+ { key: 'dy-43', platform: '抖音', label: '4:3 横版', w: 1440, h: 1080, l1: '一用力就疼?', l2: '透视腱鞘炎', hot: '腱鞘炎', color: '#25f4ee' },
14
+ { key: 'bili-43', platform: 'B站', label: '4:3 投稿封面', w: 1440, h: 1080, l1: '【3D解剖】', l2: '看懂腱鞘炎', hot: '腱鞘炎', color: '#00aeec' },
15
+ { key: 'bili-169', platform: 'B站', label: '16:9 个人空间', w: 1920, h: 1080, l1: '拇指一动就疼?', l2: '90秒看懂腱鞘炎', hot: '腱鞘炎', color: '#00aeec' },
16
+ { key: 'sph-34', platform: '视频号', label: '3:4 主页卡片', w: 1080, h: 1440, l1: '拇指疼?', l2: '看懂腱鞘炎', hot: '腱鞘炎', color: '#fa9d3b' },
17
+ { key: 'sph-43', platform: '视频号', label: '4:3 分享卡片', w: 1440, h: 1080, l1: '拇指疼?', l2: '看懂腱鞘炎', hot: '腱鞘炎', color: '#fa9d3b' },
18
+ ]
19
+
20
+ let eng: Engine | null = null
21
+
22
+ function coverState(portrait: boolean): SceneState {
23
+ const t = SHOTS[1].start + 8.6
24
+ const s = frameAt(t).views[0].state
25
+ return {
26
+ ...s,
27
+ pain: 1, friction: 1, thick: 1, xray: 1, skin: 0.8, bone: 1, tendon: 1, sheath: 1, focus: 0.5,
28
+ cam: { pos: orbit([0, 0, 0], portrait ? 2.35 : 2.0, 0.05, 0.14), target: [0, 0, 0], fov: 35, follow: 1, shift: portrait ? [0.56, 0.64] : [0.66, 0.54] },
29
+ }
30
+ }
31
+
32
+ function rr(ctx: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, r: number) {
33
+ ctx.beginPath(); ctx.moveTo(x + r, y); ctx.arcTo(x + w, y, x + w, y + h, r); ctx.arcTo(x + w, y + h, x, y + h, r)
34
+ ctx.arcTo(x, y + h, x, y, r); ctx.arcTo(x, y, x + w, y, r); ctx.closePath()
35
+ }
36
+
37
+ /** Draw a cover onto the given canvas (sized to spec) */
38
+ export function drawCover(spec: CoverSpec, canvas: HTMLCanvasElement) {
39
+ const { w, h } = spec
40
+ canvas.width = w; canvas.height = h
41
+ const ctx = canvas.getContext('2d')!
42
+ if (!eng) eng = new Engine()
43
+ eng.setSize(w, h)
44
+ const portrait = h > w
45
+ const st = coverState(portrait)
46
+ const t = st.time
47
+ eng.render({
48
+ views: [{ rect: [0, 0, 1, 1], state: st, bg: 'lab' }],
49
+ overlay: (c, api) => {
50
+ const m = Math.min(w, h), F = O.FONT
51
+ // text-side scrim
52
+ const g = portrait ? c.createLinearGradient(0, 0, 0, h * 0.55) : c.createLinearGradient(0, 0, w * 0.6, 0)
53
+ g.addColorStop(0, 'rgba(2,8,18,0.92)'); g.addColorStop(0.6, 'rgba(2,8,18,0.55)'); g.addColorStop(1, 'rgba(2,8,18,0)')
54
+ c.fillStyle = g; c.fillRect(0, 0, w, h)
55
+ // pain marker + labels
56
+ const p = api.anchor('pain'), sh = api.anchor('sheath')
57
+ O.reticle(c, p.x, p.y, m * 0.075, 1, t, O.COL.red, 1)
58
+ c.save(); c.scale(m / 1080, m / 1080)
59
+ const k = 1080 / m
60
+ O.label(c, sh.x * k, sh.y * k, sh.x * k + (portrait ? 170 : 190), sh.y * k + (portrait ? 230 : 210), '腱鞘增厚 · 通道变窄', 1, O.COL.yellow, 34)
61
+ c.restore()
62
+ // text block
63
+ const x0 = m * 0.07, y0 = portrait ? m * 0.09 : m * 0.12
64
+ c.textBaseline = 'top'; c.textAlign = 'left'
65
+ // badge
66
+ const bs = m * 0.036
67
+ c.font = `900 ${bs}px ${F}`
68
+ const btxt = '3D 解剖动画 · 医学科普'
69
+ const bw = c.measureText(btxt).width + bs * 1.4
70
+ rr(c, x0, y0, bw, bs * 1.8, bs * 0.9); c.fillStyle = 'rgba(95,212,255,0.16)'; c.fill()
71
+ c.strokeStyle = O.COL.cyan; c.lineWidth = 2; c.stroke()
72
+ c.fillStyle = O.COL.cyan; c.fillText(btxt, x0 + bs * 0.7, y0 + bs * 0.4)
73
+ // headline
74
+ const h1 = m * (spec.l1.length > 6 ? 0.105 : 0.125)
75
+ c.font = `900 ${h1}px ${F}`
76
+ c.shadowColor = 'rgba(0,0,0,0.6)'; c.shadowBlur = 20
77
+ c.fillStyle = '#fff'; c.fillText(spec.l1, x0, y0 + bs * 2.6)
78
+ const h2 = m * (spec.l2.length > 6 ? 0.115 : 0.135)
79
+ c.font = `900 ${h2}px ${F}`
80
+ const y2 = y0 + bs * 2.6 + h1 * 1.2
81
+ const idx = spec.l2.indexOf(spec.hot)
82
+ const pre = idx >= 0 ? spec.l2.slice(0, idx) : spec.l2
83
+ c.fillStyle = '#fff'; c.fillText(pre, x0, y2)
84
+ if (idx >= 0) {
85
+ const px = x0 + c.measureText(pre).width
86
+ c.shadowColor = 'rgba(255,40,40,0.9)'; c.shadowBlur = 40
87
+ const gg = c.createLinearGradient(0, y2, 0, y2 + h2); gg.addColorStop(0, '#ff7a6a'); gg.addColorStop(1, '#ff2a2a')
88
+ c.fillStyle = gg; c.fillText(spec.hot, px, y2)
89
+ c.fillText(spec.l2.slice(idx + spec.hot.length), px + c.measureText(spec.hot).width, y2)
90
+ }
91
+ c.shadowBlur = 0
92
+ // flow chips
93
+ const fs = m * 0.03
94
+ c.font = `800 ${fs}px ${F}`
95
+ let cx = x0
96
+ const cy = y2 + h2 * 1.35
97
+ const flow = ['疼痛', '定位', '处理', '松解', '恢复']
98
+ flow.forEach((f, i) => {
99
+ const tw = c.measureText(f).width + fs * 1.2
100
+ rr(c, cx, cy, tw, fs * 1.7, fs * 0.5)
101
+ c.fillStyle = i === 0 ? 'rgba(255,59,59,0.85)' : i === 4 ? 'rgba(62,224,143,0.85)' : 'rgba(255,255,255,0.14)'; c.fill()
102
+ c.fillStyle = '#fff'; c.fillText(f, cx + fs * 0.6, cy + fs * 0.35)
103
+ cx += tw
104
+ if (i < flow.length - 1) { c.fillStyle = 'rgba(255,255,255,0.6)'; c.fillText('›', cx + fs * 0.3, cy + fs * 0.3); cx += fs * 1.1 }
105
+ })
106
+ // platform accent bar + footer
107
+ c.fillStyle = spec.color; c.fillRect(0, h - m * 0.012, w, m * 0.012)
108
+ c.font = `600 ${m * 0.022}px ${F}`; c.fillStyle = 'rgba(255,255,255,0.6)'; c.textBaseline = 'bottom'
109
+ c.fillText('原创3D医学示意动画 · 仅供科普,不替代面诊', x0, h - m * 0.04)
110
+ },
111
+ }, ctx, t, { w, h })
112
+ return canvas
113
+ }
114
+
115
+ export function coverBlob(spec: CoverSpec): Promise<Blob> {
116
+ const c = drawCover(spec, document.createElement('canvas'))
117
+ return new Promise((res, rej) => c.toBlob(b => (b ? res(b) : rej(new Error('toBlob'))), 'image/png'))
118
+ }
src/video/engine.ts CHANGED
@@ -79,6 +79,13 @@ export class Engine {
79
  if (s.cam.roll) cam.up.applyAxisAngle(new THREE.Vector3(0, 0, 1), s.cam.roll)
80
  cam.lookAt(target)
81
  cam.updateProjectionMatrix()
 
 
 
 
 
 
 
82
  cam.updateMatrixWorld()
83
  }
84
 
 
79
  if (s.cam.roll) cam.up.applyAxisAngle(new THREE.Vector3(0, 0, 1), s.cam.roll)
80
  cam.lookAt(target)
81
  cam.updateProjectionMatrix()
82
+ const sh = (s.cam as { shift?: [number, number] }).shift
83
+ if (sh) {
84
+ // place the look-at point at screen fraction (fx, fy)
85
+ cam.projectionMatrix.elements[8] -= 2 * sh[0] - 1
86
+ cam.projectionMatrix.elements[9] -= 1 - 2 * sh[1]
87
+ cam.projectionMatrixInverse.copy(cam.projectionMatrix).invert()
88
+ }
89
  cam.updateMatrixWorld()
90
  }
91
 
src/video/exporter.ts CHANGED
@@ -10,7 +10,7 @@ export type Fps = 24 | 30 | 60
10
 
11
  export interface ExportProgress { phase: string; p: number; frame?: number; total?: number; eta?: number }
12
 
13
- export async function exportMp4(fps: Fps, onProgress: (e: ExportProgress) => void, signal: AbortSignal): Promise<Blob> {
14
  if (typeof VideoEncoder === 'undefined') throw new Error('当前浏览器不支持本地视频编码,请使用最新版 Chrome / Edge / Safari 17+')
15
  const W = LW, H = LH
16
  const bitrate = fps === 60 ? 16e6 : fps === 30 ? 12e6 : 10e6
@@ -33,13 +33,13 @@ export async function exportMp4(fps: Fps, onProgress: (e: ExportProgress) => voi
33
 
34
  if (audio) {
35
  // trim/pad to exact film length
36
- const n = Math.round(DURATION * sound.sampleRate)
37
  const ab = new AudioBuffer({ length: n, numberOfChannels: 2, sampleRate: sound.sampleRate })
38
  for (let c = 0; c < 2; c++) ab.copyToChannel(sound.getChannelData(Math.min(c, sound.numberOfChannels - 1)).subarray(0, n), c)
39
  await audio.add(ab); audio.close()
40
  }
41
 
42
- const total = Math.floor(DURATION * fps)
43
  const t0 = performance.now()
44
  try {
45
  for (let i = 0; i < total; i++) {
 
10
 
11
  export interface ExportProgress { phase: string; p: number; frame?: number; total?: number; eta?: number }
12
 
13
+ export async function exportMp4(fps: Fps, onProgress: (e: ExportProgress) => void, signal: AbortSignal, limit = DURATION): Promise<Blob> {
14
  if (typeof VideoEncoder === 'undefined') throw new Error('当前浏览器不支持本地视频编码,请使用最新版 Chrome / Edge / Safari 17+')
15
  const W = LW, H = LH
16
  const bitrate = fps === 60 ? 16e6 : fps === 30 ? 12e6 : 10e6
 
33
 
34
  if (audio) {
35
  // trim/pad to exact film length
36
+ const n = Math.round(limit * sound.sampleRate)
37
  const ab = new AudioBuffer({ length: n, numberOfChannels: 2, sampleRate: sound.sampleRate })
38
  for (let c = 0; c < 2; c++) ab.copyToChannel(sound.getChannelData(Math.min(c, sound.numberOfChannels - 1)).subarray(0, n), c)
39
  await audio.add(ab); audio.close()
40
  }
41
 
42
+ const total = Math.floor(limit * fps)
43
  const t0 = performance.now()
44
  try {
45
  for (let i = 0; i < total; i++) {
src/video/model.ts CHANGED
@@ -29,7 +29,7 @@ export const POSE = {
29
  /* ------------------------------------------------------------------ */
30
  export interface PropState { vis: number; [k: string]: number }
31
  export interface SceneState {
32
- cam: { pos: V3; target: V3; fov: number; roll?: number; follow?: number }
33
  arm: { pos: V3; rot: V3; twist?: { pivot: V3; axis: V3; angle: number } }
34
  pose: Pose
35
  skin: number // overall skin visibility 0..1
 
29
  /* ------------------------------------------------------------------ */
30
  export interface PropState { vis: number; [k: string]: number }
31
  export interface SceneState {
32
+ cam: { pos: V3; target: V3; fov: number; roll?: number; follow?: number; shift?: [number, number] }
33
  arm: { pos: V3; rot: V3; twist?: { pivot: V3; axis: V3; angle: number } }
34
  pose: Pose
35
  skin: number // overall skin visibility 0..1