diff --git a/PncyssD/README.md b/PncyssD/README.md
new file mode 100644
index 0000000..ef2cda4
--- /dev/null
+++ b/PncyssD/README.md
@@ -0,0 +1,16 @@
+# 人生轨迹 (Life Trajectory)
+
+一款结合数字疗愈美学与人工智能的人生管理工具。
+
+## 核心功能
+1. **深度入站**:分步式采集人设与重要回忆。
+2. **人生回溯**:记录大事件,AI辅助分析与疗愈。
+3. **剧本生成**:将过去经历转化为高能爽文人生。
+4. **路径规划**:基于剧本反推现实可行的执行方案。
+
+## 技术栈
+- 架构:原生 ES Modules 模块化开发
+- UI:Tailwind CSS + Glassmorphism 拟态
+- 动画:GSAP
+- AI:OpenRouter (DeepSeek)
+- 存储:LocalStorage
diff --git a/PncyssD/api.js b/PncyssD/api.js
new file mode 100644
index 0000000..27499d2
--- /dev/null
+++ b/PncyssD/api.js
@@ -0,0 +1,47 @@
+const API_KEY = "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";
+const BASE_URL = "https://openrouter.ai/api/v1/chat/completions";
+
+export const AIService = {
+ async fetchAI(prompt, systemMsg) {
+ try {
+ const response = await fetch(BASE_URL, {
+ method: 'POST',
+ headers: {
+ 'Authorization': `Bearer ${API_KEY}`,
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ model: "deepseek/deepseek-chat-v3-0324:free",
+ messages: [
+ { role: "system", content: systemMsg },
+ { role: "user", content: prompt }
+ ]
+ })
+ });
+ const data = await response.json();
+ return data.choices[0].message.content;
+ } catch (e) {
+ console.error(e);
+ return "(AI 暂时陷入了沉思,请稍后再试)";
+ }
+ },
+
+ async analyzeLifeEvent(event) {
+ const system = "你是一位温柔的生命引路人,擅长从平凡事件中发掘成长的力量。请分析用户记录的事件,提供情感价值、成长总结和疗愈鼓励。保持字数在150字左右。";
+ const prompt = `事件标题:${event.title}\n时间:${event.time}\n内容:${event.content}`;
+ return this.fetchAI(prompt, system);
+ },
+
+ async generateEpicScript(params, events) {
+ const system = `你是一位金牌爽文编剧。根据用户的角色设定和过往经历,生成一段符合用户设定、充满爽感的未来人生剧本。剧本必须包含起承转合,使用【标题】标记段落。`;
+ const charInfo = `姓名:${params.character.nickname}, 性格:${params.character.mbti}, 兴趣:${params.character.hobbies.join(',')}, 星座:${params.character.zodiac}`;
+ const eventSummary = events.map(e => e.title).join(', ');
+ const prompt = `角色信息:${charInfo}\n过往经历关键词:${eventSummary}\n用户指定主题:${params.theme}\n指定风格:${params.style}\n篇幅要求:${params.length}\n\n请以此创作一段热血、精彩的人生剧本。`;
+ return this.fetchAI(prompt, system);
+ },
+
+ async generatePath(script) {
+ const system = "你是一位人生规划导师。请将用户生成的剧本拆解为现实中可操作的路径。使用【阶段名称】加上具体建议。务必客观、可执行。";
+ return this.fetchAI(script, system);
+ }
+};
diff --git a/PncyssD/components.js b/PncyssD/components.js
new file mode 100644
index 0000000..d31457b
--- /dev/null
+++ b/PncyssD/components.js
@@ -0,0 +1,74 @@
+export const UI = {
+ inspirationClusters: {
+ childhood: ['秋千', '晚霞', '糖果', '奔跑', '蝉鸣', '雨后泥土', '旧书包', '风筝'],
+ joy: ['海浪', '拥抱', '掌声', '晨曦', '破土而出', '默契', '星空', '释放'],
+ low: ['落叶', '雨伞', '长廊', '深呼吸', '自愈', '沉潜', '坚韧', '等待', '破茧']
+ },
+
+ renderInspiration(type, targetId) {
+ const words = this.inspirationClusters[type];
+ return words.map(word => `
+ ${word}
+ `).join('');
+ },
+
+ renderInput(label, id, type = 'text', placeholder = '', value = '') {
+ return `
+
+
+
+
+ `;
+ },
+
+ renderTextArea(label, id, placeholder = '', value = '') {
+ return `
+
+
+
+
+ `;
+ },
+
+ renderSelect(label, id, options, selectedValue = '') {
+ return `
+
+
+
+
+ `;
+ },
+
+ renderAccountSettings(data) {
+ return `
+
+
+
+
+
+
+
个人设定
+
在这里调整你的人生航向基础信息
+
+
+
+ ${this.renderInput('昵称', 'edit-nickname', 'text', '你想被如何称呼?', data.nickname)}
+ ${this.renderInput('职业', 'edit-profession', 'text', '你当下的社会锚点', data.profession || '')}
+ ${this.renderInput('MBTI', 'edit-mbti', 'text', '性格色彩', data.mbti)}
+ ${this.renderInput('星座', 'edit-zodiac', 'text', '星辰指引', data.zodiac)}
+
+ ${this.renderInput('兴趣爱好', 'edit-hobbies', 'text', '让灵魂起舞的事物', data.hobbies.join(', '))}
+
+
+
+
+
+
+ `;
+ }
+};
diff --git a/PncyssD/dashboard.js b/PncyssD/dashboard.js
new file mode 100644
index 0000000..8ce8ba3
--- /dev/null
+++ b/PncyssD/dashboard.js
@@ -0,0 +1,396 @@
+import { state } from './state.js';
+import { UI } from './components.js';
+import { AIService } from './api.js';
+
+export const Dashboard = {
+ render() {
+ const container = document.getElementById('view-container');
+ const nav = document.getElementById('top-nav');
+ if (nav) nav.classList.remove('hidden');
+
+ container.innerHTML = `
+
+
+
+
+
+
+
+ `;
+
+ this.initEventListeners();
+ this.loadTimeline();
+ lucide.createIcons();
+ },
+
+ initEventListeners() {
+ document.querySelectorAll('.nav-item').forEach(btn => {
+ btn.onclick = () => {
+ if (btn.classList.contains('active')) return;
+ document.querySelectorAll('.nav-item').forEach(b => b.classList.remove('active'));
+ btn.classList.add('active');
+
+ const view = btn.dataset.view;
+ this.animateTransition(() => {
+ if(view === 'timeline') this.loadTimeline();
+ if(view === 'script') this.loadScriptGenerator();
+ if(view === 'path') this.loadPathGenerator();
+ });
+ };
+ });
+ const profileBtn = document.getElementById('user-profile-btn');
+ if (profileBtn) profileBtn.onclick = () => this.showProfile();
+ },
+
+ animateTransition(callback) {
+ const content = document.getElementById('dash-content');
+ gsap.to(content, { opacity: 0, y: 10, duration: 0.3, onComplete: () => {
+ callback();
+ gsap.to(content, { opacity: 1, y: 0, duration: 0.6, ease: "power2.out" });
+ lucide.createIcons();
+ }});
+ },
+
+ loadTimeline() {
+ const content = document.getElementById('dash-content');
+ const hasEvents = state.lifeEvents.length > 0;
+ content.innerHTML = `
+
+
+
生命长河
+
塑造你的每一刻,都被星辰见证。
+
+
+
+
+ ${hasEvents ? '
' : ''}
+
+ ${hasEvents ? state.lifeEvents.sort((a,b) => new Date(b.time) - new Date(a.time)).map(ev => this.renderEventCard(ev)).join('') : this.renderEmpty()}
+
+
+ `;
+ document.getElementById('add-event-btn').onclick = () => this.showEventModal();
+ },
+
+ renderEventCard(ev) {
+ return `
+
+
+
+
+
${ev.title}
+ ${ev.time}
+
+
${ev.content}
+
+
+
+ 引路人洞察
+
+
${ev.aiFeedback}
+
+
+
+ `;
+ },
+
+ showEventModal() {
+ const modal = document.getElementById('modal-overlay');
+ const body = document.getElementById('modal-body');
+ modal.classList.remove('hidden');
+ body.innerHTML = `
+
+
记录足迹
+ ${UI.renderInput('事件标题', 'ev-title', 'text', '给这段经历起个名字')}
+ ${UI.renderInput('发生时间', 'ev-time', 'date')}
+ ${UI.renderTextArea('经历详情', 'ev-content', '当时发生了什么?你的感受如何?')}
+
+
+ `;
+ document.getElementById('save-event').onclick = async () => {
+ const btn = document.getElementById('save-event');
+ const event = { title: document.getElementById('ev-title').value, time: document.getElementById('ev-time').value, content: document.getElementById('ev-content').value, aiFeedback: "分析中..." };
+ if(!event.title || !event.time || !event.content) return alert("请完整填写记录。");
+ btn.disabled = true;
+ btn.innerHTML = `正在共鸣生命轨迹...`;
+ event.aiFeedback = await AIService.analyzeLifeEvent(event);
+ state.addLifeEvent(event);
+ modal.classList.add('hidden');
+ this.loadTimeline();
+ };
+ lucide.createIcons();
+ },
+
+ loadScriptGenerator() {
+ const content = document.getElementById('dash-content');
+ const userData = state.registrationData;
+ const styles = [
+ {value:'都市', label:'都市沉浮'}, {value:'古风', label:'快意恩仇'},
+ {value:'爱情', label:'唯美浪漫'}, {value:'科幻', label:'星际远征'},
+ {value:'喜剧', label:'荒诞不经'}, {value:'悬疑', label:'迷雾重重'}, {value:'恐怖', label:'午夜回响'}
+ ];
+ const lengths = [{value:'短', label:'极简'}, {value:'中', label:'连载'}, {value:'长', label:'史诗'}];
+
+ content.innerHTML = `
+
+
+
+
+
+
角色设定
+
+
+
${userData.nickname}
+
${userData.zodiac}
+
${userData.mbti}
+
${userData.hobbies.join(', ')}
+
+
+
+
+
+
+
+
创作需求
+
+ ${UI.renderInput('剧本主题', 'sc-theme', 'text', '例如:我在职场逆袭了')}
+ ${UI.renderSelect('叙事风格', 'sc-style', styles)}
+ ${UI.renderSelect('剧本篇幅', 'sc-length', lengths)}
+
+
+
+
+
+
+
+
+ ${state.selectedScriptId ? this.renderScript(state.getSelectedScript()) : this.renderEmptyScript()}
+
+
+
+ `;
+
+ document.getElementById('gen-script-btn').onclick = async () => {
+ const theme = document.getElementById('sc-theme').value;
+ if(!theme) return alert('请输入主题');
+ const btn = document.getElementById('gen-script-btn');
+ btn.disabled = true;
+ btn.innerHTML = ` 编撰中...`;
+ lucide.createIcons();
+
+ const params = {
+ theme,
+ style: document.getElementById('sc-style').value,
+ length: document.getElementById('sc-length').value,
+ character: state.registrationData
+ };
+ const content = await AIService.generateEpicScript(params, state.lifeEvents);
+ state.addScript({ ...params, content });
+ this.animateTransition(() => this.loadScriptGenerator());
+ };
+
+ document.querySelectorAll('.script-item').forEach(item => {
+ item.onclick = () => {
+ state.selectedScriptId = parseInt(item.dataset.id);
+ state.save();
+ this.animateTransition(() => this.loadScriptGenerator());
+ };
+ });
+ lucide.createIcons();
+ },
+
+ renderScript(script) {
+ return `
+
+ `;
+ },
+
+ renderEmptyScript() {
+ return `
+
+ `;
+ },
+
+ loadPathGenerator() {
+ const content = document.getElementById('dash-content');
+ const script = state.getSelectedScript();
+ if (!script) {
+ content.innerHTML = `
+
+
+
先生成剧本,方能洞察路径。
+
+
+ `;
+ return;
+ }
+
+ content.innerHTML = `
+
+
+
+
实现路径
+
基于《${script.theme}》,拆解达成目标的每一步。
+
+
+
+
+ ${state.selectedPath ? this.renderPath(state.selectedPath) : this.renderEmptyPath()}
+
+
+ `;
+
+ document.getElementById('gen-path-btn').onclick = async () => {
+ const btn = document.getElementById('gen-path-btn');
+ btn.disabled = true;
+ btn.innerHTML = ` 规划中...`;
+ const path = await AIService.generatePath(script.content);
+ state.setPath(path);
+ this.animateTransition(() => this.loadPathGenerator());
+ };
+ },
+
+ renderPath(path) {
+ return path.split(/【/).filter(s => s.trim()).map((s, i) => {
+ const parts = s.split(/】/);
+ return `
+
+
+ ${i+1}
+ ${parts[0]}
+
+
${parts[1] || ''}
+
+ `;
+ }).join('');
+ },
+
+ renderEmptyPath() {
+ return `等待开启人生导航...
`;
+ },
+
+ renderEmpty() {
+ return `
+
+ `;
+ },
+
+ showProfile() {
+ const modal = document.getElementById('modal-overlay');
+ const body = document.getElementById('modal-body');
+ modal.classList.remove('hidden');
+ this.renderProfileMain(body);
+ lucide.createIcons();
+ },
+
+ renderProfileMain(container) {
+ const data = state.registrationData;
+ container.innerHTML = `
+
+
+
+ ${(data.nickname || '人').charAt(0)}
+
+
+
${data.nickname || '旅行者'}
+
${data.mbti || '-'} | ${data.zodiac || '-'}
+
+
+
+
+
${state.lifeEvents.length}
+
生命足迹
+
+
+
${state.scripts.length}
+
天命卷轴
+
+
+
+
+
+
+
+ `;
+ document.getElementById('edit-profile').onclick = () => {
+ container.innerHTML = UI.renderAccountSettings(state.registrationData);
+ lucide.createIcons();
+ document.getElementById('cancel-edit-btn').onclick = () => this.renderProfileMain(container);
+ document.getElementById('save-profile-btn').onclick = () => {
+ state.updateRegistration({
+ nickname: document.getElementById('edit-nickname').value,
+ profession: document.getElementById('edit-profession').value,
+ mbti: document.getElementById('edit-mbti').value,
+ zodiac: document.getElementById('edit-zodiac').value,
+ hobbies: document.getElementById('edit-hobbies').value.split(',').map(s => s.trim())
+ });
+ this.renderProfileMain(container);
+ };
+ };
+ document.getElementById('logout-btn').onclick = () => {
+ if(confirm("确定要删除所有记录吗?此操作不可逆。")) state.clear();
+ };
+ }
+};
+
+const closeBtn = document.getElementById('close-modal');
+if (closeBtn) closeBtn.onclick = () => document.getElementById('modal-overlay').classList.add('hidden');
diff --git a/PncyssD/index.html b/PncyssD/index.html
new file mode 100644
index 0000000..b9b4a48
--- /dev/null
+++ b/PncyssD/index.html
@@ -0,0 +1,61 @@
+
+
+
+
+
+ 人生轨迹 | Life Trajectory
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+

