Spaces:
Running
Running
Step 6-7: 播放器 + MP4 导出 + 文案 + 封面
Browse files- README.md +4 -2
- assets/ADebug-BJNllebx.js +1 -0
- assets/App-Ckrxctng.js +2 -0
- assets/Debug-Bc9dFGVg.js +1 -0
- assets/ErrorBoundary-DwultlP_.js +1 -0
- assets/Studio-1jRM1joF.js +171 -0
- assets/TDebug-C_pplWnw.js +2 -0
- assets/XDebug-COl9Ua8s.js +1 -0
- assets/audio-BSS1MXf9.js +1 -0
- assets/client-BlQxAbrl.js +0 -0
- assets/engine-Bmw5iF75.js +1 -0
- assets/exporter-CgYwbdYV.js +0 -0
- assets/index-BlGQAcOD.js +21 -0
- assets/index-Br42UDbl.js +1 -0
- assets/index-CXVdwQTy.js +2 -0
- assets/index-D8uigG9a.css +1 -0
- assets/index-tKuM8enU.js +14 -0
- assets/jsx-dev-runtime-Czb3f8pQ.js +14 -0
- assets/scenes-oUf6rtD_.js +1 -0
- assets/state-B_bTBsCz.js +0 -0
- index.html +19 -1
- scripts/build_static.sh +19 -0
- scripts/e2e.py +36 -0
- scripts/xtest.py +14 -0
- src/App.tsx +19 -6
- src/video/Studio.tsx +382 -0
- src/video/XDebug.tsx +14 -0
- src/video/copy.ts +134 -0
- src/video/covers.ts +118 -0
- src/video/engine.ts +7 -0
- src/video/exporter.ts +3 -3
- src/video/model.ts +1 -1
README.md
CHANGED
|
@@ -61,8 +61,8 @@ pinned: false
|
|
| 61 |
3. ✅ 程序化 3D 手部解剖模型:皮肤 / 骨骼 / 肌腱 / 腱鞘 / 关节骨架绑定 / 疼痛发光 / 器械与道具。
|
| 62 |
4. ✅ 分镜时间轴:11 镜头 + 结尾的相机运动、姿态、图层、字幕、HUD。
|
| 63 |
5. ✅ 程序化音乐与音效、旁白混音、ducking。
|
| 64 |
-
6.
|
| 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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 9 |
-
|
| 10 |
-
if (q
|
| 11 |
-
if (q
|
| 12 |
-
return <
|
|
|
|
|
|
|
|
|
|
| 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(
|
| 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(
|
| 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
|