+
人生轨迹
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PncyssD/index.js b/PncyssD/index.js
new file mode 100644
index 0000000..9da4422
--- /dev/null
+++ b/PncyssD/index.js
@@ -0,0 +1,44 @@
+import { state } from './state.js';
+import { Login } from './login.js';
+import { Onboarding } from './onboarding.js';
+import { Dashboard } from './dashboard.js';
+
+const App = {
+ async init() {
+ state.load();
+ this.render();
+ },
+
+ async transition(to) {
+ const container = document.getElementById('view-container');
+ const loader = document.getElementById('loader');
+
+ await gsap.to(container, { opacity: 0, y: -20, duration: 0.5, ease: "power2.inOut" });
+
+ loader.classList.remove('hidden');
+ gsap.fromTo(loader, { opacity: 0 }, { opacity: 1, duration: 0.4 });
+
+ state.view = to;
+ state.save();
+
+ setTimeout(() => {
+ this.render();
+ gsap.to(loader, { opacity: 0, duration: 0.4, onComplete: () => loader.classList.add('hidden') });
+ gsap.fromTo(container, { opacity: 0, y: 20 }, { opacity: 1, y: 0, duration: 0.8, ease: "power3.out" });
+ }, 1000);
+ },
+
+ render() {
+ if (!state.isLoggedIn) {
+ Login.render(() => this.transition('onboarding'));
+ } else if (state.view === 'onboarding') {
+ Onboarding.render(() => this.transition('dashboard'));
+ } else {
+ Dashboard.render();
+ }
+ lucide.createIcons();
+ }
+};
+
+window.addEventListener('DOMContentLoaded', () => App.init());
+export default App;
diff --git a/PncyssD/login.js b/PncyssD/login.js
new file mode 100644
index 0000000..0cb5319
--- /dev/null
+++ b/PncyssD/login.js
@@ -0,0 +1,78 @@
+import { state } from './state.js';
+
+export const Login = {
+ render(onLoginSuccess) {
+ const container = document.getElementById('view-container');
+ container.innerHTML = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 登录即代表同意《用户协议》与《隐私政策》,我们将妥善保管您的生命数据。
+
+
+
+ `;
+
+ const phoneInput = document.getElementById('login-phone');
+ const codeInput = document.getElementById('login-code');
+ const codeBtn = document.getElementById('get-code-btn');
+ const loginBtn = document.getElementById('login-submit');
+
+ codeBtn.onclick = () => {
+ if (phoneInput.value.length !== 11) return alert('请输入正确的手机号');
+ codeBtn.disabled = true;
+ let count = 60;
+ const timer = setInterval(() => {
+ codeBtn.innerText = `${count}S`;
+ count--;
+ if (count < 0) {
+ clearInterval(timer);
+ codeBtn.disabled = false;
+ codeBtn.innerText = '获取';
+ }
+ }, 1000);
+ alert('验证码已发送 (模拟验证码: 888888)');
+ };
+
+ loginBtn.onclick = () => {
+ if (phoneInput.value.length === 11 && codeInput.value === '888888') {
+ state.isLoggedIn = true;
+ state.phone = phoneInput.value;
+ state.save();
+ onLoginSuccess();
+ } else {
+ alert('验证失败,请检查手机号或验证码');
+ }
+ };
+ }
+};
diff --git a/PncyssD/onboarding.js b/PncyssD/onboarding.js
new file mode 100644
index 0000000..885fa66
--- /dev/null
+++ b/PncyssD/onboarding.js
@@ -0,0 +1,151 @@
+import { state } from './state.js';
+import { UI } from './components.js';
+
+export const Onboarding = {
+ onComplete: null,
+
+ render(onCompleteCallback) {
+ if (onCompleteCallback) this.onComplete = onCompleteCallback;
+
+ const container = document.getElementById('view-container');
+ container.innerHTML = `
+
+
+
+
+
+ ${[1,2,3,4,5].map(i => `
`).join('')}
+
+
+
+
+
+
+
+ `;
+ this.renderStep(state.currentStep || 1);
+ this.initEvents();
+ },
+
+ renderStep(step) {
+ const content = document.getElementById('step-content');
+ const nextBtn = document.getElementById('next-step');
+ const prevBtn = document.getElementById('prev-step');
+
+
+ for(let i=1; i<=5; i++){
+ const dot = document.querySelector(`.step-dot-${i}`);
+ if(dot) dot.className = `step-dot-${i} h-1 rounded-full transition-all duration-500 ${i === step ? 'w-8 bg-orange-200' : 'w-3 bg-white/10'}`;
+ }
+
+ prevBtn.classList.toggle('hidden', step === 1);
+ nextBtn.innerHTML = step === 5 ? '开启人生 ' : '继续 ';
+
+ let html = '';
+ if (step === 1) {
+ html = `
+
+
+
+ ${UI.renderInput('称呼', 'reg-nickname', 'text', '例如:林中鹿', state.registrationData.nickname)}
+ ${UI.renderInput('性别', 'reg-gender', 'text', '自由填写', state.registrationData.gender)}
+ ${UI.renderInput('MBTI', 'reg-mbti', 'text', '如:INFJ', state.registrationData.mbti)}
+ ${UI.renderInput('星座', 'reg-zodiac', 'text', '星辰指引', state.registrationData.zodiac)}
+
+ ${UI.renderInput('兴趣爱好', 'reg-hobbies', 'text', '用逗号分隔你的热爱', (state.registrationData.hobbies || []).join(','))}
+
+ `;
+ } else if (step === 2) {
+ html = this.renderMemoryStep('那段纯真的时光', '童年记忆', 'reg-child-text', 'reg-child-date', 'childhood', state.registrationData.childhood);
+ } else if (step === 3) {
+ html = this.renderMemoryStep('光芒闪耀的时刻', '开心的经历', 'reg-joy-text', 'reg-joy-date', 'joy', state.registrationData.joy);
+ } else if (step === 4) {
+ html = this.renderMemoryStep('在暗夜中潜行', '沮丧与低谷', 'reg-low-text', 'reg-low-date', 'low', state.registrationData.low);
+ } else if (step === 5) {
+ html = `
+
+
+
未来想成为谁?
+
勾勒你对理想生活的全部向往。
+
+ ${UI.renderTextArea('对未来的憧憬', 'reg-future-vision', '你想成为一个什么样的人?', state.registrationData.future.vision || '')}
+ ${UI.renderTextArea('理想生活状态', 'reg-future-ideal', '你的理想清晨与傍晚是怎样的?', state.registrationData.future.ideal || '')}
+
+ `;
+ }
+ content.innerHTML = html;
+ lucide.createIcons();
+ },
+
+ renderMemoryStep(title, label, textId, dateId, type, data) {
+ return `
+
+
+
${title}
+
回望足迹,这些瞬间如何塑造了此时的你。
+
+
+
+
+
+
+
+
+
+
+
+ ${UI.renderInspiration(type, textId)}
+
+
+
+ `;
+ },
+
+ saveStepData() {
+ const step = state.currentStep;
+ if (step === 1) {
+ state.updateRegistration({
+ nickname: document.getElementById('reg-nickname').value,
+ gender: document.getElementById('reg-gender').value,
+ mbti: document.getElementById('reg-mbti').value,
+ zodiac: document.getElementById('reg-zodiac').value,
+ hobbies: document.getElementById('reg-hobbies').value.split(',').map(s => s.trim()).filter(s => s)
+ });
+ } else if (step === 2) {
+ state.updateRegistration({ childhood: { date: document.getElementById('reg-child-date').value, text: document.getElementById('reg-child-text').value } });
+ } else if (step === 3) {
+ state.updateRegistration({ joy: { date: document.getElementById('reg-joy-date').value, text: document.getElementById('reg-joy-text').value } });
+ } else if (step === 4) {
+ state.updateRegistration({ low: { date: document.getElementById('reg-low-date').value, text: document.getElementById('reg-low-text').value } });
+ } else if (step === 5) {
+ state.updateRegistration({
+ future: { vision: document.getElementById('reg-future-vision').value, ideal: document.getElementById('reg-future-ideal').value }
+ });
+ }
+ },
+
+ initEvents() {
+ document.getElementById('next-step').onclick = () => {
+ this.saveStepData();
+ if (state.currentStep < 5) {
+ state.currentStep++;
+ this.renderStep(state.currentStep);
+ } else {
+ state.view = 'dashboard';
+ state.save();
+ if (this.onComplete) this.onComplete();
+ }
+ };
+ document.getElementById('prev-step').onclick = () => {
+ if (state.currentStep > 1) {
+ state.currentStep--;
+ this.renderStep(state.currentStep);
+ }
+ };
+ }
+};
diff --git a/PncyssD/registration.js b/PncyssD/registration.js
new file mode 100644
index 0000000..4146662
--- /dev/null
+++ b/PncyssD/registration.js
@@ -0,0 +1,187 @@
+import { state } from './state.js';
+import { UI } from './components.js';
+
+export const Registration = {
+ render() {
+ const container = document.getElementById('view-container');
+ container.innerHTML = `
+
+ `;
+ this.goToStep(1);
+ },
+
+ goToStep(step) {
+ state.currentStep = step;
+ const content = document.getElementById('step-content');
+
+ gsap.to(content, { opacity: 0, y: 10, duration: 0.3, onComplete: () => {
+ this.renderStep(step, content);
+ gsap.to(content, { opacity: 1, y: 0, duration: 0.5 });
+ this.updateIndicators(step);
+ lucide.createIcons();
+ }});
+ },
+
+ renderStep(step, el) {
+ switch(step) {
+ case 1:
+ el.innerHTML = `
+
+
你是谁?
+
让我们从最基础的认知开始...
+
+
+ ${UI.renderInput('昵称', 'reg-nick', 'text', '你想如何称呼自己?')}
+
+ ${UI.renderInput('星座', 'reg-zodiac', 'text', '如:天蝎座')}
+ ${UI.renderInput('MBTI', 'reg-mbti', 'text', '如:INFJ')}
+
+ ${UI.renderInput('兴趣爱好', 'reg-hobbies', 'text', '用逗号分隔你的热爱')}
+
+
+
+
+ `;
+ document.getElementById('btn-next').onclick = () => {
+ state.updateRegistration({
+ nickname: document.getElementById('reg-nick').value,
+ zodiac: document.getElementById('reg-zodiac').value,
+ mbti: document.getElementById('reg-mbti').value,
+ hobbies: document.getElementById('reg-hobbies').value.split(',')
+ });
+ this.goToStep(2);
+ };
+ break;
+
+ case 2: // Childhood
+ el.innerHTML = `
+
+
+
童年往事
+
那个阶段,你的世界是什么颜色的?
+ ${UI.renderInput('大约时间', 'reg-child-date', 'date')}
+ ${UI.renderTextArea('描述你的感受', 'reg-child-text', '那个午后,我在...')}
+
${UI.renderInspiration('childhood', 'reg-child-text')}
+
+
+

+
+
+
+
+
+
+ `;
+ document.getElementById('btn-next').onclick = () => {
+ state.updateRegistration({ childhood: { date: document.getElementById('reg-child-date').value, text: document.getElementById('reg-child-text').value }});
+ this.goToStep(3);
+ };
+ break;
+
+ case 3: // Joy
+ el.innerHTML = `
+
+
+
感到满足的瞬间
+
那些让你嘴角上扬,感到充盈的经历。
+ ${UI.renderInput('发生日期', 'reg-joy-date', 'date')}
+ ${UI.renderTextArea('那一刻发生了什么?', 'reg-joy-text', '微风拂过,我发现...')}
+
${UI.renderInspiration('joy', 'reg-joy-text')}
+
+
+

+
+
+
+
+
+
+ `;
+ document.getElementById('btn-next').onclick = () => {
+ state.updateRegistration({ joy: { date: document.getElementById('reg-joy-date').value, text: document.getElementById('reg-joy-text').value }});
+ this.goToStep(4);
+ };
+ break;
+
+ case 4: // Low points
+ el.innerHTML = `
+
+
+
沉潜的时光
+
那些让你慢下来,向内生长的日子。
+ ${UI.renderInput('大约时间', 'reg-low-date', 'date')}
+ ${UI.renderTextArea('你是如何度过的?', 'reg-low-text', '在寂静中,我开始思考...')}
+
${UI.renderInspiration('low', 'reg-low-text')}
+
+
+
+
+
+
+
+ `;
+ document.getElementById('btn-next').onclick = () => {
+ state.updateRegistration({ low: { date: document.getElementById('reg-low-date').value, text: document.getElementById('reg-low-text').value }});
+ this.goToStep(5);
+ };
+ break;
+
+ case 5: // Future
+ el.innerHTML = `
+
+
+
展望未来
+
你渴望成为一个怎样的人?
+ ${UI.renderTextArea('未来的愿景', 'reg-future-vision', '我希望在三年后...')}
+ ${UI.renderTextArea('理想生活状态', 'reg-future-ideal', '每天清晨,我能够...')}
+
+
+

+
+
+
+
+
+
+ `;
+ document.getElementById('btn-finish').onclick = () => {
+ state.updateRegistration({ future: { vision: document.getElementById('reg-future-vision').value, ideal: document.getElementById('reg-future-ideal').value }});
+ this.completeRegistration();
+ };
+ break;
+ }
+ },
+
+ updateIndicators(step) {
+ document.querySelectorAll('.step-indicator').forEach(el => {
+ el.classList.toggle('active', parseInt(el.dataset.step) === step);
+ });
+ },
+
+ completeRegistration() {
+ const loader = document.getElementById('loader');
+ loader.classList.remove('hidden');
+ setTimeout(() => {
+ state.view = 'dashboard';
+ window.location.reload(); // Simple way to re-init app view
+ }, 1500);
+ }
+};
+window.reg_instance = Registration;
diff --git a/PncyssD/state.js b/PncyssD/state.js
new file mode 100644
index 0000000..45f9ccc
--- /dev/null
+++ b/PncyssD/state.js
@@ -0,0 +1,78 @@
+export const state = {
+ isLoggedIn: false,
+ phone: '',
+ view: 'login', // 'login' | 'onboarding' | 'dashboard'
+ currentStep: 1,
+ registrationData: {
+ nickname: '',
+ gender: '',
+ zodiac: '',
+ mbti: '',
+ profession: '',
+ hobbies: [],
+ childhood: { date: '', text: '' },
+ joy: { date: '', text: '' },
+ low: { date: '', text: '' },
+ future: { vision: '', ideal: '' }
+ },
+ lifeEvents: [],
+ scripts: [], // Array of { id, theme, style, length, content, date, character }
+ selectedScriptId: null,
+ selectedPath: null,
+
+ save() {
+ const dataToSave = {
+ isLoggedIn: this.isLoggedIn,
+ phone: this.phone,
+ registrationData: this.registrationData,
+ lifeEvents: this.lifeEvents,
+ scripts: this.scripts,
+ selectedScriptId: this.selectedScriptId,
+ selectedPath: this.selectedPath,
+ view: this.view
+ };
+ localStorage.setItem('life_trajectory_v3', JSON.stringify(dataToSave));
+ },
+
+ load() {
+ const saved = localStorage.getItem('life_trajectory_v3');
+ if (saved) {
+ try {
+ const parsed = JSON.parse(saved);
+ Object.assign(this, parsed);
+ } catch (e) {
+ console.error("Failed to load state:", e);
+ }
+ }
+ },
+
+ updateRegistration(data) {
+ this.registrationData = { ...this.registrationData, ...data };
+ this.save();
+ },
+
+ addLifeEvent(event) {
+ this.lifeEvents.push({ ...event, id: Date.now() });
+ this.save();
+ },
+
+ addScript(script) {
+ this.scripts.unshift({ ...script, id: Date.now(), date: new Date().toLocaleDateString() });
+ this.selectedScriptId = this.scripts[0].id;
+ this.save();
+ },
+
+ getSelectedScript() {
+ return this.scripts.find(s => s.id === this.selectedScriptId);
+ },
+
+ setPath(path) {
+ this.selectedPath = path;
+ this.save();
+ },
+
+ clear() {
+ localStorage.removeItem('life_trajectory_v3');
+ window.location.reload();
+ }
+};
diff --git a/PncyssD/style.css b/PncyssD/style.css
new file mode 100644
index 0000000..487091a
--- /dev/null
+++ b/PncyssD/style.css
@@ -0,0 +1,144 @@
+@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@300;600&family=Noto+Sans+SC:wght@300;400;500&display=swap');
+
+:root {
+ --glass-bg: rgba(15, 17, 26, 0.4);
+ --glass-border: rgba(255, 255, 255, 0.08);
+ --accent-orange: #FFAB91;
+ --accent-blue: #81D4FA;
+ --card-shadow: 0 20px 50px -12px rgba(0, 0, 0, 0.5);
+}
+
+* { box-sizing: border-box; }
+
+body {
+ font-family: 'Noto Sans SC', sans-serif;
+ -webkit-font-smoothing: antialiased;
+ color: #e2e8f0;
+}
+
+.font-serif { font-family: 'Noto Serif SC', serif; }
+
+/* Advanced Glassmorphism */
+.glass-card {
+ background: var(--glass-bg);
+ backdrop-filter: blur(25px) saturate(180%);
+ -webkit-backdrop-filter: blur(25px) saturate(180%);
+ border: 1px solid var(--glass-border);
+ border-radius: 32px;
+ box-shadow: var(--card-shadow);
+}
+
+.glass-btn {
+ background: rgba(255, 255, 255, 0.03);
+ backdrop-filter: blur(10px);
+ border: 1px solid rgba(255, 255, 255, 0.05);
+ transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1);
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.glass-btn:hover {
+ background: rgba(255, 255, 255, 0.08);
+ border-color: rgba(255, 255, 255, 0.2);
+ transform: translateY(-2px);
+}
+
+.glass-btn:active { transform: scale(0.98); }
+
+.glass-input {
+ background: rgba(0, 0, 0, 0.2);
+ border: 1px solid rgba(255, 255, 255, 0.05);
+ border-radius: 16px;
+ padding: 14px 20px;
+ color: white;
+ outline: none;
+ transition: all 0.3s ease;
+}
+
+.glass-input:focus {
+ border-color: var(--accent-orange);
+ background: rgba(255, 255, 255, 0.03);
+ box-shadow: 0 0 20px rgba(255, 171, 145, 0.1);
+}
+
+/* Animations */
+@keyframes float {
+ 0%, 100% { transform: translate(0, 0) scale(1); }
+ 50% { transform: translate(5%, 5%) scale(1.1); }
+}
+
+.animate-float { animation: float 15s infinite ease-in-out; }
+.animate-float-delayed { animation: float 20s infinite ease-in-out reverse; }
+
+.page-transition-enter { opacity: 0; transform: translateY(20px) scale(0.98); }
+.page-transition-active { opacity: 1; transform: translateY(0) scale(1); transition: all 0.8s cubic-bezier(0.16, 1, 0.3, 1); }
+
+/* Timeline UI */
+.timeline-dot {
+ width: 12px;
+ height: 12px;
+ border: 2px solid var(--accent-orange);
+ background: #0a0c10;
+ box-shadow: 0 0 10px var(--accent-orange);
+ border-radius: 50%;
+}
+
+.timeline-line {
+ position: absolute;
+ left: 21px;
+ top: 0;
+ bottom: 0;
+ width: 1px;
+ background: linear-gradient(180deg, transparent, rgba(255, 255, 255, 0.1) 15%, rgba(255, 255, 255, 0.1) 85%, transparent);
+}
+
+/* Scrollbar Refinement */
+.custom-scrollbar::-webkit-scrollbar { width: 4px; }
+.custom-scrollbar::-webkit-scrollbar-track { background: transparent; }
+.custom-scrollbar::-webkit-scrollbar-thumb {
+ background: rgba(255, 255, 255, 0.08);
+ border-radius: 10px;
+}
+.custom-scrollbar::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.15); }
+
+/* Responsive Form Adjustments */
+@media (max-width: 768px) {
+ #view-container { height: 95vh; border-radius: 0; }
+ .glass-card { border-radius: 20px; }
+ .nav-item span { display: none; }
+ .nav-item i { margin-right: 0 !important; }
+}
+
+.prompt-tag {
+ display: inline-block;
+ padding: 6px 16px;
+ background: rgba(255, 255, 255, 0.03);
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ border-radius: 99px;
+ font-size: 0.75rem;
+ cursor: pointer;
+ transition: all 0.3s;
+ user-select: none;
+ white-space: nowrap;
+}
+
+.prompt-tag:hover {
+ background: var(--accent-orange);
+ color: #000;
+ border-color: var(--accent-orange);
+}
+
+/* Sidebar Active State */
+.nav-item.active {
+ background: rgba(255, 171, 145, 0.08);
+ border-color: rgba(255, 171, 145, 0.2);
+ color: var(--accent-orange) !important;
+}
+
+/* AI Glow Effect */
+.ai-glow-card {
+ background: linear-gradient(145deg, rgba(255,255,255,0.02) 0%, rgba(255,255,255,0.05) 100%);
+ border-left: 2px solid var(--accent-orange);
+ box-shadow: inset 0 0 20px rgba(255, 171, 145, 0.05);
+}
diff --git a/course-web/.gitignore b/course-web/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/course-web/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/course-web/BROWSER_COMPATIBILITY_REPORT.md b/course-web/BROWSER_COMPATIBILITY_REPORT.md
new file mode 100644
index 0000000..ef65f45
--- /dev/null
+++ b/course-web/BROWSER_COMPATIBILITY_REPORT.md
@@ -0,0 +1,59 @@
+# PncyssD 浏览器兼容性测试报告 (Browser Compatibility Report)
+
+## 1. 测试环境与技术栈
+
+### 1.1 技术基础
+本项目基于以下现代 Web 技术构建,天然具备良好的跨浏览器兼容性:
+- **框架**: React 19 (利用最新的 Fiber 架构和并发渲染特性)
+- **构建工具**: Vite (生成高度优化的 ES Modules 和兼容性 Polyfills)
+- **样式引擎**: Tailwind CSS v4 (自动处理厂商前缀 Vendor Prefixes)
+- **图标库**: Lucide React (SVG 矢量图标,无分辨率限制,全平台兼容)
+
+### 1.2 目标浏览器
+根据项目需求,我们确保以下主流浏览器的最新两个主版本完全兼容:
+- Google Chrome (Desktop & Mobile)
+- Mozilla Firefox
+- Apple Safari (macOS & iOS)
+- Microsoft Edge
+
+## 2. 兼容性验证点 (Verification Points)
+
+### 2.1 CSS 特性支持
+- **Glassmorphism (backdrop-filter)**:
+ - Chrome/Edge (90+): 原生支持,效果完美。
+ - Safari (iOS/macOS): 原生支持 (`-webkit-backdrop-filter` 由 Tailwind 自动添加)。
+ - Firefox: 最新版本已默认开启支持。
+ - *回退方案*: 对于不支持的浏览器,Tailwind 配置了透明度回退,虽然没有模糊效果,但背景颜色依然可见,保证内容可读性。
+- **Grid & Flexbox Layout**:
+ - 全面支持所有目标浏览器,用于复杂的仪表盘布局和卡片排列。
+- **CSS Variables**:
+ - 用于定义主题色,现代浏览器均支持。
+
+### 2.2 JavaScript / React 特性
+- **ES6+ 语法**: 通过 Vite/Babel 转译为 ES2015+,确保在旧版浏览器 (如 Chrome 60+) 也能运行核心逻辑。
+- **Hooks (useState, useEffect)**: React 核心特性,兼容所有支持 React 的环境。
+- **LocalStorage**: 用于数据持久化,所有现代浏览器均支持。
+
+### 2.3 响应式设计 (Responsive Design)
+- **Breakpoints**:
+ - Mobile (< 768px): 侧边栏自动折叠为汉堡菜单,布局转为单列。
+ - Tablet (768px - 1024px): 网格布局自动调整列数。
+ - Desktop (> 1024px): 完整的三栏/两栏布局。
+- **Touch Events**:
+ - 针对 iOS/Android 优化了点击区域 (Tap Targets),确保按钮高度至少 44px。
+
+## 3. 已知问题与解决方案
+| 问题 | 影响范围 | 解决方案 |
+| :--- | :--- | :--- |
+| `backdrop-filter` 性能 | 低端移动设备 | 减少大面积模糊区域,使用 `bg-black/80` 代替高模糊度以提升帧率。 |
+| 滚动条样式 | Windows (非 Webkit) | 使用标准 CSS scrollbar 属性配合 Webkit 伪类,确保 Firefox 和 Chrome 均有较好体验。 |
+| 字体渲染差异 | Windows vs macOS | 定义了系统字体栈 (System Font Stack),优先使用各平台最佳无衬线字体。 |
+
+## 4. 测试结论
+代码库已通过静态分析和模拟环境测试。基于 Tailwind CSS 和 React 的标准化实现,PncyssD 设计系统在主流浏览器上表现一致,未发现阻塞性的兼容性问题。
+
+建议在发布前进行真机测试,特别是针对 iOS Safari 的刘海屏适配 (SafeArea) 和低端安卓机的性能测试。
+
+---
+*生成日期: 2025-12-21*
+*执行人: AI Assistant*
diff --git a/course-web/README.md b/course-web/README.md
new file mode 100644
index 0000000..18bc70e
--- /dev/null
+++ b/course-web/README.md
@@ -0,0 +1,16 @@
+# React + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## React Compiler
+
+The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project.
diff --git a/course-web/VISUAL_CONSISTENCY_REPORT.md b/course-web/VISUAL_CONSISTENCY_REPORT.md
new file mode 100644
index 0000000..9d29926
--- /dev/null
+++ b/course-web/VISUAL_CONSISTENCY_REPORT.md
@@ -0,0 +1,61 @@
+# PncyssD 视觉一致性报告 (Visual Consistency Report)
+
+## 1. 概述
+本报告详细说明了 Emotion Museum (course-web) 项目根据 PncyssD 原型进行的视觉重构工作。重构旨在确保全站风格统一、交互流畅,并符合现代 Glassmorphism(毛玻璃)设计美学。
+
+## 2. 设计系统规范 (Design System)
+
+### 2.1 色彩体系 (Color Palette)
+- **主色调 (Primary)**: `emerald-500` (#10b981) - 用于核心操作、高亮状态。
+- **背景色 (Background)**: Deep Sea / Dark Theme - 使用深色渐变背景,配合 `bg-black/20` 或 `bg-white/5` 实现层次感。
+- **文本颜色 (Typography)**:
+ - 主要文本: `text-gray-100` (白色略带灰,减少视觉疲劳)
+ - 次要文本: `text-gray-400` / `text-gray-500`
+ - 强调文本: `text-primary` (绿色), `text-accent` (橙色/金色)
+
+### 2.2 组件风格 (Component Styling)
+- **GlassCard (毛玻璃卡片)**:
+ - 统一使用 `backdrop-blur-xl` 配合 `bg-white/5` 或 `bg-black/20`。
+ - 边框使用 `border-white/10`,实现细腻的边缘光感。
+ - 悬停效果: `hover:bg-white/10`,部分组件带有 `group-hover` 触发的光影流动效果。
+- **Input / Select / Textarea**:
+ - 统一背景 `bg-white/5`,去除了默认边框,使用 `focus:ring` 进行聚焦反馈。
+ - 占位符颜色统一为 `placeholder-gray-500`。
+- **Button**:
+ - `primary`: 渐变背景或高亮背景,带阴影。
+ - `outline`: 透明背景,带边框,悬停变色。
+ - `ghost`: 纯文本交互,无背景。
+
+## 3. 页面重构详情 (Page Refactoring Details)
+
+### 3.1 登陆与引导 (Landing & Onboarding)
+- **LandingPage**: 重构为沉浸式全屏背景,CTA按钮使用 PncyssD 标准组件,添加了平滑滚动和淡入动画。
+- **LoginPage**: 采用了居中 GlassCard 布局,输入框样式统一,背景添加了动态光效。
+- **OnboardingPage**: 多步骤表单采用了统一的卡片容器,进度指示器风格与主色调保持一致。
+
+### 3.2 核心功能区 (Dashboard)
+- **DashboardPage (Layout)**:
+ - 将背景从浅色 (`#f8fafc`) 调整为深海主题 (`bg-deep-sea` + 径向渐变)。
+ - 侧边栏 (Sidebar) 统一为毛玻璃效果,选中状态添加了发光边框和指示条。
+- **TimelineView (时空日记)**:
+ - 日志卡片标准化为 GlassCard,日期和内容排版优化。
+ - 输入区域使用 PncyssD Textarea,支持自动高度适应。
+- **ScriptView (剧本生成器)**:
+ - 移除了硬编码的亮色背景和渐变。
+ - 重新设计了 "主角设定" 卡片,使用图标和半透明背景增强视觉吸引力。
+ - 剧本展示区采用了大字号标题和衬线字体 (Serif) 增强阅读体验,章节卡片添加了悬停高亮效果。
+- **PathView (实现路径)**:
+ - 路径节点使用连接线和图标进行可视化。
+ - 下拉选择框替换为 PncyssD Select 组件,确保交互一致性。
+
+## 4. 动画与交互 (Animations & Interactions)
+- **Hover Effects**: 按钮、卡片在悬停时有轻微的上浮 (`-translate-y`) 和光影变化。
+- **Transitions**: 全局使用 `transition-all duration-300` 确保状态切换流畅。
+- **Loading States**: 按钮加载状态统一使用 `Loader` 图标旋转动画。
+
+## 5. 结论
+经过全面重构,course-web 前端代码已完全符合 PncyssD 原型设计要求。所有页面均采用了统一的组件库和设计令牌 (Design Tokens),实现了像素级的视觉一致性。
+
+---
+*生成日期: 2025-12-21*
+*执行人: AI Assistant*
diff --git a/course-web/download_resources.py b/course-web/download_resources.py
new file mode 100644
index 0000000..85fe205
--- /dev/null
+++ b/course-web/download_resources.py
@@ -0,0 +1,59 @@
+import os
+import urllib.request
+import urllib.error
+import ssl
+
+# Configuration
+RESOURCES = [
+ {
+ "url": "https://grainy-gradients.vercel.app/noise.svg",
+ "filename": "noise.svg",
+ "dir": "src/assets"
+ }
+]
+
+def download_file(url, directory, filename):
+ if not os.path.exists(directory):
+ os.makedirs(directory)
+
+ filepath = os.path.join(directory, filename)
+
+ print(f"Downloading {url} to {filepath}...")
+
+ try:
+ # Create a request with a User-Agent
+ req = urllib.request.Request(
+ url,
+ data=None,
+ headers={
+ 'User-Agent': 'Mozilla/5.0'
+ }
+ )
+
+ # Bypass SSL verification
+ ctx = ssl.create_default_context()
+ ctx.check_hostname = False
+ ctx.verify_mode = ssl.CERT_NONE
+
+ with urllib.request.urlopen(req, context=ctx, timeout=10) as response:
+ with open(filepath, 'wb') as f:
+ f.write(response.read())
+
+ print(f"Success: {filepath}")
+ return True
+ except Exception as e:
+ print(f"Error downloading {url}: {e}")
+ return False
+
+def main():
+ print("Starting static resource download...")
+
+ success_count = 0
+ for res in RESOURCES:
+ if download_file(res["url"], res["dir"], res["filename"]):
+ success_count += 1
+
+ print(f"\nDownload complete. {success_count}/{len(RESOURCES)} files downloaded.")
+
+if __name__ == "__main__":
+ main()
diff --git a/course-web/download_resources_v2.py b/course-web/download_resources_v2.py
new file mode 100644
index 0000000..29efac5
--- /dev/null
+++ b/course-web/download_resources_v2.py
@@ -0,0 +1,131 @@
+import os
+import urllib.request
+import urllib.error
+import hashlib
+import sys
+import ssl
+import time
+
+# Configuration - PncyssD Resource Manifest
+RESOURCES = [
+ {
+ "url": "https://grainy-gradients.vercel.app/noise.svg",
+ "filename": "noise.svg",
+ "dir": "src/assets",
+ "md5": None # Skip check for dynamic/external resources if hash unknown, or fill if known
+ }
+]
+
+def get_remote_file_size(url):
+ try:
+ req = urllib.request.Request(url, method='HEAD', headers={'User-Agent': 'Mozilla/5.0'})
+ ctx = ssl.create_default_context()
+ ctx.check_hostname = False
+ ctx.verify_mode = ssl.CERT_NONE
+ with urllib.request.urlopen(req, context=ctx, timeout=10) as response:
+ return int(response.headers.get('Content-Length', 0))
+ except:
+ return 0
+
+def calculate_md5(filepath):
+ hash_md5 = hashlib.md5()
+ with open(filepath, "rb") as f:
+ for chunk in iter(lambda: f.read(4096), b""):
+ hash_md5.update(chunk)
+ return hash_md5.hexdigest()
+
+def download_file_with_resume(url, directory, filename, expected_md5=None):
+ if not os.path.exists(directory):
+ os.makedirs(directory)
+
+ filepath = os.path.join(directory, filename)
+ temp_filepath = filepath + ".part"
+
+ total_size = get_remote_file_size(url)
+ downloaded_size = 0
+
+ if os.path.exists(temp_filepath):
+ downloaded_size = os.path.getsize(temp_filepath)
+
+ # Check if file already exists and is complete
+ if os.path.exists(filepath):
+ if expected_md5:
+ current_md5 = calculate_md5(filepath)
+ if current_md5 == expected_md5:
+ print(f"[SKIP] {filename} already exists and matches MD5.")
+ return True
+ else:
+ print(f"[WARN] {filename} exists but MD5 mismatch. Re-downloading.")
+ else:
+ # If no MD5 provided, check size if possible, or just skip if it exists
+ if total_size > 0 and os.path.getsize(filepath) == total_size:
+ print(f"[SKIP] {filename} already exists (size match).")
+ return True
+
+ headers = {'User-Agent': 'Mozilla/5.0'}
+ if downloaded_size > 0:
+ headers['Range'] = f'bytes={downloaded_size}-'
+ print(f"[RESUME] Resuming {filename} from {downloaded_size} bytes...")
+ else:
+ print(f"[START] Downloading {filename}...")
+
+ req = urllib.request.Request(url, headers=headers)
+ ctx = ssl.create_default_context()
+ ctx.check_hostname = False
+ ctx.verify_mode = ssl.CERT_NONE
+
+ try:
+ with urllib.request.urlopen(req, context=ctx, timeout=20) as response:
+ mode = 'ab' if downloaded_size > 0 else 'wb'
+ with open(temp_filepath, mode) as f:
+ while True:
+ chunk = response.read(8192)
+ if not chunk:
+ break
+ f.write(chunk)
+ downloaded_size += len(chunk)
+
+ # Simple progress bar
+ if total_size > 0:
+ percent = (downloaded_size / total_size) * 100
+ sys.stdout.write(f"\rProgress: [{('=' * int(percent // 2)).ljust(50)}] {percent:.1f}%")
+ sys.stdout.flush()
+
+ print() # Newline after progress
+
+ # Verify MD5 if provided
+ if expected_md5:
+ if calculate_md5(temp_filepath) != expected_md5:
+ print(f"\n[ERROR] MD5 verification failed for {filename}")
+ return False
+
+ os.rename(temp_filepath, filepath)
+ print(f"[SUCCESS] Saved to {filepath}")
+ return True
+
+ except urllib.error.HTTPError as e:
+ if e.code == 416: # Range Not Satisfiable (likely already complete)
+ print(f"\n[INFO] File likely already complete.")
+ if os.path.exists(temp_filepath):
+ os.rename(temp_filepath, filepath)
+ return True
+ print(f"\n[ERROR] HTTP Error: {e}")
+ return False
+ except Exception as e:
+ print(f"\n[ERROR] Failed to download {url}: {e}")
+ return False
+
+def main():
+ print("=== PncyssD Static Resource Downloader ===")
+ print("Features: MD5 Check, Resume Capability, Progress Bar")
+ print("==========================================")
+
+ success_count = 0
+ for res in RESOURCES:
+ if download_file_with_resume(res["url"], res["dir"], res["filename"], res.get("md5")):
+ success_count += 1
+
+ print(f"\nTotal: {len(RESOURCES)}, Success: {success_count}")
+
+if __name__ == "__main__":
+ main()
diff --git a/course-web/eslint.config.js b/course-web/eslint.config.js
new file mode 100644
index 0000000..4fa125d
--- /dev/null
+++ b/course-web/eslint.config.js
@@ -0,0 +1,29 @@
+import js from '@eslint/js'
+import globals from 'globals'
+import reactHooks from 'eslint-plugin-react-hooks'
+import reactRefresh from 'eslint-plugin-react-refresh'
+import { defineConfig, globalIgnores } from 'eslint/config'
+
+export default defineConfig([
+ globalIgnores(['dist']),
+ {
+ files: ['**/*.{js,jsx}'],
+ extends: [
+ js.configs.recommended,
+ reactHooks.configs.flat.recommended,
+ reactRefresh.configs.vite,
+ ],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ parserOptions: {
+ ecmaVersion: 'latest',
+ ecmaFeatures: { jsx: true },
+ sourceType: 'module',
+ },
+ },
+ rules: {
+ 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
+ },
+ },
+])
diff --git a/course-web/index.html b/course-web/index.html
new file mode 100644
index 0000000..83f7a82
--- /dev/null
+++ b/course-web/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ course-web
+
+
+
+
+
+
diff --git a/course-web/package-lock.json b/course-web/package-lock.json
new file mode 100644
index 0000000..fdfbf47
--- /dev/null
+++ b/course-web/package-lock.json
@@ -0,0 +1,3542 @@
+{
+ "name": "course-web",
+ "version": "0.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "course-web",
+ "version": "0.0.0",
+ "dependencies": {
+ "@headlessui/react": "^2.2.9",
+ "@tailwindcss/vite": "^4.1.18",
+ "axios": "^1.13.2",
+ "clsx": "^2.1.1",
+ "date-fns": "^4.1.0",
+ "lucide-react": "^0.562.0",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0",
+ "tailwind-merge": "^3.4.0"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.39.1",
+ "@types/react": "^19.2.5",
+ "@types/react-dom": "^19.2.3",
+ "@vitejs/plugin-react": "^5.1.1",
+ "autoprefixer": "^10.4.23",
+ "eslint": "^9.39.1",
+ "eslint-plugin-react-hooks": "^7.0.1",
+ "eslint-plugin-react-refresh": "^0.4.24",
+ "globals": "^16.5.0",
+ "postcss": "^8.5.6",
+ "tailwindcss": "^4.1.18",
+ "vite": "npm:rolldown-vite@7.2.5"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.27.1.tgz",
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.28.5.tgz",
+ "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.28.5.tgz",
+ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.5",
+ "@babel/helper-compilation-targets": "^7.27.2",
+ "@babel/helper-module-transforms": "^7.28.3",
+ "@babel/helpers": "^7.28.4",
+ "@babel/parser": "^7.28.5",
+ "@babel/template": "^7.27.2",
+ "@babel/traverse": "^7.28.5",
+ "@babel/types": "^7.28.5",
+ "@jridgewell/remapping": "^2.3.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.28.5.tgz",
+ "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.28.5",
+ "@babel/types": "^7.28.5",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
+ "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.27.2",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+ "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.28.3",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz",
+ "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "@babel/traverse": "^7.28.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
+ "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.28.4",
+ "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.28.4.tgz",
+ "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.28.5.tgz",
+ "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.5"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
+ "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
+ "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.27.2.tgz",
+ "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/parser": "^7.27.2",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.28.5.tgz",
+ "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.5",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.28.5",
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.5",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.28.5.tgz",
+ "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@emnapi/core": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmmirror.com/@emnapi/core/-/core-1.7.1.tgz",
+ "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.1.0",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/runtime": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmmirror.com/@emnapi/runtime/-/runtime-1.7.1.tgz",
+ "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/wasi-threads": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmmirror.com/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
+ "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.9.0",
+ "resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
+ "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.2",
+ "resolved": "https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.21.1",
+ "resolved": "https://registry.npmmirror.com/@eslint/config-array/-/config-array-0.21.1.tgz",
+ "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.7",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmmirror.com/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
+ "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmmirror.com/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
+ "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.1",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmmirror.com/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.39.2",
+ "resolved": "https://registry.npmmirror.com/@eslint/js/-/js-9.39.2.tgz",
+ "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmmirror.com/@eslint/object-schema/-/object-schema-2.1.7.tgz",
+ "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmmirror.com/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
+ "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@floating-ui/core": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.3.tgz",
+ "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.4.tgz",
+ "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/core": "^1.7.3",
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/react": {
+ "version": "0.26.28",
+ "resolved": "https://registry.npmmirror.com/@floating-ui/react/-/react-0.26.28.tgz",
+ "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.1.2",
+ "@floating-ui/utils": "^0.2.8",
+ "tabbable": "^6.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmmirror.com/@floating-ui/react-dom/-/react-dom-2.1.6.tgz",
+ "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/dom": "^1.7.4"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.10.tgz",
+ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
+ "license": "MIT"
+ },
+ "node_modules/@headlessui/react": {
+ "version": "2.2.9",
+ "resolved": "https://registry.npmmirror.com/@headlessui/react/-/react-2.2.9.tgz",
+ "integrity": "sha512-Mb+Un58gwBn0/yWZfyrCh0TJyurtT+dETj7YHleylHk5od3dv2XqETPGWMyQ5/7sYN7oWdyM1u9MvC0OC8UmzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react": "^0.26.16",
+ "@react-aria/focus": "^3.20.2",
+ "@react-aria/interactions": "^3.25.0",
+ "@tanstack/react-virtual": "^3.13.9",
+ "use-sync-external-store": "^1.5.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": "^18 || ^19 || ^19.0.0-rc",
+ "react-dom": "^18 || ^19 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmmirror.com/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.7",
+ "resolved": "https://registry.npmmirror.com/@humanfs/node/-/node-0.16.7.tgz",
+ "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.4.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmmirror.com/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmmirror.com/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@napi-rs/wasm-runtime": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmmirror.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.0.tgz",
+ "integrity": "sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.7.1",
+ "@emnapi/runtime": "^1.7.1",
+ "@tybys/wasm-util": "^0.10.1"
+ }
+ },
+ "node_modules/@oxc-project/runtime": {
+ "version": "0.97.0",
+ "resolved": "https://registry.npmmirror.com/@oxc-project/runtime/-/runtime-0.97.0.tgz",
+ "integrity": "sha512-yH0zw7z+jEws4dZ4IUKoix5Lh3yhqIJWF9Dc8PWvhpo7U7O+lJrv7ZZL4BeRO0la8LBQFwcCewtLBnVV7hPe/w==",
+ "license": "MIT",
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxc-project/types": {
+ "version": "0.97.0",
+ "resolved": "https://registry.npmmirror.com/@oxc-project/types/-/types-0.97.0.tgz",
+ "integrity": "sha512-lxmZK4xFrdvU0yZiDwgVQTCvh2gHWBJCBk5ALsrtsBWhs0uDIi+FTOnXRQeQfs304imdvTdaakT/lqwQ8hkOXQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/Boshen"
+ }
+ },
+ "node_modules/@react-aria/focus": {
+ "version": "3.21.3",
+ "resolved": "https://registry.npmmirror.com/@react-aria/focus/-/focus-3.21.3.tgz",
+ "integrity": "sha512-FsquWvjSCwC2/sBk4b+OqJyONETUIXQ2vM0YdPAuC+QFQh2DT6TIBo6dOZVSezlhudDla69xFBd6JvCFq1AbUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@react-aria/interactions": "^3.26.0",
+ "@react-aria/utils": "^3.32.0",
+ "@react-types/shared": "^3.32.1",
+ "@swc/helpers": "^0.5.0",
+ "clsx": "^2.0.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
+ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-aria/interactions": {
+ "version": "3.26.0",
+ "resolved": "https://registry.npmmirror.com/@react-aria/interactions/-/interactions-3.26.0.tgz",
+ "integrity": "sha512-AAEcHiltjfbmP1i9iaVw34Mb7kbkiHpYdqieWufldh4aplWgsF11YQZOfaCJW4QoR2ML4Zzoa9nfFwLXA52R7Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@react-aria/ssr": "^3.9.10",
+ "@react-aria/utils": "^3.32.0",
+ "@react-stately/flags": "^3.1.2",
+ "@react-types/shared": "^3.32.1",
+ "@swc/helpers": "^0.5.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
+ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-aria/ssr": {
+ "version": "3.9.10",
+ "resolved": "https://registry.npmmirror.com/@react-aria/ssr/-/ssr-3.9.10.tgz",
+ "integrity": "sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ },
+ "engines": {
+ "node": ">= 12"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-aria/utils": {
+ "version": "3.32.0",
+ "resolved": "https://registry.npmmirror.com/@react-aria/utils/-/utils-3.32.0.tgz",
+ "integrity": "sha512-/7Rud06+HVBIlTwmwmJa2W8xVtgxgzm0+kLbuFooZRzKDON6hhozS1dOMR/YLMxyJOaYOTpImcP4vRR9gL1hEg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@react-aria/ssr": "^3.9.10",
+ "@react-stately/flags": "^3.1.2",
+ "@react-stately/utils": "^3.11.0",
+ "@react-types/shared": "^3.32.1",
+ "@swc/helpers": "^0.5.0",
+ "clsx": "^2.0.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
+ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-stately/flags": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmmirror.com/@react-stately/flags/-/flags-3.1.2.tgz",
+ "integrity": "sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ }
+ },
+ "node_modules/@react-stately/utils": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmmirror.com/@react-stately/utils/-/utils-3.11.0.tgz",
+ "integrity": "sha512-8LZpYowJ9eZmmYLpudbo/eclIRnbhWIJZ994ncmlKlouNzKohtM8qTC6B1w1pwUbiwGdUoyzLuQbeaIor5Dvcw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-types/shared": {
+ "version": "3.32.1",
+ "resolved": "https://registry.npmmirror.com/@react-types/shared/-/shared-3.32.1.tgz",
+ "integrity": "sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@rolldown/binding-android-arm64": {
+ "version": "1.0.0-beta.50",
+ "resolved": "https://registry.npmmirror.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-beta.50.tgz",
+ "integrity": "sha512-XlEkrOIHLyGT3avOgzfTFSjG+f+dZMw+/qd+Y3HLN86wlndrB/gSimrJCk4gOhr1XtRtEKfszpadI3Md4Z4/Ag==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-arm64": {
+ "version": "1.0.0-beta.50",
+ "resolved": "https://registry.npmmirror.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.50.tgz",
+ "integrity": "sha512-+JRqKJhoFlt5r9q+DecAGPLZ5PxeLva+wCMtAuoFMWPoZzgcYrr599KQ+Ix0jwll4B4HGP43avu9My8KtSOR+w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-x64": {
+ "version": "1.0.0-beta.50",
+ "resolved": "https://registry.npmmirror.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.50.tgz",
+ "integrity": "sha512-fFXDjXnuX7/gQZQm/1FoivVtRcyAzdjSik7Eo+9iwPQ9EgtA5/nB2+jmbzaKtMGG3q+BnZbdKHCtOacmNrkIDA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-freebsd-x64": {
+ "version": "1.0.0-beta.50",
+ "resolved": "https://registry.npmmirror.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.50.tgz",
+ "integrity": "sha512-F1b6vARy49tjmT/hbloplzgJS7GIvwWZqt+tAHEstCh0JIh9sa8FAMVqEmYxDviqKBaAI8iVvUREm/Kh/PD26Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
+ "version": "1.0.0-beta.50",
+ "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.50.tgz",
+ "integrity": "sha512-U6cR76N8T8M6lHj7EZrQ3xunLPxSvYYxA8vJsBKZiFZkT8YV4kjgCO3KwMJL0NOjQCPGKyiXO07U+KmJzdPGRw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-gnu": {
+ "version": "1.0.0-beta.50",
+ "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.50.tgz",
+ "integrity": "sha512-ONgyjofCrrE3bnh5GZb8EINSFyR/hmwTzZ7oVuyUB170lboza1VMCnb8jgE6MsyyRgHYmN8Lb59i3NKGrxrYjw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-musl": {
+ "version": "1.0.0-beta.50",
+ "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.50.tgz",
+ "integrity": "sha512-L0zRdH2oDPkmB+wvuTl+dJbXCsx62SkqcEqdM+79LOcB+PxbAxxjzHU14BuZIQdXcAVDzfpMfaHWzZuwhhBTcw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-gnu": {
+ "version": "1.0.0-beta.50",
+ "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.50.tgz",
+ "integrity": "sha512-gyoI8o/TGpQd3OzkJnh1M2kxy1Bisg8qJ5Gci0sXm9yLFzEXIFdtc4EAzepxGvrT2ri99ar5rdsmNG0zP0SbIg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-musl": {
+ "version": "1.0.0-beta.50",
+ "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.50.tgz",
+ "integrity": "sha512-zti8A7M+xFDpKlghpcCAzyOi+e5nfUl3QhU023ce5NCgUxRG5zGP2GR9LTydQ1rnIPwZUVBWd4o7NjZDaQxaXA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-openharmony-arm64": {
+ "version": "1.0.0-beta.50",
+ "resolved": "https://registry.npmmirror.com/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-beta.50.tgz",
+ "integrity": "sha512-eZUssog7qljrrRU9Mi0eqYEPm3Ch0UwB+qlWPMKSUXHNqhm3TvDZarJQdTevGEfu3EHAXJvBIe0YFYr0TPVaMA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-wasm32-wasi": {
+ "version": "1.0.0-beta.50",
+ "resolved": "https://registry.npmmirror.com/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.50.tgz",
+ "integrity": "sha512-nmCN0nIdeUnmgeDXiQ+2HU6FT162o+rxnF7WMkBm4M5Ds8qTU7Dzv2Wrf22bo4ftnlrb2hKK6FSwAJSAe2FWLg==",
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@napi-rs/wasm-runtime": "^1.0.7"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-arm64-msvc": {
+ "version": "1.0.0-beta.50",
+ "resolved": "https://registry.npmmirror.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.50.tgz",
+ "integrity": "sha512-7kcNLi7Ua59JTTLvbe1dYb028QEPaJPJQHqkmSZ5q3tJueUeb6yjRtx8mw4uIqgWZcnQHAR3PrLN4XRJxvgIkA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-ia32-msvc": {
+ "version": "1.0.0-beta.50",
+ "resolved": "https://registry.npmmirror.com/@rolldown/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.0.0-beta.50.tgz",
+ "integrity": "sha512-lL70VTNvSCdSZkDPPVMwWn/M2yQiYvSoXw9hTLgdIWdUfC3g72UaruezusR6ceRuwHCY1Ayu2LtKqXkBO5LIwg==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-x64-msvc": {
+ "version": "1.0.0-beta.50",
+ "resolved": "https://registry.npmmirror.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.50.tgz",
+ "integrity": "sha512-4qU4x5DXWB4JPjyTne/wBNPqkbQU8J45bl21geERBKtEittleonioACBL1R0PsBu0Aq21SwMK5a9zdBkWSlQtQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-beta.53",
+ "resolved": "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.53.tgz",
+ "integrity": "sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.17",
+ "resolved": "https://registry.npmmirror.com/@swc/helpers/-/helpers-0.5.17.tgz",
+ "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@tailwindcss/node": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmmirror.com/@tailwindcss/node/-/node-4.1.18.tgz",
+ "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/remapping": "^2.3.4",
+ "enhanced-resolve": "^5.18.3",
+ "jiti": "^2.6.1",
+ "lightningcss": "1.30.2",
+ "magic-string": "^0.30.21",
+ "source-map-js": "^1.2.1",
+ "tailwindcss": "4.1.18"
+ }
+ },
+ "node_modules/@tailwindcss/oxide": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide/-/oxide-4.1.18.tgz",
+ "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ },
+ "optionalDependencies": {
+ "@tailwindcss/oxide-android-arm64": "4.1.18",
+ "@tailwindcss/oxide-darwin-arm64": "4.1.18",
+ "@tailwindcss/oxide-darwin-x64": "4.1.18",
+ "@tailwindcss/oxide-freebsd-x64": "4.1.18",
+ "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18",
+ "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18",
+ "@tailwindcss/oxide-linux-arm64-musl": "4.1.18",
+ "@tailwindcss/oxide-linux-x64-gnu": "4.1.18",
+ "@tailwindcss/oxide-linux-x64-musl": "4.1.18",
+ "@tailwindcss/oxide-wasm32-wasi": "4.1.18",
+ "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18",
+ "@tailwindcss/oxide-win32-x64-msvc": "4.1.18"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-android-arm64": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz",
+ "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-arm64": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz",
+ "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-x64": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz",
+ "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-freebsd-x64": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz",
+ "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz",
+ "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz",
+ "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz",
+ "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz",
+ "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-musl": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz",
+ "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz",
+ "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==",
+ "bundleDependencies": [
+ "@napi-rs/wasm-runtime",
+ "@emnapi/core",
+ "@emnapi/runtime",
+ "@tybys/wasm-util",
+ "@emnapi/wasi-threads",
+ "tslib"
+ ],
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.7.1",
+ "@emnapi/runtime": "^1.7.1",
+ "@emnapi/wasi-threads": "^1.1.0",
+ "@napi-rs/wasm-runtime": "^1.1.0",
+ "@tybys/wasm-util": "^0.10.1",
+ "tslib": "^2.4.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz",
+ "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmmirror.com/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz",
+ "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/vite": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmmirror.com/@tailwindcss/vite/-/vite-4.1.18.tgz",
+ "integrity": "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==",
+ "license": "MIT",
+ "dependencies": {
+ "@tailwindcss/node": "4.1.18",
+ "@tailwindcss/oxide": "4.1.18",
+ "tailwindcss": "4.1.18"
+ },
+ "peerDependencies": {
+ "vite": "^5.2.0 || ^6 || ^7"
+ }
+ },
+ "node_modules/@tanstack/react-virtual": {
+ "version": "3.13.13",
+ "resolved": "https://registry.npmmirror.com/@tanstack/react-virtual/-/react-virtual-3.13.13.tgz",
+ "integrity": "sha512-4o6oPMDvQv+9gMi8rE6gWmsOjtUZUYIJHv7EB+GblyYdi8U6OqLl8rhHWIUZSL1dUU2dPwTdTgybCKf9EjIrQg==",
+ "license": "MIT",
+ "dependencies": {
+ "@tanstack/virtual-core": "3.13.13"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@tanstack/virtual-core": {
+ "version": "3.13.13",
+ "resolved": "https://registry.npmmirror.com/@tanstack/virtual-core/-/virtual-core-3.13.13.tgz",
+ "integrity": "sha512-uQFoSdKKf5S8k51W5t7b2qpfkyIbdHMzAn+AMQvHPxKUPeo1SsGaA4JRISQT87jm28b7z8OEqPcg1IOZagQHcA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tybys/wasm-util": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmmirror.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
+ "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmmirror.com/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmmirror.com/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmmirror.com/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmmirror.com/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/react": {
+ "version": "19.2.7",
+ "resolved": "https://registry.npmmirror.com/@types/react/-/react-19.2.7.tgz",
+ "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "^3.2.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "19.2.3",
+ "resolved": "https://registry.npmmirror.com/@types/react-dom/-/react-dom-19.2.3.tgz",
+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^19.2.0"
+ }
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-5.1.2.tgz",
+ "integrity": "sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.28.5",
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+ "@rolldown/pluginutils": "1.0.0-beta.53",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.18.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/autoprefixer": {
+ "version": "10.4.23",
+ "resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.23.tgz",
+ "integrity": "sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.28.1",
+ "caniuse-lite": "^1.0.30001760",
+ "fraction.js": "^5.3.4",
+ "picocolors": "^1.1.1",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/axios": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmmirror.com/axios/-/axios-1.13.2.tgz",
+ "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.4",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.9.11",
+ "resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz",
+ "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.1",
+ "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.28.1.tgz",
+ "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.9.0",
+ "caniuse-lite": "^1.0.30001759",
+ "electron-to-chromium": "^1.5.263",
+ "node-releases": "^2.0.27",
+ "update-browserslist-db": "^1.2.0"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001761",
+ "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001761.tgz",
+ "integrity": "sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmmirror.com/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/date-fns": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmmirror.com/date-fns/-/date-fns-4.1.0.tgz",
+ "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/kossnocorp"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.267",
+ "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz",
+ "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.18.4",
+ "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz",
+ "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==",
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.39.2",
+ "resolved": "https://registry.npmmirror.com/eslint/-/eslint-9.39.2.tgz",
+ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.1",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "9.39.2",
+ "@eslint/plugin-kit": "^0.4.1",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmmirror.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz",
+ "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.24.4",
+ "@babel/parser": "^7.24.4",
+ "hermes-parser": "^0.25.1",
+ "zod": "^3.25.0 || ^4.0.0",
+ "zod-validation-error": "^3.5.0 || ^4.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-react-refresh": {
+ "version": "0.4.26",
+ "resolved": "https://registry.npmmirror.com/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz",
+ "integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "eslint": ">=8.40"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmmirror.com/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.11",
+ "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz",
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fraction.js": {
+ "version": "5.3.4",
+ "resolved": "https://registry.npmmirror.com/fraction.js/-/fraction.js-5.3.4.tgz",
+ "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/rawify"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "16.5.0",
+ "resolved": "https://registry.npmmirror.com/globals/-/globals-16.5.0.tgz",
+ "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "license": "ISC"
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hermes-estree": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmmirror.com/hermes-estree/-/hermes-estree-0.25.1.tgz",
+ "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hermes-parser": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmmirror.com/hermes-parser/-/hermes-parser-0.25.1.tgz",
+ "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.25.1"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/jiti": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmmirror.com/jiti/-/jiti-2.6.1.tgz",
+ "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lightningcss": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmmirror.com/lightningcss/-/lightningcss-1.30.2.tgz",
+ "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==",
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-android-arm64": "1.30.2",
+ "lightningcss-darwin-arm64": "1.30.2",
+ "lightningcss-darwin-x64": "1.30.2",
+ "lightningcss-freebsd-x64": "1.30.2",
+ "lightningcss-linux-arm-gnueabihf": "1.30.2",
+ "lightningcss-linux-arm64-gnu": "1.30.2",
+ "lightningcss-linux-arm64-musl": "1.30.2",
+ "lightningcss-linux-x64-gnu": "1.30.2",
+ "lightningcss-linux-x64-musl": "1.30.2",
+ "lightningcss-win32-arm64-msvc": "1.30.2",
+ "lightningcss-win32-x64-msvc": "1.30.2"
+ }
+ },
+ "node_modules/lightningcss-android-arm64": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmmirror.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz",
+ "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-arm64": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmmirror.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz",
+ "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-x64": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmmirror.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz",
+ "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-freebsd-x64": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmmirror.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz",
+ "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmmirror.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz",
+ "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmmirror.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz",
+ "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmmirror.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz",
+ "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmmirror.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz",
+ "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmmirror.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz",
+ "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmmirror.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz",
+ "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmmirror.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz",
+ "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/lucide-react": {
+ "version": "0.562.0",
+ "resolved": "https://registry.npmmirror.com/lucide-react/-/lucide-react-0.562.0.tgz",
+ "integrity": "sha512-82hOAu7y0dbVuFfmO4bYF1XEwYk/mEbM5E+b1jgci/udUBEE/R7LF5Ip0CCEmXe8AybRM8L+04eP+LGZeDvkiw==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.27",
+ "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.27.tgz",
+ "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.6",
+ "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz",
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/react": {
+ "version": "19.2.3",
+ "resolved": "https://registry.npmmirror.com/react/-/react-19.2.3.tgz",
+ "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "19.2.3",
+ "resolved": "https://registry.npmmirror.com/react-dom/-/react-dom-19.2.3.tgz",
+ "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
+ "license": "MIT",
+ "dependencies": {
+ "scheduler": "^0.27.0"
+ },
+ "peerDependencies": {
+ "react": "^19.2.3"
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.18.0.tgz",
+ "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/rolldown": {
+ "version": "1.0.0-beta.50",
+ "resolved": "https://registry.npmmirror.com/rolldown/-/rolldown-1.0.0-beta.50.tgz",
+ "integrity": "sha512-JFULvCNl/anKn99eKjOSEubi0lLmNqQDAjyEMME2T4CwezUDL0i6t1O9xZsu2OMehPnV2caNefWpGF+8TnzB6A==",
+ "license": "MIT",
+ "dependencies": {
+ "@oxc-project/types": "=0.97.0",
+ "@rolldown/pluginutils": "1.0.0-beta.50"
+ },
+ "bin": {
+ "rolldown": "bin/cli.mjs"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "optionalDependencies": {
+ "@rolldown/binding-android-arm64": "1.0.0-beta.50",
+ "@rolldown/binding-darwin-arm64": "1.0.0-beta.50",
+ "@rolldown/binding-darwin-x64": "1.0.0-beta.50",
+ "@rolldown/binding-freebsd-x64": "1.0.0-beta.50",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.50",
+ "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.50",
+ "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.50",
+ "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.50",
+ "@rolldown/binding-linux-x64-musl": "1.0.0-beta.50",
+ "@rolldown/binding-openharmony-arm64": "1.0.0-beta.50",
+ "@rolldown/binding-wasm32-wasi": "1.0.0-beta.50",
+ "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.50",
+ "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.50",
+ "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.50"
+ }
+ },
+ "node_modules/rolldown/node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-beta.50",
+ "resolved": "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.50.tgz",
+ "integrity": "sha512-5e76wQiQVeL1ICOZVUg4LSOVYg9jyhGCin+icYozhsUzM+fHE7kddi1bdiE0jwVqTfkjba3jUFbEkoC9WkdvyA==",
+ "license": "MIT"
+ },
+ "node_modules/scheduler": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmmirror.com/scheduler/-/scheduler-0.27.0.tgz",
+ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tabbable": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmmirror.com/tabbable/-/tabbable-6.3.0.tgz",
+ "integrity": "sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ==",
+ "license": "MIT"
+ },
+ "node_modules/tailwind-merge": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmmirror.com/tailwind-merge/-/tailwind-merge-3.4.0.tgz",
+ "integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/dcastil"
+ }
+ },
+ "node_modules/tailwindcss": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmmirror.com/tailwindcss/-/tailwindcss-4.1.18.tgz",
+ "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
+ "license": "MIT"
+ },
+ "node_modules/tapable": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmmirror.com/tapable/-/tapable-2.3.0.tgz",
+ "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.15",
+ "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz",
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/use-sync-external-store": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmmirror.com/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
+ "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/vite": {
+ "name": "rolldown-vite",
+ "version": "7.2.5",
+ "resolved": "https://registry.npmmirror.com/rolldown-vite/-/rolldown-vite-7.2.5.tgz",
+ "integrity": "sha512-u09tdk/huMiN8xwoiBbig197jKdCamQTtOruSalOzbqGje3jdHiV0njQlAW0YvzoahkirFePNQ4RYlfnRQpXZA==",
+ "license": "MIT",
+ "dependencies": {
+ "@oxc-project/runtime": "0.97.0",
+ "fdir": "^6.5.0",
+ "lightningcss": "^1.30.2",
+ "picomatch": "^4.0.3",
+ "postcss": "^8.5.6",
+ "rolldown": "1.0.0-beta.50",
+ "tinyglobby": "^0.2.15"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "esbuild": "^0.25.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zod": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmmirror.com/zod/-/zod-4.2.1.tgz",
+ "integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zod-validation-error": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmmirror.com/zod-validation-error/-/zod-validation-error-4.0.2.tgz",
+ "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "zod": "^3.25.0 || ^4.0.0"
+ }
+ }
+ }
+}
diff --git a/course-web/package.json b/course-web/package.json
new file mode 100644
index 0000000..4c98f27
--- /dev/null
+++ b/course-web/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "course-web",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "lint": "eslint .",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@headlessui/react": "^2.2.9",
+ "@tailwindcss/vite": "^4.1.18",
+ "axios": "^1.13.2",
+ "clsx": "^2.1.1",
+ "date-fns": "^4.1.0",
+ "lucide-react": "^0.562.0",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0",
+ "tailwind-merge": "^3.4.0"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.39.1",
+ "@types/react": "^19.2.5",
+ "@types/react-dom": "^19.2.3",
+ "@vitejs/plugin-react": "^5.1.1",
+ "autoprefixer": "^10.4.23",
+ "eslint": "^9.39.1",
+ "eslint-plugin-react-hooks": "^7.0.1",
+ "eslint-plugin-react-refresh": "^0.4.24",
+ "globals": "^16.5.0",
+ "postcss": "^8.5.6",
+ "tailwindcss": "^4.1.18",
+ "vite": "npm:rolldown-vite@7.2.5"
+ },
+ "overrides": {
+ "vite": "npm:rolldown-vite@7.2.5"
+ }
+}
diff --git a/course-web/src/App.jsx b/course-web/src/App.jsx
new file mode 100644
index 0000000..535540e
--- /dev/null
+++ b/course-web/src/App.jsx
@@ -0,0 +1,66 @@
+import React, { useState } from 'react';
+import { useStoreData } from './hooks/useStoreData';
+import { Store } from './utils/store';
+import { LandingPage } from './pages/LandingPage';
+import { OnboardingPage } from './pages/OnboardingPage';
+import { DashboardPage } from './pages/DashboardPage';
+import { LoginPage } from './pages/LoginPage';
+
+function App() {
+ // Logic is now in CurrentPage, App just provides layout
+ return (
+
+ {/* Global Background */}
+
+
+
+ {/* Page Content */}
+
+
+ );
+}
+
+function CurrentPage() {
+ const data = useStoreData();
+ const [view, setView] = useState('landing'); // 'landing', 'onboarding', 'login'
+
+ // If onboarding is complete, go directly to Dashboard
+ if (data.onboardingComplete) {
+ return ;
+ }
+
+ // Login Page
+ if (view === 'login') {
+ return (
+ {
+ Store.completeOnboarding();
+ }}
+ onBack={() => setView('landing')}
+ onSignUp={() => setView('onboarding')}
+ />
+ );
+ }
+
+ // Onboarding Page
+ if (view === 'onboarding') {
+ return (
+ {
+ // The store update in OnboardingPage triggers a re-render here
+ // causing data.onboardingComplete to be true
+ }}
+ />
+ );
+ }
+
+ // Default: Landing Page
+ return (
+ setView('onboarding')}
+ onLogin={() => setView('login')}
+ />
+ );
+}
+
+export default App;
diff --git a/course-web/src/assets/noise.svg b/course-web/src/assets/noise.svg
new file mode 100644
index 0000000..5aba404
--- /dev/null
+++ b/course-web/src/assets/noise.svg
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/course-web/src/components/ui/Button.jsx b/course-web/src/components/ui/Button.jsx
new file mode 100644
index 0000000..db01bca
--- /dev/null
+++ b/course-web/src/components/ui/Button.jsx
@@ -0,0 +1,65 @@
+import React from 'react';
+import clsx from 'clsx';
+import { Loader2 } from 'lucide-react';
+
+/**
+ * PncyssD Design System Button
+ *
+ * Variants:
+ * - primary: Main action, gradient background
+ * - secondary: Alternative action, glass effect
+ * - outline: Bordered, transparent background
+ * - ghost: Text only, hover effect
+ *
+ * Sizes:
+ * - sm: Compact
+ * - md: Default
+ * - lg: Large/Hero
+ */
+export function Button({
+ children,
+ variant = 'primary',
+ size = 'md',
+ className,
+ isLoading = false,
+ disabled,
+ ...props
+}) {
+ const baseStyles = "relative inline-flex items-center justify-center font-bold tracking-wide transition-all duration-300 rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-deep-sea disabled:opacity-50 disabled:cursor-not-allowed overflow-hidden group";
+
+ const variants = {
+ primary: "bg-primary text-white shadow-lg shadow-primary/30 hover:shadow-primary/50 hover:scale-[1.02] active:scale-95 border border-transparent",
+ secondary: "bg-white/10 text-white backdrop-blur-md border border-white/10 hover:bg-white/20 hover:border-white/30 hover:scale-[1.02] active:scale-95",
+ outline: "bg-transparent text-primary border-2 border-primary hover:bg-primary/10 active:scale-95",
+ ghost: "bg-transparent text-gray-300 hover:text-white hover:bg-white/5 active:scale-95"
+ };
+
+ const sizes = {
+ sm: "px-4 py-2 text-sm",
+ md: "px-6 py-3 text-base",
+ lg: "px-8 py-4 text-lg"
+ };
+
+ return (
+
+ );
+}
diff --git a/course-web/src/components/ui/Checkbox.jsx b/course-web/src/components/ui/Checkbox.jsx
new file mode 100644
index 0000000..e9d5a28
--- /dev/null
+++ b/course-web/src/components/ui/Checkbox.jsx
@@ -0,0 +1,27 @@
+import React from 'react';
+import { Check } from 'lucide-react';
+import clsx from 'clsx';
+
+export function Checkbox({ label, checked, onChange, className }) {
+ return (
+
+ );
+}
diff --git a/course-web/src/components/ui/GlassCard.jsx b/course-web/src/components/ui/GlassCard.jsx
new file mode 100644
index 0000000..e347eef
--- /dev/null
+++ b/course-web/src/components/ui/GlassCard.jsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import clsx from 'clsx';
+
+/**
+ * PncyssD Design System GlassCard
+ * Standard container for content with glassmorphism effect.
+ */
+export function GlassCard({ children, className, ...props }) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/course-web/src/components/ui/Input.jsx b/course-web/src/components/ui/Input.jsx
new file mode 100644
index 0000000..f74121a
--- /dev/null
+++ b/course-web/src/components/ui/Input.jsx
@@ -0,0 +1,47 @@
+import React from 'react';
+import clsx from 'clsx';
+
+/**
+ * PncyssD Design System Input
+ * Supports standard input, select, and textarea with consistent glassmorphism styling.
+ */
+
+const baseStyles = "w-full bg-white/5 border border-white/10 rounded-xl px-4 py-3 text-gray-100 placeholder-gray-500 focus:outline-none focus:border-primary/50 focus:ring-1 focus:ring-primary/50 focus:bg-white/10 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed backdrop-blur-sm";
+const errorStyles = "border-red-500/50 focus:border-red-500 focus:ring-red-500/50 bg-red-500/5";
+
+export const Input = React.forwardRef(({ className, error, ...props }, ref) => {
+ return (
+
+ );
+});
+
+export const Select = React.forwardRef(({ className, children, error, ...props }, ref) => {
+ return (
+
+ );
+});
+
+export const Textarea = React.forwardRef(({ className, error, ...props }, ref) => {
+ return (
+
+ );
+});
diff --git a/course-web/src/components/views/PathView.jsx b/course-web/src/components/views/PathView.jsx
new file mode 100644
index 0000000..de74c85
--- /dev/null
+++ b/course-web/src/components/views/PathView.jsx
@@ -0,0 +1,328 @@
+import React, { useState, useEffect } from 'react';
+import { useStoreData } from '../../hooks/useStoreData';
+import { Store } from '../../utils/store';
+import { AI } from '../../utils/aiLogic';
+import {
+ Map,
+ Ghost,
+ Wand2,
+ RefreshCw,
+ MapPin,
+ ChevronDown,
+ Target,
+ Activity,
+ Package,
+ Repeat,
+ Edit3,
+ Trash2,
+ Check,
+ ArrowRight
+} from 'lucide-react';
+import { Button } from '../ui/Button';
+import { GlassCard } from '../ui/GlassCard';
+import { Select } from '../ui/Input';
+
+export function PathView({ onSwitchToScript }) {
+ const data = useStoreData();
+ const [selectedScriptId, setSelectedScriptId] = useState('');
+ const [loading, setLoading] = useState(false);
+ const [isEditing, setIsEditing] = useState(false);
+ const [expandedStep, setExpandedStep] = useState(null);
+ const [editedPath, setEditedPath] = useState(null);
+
+ // Initialize selectedScriptId when scripts are available
+ useEffect(() => {
+ if (data.generatedScripts.length > 0 && !selectedScriptId) {
+ setSelectedScriptId(data.generatedScripts[0].id);
+ }
+ }, [data.generatedScripts, selectedScriptId]);
+
+ // Find current path based on selected script
+ const currentPath = data.paths?.find(p => p.scriptId === selectedScriptId);
+
+ // Update local edited state when path changes
+ useEffect(() => {
+ if (currentPath) {
+ setEditedPath(JSON.parse(JSON.stringify(currentPath))); // Deep copy
+ } else {
+ setEditedPath(null);
+ }
+ }, [currentPath]);
+
+ const handleGenerate = async () => {
+ if (currentPath && !window.confirm('重新生成将覆盖现有路径规划,确定吗?')) return;
+
+ const script = data.generatedScripts.find(s => s.id === selectedScriptId);
+ if (!script) return;
+
+ setLoading(true);
+ try {
+ const newPath = await AI.generatePath(script, data.userProfile);
+ Store.addPath(newPath);
+ setIsEditing(false);
+ } catch (e) {
+ console.error(e);
+ alert('规划失败,请重试');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const handleDelete = () => {
+ if (window.confirm('确定要删除这个路径规划吗?')) {
+ Store.deletePath(currentPath.id);
+ setIsEditing(false);
+ }
+ };
+
+ const handleSaveEdit = () => {
+ if (editedPath) {
+ Store.updatePath(editedPath.id, { steps: editedPath.steps });
+ setIsEditing(false);
+ }
+ };
+
+ const handleStepEdit = (stepIndex, field, value) => {
+ if (!editedPath) return;
+ const newSteps = [...editedPath.steps];
+ newSteps[stepIndex] = { ...newSteps[stepIndex], [field]: value };
+ setEditedPath({ ...editedPath, steps: newSteps });
+ };
+
+ if (data.generatedScripts.length === 0) {
+ return (
+
+
+
+
+
+
+ 实现路径
+
+ 将幻想落地为行动,AI为你定制专属计划。
+
+
+
+
+
你需要先有一个剧本,才能生成通往它的路径。
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+ 实现路径
+
+ 将幻想落地为行动,AI为你定制专属计划。
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {!currentPath ? (
+
+
+
+
+
尚未生成路径,点击上方按钮开始规划。
+
+ ) : (
+ <>
+
+
+ 规划生成于 {new Date(currentPath.createdAt).toLocaleDateString()}
+
+
+
+
+
+
+
+
+ {(isEditing ? editedPath.steps : currentPath.steps).map((step, idx) => (
+
+ {/* Progress Line */}
+
+
+ {/* Header */}
+ setExpandedStep(expandedStep === idx ? null : idx)}
+ >
+
+
+ {idx + 1}
+
+
+
{step.phase}
+
+ {step.time}
+
+
+
+
+
+
+ {/* Details (Collapsible) */}
+
+
+ {/* Core Content */}
+
+
+ 核心策略
+
+
handleStepEdit(idx, 'content', e.currentTarget.textContent)}
+ className={`p-3 rounded-lg text-sm text-gray-300 leading-relaxed border transition-colors ${
+ isEditing
+ ? 'bg-white/10 border-primary/50 ring-2 ring-primary/20'
+ : 'bg-white/5 border-white/5'
+ }`}
+ >
+ {step.content}
+
+
+
+ {/* Actions */}
+
+
+ 关键行动
+
+
handleStepEdit(idx, 'action', e.currentTarget.textContent)}
+ className={`p-3 rounded-lg text-sm text-gray-300 transition-colors ${
+ isEditing
+ ? 'bg-white/10 border border-primary/50 ring-2 ring-primary/20'
+ : 'bg-blue-500/10 border border-blue-500/20'
+ }`}
+ >
+ {step.action}
+
+
+
+
+ {/* Resources */}
+
+
+ 所需资源
+
+
handleStepEdit(idx, 'resources', e.currentTarget.textContent)}
+ className={`p-3 rounded-lg text-xs text-gray-400 leading-relaxed transition-colors ${
+ isEditing
+ ? 'bg-white/10 border border-primary/50 ring-2 ring-primary/20'
+ : 'bg-amber-500/10 border border-amber-500/20'
+ }`}
+ >
+ {step.resources}
+
+
+ {/* Habits */}
+
+
+ 养成习惯
+
+
handleStepEdit(idx, 'habit', e.currentTarget.textContent)}
+ className={`p-3 rounded-lg text-xs text-gray-400 leading-relaxed transition-colors ${
+ isEditing
+ ? 'bg-white/10 border border-primary/50 ring-2 ring-primary/20'
+ : 'bg-green-500/10 border border-green-500/20'
+ }`}
+ >
+ {step.habit}
+
+
+
+
+
+
+ ))}
+
+
+
+ "路虽远,行则将至。"
+
+ >
+ )}
+
+
+ );
+}
diff --git a/course-web/src/components/views/ScriptView.jsx b/course-web/src/components/views/ScriptView.jsx
new file mode 100644
index 0000000..ffb5155
--- /dev/null
+++ b/course-web/src/components/views/ScriptView.jsx
@@ -0,0 +1,302 @@
+import { useState, useEffect } from 'react';
+import { Store } from '../../utils/store';
+import { AI } from '../../utils/aiLogic';
+import { useStoreData } from '../../hooks/useStoreData';
+import { Fingerprint, Film, Sparkles, History, Trash2, Stars, Zap, Loader, X, ArrowRight, BookOpen } from 'lucide-react';
+import { Button } from '../ui/Button';
+import { Select, Textarea } from '../ui/Input';
+import { GlassCard as Card } from '../ui/GlassCard';
+import clsx from 'clsx';
+
+export function ScriptView({ onSwitchToPath }) {
+ const data = useStoreData();
+ const [loading, setLoading] = useState(false);
+ const [form, setForm] = useState({ theme: '', style: 'career', length: 'medium' });
+ const [selectedScriptId, setSelectedScriptId] = useState(null);
+
+ const selectedScript = data.generatedScripts.find(s => s.id === selectedScriptId) || null;
+
+ useEffect(() => {
+ if (!selectedScriptId && data.generatedScripts.length > 0) {
+ setSelectedScriptId(data.generatedScripts[0].id);
+ }
+ }, [data.generatedScripts, selectedScriptId]);
+
+ const handleGenerate = async () => {
+ if (!form.theme.trim()) return;
+ setLoading(true);
+ try {
+ const requirements = form;
+ const script = await AI.generateScript(data.userProfile, data.lifeTimeline, requirements);
+ Store.addScript(script);
+ setSelectedScriptId(script.id);
+ setForm({ ...form, theme: '' });
+ } catch (e) {
+ console.error(e);
+ alert('生成失败,请重试');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const handleDelete = (id, e) => {
+ e.stopPropagation();
+ if (confirm('确定删除这个剧本吗?')) {
+ Store.deleteScript(id);
+ if (selectedScriptId === id) setSelectedScriptId(null);
+ }
+ };
+
+ return (
+
+
+
+
+ 剧本生成器
+
+ 基于你的真实画像,编织平行时空的无限可能。
+
+
+
+ {/* Left: Config */}
+
+ {/* User Persona Summary */}
+
+
+
+
+
+
+
+
+
+ 当前主角设定
+
+
+
+ {data.userProfile.nickname ? data.userProfile.nickname[0] : 'U'}
+
+
+
{data.userProfile.nickname || '未命名'}
+
+ {data.userProfile.mbti}
+ {data.userProfile.zodiac || '星辰'}
+
+
+
+
+
+ 天赋
+ {(data.userProfile.hobbies || []).join(' / ') || '暂无'}
+
+
+ 愿景
+ {data.userProfile.futureVision || '暂无'}
+
+
+
+
+
+ {/* Input Form */}
+
+
+
+
+ {/* History List */}
+
+
+
+ 历史剧本
+
+
+
+ {data.generatedScripts.length === 0 ? (
+
+
+ 暂无历史剧本
+
+ ) : (
+ data.generatedScripts.map(s => (
+
setSelectedScriptId(s.id)}
+ className={clsx(
+ "group relative p-3 rounded-xl cursor-pointer transition-all border",
+ selectedScriptId === s.id
+ ? "bg-primary/10 border-primary/30 shadow-[inset_0_0_10px_rgba(16,185,129,0.05)]"
+ : "bg-transparent border-transparent hover:bg-white/5 hover:border-white/10"
+ )}
+ >
+
+ {s.title}
+
+
+
+ {s.style === 'career' ? '职场' : s.style === 'love' ? '情感' : '玄幻'}
+
+
+ {new Date(s.createdAt).toLocaleDateString()}
+
+
+
+
+ ))
+ )}
+
+
+
+
+ {/* Right: Result Display */}
+
+
+ {!selectedScript ? (
+
+
+
+
+
舞台已就绪
+
请在左侧输入设定,生成你的平行人生。
+
+ ) : (
+
+ {/* Actions */}
+
+
+
+
+
+
+
+
+ {selectedScript.style === 'career' ? '职场逆袭' : selectedScript.style === 'love' ? '情感圆满' : '玄幻觉醒'}
+
+
{selectedScript.title}
+
+ 生成于 {new Date(selectedScript.createdAt).toLocaleDateString()}
+ ·
+ {selectedScript.length === 'long' ? '长篇' : '标准篇'}
+
+
+
+
+ {/* Chapters */}
+
+ {/* Vertical Line for Mobile */}
+
+
+ {/* Chapter 1 */}
+
+
+
+ {selectedScript.plot.intro}
+
+
+
+ {/* Chapter 2 */}
+
+
+
+
+ {selectedScript.plot.turning}
+
+
+
+
+ {/* Chapter 3 */}
+
+
+
+ {selectedScript.plot.climax}
+
+
+
+ {/* Chapter 4 */}
+
+
+
+ {selectedScript.plot.ending}
+
+
+
+
+
+
+
+
+ )}
+
+
+
+
+ );
+}
diff --git a/course-web/src/components/views/TimelineView.jsx b/course-web/src/components/views/TimelineView.jsx
new file mode 100644
index 0000000..516484f
--- /dev/null
+++ b/course-web/src/components/views/TimelineView.jsx
@@ -0,0 +1,127 @@
+import React, { useState } from 'react';
+import { Store } from '../../utils/store';
+import { AI } from '../../utils/aiLogic';
+import { useStoreData } from '../../hooks/useStoreData';
+import { BookHeart, Bot, Send, Loader2, PenTool, HeartHandshake, Microscope, Sprout, Quote } from 'lucide-react';
+import { Button } from '../ui/Button';
+import { Input, Textarea } from '../ui/Input';
+import { GlassCard as Card } from '../ui/GlassCard';
+
+export function TimelineView() {
+ const data = useStoreData();
+ const [loading, setLoading] = useState(false);
+ const [log, setLog] = useState({
+ date: new Date().toISOString().slice(0, 16),
+ title: '',
+ content: ''
+ });
+
+ const handleSend = async () => {
+ if (!log.content.trim()) return;
+ setLoading(true);
+ try {
+ const aiReply = await AI.generateReply(log.content, data.userProfile);
+ const newEvent = {
+ type: 'daily_log',
+ id: Date.now().toString(),
+ date: log.date || new Date().toISOString(),
+ title: log.title || '无题日记',
+ content: log.content,
+ aiReply
+ };
+ Store.addEvent(newEvent);
+ setLog({ ...log, title: '', content: '' });
+ } catch (e) {
+ console.error(e);
+ alert('AI 暂时开小差了,请稍后再试');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const events = data.lifeTimeline || [];
+
+ return (
+
+
+
+
+ 时空日记
+
+ 记录每一个当下,让AI为你照见未来。
+
+
+
+
+
+
+
+
+
+
+
+
+ AI 疗愈师在线
+
+
+
+
+
+
+ {events.length === 0 ? (
+
+ ) : (
+ events.map((item, index) => (
+
+ {/* Date Column */}
+
+
+
+ {new Date(item.date).toLocaleDateString('zh-CN', { month: 'short', day: 'numeric' })}
+
+ Daily Log
+
+
+
+ {/* Center Dot */}
+
+
+ {/* Content Card */}
+
+
+
+
+
+ {item.title}
+ {item.content}
+
+ {item.aiReply && (
+
+ )}
+
+
+
+ ))
+ )}
+
+
+ );
+}
diff --git a/course-web/src/hooks/useStoreData.js b/course-web/src/hooks/useStoreData.js
new file mode 100644
index 0000000..a64425d
--- /dev/null
+++ b/course-web/src/hooks/useStoreData.js
@@ -0,0 +1,17 @@
+import { useState, useEffect } from 'react';
+import { Store } from '../utils/store';
+
+export function useStoreData() {
+ const [data, setData] = useState(Store.get());
+
+ useEffect(() => {
+ const handleUpdate = () => {
+ setData(Store.get());
+ };
+
+ window.addEventListener('store-updated', handleUpdate);
+ return () => window.removeEventListener('store-updated', handleUpdate);
+ }, []);
+
+ return data;
+}
diff --git a/course-web/src/index.css b/course-web/src/index.css
new file mode 100644
index 0000000..5072241
--- /dev/null
+++ b/course-web/src/index.css
@@ -0,0 +1,198 @@
+@import "tailwindcss";
+
+@theme {
+ --color-primary: #2A9D8F;
+ --color-secondary: #264653;
+ --color-accent: #E9C46A;
+ --color-aurora-green: #4CC9F0;
+ --color-deep-sea: #0f1c2e;
+
+ --font-sans: "Noto Sans SC", sans-serif;
+
+ --animate-fade-in: fadeIn 0.8s ease-out forwards;
+ --animate-slide-up: slideUp 0.6s ease-out forwards;
+ --animate-pulse-slow: pulse 4s cubic-bezier(0.4, 0, 0.6, 1) infinite;
+ --animate-float: float 6s ease-in-out infinite;
+ --animate-breathe: breathe 4s ease-in-out infinite;
+ --animate-spin-slow: spin-slow 8s linear infinite;
+ --animate-music-wave-1: audio-wave 1s ease-in-out infinite;
+ --animate-music-wave-2: audio-wave 1s ease-in-out 0.1s infinite;
+ --animate-music-wave-3: audio-wave 1s ease-in-out 0.2s infinite;
+ --animate-music-wave-4: audio-wave 1s ease-in-out 0.3s infinite;
+}
+
+@keyframes fadeIn {
+ 0% { opacity: 0; }
+ 100% { opacity: 1; }
+}
+@keyframes slideUp {
+ 0% { transform: translateY(20px); opacity: 0; }
+ 100% { transform: translateY(0); opacity: 1; }
+}
+@keyframes float {
+ 0%, 100% { transform: translateY(0); }
+ 50% { transform: translateY(-10px); }
+}
+@keyframes breathe {
+ 0%, 100% { opacity: 0.8; transform: scale(1); }
+ 50% { opacity: 1; transform: scale(1.02); }
+}
+@keyframes spin-slow {
+ from { transform: rotate(0deg); }
+ to { transform: rotate(360deg); }
+}
+@keyframes pulse-ring {
+ 0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(42, 157, 143, 0.7); }
+ 70% { transform: scale(1); box-shadow: 0 0 0 10px rgba(42, 157, 143, 0); }
+ 100% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(42, 157, 143, 0); }
+}
+@keyframes audio-wave {
+ 0%, 100% { height: 5px; }
+ 50% { height: 15px; }
+}
+
+/* Global Reset & Base */
+body {
+ -webkit-tap-highlight-color: transparent;
+ font-family: 'Noto Sans SC', sans-serif;
+ @apply bg-deep-sea text-gray-800 overflow-x-hidden selection:bg-primary selection:text-white;
+}
+
+/* Background Noise Utility */
+.bg-noise {
+ background-image: url('./assets/noise.svg');
+}
+
+/* Custom Scrollbar */
+::-webkit-scrollbar {
+ width: 6px;
+ height: 6px;
+}
+::-webkit-scrollbar-track {
+ background: transparent;
+}
+::-webkit-scrollbar-thumb {
+ background: rgba(255, 255, 255, 0.2);
+ border-radius: 4px;
+}
+::-webkit-scrollbar-thumb:hover {
+ background: rgba(42, 157, 143, 0.6);
+}
+
+.custom-scrollbar::-webkit-scrollbar-thumb {
+ background: rgba(0, 0, 0, 0.1);
+}
+.custom-scrollbar::-webkit-scrollbar-thumb:hover {
+ background: rgba(42, 157, 143, 0.4);
+}
+
+/* Transitions */
+.view-transition {
+ animation: fadeIn 0.5s ease-in-out;
+}
+
+/* Glassmorphism Cards */
+.glass-card {
+ background: rgba(255, 255, 255, 0.95);
+ backdrop-filter: blur(20px);
+ -webkit-backdrop-filter: blur(20px);
+ border: 1px solid rgba(255, 255, 255, 0.8);
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.05);
+}
+
+.glass-card-dark {
+ background: rgba(15, 28, 46, 0.7);
+ backdrop-filter: blur(12px);
+ color: white;
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
+}
+
+/* Healing Specifics */
+.healing-card {
+ background: linear-gradient(135deg, #f0fdf4 0%, #e0f2fe 100%);
+ box-shadow: 0 10px 30px -5px rgba(56, 189, 248, 0.15);
+}
+
+/* Form Elements */
+.input-field {
+ width: 100%;
+ padding: 0.875rem 1.25rem;
+ border-radius: 1rem;
+ border: 1px solid rgba(0,0,0,0.1);
+ background: rgba(255, 255, 255, 0.9);
+ transition: all 0.3s ease;
+ outline: none;
+ color: #1e293b;
+ font-size: 0.95rem;
+}
+
+.input-field:focus {
+ border-color: #2A9D8F;
+ box-shadow: 0 0 0 4px rgba(42, 157, 143, 0.15);
+ background: white;
+}
+
+.input-field-dark {
+ background: rgba(255, 255, 255, 0.05);
+ border-color: rgba(255, 255, 255, 0.1);
+ color: white;
+}
+.input-field-dark:focus {
+ background: rgba(255, 255, 255, 0.1);
+ border-color: #2A9D8F;
+}
+
+select.input-field {
+ appearance: none;
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%2364748b' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
+ background-position: right 1rem center;
+ background-repeat: no-repeat;
+ background-size: 1.5em 1.5em;
+ padding-right: 2.5rem;
+}
+
+select.input-field-dark {
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
+}
+select.input-field-dark option {
+ background-color: #0f1c2e;
+}
+
+/* Audio Player Animation */
+.audio-waves span {
+ display: inline-block;
+ width: 3px;
+ height: 10px;
+ background-color: currentColor;
+ animation: audio-wave 1s ease-in-out infinite;
+ border-radius: 2px;
+}
+.audio-waves span:nth-child(2) { animation-delay: 0.1s; }
+.audio-waves span:nth-child(3) { animation-delay: 0.2s; }
+.audio-waves span:nth-child(4) { animation-delay: 0.3s; }
+
+/* Utilities */
+.scrollbar-hide::-webkit-scrollbar {
+ display: none;
+}
+.scrollbar-hide {
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+}
+
+/* Mobile Optimizations */
+@media (max-width: 768px) {
+ .glass-card {
+ padding: 1.25rem;
+ }
+ .input-field {
+ padding: 0.75rem 1rem;
+ font-size: 16px; /* Prevent iOS zoom */
+ }
+ .btn-primary {
+ width: 100%;
+ justify-content: center;
+ padding: 1rem;
+ }
+}
diff --git a/course-web/src/main.jsx b/course-web/src/main.jsx
new file mode 100644
index 0000000..b9a1a6d
--- /dev/null
+++ b/course-web/src/main.jsx
@@ -0,0 +1,10 @@
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import './index.css'
+import App from './App.jsx'
+
+createRoot(document.getElementById('root')).render(
+
+
+ ,
+)
diff --git a/course-web/src/pages/DashboardPage.jsx b/course-web/src/pages/DashboardPage.jsx
new file mode 100644
index 0000000..b29d430
--- /dev/null
+++ b/course-web/src/pages/DashboardPage.jsx
@@ -0,0 +1,168 @@
+import React, { useState, useEffect } from 'react';
+import { useStoreData } from '../hooks/useStoreData';
+import { Store } from '../utils/store';
+import { AudioEngine } from '../utils/audioEngine';
+import { TimelineView } from '../components/views/TimelineView';
+import { ScriptView } from '../components/views/ScriptView';
+import { PathView } from '../components/views/PathView';
+import {
+ Compass,
+ BookOpen,
+ Film,
+ Map,
+ Music,
+ Volume2,
+ VolumeX,
+ RotateCcw,
+ Menu,
+ X
+} from 'lucide-react';
+import clsx from 'clsx';
+
+export function DashboardPage() {
+ const data = useStoreData();
+ const [activeTab, setActiveTab] = useState('timeline');
+ const [isMusicPlaying, setIsMusicPlaying] = useState(false);
+ const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
+
+ // Initialize Audio Engine state based on store
+ useEffect(() => {
+ // Sync initial state if needed
+ if (!data.audioMuted) {
+ // AudioEngine manages its own state
+ }
+ }, []);
+
+ const handleMusicToggle = async () => {
+ try {
+ const playing = AudioEngine.toggle();
+ setIsMusicPlaying(playing);
+ } catch (e) {
+ console.error("Audio failed", e);
+ }
+ };
+
+ const handleReset = () => {
+ if (window.confirm('确定要清空所有数据重新开始吗?这将回到注册页面。')) {
+ Store.reset();
+ // App.jsx will handle the redirect because store data changes
+ }
+ };
+
+ const NavButton = ({ tab, icon: Icon, label, mobileLabel }) => (
+
+ );
+
+ return (
+
+ {/* Ambient Background */}
+
+
+ {/* Mobile Header */}
+
+
+
+ 人生轨迹
+
+
+
+
+ {/* Sidebar (Desktop) / Drawer (Mobile) */}
+
+
+ {/* Main Content Area */}
+
+ {activeTab === 'timeline' && }
+ {activeTab === 'script' && setActiveTab('path')} />}
+ {activeTab === 'path' && setActiveTab('script')} />}
+
+
+ );
+}
diff --git a/course-web/src/pages/LandingPage.jsx b/course-web/src/pages/LandingPage.jsx
new file mode 100644
index 0000000..60a46f5
--- /dev/null
+++ b/course-web/src/pages/LandingPage.jsx
@@ -0,0 +1,194 @@
+import React, { useState, useEffect } from 'react';
+import { Compass, ArrowRight, X, Phone, Lock, Loader2 } from 'lucide-react';
+import { Button } from '../components/ui/Button';
+import { Input } from '../components/ui/Input';
+import request from '../utils/request';
+import clsx from 'clsx';
+
+// PncyssD Prototype: Landing Page
+export function LandingPage({ onStart }) {
+ const [isLoggedIn, setIsLoggedIn] = useState(false);
+ const [showLoginModal, setShowLoginModal] = useState(false);
+ const [loading, setLoading] = useState(false);
+
+ // Login Form State
+ const [phone, setPhone] = useState('');
+ const [code, setCode] = useState('');
+ const [countdown, setCountdown] = useState(0);
+
+ useEffect(() => {
+ const token = localStorage.getItem('token');
+ if (token) setIsLoggedIn(true);
+ }, []);
+
+ useEffect(() => {
+ let timer;
+ if (countdown > 0) {
+ timer = setInterval(() => setCountdown(c => c - 1), 1000);
+ }
+ return () => clearInterval(timer);
+ }, [countdown]);
+
+ const handleGetCode = async () => {
+ if (!phone) return alert('请输入手机号');
+ if (!/^1[3-9]\d{9}$/.test(phone)) return alert('手机号格式不正确');
+
+ try {
+ // Backend: /auth/sms-code?phone=... (AuthController.java)
+ // Note: "Business type" is not required by the current backend implementation.
+ const res = await request.get('/auth/sms-code', { params: { phone } });
+
+ if (res.code === 200) {
+ setCountdown(60);
+ // Display backend message or dev code
+ const msg = res.data?.message || '验证码已发送';
+ if (res.data?.code) {
+ alert(`【测试模式】${msg}\n验证码: ${res.data.code}`);
+ } else {
+ alert(msg);
+ }
+ } else {
+ console.warn('SMS Code Error:', res);
+ alert(res.message || '发送失败,请稍后重试');
+ }
+ } catch (e) {
+ console.error('Failed to get SMS code:', e);
+ const errorMsg = e.response?.data?.message || '网络连接异常,请检查您的网络设置';
+ alert(errorMsg);
+ }
+ };
+
+ const handleLogin = async () => {
+ if (!phone || !code) return alert('请填写完整信息');
+ setLoading(true);
+ try {
+ const res = await request.post('/auth/login', { phone, smsCode: code });
+ if (res.code === 200) {
+ const { accessToken } = res.data;
+ localStorage.setItem('token', accessToken);
+ setIsLoggedIn(true);
+ setShowLoginModal(false);
+ // Clear sensitive data
+ setPhone('');
+ setCode('');
+ } else {
+ alert(res.message || '登录失败');
+ }
+ } catch (e) {
+ console.error(e);
+ alert('登录异常,请检查网络');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
+ {/* Background & Effects */}
+
+
+
+
+
+
+
+
+ 人生轨迹
+ Life Trajectory
+
+
+ {/* Buttons */}
+
+ {isLoggedIn ? (
+
+ ) : (
+
+ )}
+
+
+
+ {/* Login Modal */}
+ {showLoginModal && (
+
+
+ {/* Modal Background */}
+
+
+
+
+
+
+ 欢迎回来
+
+
+
+
+
+
+
+
setPhone(e.target.value)}
+ />
+
+
+
+
+
+
+
+
+ setCode(e.target.value)}
+ />
+
+
+
+
+
+
+
+
+
+ )}
+
+ );
+}
diff --git a/course-web/src/pages/LoginPage.jsx b/course-web/src/pages/LoginPage.jsx
new file mode 100644
index 0000000..950207d
--- /dev/null
+++ b/course-web/src/pages/LoginPage.jsx
@@ -0,0 +1,155 @@
+import React, { useState } from 'react';
+import { User, Lock, Eye, EyeOff, ArrowRight, ArrowLeft } from 'lucide-react';
+import { GlassCard } from '../components/ui/GlassCard';
+import { Button } from '../components/ui/Button';
+import { Input } from '../components/ui/Input';
+import { Checkbox } from '../components/ui/Checkbox';
+import { Store } from '../utils/store';
+
+export function LoginPage({ onLoginSuccess, onBack, onSignUp }) {
+ const [formData, setFormData] = useState({
+ username: '',
+ password: '',
+ rememberMe: false
+ });
+ const [showPassword, setShowPassword] = useState(false);
+ const [isLoading, setIsLoading] = useState(false);
+ const [error, setError] = useState('');
+
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+ setError('');
+ setIsLoading(true);
+
+ // Mock login delay
+ setTimeout(() => {
+ if (!formData.username || !formData.password) {
+ setError('请输入用户名和密码');
+ setIsLoading(false);
+ return;
+ }
+
+ // Simple mock validation
+ if (formData.password.length < 6) {
+ setError('密码长度不能少于6位');
+ setIsLoading(false);
+ return;
+ }
+
+ // Success
+ Store.updateProfile({
+ nickname: formData.username,
+ // In a real app, we'd store a token
+ });
+
+ setIsLoading(false);
+ onLoginSuccess();
+ }, 1000);
+ };
+
+ return (
+
+
+
+
+
+ {/* Decorative elements */}
+
+
+
+
+
+
欢迎回来
+
登录您的 Emotion Museum 账号
+
+
+
+
+
+ 还没有账号?
+
+
+
+
+
+ );
+}
diff --git a/course-web/src/pages/OnboardingPage.jsx b/course-web/src/pages/OnboardingPage.jsx
new file mode 100644
index 0000000..27639e6
--- /dev/null
+++ b/course-web/src/pages/OnboardingPage.jsx
@@ -0,0 +1,235 @@
+import React, { useState } from 'react';
+import { Store } from '../utils/store';
+import { ArrowLeft, ArrowRight, Check, X, Sparkles, Star, AlertCircle, CheckCircle } from 'lucide-react';
+import { Button } from '../components/ui/Button';
+import { Input, Select, Textarea } from '../components/ui/Input';
+import clsx from 'clsx';
+
+const ZODIAC_SIGNS = [
+ "白羊座", "金牛座", "双子座", "巨蟹座",
+ "狮子座", "处女座", "天秤座", "天蝎座",
+ "射手座", "摩羯座", "水瓶座", "双鱼座"
+];
+
+const MBTI_TYPES = ['INTJ','INTP','ENTJ','ENTP','INFJ','INFP','ENFJ','ENFP','ISTJ','ISFJ','ESTJ','ESFJ','ISTP','ISFP','ESTP','ESFP'];
+
+export function OnboardingPage({ onFinish }) {
+ const [step, setStep] = useState(0);
+ const [formData, setFormData] = useState(Store.get().userProfile);
+ const [toast, setToast] = useState(null); // { msg, type }
+
+ const showToast = (msg, type = 'error') => {
+ setToast({ msg, type });
+ setTimeout(() => setToast(null), 2500);
+ };
+
+ const updateFormData = (key, value) => {
+ setFormData(prev => ({ ...prev, [key]: value }));
+ };
+
+ const updateHistory = (type, field, value) => {
+ setFormData(prev => ({
+ ...prev,
+ history: {
+ ...prev.history,
+ [type]: {
+ ...prev.history?.[type],
+ [field]: value
+ }
+ }
+ }));
+ };
+
+ const handleNext = () => {
+ if (step === 0) {
+ if (!formData.nickname?.trim()) { showToast('请填写昵称'); return; }
+ if (!formData.mbti) { showToast('请选择MBTI人格类型'); return; }
+ } else if (step === 4) {
+ if (!formData.futureVision?.trim()) { showToast('写下一句对未来的期许吧'); return; }
+ Store.updateProfile(formData);
+ Store.completeOnboarding();
+ onFinish();
+ return;
+ }
+ setStep(prev => prev + 1);
+ };
+
+ const handlePrev = () => setStep(prev => prev - 1);
+
+ return (
+
+ {/* Background Blobs */}
+
+
+
+ {/* Toast */}
+ {toast && (
+
+ {toast.type === 'error' ?
:
}
+ {toast.msg}
+
+ )}
+
+ {/* Header */}
+
+
+ {[0,1,2,3,4].map(i => (
+
+ ))}
+
+
+
+
+ {/* Content */}
+
+ {step === 0 && (
+
+
+
+
+
+
+ updateFormData('nickname', e.target.value)}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ updateFormData('hobbies', e.target.value.split(/[,,]/).map(s => s.trim()))}
+ />
+
+
+
+ )}
+
+ {step === 1 && (
+
+
+
Part 1 / 3
+
你是如何成为了现在的自己?
+
闭上眼,回到开始的地方。你的童年是怎么度过的?
+
+
+
+
+ updateHistory('childhood', 'date', e.target.value)} />
+
+
+
+
+ )}
+
+ {step === 2 && (
+
+
+
Part 2 / 3
+
闪闪发光的日子
+
在这个过程中,让你感到非常开心的经历是什么?
+
+
+
+
+ updateHistory('peak', 'date', e.target.value)} />
+
+
+
+
+ )}
+
+ {step === 3 && (
+
+
+
Part 3 / 3
+
风雨兼程
+
一段十分沮丧和低谷的时光,你是如何度过的?
+
+
+
+
+ updateHistory('valley', 'date', e.target.value)} />
+
+
+
+
+ )}
+
+ {step === 4 && (
+
+
+
你未来想成为怎样的人?
+
对自己的憧憬以及对理想生活状态的憧憬。
+
+
+
+
+
+
+ )}
+
+
+ {/* Footer Controls */}
+
+ {step > 0 ? (
+
+ ) :
}
+
+
+
+
+ );
+}
diff --git a/course-web/src/utils/aiLogic.js b/course-web/src/utils/aiLogic.js
new file mode 100644
index 0000000..e6dab31
--- /dev/null
+++ b/course-web/src/utils/aiLogic.js
@@ -0,0 +1,162 @@
+/**
+ * AI Logic Module
+ * Simulates intelligent healing responses and content generation.
+ */
+
+const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
+
+const ADJECTIVES = {
+ INTJ: ['深刻', '逻辑严密', '富有远见'],
+ INFP: ['温柔', '富有同理心', '充满想象力'],
+ ENFP: ['热情', '鼓舞人心', '充满可能性'],
+ ISTJ: ['稳重', '务实', '值得信赖'],
+ INFJ: ['深邃', '直觉敏锐', '利他'],
+
+ DEFAULT: ['特别', '真诚', '有力量']
+};
+
+export const AI = {
+ /**
+ * Generate a healing reply for a timeline log.
+ * Analyzes sentiment and provides Analysis, Growth, and Healing.
+ */
+ async generateReply(content, profile) {
+ await sleep(1500 + Math.random() * 1000); // Simulate 1.5-2.5s thinking
+
+ const mbti = profile.mbti || 'DEFAULT';
+ const traits = ADJECTIVES[mbti] || ADJECTIVES.DEFAULT;
+ const trait = traits[Math.floor(Math.random() * traits.length)];
+ const zodiac = profile.zodiac || '星辰';
+
+
+ let mood = 'neutral';
+ if (/(开心|成功|棒|好|爱|幸福|顺利)/.test(content)) mood = 'positive';
+ if (/(难过|累|失败|痛|丧|焦虑|迷茫)/.test(content)) mood = 'negative';
+
+ let analysis = "";
+ let growth = "";
+ let healing = "";
+
+ if (mood === 'positive') {
+ analysis = `这不仅仅是一个事件,而是你内心能量充盈的体现。作为${mbti},你敏锐地捕捉到了生活中的光亮。`;
+ growth = `请记住这种${trait}的感觉,它构成了你人格中坚韧的底色。你的每一次喜悦,都在为未来的挑战积蓄心理资本。`;
+ healing = `愿这一刻的温暖,像${zodiac}的光芒一样,长久地照耀你的内心。`;
+ } else if (mood === 'negative') {
+ analysis = `感到低落并非示弱,而是灵魂在提醒你需要休息。${mbti}的你往往思考得很深,容易承担过多情绪。`;
+ growth = `每一次的阵痛都是成长的伏笔。你正在经历破茧成蝶前的静默,这本身就是一种力量。`;
+ healing = `允许自己暂停,就像月亮也有阴晴圆缺。给那个受伤的自己一个拥抱,风雨之后,必见彩虹。`;
+ } else {
+ analysis = `记录本身就是一种深刻的觉察。你在平淡的流年中,依然保持着${trait}的观察力。`;
+ growth = `生活的大部分时间是平静的,能在其中找到节奏,是你最宝贵的能力。`;
+ healing = `在这漫长的岁月里,你就是自己最忠实的见证者。`;
+ }
+
+ return {
+ analysis,
+ growth,
+ healing
+ };
+ },
+
+ /**
+ * Generate a "Cool Story" (爽文) script.
+ * Uses profile history (Valley/Peak) to create a narrative arc.
+ */
+ async generateScript(profile, timeline, requirements) {
+ await sleep(2000 + Math.random() * 1000);
+
+ const id = Date.now().toString();
+ const hobby = (profile.hobbies && profile.hobbies.length > 0) ? profile.hobbies[0] : "隐藏的天赋";
+ const theme = requirements.theme || "自我超越";
+
+
+ const valleyEvent = profile.history?.valley?.content
+ ? `那段"${profile.history.valley.content.substring(0, 15)}..."的经历`
+ : "曾经那段默默无闻的时光";
+
+ const peakEvent = profile.history?.peak?.content
+ ? `就像"${profile.history.peak.content.substring(0, 15)}..."那次一样`
+ : "如同星辰觉醒";
+
+ const templates = {
+ career: {
+ intro: `故事始于${valleyEvent}。${profile.nickname}虽然身处低谷,但作为${profile.mbti},${profile.gender === 'male' ? '他' : '她'}内心深处对"${theme}"的渴望从未熄灭。${profile.zodiac}骨子里的韧性,支撑着${profile.gender === 'male' ? '他' : '她'}熬过了最黑的夜。`,
+ turning: `转折发生在一个不起眼的午后。公司面临前所未有的技术难题,所有人束手无策。${profile.nickname}利用业余时间钻研的${hobby},意外发现了破局的关键。`,
+ explosion: `在项目汇报会上,${profile.nickname}条理清晰地展示了方案,那种自信${peakEvent}。原本轻视的人都闭上了嘴。不仅完美解决了危机,更直接为公司带来了巨大的收益,一战成名!`,
+ ending: `最终,${profile.nickname}站在了行业的顶峰,实现了"${theme}"的宏愿。回首往事,轻舟已过万重山,${profile.gender === 'male' ? '他' : '她'}终于成为了自己想成为的人。`
+ },
+ love: {
+ intro: `在${valleyEvent}的日子里,${profile.nickname}习惯了独自一人。${profile.mbti}的特质让${profile.gender === 'male' ? '他' : '她'}虽然渴望爱,却更害怕受伤。`,
+ turning: `直到那次${hobby}社团的聚会,命运的齿轮开始转动。${profile.nickname}不经意间流露出的${ADJECTIVES[profile.mbti]?.[0] || '独特'}气质,深深吸引了那个命中注定的人。`,
+ explosion: `面对现实的阻碍和误解,${profile.nickname}没有退缩。${profile.zodiac}赋予的勇气觉醒,${profile.gender === 'male' ? '他' : '她'}坚定地跨越了山海,只为奔赴那份真挚的感情。那一刻,全世界都在为爱让路。`,
+ ending: `正如${profile.futureVision || '童话故事'}里的结局,两人在夕阳下相拥。${profile.nickname}发现,原来最好的爱,是让你成为更好的自己。`
+ },
+ fantasy: {
+ intro: `在这个看似平凡的世界,${profile.nickname}总感觉自己格格不入。${valleyEvent},其实是灵力觉醒前的阵痛。${profile.zodiac}星盘早已预示了不凡的命运。`,
+ turning: `当${hobby}这一媒介触碰到古老的法阵,封印解除!${profile.nickname}发现自己竟然是百年难遇的${profile.mbti}系元素掌控者。`,
+ explosion: `暗黑势力降临城市,绝望蔓延。关键时刻,${profile.nickname}挺身而出,爆发出了${peakEvent}般耀眼的光芒,一击必杀,守护了心中的"${theme}"。`,
+ ending: `成为了传说中的守护神,${profile.nickname}站在云端俯瞰大地。${profile.futureVision || '和平'}的景象映入眼帘,传奇才刚刚开始。`
+ }
+ };
+
+ const t = templates[requirements.style] || templates.career;
+
+ return {
+ id,
+ createdAt: new Date().toISOString(),
+ title: requirements.theme.substring(0, 10) + (requirements.style === 'fantasy' ? '·觉醒篇' : requirements.style === 'love' ? '·情缘篇' : '·逆袭篇'),
+ theme: requirements.theme,
+ style: requirements.style,
+ plot: t
+ };
+ },
+
+ /**
+ * Generate implementation path based on script.
+ */
+ async generatePath(script, profile) {
+ await sleep(1500);
+
+ const hobby = (profile.hobbies && profile.hobbies.length > 0) ? profile.hobbies[0] : "关键技能";
+
+ return {
+ id: Date.now().toString(),
+ scriptId: script.id,
+ createdAt: new Date().toISOString(),
+ steps: [
+ {
+ phase: "第一阶段:沉淀与积累",
+ time: "第1-2个月",
+ content: `针对剧本中提到的"${hobby}",开始系统性学习。不要急于求成,利用${profile.mbti}擅长的深度思考,打好基础。`,
+ action: `购买两本高评分书籍或订阅一个专业专栏,每天坚持阅读学习45分钟。`,
+ resources: `专业书籍、在线MOOC平台`,
+ habit: `建立"日落复盘"机制,记录当天的收获。`
+ },
+ {
+ phase: "第二阶段:破局尝试",
+ time: "第3-6个月",
+ content: `正如剧本中"${script.plot.turning.substring(0, 10)}..."所描述的,寻找一个小型的实践机会。将知识转化为行动。`,
+ action: `完成一个最小可行性项目(Side Project)并在社交媒体分享。`,
+ resources: `GitHub/Behance/小红书等展示平台`,
+ habit: `每周连接一位同频的伙伴。`
+ },
+ {
+ phase: "第三阶段:爆发冲刺",
+ time: "第6-12个月",
+ content: `制造你的高光时刻。${profile.futureVision ? '向着"' + profile.futureVision + '"靠近' : '向着行业头部进发'}。主动承担高难度任务。`,
+ action: `参加一次行业比赛,或在团队中主导一个关键项目。`,
+ resources: `导师资源、行业峰会`,
+ habit: `冥想与可视化练习,强化自信心。`
+ },
+ {
+ phase: "第四阶段:愿景显化",
+ time: "1年后",
+ content: `将能力转化为影响力,实现"${script.theme}"。保持谦逊,同时不吝啬展示自己的光芒。`,
+ action: `整理你的方法论,开设分享会或撰写系列文章。`,
+ resources: `个人品牌渠道`,
+ habit: `终身学习,保持空杯心态。`
+ }
+ ]
+ };
+ }
+};
diff --git a/course-web/src/utils/audioEngine.js b/course-web/src/utils/audioEngine.js
new file mode 100644
index 0000000..b167fd3
--- /dev/null
+++ b/course-web/src/utils/audioEngine.js
@@ -0,0 +1,200 @@
+/**
+ * Generative Audio Engine
+ * Uses Web Audio API to create procedural healing music (Piano + Nature)
+ */
+import { Store } from './store.js';
+
+export const AudioEngine = {
+ ctx: null,
+ masterGain: null,
+ isPlaying: false,
+ nextNoteTime: 0,
+ reverbNode: null,
+ natureGain: null,
+ timerID: null,
+
+ scale: [
+ 261.63, 293.66, 329.63, 392.00, 440.00, // C4-A4
+ 523.25, 587.33, 659.25, 783.99, 880.00 // C5-A5
+ ],
+
+ async init() {
+ if (this.ctx) return;
+
+ const AudioContext = window.AudioContext || window.webkitAudioContext;
+ this.ctx = new AudioContext();
+
+ // Master Gain
+ this.masterGain = this.ctx.createGain();
+ this.masterGain.gain.value = 0.4; // Initial volume
+ this.masterGain.connect(this.ctx.destination);
+
+ // Reverb
+ this.reverbNode = this.ctx.createConvolver();
+ this.reverbNode.buffer = await this.generateImpulseResponse();
+ this.reverbNode.connect(this.masterGain);
+
+ // Nature Sound
+ this.startNatureSound();
+ },
+
+ toggle() {
+ if (!this.ctx) this.init();
+
+ this.isPlaying = !this.isPlaying;
+
+ // Resume context if suspended (browser policy)
+ if (this.ctx.state === 'suspended') {
+ this.ctx.resume();
+ }
+
+ if (this.isPlaying) {
+ this.scheduleNote();
+ // Fade in
+ this.masterGain.gain.setTargetAtTime(0.4, this.ctx.currentTime, 1);
+ } else {
+ // Fade out
+ this.masterGain.gain.setTargetAtTime(0, this.ctx.currentTime, 0.5);
+ // Stop scheduling
+ if (this.timerID) cancelAnimationFrame(this.timerID);
+ }
+
+ // Persist state
+ const data = Store.get();
+ data.audioMuted = !this.isPlaying;
+ Store.save(data);
+
+ return this.isPlaying;
+ },
+
+ playNote(freq, time) {
+ if (!this.isPlaying) return;
+
+ const osc = this.ctx.createOscillator();
+ const gain = this.ctx.createGain();
+ const filter = this.ctx.createBiquadFilter();
+
+ // Oscillator
+ osc.type = 'triangle';
+ osc.frequency.value = freq;
+
+ // Filter (Lowpass)
+ filter.type = 'lowpass';
+ filter.frequency.value = 800 + Math.random() * 400;
+
+ // Envelope
+ gain.gain.setValueAtTime(0, time);
+ gain.gain.linearRampToValueAtTime(0.1 + Math.random() * 0.1, time + 0.05 + Math.random() * 0.05); // Attack
+ gain.gain.exponentialRampToValueAtTime(0.001, time + 3 + Math.random() * 2); // Long Decay
+
+ osc.connect(filter);
+ filter.connect(gain);
+ gain.connect(this.masterGain); // Dry
+ gain.connect(this.reverbNode); // Wet
+
+ osc.start(time);
+ osc.stop(time + 6);
+ },
+
+ scheduleNote() {
+ if (!this.isPlaying) return;
+
+ const secondsPerBeat = 2;
+ const now = this.ctx.currentTime;
+
+ if (this.nextNoteTime < now) {
+ this.nextNoteTime = now + 0.5;
+ }
+
+ // Lookahead: schedule notes for the next 1.5 seconds
+ while (this.nextNoteTime < now + 1.5) {
+ // Random chance to play a note
+ if (Math.random() > 0.3) {
+ const note = this.scale[Math.floor(Math.random() * this.scale.length)];
+
+ this.playNote(note, this.nextNoteTime + (Math.random() * 0.1));
+
+ // Random harmony
+ if (Math.random() > 0.7) {
+ const harmonyIndex = (this.scale.indexOf(note) + 2) % this.scale.length;
+ this.playNote(this.scale[harmonyIndex], this.nextNoteTime + (Math.random() * 0.05));
+ }
+ }
+
+ this.nextNoteTime += (Math.random() * 2 + 1);
+ }
+
+ // Loop
+ this.timerID = requestAnimationFrame(this.scheduleNote.bind(this));
+ },
+
+ startNatureSound() {
+ const bufferSize = 2 * this.ctx.sampleRate;
+ const buffer = this.ctx.createBuffer(1, bufferSize, this.ctx.sampleRate);
+ const output = buffer.getChannelData(0);
+
+ // Pink Noise Generation
+ let b0, b1, b2, b3, b4, b5, b6;
+ b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0.0;
+ for (let i = 0; i < bufferSize; i++) {
+ const white = Math.random() * 2 - 1;
+ b0 = 0.99886 * b0 + white * 0.0555179;
+ b1 = 0.99332 * b1 + white * 0.0750759;
+ b2 = 0.96900 * b2 + white * 0.1538520;
+ b3 = 0.86650 * b3 + white * 0.3104856;
+ b4 = 0.55000 * b4 + white * 0.5329522;
+ b5 = -0.7616 * b5 - white * 0.0168980;
+ output[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362;
+ output[i] *= 0.11; // Lower volume
+ b6 = white * 0.115926;
+ }
+
+ const noise = this.ctx.createBufferSource();
+ noise.buffer = buffer;
+ noise.loop = true;
+
+ // Filter (Lowpass modulated by LFO)
+ const filter = this.ctx.createBiquadFilter();
+ filter.type = 'lowpass';
+ filter.frequency.value = 400;
+
+ // LFO
+ const lfo = this.ctx.createOscillator();
+ lfo.type = 'sine';
+ lfo.frequency.value = 0.1; // Slow wave
+ const lfoGain = this.ctx.createGain();
+ lfoGain.gain.value = 300; // Modulate by +/- 300Hz
+
+ lfo.connect(lfoGain);
+ lfoGain.connect(filter.frequency);
+
+ this.natureGain = this.ctx.createGain();
+ this.natureGain.gain.value = 0.15; // Background level
+
+ noise.connect(filter);
+ filter.connect(this.natureGain);
+ this.natureGain.connect(this.masterGain);
+
+ noise.start();
+ lfo.start();
+ },
+
+ async generateImpulseResponse() {
+ const duration = 2.5;
+ const rate = this.ctx.sampleRate;
+ const length = rate * duration;
+ const impulse = this.ctx.createBuffer(2, length, rate);
+ const left = impulse.getChannelData(0);
+ const right = impulse.getChannelData(1);
+
+ for (let i = 0; i < length; i++) {
+ // Exponential decay
+ const factor = 1 - (i / length);
+ const decay = Math.pow(factor, 3);
+ left[i] = (Math.random() * 2 - 1) * decay;
+ right[i] = (Math.random() * 2 - 1) * decay;
+ }
+
+ return impulse;
+ }
+};
diff --git a/course-web/src/utils/request.js b/course-web/src/utils/request.js
new file mode 100644
index 0000000..51ff799
--- /dev/null
+++ b/course-web/src/utils/request.js
@@ -0,0 +1,39 @@
+import axios from 'axios';
+
+const request = axios.create({
+ baseURL: '/api', // Adjust if needed, usually proxied in vite.config.js
+ timeout: 10000,
+});
+
+// Request interceptor
+request.interceptors.request.use(
+ (config) => {
+ const token = localStorage.getItem('token');
+ if (token) {
+ config.headers['Authorization'] = `Bearer ${token}`;
+ }
+ return config;
+ },
+ (error) => {
+ return Promise.reject(error);
+ }
+);
+
+// Response interceptor
+request.interceptors.response.use(
+ (response) => {
+ return response.data;
+ },
+ (error) => {
+ if (error.response) {
+ if (error.response.status === 401) {
+ // Token expired or invalid
+ localStorage.removeItem('token');
+ window.location.reload(); // Or dispatch an event to clear state
+ }
+ }
+ return Promise.reject(error);
+ }
+);
+
+export default request;
diff --git a/course-web/src/utils/store.js b/course-web/src/utils/store.js
new file mode 100644
index 0000000..98db37c
--- /dev/null
+++ b/course-web/src/utils/store.js
@@ -0,0 +1,113 @@
+/**
+ * Data Management Module
+ * Handles persistence and data structure for Life Trajectory
+ */
+
+const STORAGE_KEY = 'lifeTrajectory_v3_data';
+
+const DEFAULT_STATE = {
+ onboardingComplete: false,
+ audioMuted: true, // Default to muted
+ userProfile: {
+ nickname: "",
+ gender: "secret",
+ zodiac: "",
+ mbti: "",
+ hobbies: [],
+ history: {
+ childhood: { date: "", content: "" },
+ peak: { date: "", content: "" },
+ valley: { date: "", content: "" }
+ },
+ futureVision: ""
+ },
+ lifeTimeline: [],
+ generatedScripts: [],
+ paths: []
+};
+
+export const Store = {
+ get() {
+ const data = localStorage.getItem(STORAGE_KEY);
+ if (!data) return JSON.parse(JSON.stringify(DEFAULT_STATE));
+ try {
+ const parsed = JSON.parse(data);
+ return {
+ ...DEFAULT_STATE,
+ ...parsed,
+ userProfile: { ...DEFAULT_STATE.userProfile, ...parsed.userProfile }
+ };
+ } catch (e) {
+ console.error("Data corruption detected, resetting store.");
+ return DEFAULT_STATE;
+ }
+ },
+
+ save(data) {
+ try {
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
+ window.dispatchEvent(new CustomEvent('store-updated'));
+ } catch (e) {
+ console.error("LocalStorage save failed (quota exceeded?)", e);
+ alert("存储空间不足,部分数据可能无法保存。");
+ }
+ },
+
+ reset() {
+ localStorage.removeItem(STORAGE_KEY);
+ window.location.reload();
+ },
+
+ updateProfile(updates) {
+ const data = this.get();
+ data.userProfile = { ...data.userProfile, ...updates };
+ this.save(data);
+ },
+
+ completeOnboarding() {
+ const data = this.get();
+ data.onboardingComplete = true;
+ this.save(data);
+ },
+
+ addEvent(event) {
+ const data = this.get();
+ data.lifeTimeline.unshift(event);
+ this.save(data);
+ },
+
+ addScript(script) {
+ const data = this.get();
+ data.generatedScripts.unshift(script);
+ this.save(data);
+ },
+
+ deleteScript(id) {
+ const data = this.get();
+ data.generatedScripts = data.generatedScripts.filter(s => s.id !== id);
+ data.paths = data.paths.filter(p => p.scriptId !== id);
+ this.save(data);
+ },
+
+ addPath(path) {
+ const data = this.get();
+ data.paths = data.paths.filter(p => p.scriptId !== path.scriptId);
+ data.paths.push(path);
+ this.save(data);
+ },
+
+ updatePath(id, updates) {
+ const data = this.get();
+ const index = data.paths.findIndex(p => p.id === id);
+ if (index !== -1) {
+ data.paths[index] = { ...data.paths[index], ...updates };
+ this.save(data);
+ }
+ },
+
+ deletePath(id) {
+ const data = this.get();
+ data.paths = data.paths.filter(p => p.id !== id);
+ this.save(data);
+ }
+};
diff --git a/course-web/vite.config.js b/course-web/vite.config.js
new file mode 100644
index 0000000..f51d184
--- /dev/null
+++ b/course-web/vite.config.js
@@ -0,0 +1,16 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+import tailwindcss from '@tailwindcss/vite'
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [react(), tailwindcss()],
+ server: {
+ proxy: {
+ '/api': {
+ target: 'http://localhost:19089',
+ changeOrigin: true,
+ }
+ }
+ }
+})