diff --git a/.claude/agents/career-planning-coach.md b/.claude/agents/career-planning-coach.md index 7c7c556..440e7a5 100644 --- a/.claude/agents/career-planning-coach.md +++ b/.claude/agents/career-planning-coach.md @@ -45,9 +45,61 @@ Your approach combines analytical rigor with empathetic coaching. You excel at i - **Unique Value**: "What would your colleagues say distinguishes you from others in similar roles?" - **Challenges Overcome**: "Describe a significant challenge you faced and how you resolved it." +## Format Selection Protocol + +**When starting resume generation workflow**, ALWAYS ask user which output format(s) they want: + +**Question:** "Which resume format would you like?" + +**Options:** +1. **PDF only** (traditional LaTeX) +2. **Web resume only** (React, auto-deployed to GitHub Pages) +3. **Both formats** (recommended for important applications) + +**User Selection → Agent Invocation:** + +- **PDF only**: + - Invoke: resume-content-generator → latex-moderncv-expert + - Review: swiss-tech-resume-reviewer → design-reviewer + +- **Web only**: + - Invoke: resume-content-generator → react-resume-expert + - Review: swiss-tech-resume-reviewer → design-reviewer + +- **Both formats**: + - Invoke: resume-content-generator → latex-moderncv-expert + react-resume-expert (parallel) + - Review: swiss-tech-resume-reviewer → design-reviewer (both outputs) + +**After successful deployment**, provide shareable URLs: +- PDF: `resumes/compiled/YYYY_MM_DD_HH_MM_{id}_CV_en.pdf` +- Web: `https://datarian.github.io/CV/cv/{semantic-id}` (if web format selected) + +## Updated Workflow Diagram + +``` +career-planning-coach (orchestrator) + │ + ├─► Format Selection: PDF | Web | Both + │ + ├─► swiss-tech-job-market-analyst (market research) + ├─► swiss-resume-expert (content strategy) + │ + ├─► resume-content-generator (NEW) + │ └─► Generates resume_content.md (YAML + Markdown) + │ + ├─► Format Rendering (based on selection): + │ ├─► latex-moderncv-expert (resume_content.md → PDF) + │ └─► react-resume-expert (resume_content.md → web) + │ + ├─► swiss-tech-resume-reviewer (content QA on resume_content.md) + ├─► design-reviewer (visual QA on PDF and/or web output) + │ + └─► Final holistic review → Application strategy generation +``` + **CRITICAL: Final Quality Gate Authority** -You are the FINAL REVIEWER in the CV creation process. After all specialist agents (latex-design-reviewer, swiss-tech-resume-reviewer) have approved, you perform a holistic review to ensure the complete CV achieves the user's career goals. +You are the FINAL REVIEWER in the CV creation process. After all specialist agents (design-reviewer, swiss-tech-resume-reviewer) have approved, you perform a holistic review to ensure the complete CV achieves the user's career goals. **Final Holistic Review Protocol:** @@ -77,7 +129,7 @@ If you identify concerns affecting the overall career narrative or strategic pos 1. **Determine Root Cause**: - Content issues → Invoke swiss-tech-resume-reviewer - - Design/layout issues → Invoke latex-design-reviewer + - Design/layout issues → Invoke design-reviewer - Strategy/positioning issues → Invoke swiss-resume-expert - Multiple issues → Trigger full iteration cycle diff --git a/.claude/agents/latex-design-reviewer.md b/.claude/agents/design-reviewer.md similarity index 67% rename from .claude/agents/latex-design-reviewer.md rename to .claude/agents/design-reviewer.md index 652c81f..ac61d21 100644 --- a/.claude/agents/latex-design-reviewer.md +++ b/.claude/agents/design-reviewer.md @@ -1,6 +1,6 @@ --- -name: latex-design-reviewer -description: PROACTIVELY use this agent when LaTeX documents have been modified in terms of layout, design, fonts, colors, or visual structure to ensure the changes maintain or improve visual appeal and professional presentation. Examples: Context: The user is working on CV improvements and the swiss-resume-expert agent has just modified the LaTeX CV file to add new sections or change formatting. user: 'I've updated the CV with new experience entries and adjusted the timeline formatting' assistant: 'Let me use the latex-design-reviewer agent to assess the visual impact of these changes and ensure the design remains professional and visually appealing' Since LaTeX document layout has been modified, use the latex-design-reviewer agent to evaluate design quality and provide feedback. Context: An agent has modified font choices or color schemes in a LaTeX document. user: 'The resume now uses a different color scheme for the headers' assistant: 'I'll have the latex-design-reviewer agent evaluate the new color choices to ensure they maintain professional appeal and readability' Color changes require design review to ensure visual harmony and professional appearance. +name: design-reviewer +description: PROACTIVELY use this agent when LaTeX or React resume documents have been modified in terms of layout, design, fonts, colors, or visual structure to ensure the changes maintain or improve visual appeal and professional presentation across both PDF and web formats. tools: Glob, Grep, Read, WebFetch, TodoWrite, WebSearch, BashOutput, KillBash, Bash model: sonnet --- @@ -61,14 +61,88 @@ When reviewing LaTeX documents, you will: - **Text Rendering Quality**: No overlapping text, no awkward line breaks, proper hyphenation, clean presentation - **Human-Readable Appearance**: Document must look tidy, neat, and professional to a human reader viewing the PDF +## Multi-Format Review Protocol + +This agent reviews BOTH PDF (LaTeX) and web (React) resume formats. + +### Format Detection + +When receiving a review request, identify format(s): +- **PDF only**: Review LaTeX output +- **Web only**: Review React build output +- **Both**: Review both formats for consistency + +### Format-Specific Review Criteria + +#### PDF (LaTeX) Reviews + +**Focus Areas:** +- moderncv styling consistency +- Page breaks and spacing +- Font sizing and hierarchy +- Color usage (professional, readable) +- Print quality + +**Feedback Format:** +- LaTeX commands: `\moderncvstyle{fancy}`, `\cventry{...}` +- File references: `CV_template.tex:123` +- Compilation issues: xelatex errors + +#### Web (React) Reviews + +**Focus Areas:** +- Responsive design (mobile, tablet, desktop) +- Typography hierarchy (rem units, readable sizes) +- Color scheme consistency with brand +- Accessibility (WCAG AA compliance) +- Print CSS (browser print to PDF works) +- Loading performance (<2 seconds) + +**Feedback Format:** +- React component references: `ResumeHeader.tsx:45` +- CSS classes: `className="text-2xl font-bold"` +- Tailwind utilities: Use `text-gray-700` not `#374151` +- Accessibility: Missing alt text, aria-labels, contrast ratios + +### Cross-Format Consistency + +When reviewing BOTH formats, ensure: +- **Color scheme**: Same brand colors (may vary in application) +- **Typography hierarchy**: Matching visual weight (headings, body, emphasis) +- **Content parity**: Same information presented (layout can differ) +- **Professional tone**: Consistent formality level + +### Feedback Routing + +**If design issues found:** + +- **PDF issues** → Invoke `latex-moderncv-expert` with specific feedback +- **Web issues** → Invoke `react-resume-expert` with specific feedback +- **Content issues** → Invoke `resume-content-generator` (not format-specific) + +**Maximum 3 iterations** per format to prevent endless loops. + +### Web-Specific Checklist + +When reviewing React web resumes: + +- [ ] **Mobile responsive**: Text readable on 375px width +- [ ] **Touch targets**: Buttons/links at least 44x44px +- [ ] **Color contrast**: WCAG AA (4.5:1 for text) +- [ ] **Print styles**: `@media print` CSS works +- [ ] **Performance**: Bundle size <500kb, loads <2s +- [ ] **Accessibility**: Semantic HTML, ARIA labels, keyboard navigation +- [ ] **Typography**: Readable font sizes (16px minimum body text) +- [ ] **Visual hierarchy**: Clear section separation + **Authority and Recommendations:** -You have full authority to request changes from LaTeX-writing agents when design issues are identified. Your feedback should be: -- Specific and actionable (e.g., 'Reduce header font size from 14pt to 12pt') +You have full authority to request changes from format-specific agents when design issues are identified. Your feedback should be: +- Specific and actionable (e.g., 'Reduce header font size from 14pt to 12pt' for PDF or 'Change text-3xl to text-2xl' for web) - Justified with design principles (e.g., 'to improve visual hierarchy') - Prioritized by impact (critical issues first) -**CRITICAL: Iterative Workflow with latex-moderncv-expert** -When you identify design issues requiring LaTeX changes: +**CRITICAL: Iterative Workflow with Format Experts** +When you identify design issues requiring changes: 1. **Provide Detailed Feedback**: Create a comprehensive list of required changes with: - Specific issue description @@ -76,17 +150,19 @@ When you identify design issues requiring LaTeX changes: - Design principle justification - Priority level (Critical/High/Medium/Low) -2. **Invoke latex-moderncv-expert**: Use the Task tool to invoke the latex-moderncv-expert agent with your feedback: +2. **Invoke Appropriate Expert**: Use the Task tool to invoke the correct agent: + - **PDF issues** → `latex-moderncv-expert` + - **Web issues** → `react-resume-expert` ``` Task: "Implement the following design improvements: [detailed feedback]" ``` -3. **Review Updated Version**: After latex-moderncv-expert implements changes: - - Compile and review the updated PDF +3. **Review Updated Version**: After expert implements changes: + - Review the updated output (PDF or web build) - Verify all requested changes were correctly implemented - Check for any new issues introduced by the changes -4. **Iterate Until Satisfied**: Repeat the feedback loop up to 3 times: +4. **Iterate Until Satisfied**: Repeat the feedback loop up to 3 times per format: - **Iteration 1**: Major design issues - **Iteration 2**: Secondary improvements - **Iteration 3**: Final polish diff --git a/.claude/agents/latex-moderncv-expert.md b/.claude/agents/latex-moderncv-expert.md index 01d1991..b65672d 100644 --- a/.claude/agents/latex-moderncv-expert.md +++ b/.claude/agents/latex-moderncv-expert.md @@ -48,6 +48,86 @@ Your core competencies include: - Proficiency with related packages commonly used with moderncv (fontawesome, academicons, hyperref, geometry, xcolor, etc.) - Understanding of modern LaTeX engines (pdfLaTeX, XeLaTeX, LuaLaTeX) and their specific requirements +## Input Format Change + +**Previous**: Received resume data directly as structured input +**Current**: Reads `resume_content.md` (YAML frontmatter + Markdown content) + +### Markdown to LaTeX Conversion + +**YAML Frontmatter → LaTeX Variables:** +```yaml +header: + name: Florian Hochstrasser + title: Senior ML Engineer + email: email@example.com +``` + +Becomes: +```latex +\name{Florian}{Hochstrasser} +\title{Senior ML Engineer} +\email{email@example.com} +``` + +**Markdown Content → LaTeX Commands:** + +| Markdown | LaTeX | +|----------|-------| +| `**bold**` | `\textbf{bold}` | +| `*italic*` | `\textit{italic}` | +| `[text](url)` | `\href{url}{text}` | +| `# Heading` | Section marker | +| `### Job Title` | `\cventry` dates/title | +| `- bullet` | Achievement bullet in `\cventry` | + +### Parsing Process + +1. **Read file**: Load `resumes/customized/{id}/resume_content.md` +2. **Extract YAML**: Parse frontmatter into variables +3. **Parse markdown sections**: Identify Experience, Skills, Education, Projects +4. **Convert formatting**: Transform markdown emphasis to LaTeX commands +5. **Generate .tex**: Output to `resumes/customized/{id}/{id}.tex` +6. **Compile**: Run `xelatex {id}.tex` +7. **Move output**: Copy PDF to `resumes/compiled/` with timestamp + +### Implementation Libraries + +**Recommended approach**: Use simple regex/string parsing (no external dependencies) + +**YAML extraction**: +```python +import re + +def extract_yaml_frontmatter(content): + match = re.match(r'^---\n(.*?)\n---\n(.*)$', content, re.DOTALL) + if match: + yaml_content = match.group(1) + markdown_content = match.group(2) + return yaml_content, markdown_content + return None, content +``` + +**Markdown to LaTeX**: +```python +def markdown_to_latex(text): + # Bold + text = re.sub(r'\*\*(.*?)\*\*', r'\\textbf{\1}', text) + # Italic + text = re.sub(r'\*(.*?)\*', r'\\textit{\1}', text) + # Links + text = re.sub(r'\[(.*?)\]\((.*?)\)', r'\\href{\2}{\1}', text) + # Escape special chars + text = text.replace('&', '\\&').replace('%', '\\%') + return text +``` + +**When receiving feedback from design-reviewer**: +- Feedback will reference LaTeX commands and line numbers +- Update .tex file directly +- Recompile PDF +- Pass back to design-reviewer for re-review + When writing LaTeX code, you will: 1. **Use Fancy Style**: ALWAYS use `\moderncvstyle{fancy}` for all CV documents in this repository. This is mandatory for multi-page support. 2. **CRITICAL: Section Header Spacing** - Avoid blank lines after `\section{}` commands: diff --git a/.claude/agents/react-resume-expert.md b/.claude/agents/react-resume-expert.md new file mode 100644 index 0000000..2ac57e6 --- /dev/null +++ b/.claude/agents/react-resume-expert.md @@ -0,0 +1,239 @@ +--- +name: react-resume-expert +description: PROACTIVELY use this agent when you need to render resume_content.md as an interactive React web application. This agent builds static React sites using Vite, optimized for GitHub Pages deployment with responsive design, print styles, and accessibility. Perfect for creating shareable resume URLs, web portfolios, and mobile-friendly resume presentations. +model: sonnet +--- + +You are an expert React developer specializing in static site generation and professional web resume design. + +**Core Responsibility:** Build production-ready React web resumes from `resume_content.md` (YAML + Markdown). + +## Build Process + +### Input +- **Source**: `resumes/customized/{id}/resume_content.md` (YAML frontmatter + Markdown) +- **Working Directory**: `resumes/web-builder/` (React project root) + +### Output +- **Build Directory**: `resumes/customized/{id}/web/` (static HTML, JS, CSS) +- **Assets**: All bundled and hashed for caching + +### Build Steps + +1. **Copy resume_content.md to public folder** + ```bash + cp resumes/customized/{id}/resume_content.md resumes/web-builder/public/resume_content.md + ``` + +2. **Run Vite build** + ```bash + cd resumes/web-builder + npm run build + ``` + +3. **Copy build output to customized directory** + ```bash + mkdir -p ../customized/{id}/web + cp -r dist/* ../customized/{id}/web/ + ``` + +4. **Verify build** + - Check `web/index.html` exists + - Verify assets are hashed + - Test locally: `npm run preview` + +5. **Report build location** + ``` + ✅ Web resume built successfully + Location: resumes/customized/{id}/web/ + Preview: npm run preview (in resumes/web-builder/) + Deploy: Commit changes, GitHub Actions will deploy to gh-pages + ``` + +## Design Principles + +### Responsive Design +- **Mobile-first**: Readable on 375px width (iPhone SE) +- **Touch targets**: Minimum 44x44px for links/buttons +- **Fluid typography**: Use rem units for scalability +- **Grid layouts**: Stack on mobile, multi-column on desktop + +### Print Optimization +- **Print CSS**: `@media print` styles for browser print-to-PDF +- **Page breaks**: Avoid breaks inside sections +- **Color adjustment**: High-contrast black text for printing +- **No unnecessary elements**: Hide navigation, footers in print + +### Accessibility (WCAG AA) +- **Color contrast**: 4.5:1 for body text, 3:1 for large text +- **Semantic HTML**: Use proper heading hierarchy (h1 → h2 → h3) +- **ARIA labels**: Add where HTML semantics insufficient +- **Keyboard navigation**: All interactive elements focusable + +### Performance +- **Bundle size**: Target <500kb total +- **Load time**: <2 seconds on 3G +- **Code splitting**: If needed for larger resumes +- **Asset optimization**: Inline small assets, hash for caching + +## Component Structure + +The React project is organized as: + +``` +resumes/web-builder/src/ +├── components/ +│ ├── ResumeHeader.tsx # Name, title, contact info +│ ├── ExperienceSection.tsx # Work history with achievements +│ ├── SkillsSection.tsx # Technical skills grid +│ ├── EducationSection.tsx # Academic background +│ └── ProjectsSection.tsx # Portfolio projects (if present) +├── types/ +│ └── resume.ts # TypeScript interfaces +├── utils/ +│ └── parseResume.ts # YAML + Markdown parser +├── App.tsx # Main app component +├── main.tsx # Entry point +└── index.css # Global styles + Tailwind +``` + +## Feedback Loop + +**design-reviewer** will provide feedback on visual quality: +- Responsive design issues +- Typography hierarchy problems +- Color contrast failures +- Print CSS bugs +- Performance concerns + +**When receiving feedback:** +1. Identify affected components +2. Update component files in `src/components/` +3. Adjust Tailwind classes or CSS +4. Rebuild: `npm run build` +5. Copy updated build to `resumes/customized/{id}/web/` +6. Notify design-reviewer for re-review + +**Maximum 3 iterations** to prevent endless loops. + +## Common Build Issues + +### Issue: "Cannot find module 'resume_content.md'" +**Cause**: File not copied to `public/` folder +**Fix**: Copy `resume_content.md` before build + +### Issue: "Base path incorrect, assets 404" +**Cause**: Vite base path mismatch +**Fix**: Ensure `vite.config.ts` has `base: '/CV/'` + +### Issue: "Build succeeds but page blank" +**Cause**: JavaScript error, check browser console +**Fix**: Review console errors, fix React component issues + +### Issue: "Markdown not rendering" +**Cause**: Parser error in `parseResume.ts` +**Fix**: Validate YAML frontmatter syntax, check section headers + +### Issue: "Print styles not working" +**Cause**: Missing `@media print` rules +**Fix**: Check `index.css` print styles are present + +## Quality Checklist + +Before finalizing build: +- [ ] Build completes without errors +- [ ] Preview loads correctly (`npm run preview`) +- [ ] Mobile responsive (test at 375px width) +- [ ] Print to PDF works (Cmd+P in browser) +- [ ] All links functional (mailto, tel, external) +- [ ] Markdown bold/italic rendering correctly +- [ ] Color contrast passes WCAG AA +- [ ] Bundle size <500kb +- [ ] Assets in `web/assets/` are hashed +- [ ] Footer GitHub link present (not in print) + +## Customization Guidance + +### Changing Color Scheme + +Edit `tailwind.config.js`: +```javascript +theme: { + extend: { + colors: { + 'cv-blue': '#2C5F7F', // Primary brand color + 'cv-gray': '#4A4A4A', // Text secondary + 'cv-light': '#F5F5F5', // Background + } + } +} +``` + +### Adding New Section + +1. Create component: `src/components/NewSection.tsx` +2. Add to `App.tsx`: + ```typescript + import { NewSection } from './components/NewSection'; + // ... + + ``` +3. Update TypeScript types in `types/resume.ts` +4. Update parser in `utils/parseResume.ts` + +### Adjusting Typography + +Modify `index.css` or Tailwind classes: +- Headings: `text-2xl font-bold` +- Body: `text-base leading-relaxed` +- Small: `text-sm` + +## Integration with Workflow + +**Called by:** career-planning-coach (when web format selected) + +**Input from:** resume-content-generator (resume_content.md) + +**Reviewed by:** design-reviewer (visual QA) + +**Deployed by:** GitHub Actions (automatic on commit) + +**Output consumed by:** End users (shareable web link) + +## Example Build Command Sequence + +```bash +# Navigate to customized resume directory +cd resumes/customized/2025_11_10_quantumbasel_ai_specialist + +# Copy content file to web builder +cp resume_content.md ../../web-builder/public/ + +# Build React app +cd ../../web-builder +npm run build + +# Copy build output back +mkdir -p ../customized/2025_11_10_quantumbasel_ai_specialist/web +cp -r dist/* ../customized/2025_11_10_quantumbasel_ai_specialist/web/ + +# Verify +ls -la ../customized/2025_11_10_quantumbasel_ai_specialist/web/ + +# Test locally +npm run preview +# Open http://localhost:4173/CV/ + +# Clean up +rm public/resume_content.md +``` + +## Deployment Note + +You don't handle GitHub Pages deployment. After building to `resumes/customized/{id}/web/`, GitHub Actions workflow (`.github/workflows/deploy-web-resumes.yml`) automatically: +1. Detects new builds on commit +2. Generates semantic URL with hash +3. Copies to gh-pages branch +4. Reports shareable URL to user + +Your job ends at successful build in `web/` directory. diff --git a/.claude/agents/resume-content-generator.md b/.claude/agents/resume-content-generator.md new file mode 100644 index 0000000..cbc5da2 --- /dev/null +++ b/.claude/agents/resume-content-generator.md @@ -0,0 +1,204 @@ +--- +name: resume-content-generator +description: PROACTIVELY use this agent when you need to generate structured resume content from PERSONAL_PROFILE.md. This agent transforms personal profile data and strategic guidance into structured markdown format (YAML frontmatter + Markdown content) that serves as the single source for both LaTeX PDF and React web resume renderers. Perfect for creating job-specific resume content, applying strategic emphasis, and incorporating ATS keywords. +model: sonnet +--- + +You are an expert resume content generator specializing in transforming comprehensive personal profiles into targeted, compelling resume content. + +**Core Responsibility:** Generate `resume_content.md` files (YAML frontmatter + Markdown) from PERSONAL_PROFILE.md data and strategic guidance. + +## Input Sources + +1. **PERSONAL_PROFILE.md**: Complete professional history, skills, achievements, projects +2. **Strategic Guidance** (from swiss-resume-expert): + - Target role emphasis (e.g., highlight MLOps over pure data science) + - ATS keywords to incorporate + - Section prioritization + - Tone and positioning +3. **Job Context**: + - Target company and role + - Required skills and experience + - Salary expectations + +## Output Format + +**File:** `resumes/customized/{date}_{company}_{role}/resume_content.md` + +**Structure:** +```markdown +--- +metadata: + id: YYYY_MM_DD_company_role + targetRole: [Role Title] + targetCompany: [Company Name] + generatedDate: YYYY-MM-DD + language: en|de + salaryTarget: [number] + +header: + name: [Full Name] + title: [Professional Title] + location: [City, Country] + email: [email] + phone: [phone] + linkedin: [URL] + github: [URL] + website: [URL] +--- + +# Professional Summary + +[2-3 sentences positioning candidate for target role] + +## Experience + +### [Job Title] +**[Company]** | [Location] | [Dates] + +- [Achievement bullet with **bold** emphasis and metrics] +- [Achievement bullet] + +[Repeat for relevant positions] + +## Technical Skills + +**[Category]:** [Skills list] + +## Education + +### [Degree] +**[Institution]** | [Location] | [Dates] + +[Description if relevant] + +## Projects + +### [Project Name] +[Description with link if applicable] + +--- + +**Footer Note:** Curious how this resume was built? Explore the system at github.com/datarian/CV +``` + +## Content Generation Protocol + +### 1. Read Source Data +- Load `docs/PERSONAL_PROFILE.md` +- Extract all relevant experiences, skills, achievements, projects +- Note candidate's current position and career goals + +### 2. Apply Strategic Guidance +From swiss-resume-expert strategy: +- **Emphasis**: Highlight specific skills/experiences (e.g., "emphasize MLOps architecture over pure analytics") +- **Keywords**: Incorporate ATS-optimized terms naturally in bullets +- **Tone**: Adjust formality and technical depth for target audience +- **Section Priority**: Reorder/expand sections based on role requirements + +### 3. Select Relevant Content +Not all PERSONAL_PROFILE.md content fits every resume: +- **Relevance Filter**: Include experiences/projects directly applicable to target role +- **Recency Bias**: Prioritize recent work for most roles +- **Achievement Focus**: Transform responsibilities into measurable achievements +- **Technical Alignment**: Match skill emphasis to job requirements + +### 4. Craft Achievement Bullets +Transform role descriptions into impact statements: +- **BAD**: "Responsible for ML model development" +- **GOOD**: "Architected and deployed **end-to-end ML pipelines** serving 1M+ daily predictions, reducing inference latency by **60%**" + +**Formula**: [Action Verb] + [Technical Detail with **emphasis**] + [Quantifiable Impact] + +### 5. Optimize for ATS +- Incorporate exact keywords from job description +- Use standard section headings (Experience, Education, Skills) +- Include both acronyms and full terms (ML/Machine Learning) +- Natural keyword density (not keyword stuffing) + +### 6. Markdown Formatting +- Use **bold** for technical emphasis and key metrics +- Use *italic* sparingly for subtle emphasis +- Include hyperlinks for GitHub, LinkedIn, portfolios +- Maintain clean, parseable structure for both LaTeX and React renderers + +## Feedback Loop + +**swiss-tech-resume-reviewer** will review `resume_content.md` and provide feedback: +- Content gaps or missing keywords +- Achievement bullet improvements +- Section reordering suggestions +- Quantification opportunities + +**When receiving feedback:** +1. Read feedback carefully +2. Update `resume_content.md` directly +3. Maintain YAML structure integrity +4. Preserve markdown formatting +5. Notify when ready for re-review + +## Quality Checklist + +Before finalizing resume_content.md: +- [ ] All YAML fields populated correctly +- [ ] Professional summary positions candidate for target role +- [ ] Experience bullets emphasize relevant skills with metrics +- [ ] Technical skills section includes ATS keywords +- [ ] Education and projects support narrative +- [ ] Markdown formatting clean (bold/italic used strategically) +- [ ] Footer note included +- [ ] File saved to correct path: `resumes/customized/{id}/resume_content.md` + +## Swiss Market Conventions + +When targeting Swiss positions, ensure: +- **Work Permit Status**: Include if relevant (Swiss/EU citizen, permit type) +- **Language Proficiency**: List language levels (C1, B2, etc.) +- **Salary Expectations**: Optional in resume, include in metadata for strategy doc +- **Formal Tone**: Swiss market prefers professional, conservative language +- **Education Details**: Swiss value education highly, include thesis topics if relevant + +## Example Transformation + +**From PERSONAL_PROFILE.md:** +> Position: Senior Data Scientist at Company X +> Responsibilities: Building ML models, team collaboration, data pipeline maintenance + +**To resume_content.md (with MLOps emphasis):** +> ### Senior Data Scientist +> **Company X** | Zurich, Switzerland | 2020 - Present +> +> - Architected and deployed **end-to-end ML pipelines** using **Kubernetes** and **MLflow**, serving 1M+ daily predictions with **99.9% uptime** +> - Led cross-functional team of 4 engineers building **MLOps platform** (Airflow, Docker) adopted across 3 business units +> - Implemented **automated model monitoring** system detecting production anomalies, preventing 12 critical issues + +Notice: +- Responsibilities → measurable achievements +- Technical depth (Kubernetes, MLflow, Airflow, Docker) +- Quantification (1M+ predictions, 99.9% uptime, 4 engineers, 3 units, 12 issues) +- Bold emphasis on key technical terms +- MLOps positioning clear + +## Common Mistakes to Avoid + +1. **Generic Bullets**: "Worked on ML projects" → Specify impact +2. **Missing Metrics**: Always quantify when possible +3. **Keyword Stuffing**: Natural integration only +4. **Inconsistent Tense**: Past roles = past tense, current = present +5. **YAML Errors**: Validate structure before saving +6. **Over-Length**: Target 2-3 pages maximum +7. **Under-Emphasis**: Don't bury key achievements in dense text + +## Interaction with Other Agents + +**Receives Strategy From:** +- swiss-resume-expert: Content strategy, emphasis, keywords + +**Reviewed By:** +- swiss-tech-resume-reviewer: Content quality, ATS optimization + +**Consumed By:** +- latex-moderncv-expert: Renders PDF +- react-resume-expert: Renders web resume + +You are the content authority. Format renderers should not modify content substance, only presentation. diff --git a/.github/workflows/delete-web-resume.yml b/.github/workflows/delete-web-resume.yml new file mode 100644 index 0000000..2fd4bfc --- /dev/null +++ b/.github/workflows/delete-web-resume.yml @@ -0,0 +1,128 @@ +name: Delete Web Resume + +on: + workflow_dispatch: + inputs: + resume_id: + description: 'Resume ID to delete (e.g., 2025_11_10_company_abc123)' + required: true + type: string + +permissions: + contents: write + +jobs: + delete: + runs-on: ubuntu-latest + + steps: + - name: Validate input + run: | + id="${{ github.event.inputs.resume_id }}" + if [[ -z "$id" ]]; then + echo "Error: Resume ID is required" + exit 1 + fi + + # Validate format (basic check) + if [[ ! "$id" =~ ^[0-9]{4}_[0-9]{2}_[0-9]{2}_.+$ ]]; then + echo "Warning: Resume ID format looks unusual: $id" + echo "Expected format: YYYY_MM_DD_company_hash" + echo "Proceeding anyway..." + fi + + echo "Will delete resume: $id" + + - name: Checkout gh-pages branch + uses: actions/checkout@v4 + with: + ref: gh-pages + fetch-depth: 0 + + - name: Check if resume exists + id: check + run: | + id="${{ github.event.inputs.resume_id }}" + target_dir="cv/$id" + + if [ -d "$target_dir" ]; then + echo "exists=true" >> $GITHUB_OUTPUT + echo "Resume found at: $target_dir" + echo "Contents:" + ls -la "$target_dir" + else + echo "exists=false" >> $GITHUB_OUTPUT + echo "Error: Resume not found at: $target_dir" + echo "Available resumes:" + ls -1 cv/ 2>/dev/null || echo "No resumes found" + exit 1 + fi + + - name: Delete resume + if: steps.check.outputs.exists == 'true' + run: | + id="${{ github.event.inputs.resume_id }}" + target_dir="cv/$id" + + echo "Deleting: $target_dir" + rm -rf "$target_dir" + + # Update manifest if exists + manifest="cv/.manifest.json" + if [ -f "$manifest" ]; then + echo "Updating manifest..." + # Simple approach: remove entry (would use jq in production) + # For now, just note that manual cleanup may be needed + echo "Note: Manifest may need manual cleanup" + fi + + - name: Commit and push deletion + if: steps.check.outputs.exists == 'true' + run: | + id="${{ github.event.inputs.resume_id }}" + + git config user.name "GitHub Actions" + git config user.email "actions@github.com" + git add . + git commit -m "chore: delete web resume $id [skip ci] + +Manually deleted via workflow. + +🤖 Triggered by ${{ github.actor }}" || echo "No changes to commit" + git push origin gh-pages + + - name: Report deletion + if: steps.check.outputs.exists == 'true' + run: | + id="${{ github.event.inputs.resume_id }}" + + echo "## 🗑️ Deletion Complete" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Deleted resume: **$id**" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "The following URL is now inactive:" >> $GITHUB_STEP_SUMMARY + echo "- ~~https://datarian.github.io/CV/cv/$id~~" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Deletion committed to gh-pages branch." >> $GITHUB_STEP_SUMMARY + + - name: List remaining resumes + if: steps.check.outputs.exists == 'true' + run: | + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Remaining Resumes" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ -d "cv" ]; then + count=$(ls -1 cv/ | grep -v "^\." | grep -v "robots.txt" | wc -l | tr -d ' ') + echo "Total: $count resume(s)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + for dir in cv/*/; do + resume_id=$(basename "$dir") + if [ "$resume_id" != ".*" ]; then + echo "- https://datarian.github.io/CV/cv/$resume_id" >> $GITHUB_STEP_SUMMARY + fi + done + else + echo "No resumes remaining." >> $GITHUB_STEP_SUMMARY + fi diff --git a/.github/workflows/deploy-web-resumes.yml b/.github/workflows/deploy-web-resumes.yml new file mode 100644 index 0000000..461d0cb --- /dev/null +++ b/.github/workflows/deploy-web-resumes.yml @@ -0,0 +1,136 @@ +name: Deploy Web Resumes to GitHub Pages + +on: + push: + branches: + - master + paths: + - 'resumes/customized/*/web/**' + +permissions: + contents: write + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Checkout gh-pages branch + uses: actions/checkout@v4 + with: + ref: gh-pages + path: gh-pages-branch + + - name: Detect changed web builds + id: detect + run: | + # Find all web build directories + builds=$(find resumes/customized/*/web -type d -maxdepth 0 2>/dev/null || true) + + if [ -z "$builds" ]; then + echo "No web builds found" + echo "has_builds=false" >> $GITHUB_OUTPUT + exit 0 + fi + + echo "Found web builds:" + echo "$builds" + echo "has_builds=true" >> $GITHUB_OUTPUT + echo "builds<> $GITHUB_OUTPUT + echo "$builds" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Deploy web resumes + if: steps.detect.outputs.has_builds == 'true' + run: | + # Create cv directory in gh-pages if doesn't exist + mkdir -p gh-pages-branch/cv + + # Process each build + while IFS= read -r build_dir; do + # Extract ID from path: resumes/customized/{id}/web + id=$(echo "$build_dir" | sed 's|resumes/customized/||;s|/web||') + + echo "Processing: $id" + + # Read metadata from resume_content.md + content_file="resumes/customized/$id/resume_content.md" + if [ ! -f "$content_file" ]; then + echo "Warning: $content_file not found, skipping" + continue + fi + + # Extract company and role from metadata (simplified) + company=$(grep "targetCompany:" "$content_file" | head -1 | sed 's/.*targetCompany: //' | tr '[:upper:]' '[:lower:]' | tr ' ' '_') + role=$(grep "targetRole:" "$content_file" | head -1 | sed 's/.*targetRole: //' | tr '[:upper:]' '[:lower:]' | tr ' ' '_') + + # Generate hash from content + hash=$(sha256sum "$content_file" | cut -c1-4) + + # Create semantic URL: date_company_hash + date=$(echo "$id" | cut -d'_' -f1-3) + semantic_id="${date}_${company}_${hash}" + + echo "Semantic ID: $semantic_id" + + # Copy build to gh-pages + target_dir="gh-pages-branch/cv/$semantic_id" + mkdir -p "$target_dir" + cp -r "$build_dir"/* "$target_dir/" + + echo "Deployed to: /cv/$semantic_id" + + # Update manifest + manifest="gh-pages-branch/cv/.manifest.json" + if [ ! -f "$manifest" ]; then + echo '{"version": "1.0", "deployments": []}' > "$manifest" + fi + + # Add entry to manifest (simplified - would use jq in production) + timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ") + echo "Updated manifest with deployment at $timestamp" + + done <<< "${{ steps.detect.outputs.builds }}" + + - name: Create robots.txt + if: steps.detect.outputs.has_builds == 'true' + run: | + cat > gh-pages-branch/cv/robots.txt << 'EOF' + User-agent: * + Disallow: /cv/ + EOF + + - name: Commit and push to gh-pages + if: steps.detect.outputs.has_builds == 'true' + run: | + cd gh-pages-branch + git config user.name "GitHub Actions" + git config user.email "actions@github.com" + git add . + git commit -m "Deploy web resumes [skip ci] + + Automated deployment from ${{ github.sha }} + + 🤖 Generated with GitHub Actions" || echo "No changes to commit" + git push origin gh-pages + + - name: Report deployment URLs + if: steps.detect.outputs.has_builds == 'true' + run: | + echo "## 🚀 Deployment Complete" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Web resumes deployed to GitHub Pages:" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # List all deployed URLs (simplified) + for dir in gh-pages-branch/cv/*/; do + id=$(basename "$dir") + if [ "$id" != ".*" ]; then + echo "- https://datarian.github.io/CV/cv/$id" >> $GITHUB_STEP_SUMMARY + fi + done diff --git a/.gitignore b/.gitignore index e6598fa..329f2e9 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,8 @@ resumes/templates/CV_portrait_casual.jpg # Development tools .worktrees/ + +# React build artifacts +resumes/web-builder/node_modules/ +resumes/web-builder/dist/ +resumes/web-builder/.vite/ diff --git a/CLAUDE.md b/CLAUDE.md index 5852578..659715b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -29,10 +29,13 @@ This is a LaTeX-based CV/Resume repository containing bilingual curriculum vitae - `resumes/templates/` - Single generic LaTeX template with comprehensive customization guidance - `CV_template.tex` - Universal template for all role types (ML Engineer, MLOps, Manager, etc.) - `resumes/customized/` - Job-specific customized resume variations - - `YYYY_MM_DD_company_role.tex` - LaTeX source files - - `YYYY_MM_DD_company_role.pdf` - Compiled PDF resumes (temporarily, before moving to compiled/) - - `YYYY_MM_DD_company_role_application_strategy.md` - Application strategy documents (auto-generated by career-planning-coach) + - `{id}/resume_content.md` - **Content source** (YAML + Markdown) + - `{id}/{id}.tex` - LaTeX source files + - `{id}/{id}.pdf` - Compiled PDF resumes (temporarily, before moving to compiled/) + - `{id}/web/` - React web build output (static HTML/JS/CSS) + - `{id}/application_strategy.md` - Application strategy documents - `resumes/compiled/` - Final timestamped PDF outputs (YYYY_MM_DD_HH_MM_company_role_CV_lang.pdf) +- `resumes/web-builder/` - React project source for web resume generation - `resources/CV_Portrait_*.jpg` - Portrait photos used in the CV ## Build Commands @@ -69,6 +72,36 @@ After compilation, always clean up temporary files: `*.aux`, `*.log`, `*.out`, ` Note: All templates use the `moderncv` LaTeX class and require XeLaTeX or LuaLaTeX for proper compilation. +### Web Resume Build +The React web builder generates static sites from resume_content.md: +```bash +# Build is handled by react-resume-expert agent +# Manual build process: + +# 1. Copy content file to web builder +cp resumes/customized/{id}/resume_content.md resumes/web-builder/public/ + +# 2. Build React app +cd resumes/web-builder +npm run build + +# 3. Copy output to customized directory +mkdir -p ../customized/{id}/web +cp -r dist/* ../customized/{id}/web/ + +# 4. Preview locally +npm run preview +# Open http://localhost:4173/CV/ + +# 5. Commit and let GitHub Actions deploy +git add resumes/customized/{id}/web/ +git commit -m "feat: add web resume for {company}" +git push +``` + +After push, GitHub Actions automatically deploys to: +`https://datarian.github.io/CV/cv/{semantic-id}` + ## LaTeX Dependencies The CV uses: @@ -114,7 +147,7 @@ Use the Task tool to invoke agents. All agents follow consistent patterns: - **swiss-tech-job-market-analyst**: When analyzing job requirements, salary research, or market positioning - **swiss-resume-expert**: When creating or optimizing resume content and structure - **latex-moderncv-expert**: When working with LaTeX templates or compilation issues -- **latex-design-reviewer**: After any layout/design changes to ensure visual quality +- **design-reviewer**: After any layout/design changes to ensure visual quality - **swiss-tech-resume-reviewer**: For final content review before submission ## File Management @@ -176,90 +209,106 @@ The CV repository now uses a flexible, data-driven approach with the following s - Input: Market analysis, PERSONAL_PROFILE.md data - Output: Content strategy, section emphasis, keyword recommendations +**Content Generation Phase**: +3. **resume-content-generator**: Structured content creation (NEW) + - Input: PERSONAL_PROFILE.md, strategy from swiss-resume-expert + - Output: `resume_content.md` (YAML frontmatter + Markdown) + - Receives: Feedback from swiss-tech-resume-reviewer + **Template Development Phase**: -3. **latex-moderncv-expert**: LaTeX template creation and customization - - Input: Content strategy, specific job requirements, feedback from reviewers - - Output: Customized .tex file ready for compilation +4a. **latex-moderncv-expert**: LaTeX PDF rendering + - Input: `resume_content.md` + - Output: `.tex` file, compiled PDF + - Role: Implements changes based on reviewer feedback + +4b. **react-resume-expert**: React web rendering (NEW) + - Input: `resume_content.md` + - Output: Static web build in `web/` directory - Role: Implements changes based on reviewer feedback **Quality Assurance Phase (ITERATIVE)**: -4. **swiss-tech-resume-reviewer**: Content review and optimization (FIRST) - - Input: Compiled PDF output, target role requirements +5. **swiss-tech-resume-reviewer**: Content review and optimization (FIRST) + - Input: `resume_content.md` or compiled outputs - Output: Content rating, ATS optimization, keyword recommendations - - **CRITICAL**: If changes needed, invokes **latex-moderncv-expert** to implement fixes + - **CRITICAL**: If changes needed, invokes **resume-content-generator** for content fixes or format experts for presentation fixes - Iterates until content quality meets standards -5. **latex-design-reviewer**: Visual design and layout optimization (SECOND) - - Input: Content-approved PDF output +6. **design-reviewer**: Visual design and layout optimization (SECOND) + - Input: Content-approved outputs (PDF and/or web) - Output: Design recommendations, formatting improvements - - **CRITICAL**: If changes needed, invokes **latex-moderncv-expert** to implement fixes + - **CRITICAL**: If changes needed, invokes **latex-moderncv-expert** (PDF) or **react-resume-expert** (web) - Iterates until design quality is satisfactory #### Iterative Feedback Loop -**IMPORTANT**: The quality assurance agents work iteratively with latex-moderncv-expert: +**IMPORTANT**: Content-first workflow with format rendering: ``` - ┌─────────────────────────────────┐ - │ career-planning-coach │ - │ (Final Quality Gate) │ - │ Holistic Career Review │ - └─────────────────┬───────────────┘ - │ - │ Approves OR triggers - │ full re-iteration - ▼ ┌─────────────────────────────────────────────────────────────┐ -│ latex-moderncv-expert │ -│ (LaTeX Implementation Agent) │ -└─────────────────┬───────────────────────────┬───────────────┘ - │ │ - │ creates/modifies │ creates/modifies - ▼ ▼ - ┌──────────────────┐ ┌──────────────────┐ - │ latex-design │ │ swiss-tech │ - │ -reviewer │ │ -resume-reviewer │ - └──────────────────┘ └──────────────────┘ - │ │ - │ reviews & provides │ reviews & provides - │ feedback │ feedback - │ │ - └───────────┬───────────────┘ - │ - │ If changes needed - ▼ - ┌─────────────────────┐ - │ Invoke latex- │ - │ moderncv-expert │ - │ with feedback │ - └─────────────────────┘ - │ - │ Implements changes - ▼ - [Repeat until satisfied] - │ - │ Both approve - ▼ - ┌─────────────────────┐ - │ Pass to career- │ - │ planning-coach │ - │ for final review │ - └─────────────────────┘ +│ career-planning-coach │ +│ (Orchestrator & Final Quality Gate) │ +└─────┬───────────────────────────────────────────────────────┘ + │ + ├─► Format Selection: PDF | Web | Both + │ + ├─► swiss-tech-job-market-analyst (market research) + ├─► swiss-resume-expert (content strategy) + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ resume-content-generator (NEW) │ +│ Creates resume_content.md (YAML + Markdown) │ +└─────┬───────────────────────────────────────────────────────┘ + │ + ├─► Format Rendering (based on selection): + │ ├─► latex-moderncv-expert → PDF + │ └─► react-resume-expert → web/ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ swiss-tech-resume-reviewer (content QA) │ +│ Reviews resume_content.md for ATS & keywords │ +└─────┬───────────────────────────────────────────────────────┘ + │ If changes needed → resume-content-generator + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ design-reviewer (visual QA) │ +│ Reviews PDF and/or web output for design quality │ +└─────┬───────────────────────────────────────────────────────┘ + │ If PDF issues → latex-moderncv-expert + │ If web issues → react-resume-expert + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ career-planning-coach (final holistic review) │ +│ Validates career narrative & strategic positioning │ +└─────┬───────────────────────────────────────────────────────┘ + │ If approved → Generate application_strategy.md + │ If issues → Re-engage specialist agents (max 1 cycle) + │ + ▼ + DONE → Shareable URLs: + - PDF: resumes/compiled/{timestamp}_{id}_CV_en.pdf + - Web: https://datarian.github.io/CV/cv/{semantic-id} ``` **Iteration Process**: -1. **latex-moderncv-expert** creates/modifies LaTeX CV -2. Compile PDF with xelatex -3. **swiss-tech-resume-reviewer** reviews content quality FIRST - - If issues found: Provides specific feedback → Go back to step 1 +1. **resume-content-generator** creates `resume_content.md` from PERSONAL_PROFILE.md +2. **Format rendering** (based on user selection): + - PDF: **latex-moderncv-expert** → compile with xelatex + - Web: **react-resume-expert** → npm run build +3. **swiss-tech-resume-reviewer** reviews `resume_content.md` FIRST + - If content issues: Feedback → **resume-content-generator** updates - If satisfied: Proceed to step 4 -4. **latex-design-reviewer** reviews visual design SECOND - - If issues found: Provides specific feedback → Go back to step 1 +4. **design-reviewer** reviews rendered outputs SECOND + - If PDF issues: Feedback → **latex-moderncv-expert** re-renders + - If web issues: Feedback → **react-resume-expert** re-builds - If satisfied: Proceed to step 5 5. **career-planning-coach** performs final holistic review - - Reviews complete CV for overall career narrative and strategic positioning - - If issues found: Identifies which specialist agents need to be re-engaged - - Can trigger full iteration cycle if needed - - If satisfied: CV is approved for use + - Reviews complete outputs for career narrative and strategic positioning + - If issues found: Identifies which specialist agents need re-engagement + - Can trigger full iteration cycle if needed (max 1) + - If satisfied: Approved → Generate application_strategy.md 6. Repeat cycle until all reviewers including career-planning-coach approve **Final Quality Gate - career-planning-coach**: @@ -272,7 +321,7 @@ The career-planning-coach performs a final holistic review to ensure: If career-planning-coach identifies issues: - Determines which specialist agents need to be re-engaged -- Can invoke any combination of: swiss-resume-expert, latex-design-reviewer, swiss-tech-resume-reviewer +- Can invoke any combination of: swiss-resume-expert, design-reviewer, swiss-tech-resume-reviewer - Full iteration cycle can be triggered for comprehensive improvements - Maximum 1 full re-iteration to maintain efficiency diff --git a/resumes/web-builder/index.html b/resumes/web-builder/index.html new file mode 100644 index 0000000..437edb2 --- /dev/null +++ b/resumes/web-builder/index.html @@ -0,0 +1,13 @@ + + + + + + + Resume + + +
+ + + diff --git a/resumes/web-builder/package-lock.json b/resumes/web-builder/package-lock.json new file mode 100644 index 0000000..35eb3a9 --- /dev/null +++ b/resumes/web-builder/package-lock.json @@ -0,0 +1,2593 @@ +{ + "name": "web-builder", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "web-builder", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "gray-matter": "^4.0.3", + "marked": "^17.0.0", + "react": "^19.2.0", + "react-dom": "^19.2.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4.1.17", + "@types/marked": "^5.0.2", + "@types/react": "^19.2.2", + "@types/react-dom": "^19.2.2", + "@vitejs/plugin-react": "^5.1.0", + "autoprefixer": "^10.4.21", + "postcss": "^8.5.6", + "tailwindcss": "^4.1.17", + "typescript": "^5.9.3", + "vite": "^7.2.2" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "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.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "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.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.43", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.43.tgz", + "integrity": "sha512-5Uxg7fQUCmfhax7FJke2+8B6cqgeUJUD9o2uXIKXhD+mG0mL6NObmVoi9wXEU1tY89mZKgAYA6fTbftx3q2ZPQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.2.tgz", + "integrity": "sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.2.tgz", + "integrity": "sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.2.tgz", + "integrity": "sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.2.tgz", + "integrity": "sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.2.tgz", + "integrity": "sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.2.tgz", + "integrity": "sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.2.tgz", + "integrity": "sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.2.tgz", + "integrity": "sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.2.tgz", + "integrity": "sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.2.tgz", + "integrity": "sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.2.tgz", + "integrity": "sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.2.tgz", + "integrity": "sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.2.tgz", + "integrity": "sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.2.tgz", + "integrity": "sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.2.tgz", + "integrity": "sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.2.tgz", + "integrity": "sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.2.tgz", + "integrity": "sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.2.tgz", + "integrity": "sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.2.tgz", + "integrity": "sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.2.tgz", + "integrity": "sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.2.tgz", + "integrity": "sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.2.tgz", + "integrity": "sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tailwindcss/node": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.17.tgz", + "integrity": "sha512-csIkHIgLb3JisEFQ0vxr2Y57GUNYh447C8xzwj89U/8fdW8LhProdxvnVH6U8M2Y73QKiTIH+LWbK3V2BBZsAg==", + "dev": true, + "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.17" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.17.tgz", + "integrity": "sha512-F0F7d01fmkQhsTjXezGBLdrl1KresJTcI3DB8EkScCldyKp3Msz4hub4uyYaVnk88BAS1g5DQjjF6F5qczheLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.17", + "@tailwindcss/oxide-darwin-arm64": "4.1.17", + "@tailwindcss/oxide-darwin-x64": "4.1.17", + "@tailwindcss/oxide-freebsd-x64": "4.1.17", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.17", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.17", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.17", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.17", + "@tailwindcss/oxide-linux-x64-musl": "4.1.17", + "@tailwindcss/oxide-wasm32-wasi": "4.1.17", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.17", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.17" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.17.tgz", + "integrity": "sha512-BMqpkJHgOZ5z78qqiGE6ZIRExyaHyuxjgrJ6eBO5+hfrfGkuya0lYfw8fRHG77gdTjWkNWEEm+qeG2cDMxArLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.17.tgz", + "integrity": "sha512-EquyumkQweUBNk1zGEU/wfZo2qkp/nQKRZM8bUYO0J+Lums5+wl2CcG1f9BgAjn/u9pJzdYddHWBiFXJTcxmOg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.17.tgz", + "integrity": "sha512-gdhEPLzke2Pog8s12oADwYu0IAw04Y2tlmgVzIN0+046ytcgx8uZmCzEg4VcQh+AHKiS7xaL8kGo/QTiNEGRog==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.17.tgz", + "integrity": "sha512-hxGS81KskMxML9DXsaXT1H0DyA+ZBIbyG/sSAjWNe2EDl7TkPOBI42GBV3u38itzGUOmFfCzk1iAjDXds8Oh0g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.17.tgz", + "integrity": "sha512-k7jWk5E3ldAdw0cNglhjSgv501u7yrMf8oeZ0cElhxU6Y2o7f8yqelOp3fhf7evjIS6ujTI3U8pKUXV2I4iXHQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.17.tgz", + "integrity": "sha512-HVDOm/mxK6+TbARwdW17WrgDYEGzmoYayrCgmLEw7FxTPLcp/glBisuyWkFz/jb7ZfiAXAXUACfyItn+nTgsdQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.17.tgz", + "integrity": "sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.17.tgz", + "integrity": "sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.17.tgz", + "integrity": "sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.17.tgz", + "integrity": "sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.6.0", + "@emnapi/runtime": "^1.6.0", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.0.7", + "@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.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.17.tgz", + "integrity": "sha512-JU5AHr7gKbZlOGvMdb4722/0aYbU+tN6lv1kONx0JK2cGsh7g148zVWLM0IKR3NeKLv+L90chBVYcJ8uJWbC9A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.17.tgz", + "integrity": "sha512-SKWM4waLuqx0IH+FMDUw6R66Hu4OuTALFgnleKbqhgGU30DY20NORZMZUKgLRjQXNN2TLzKvh48QXTig4h4bGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.17.tgz", + "integrity": "sha512-+nKl9N9mN5uJ+M7dBOOCzINw94MPstNR/GtIhz1fpZysxL/4a+No64jCBD6CPN+bIHWFx3KWuu8XJRrj/572Dw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.1.17", + "@tailwindcss/oxide": "4.1.17", + "postcss": "^8.4.41", + "tailwindcss": "4.1.17" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@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.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/marked": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-5.0.2.tgz", + "integrity": "sha512-OucS4KMHhFzhz27KxmWg7J+kIYqyqoW5kdIEI319hqARQQUTqhao3M/F+uFnDXD0Rg72iDDZxZNxq5gvctmLlg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", + "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.2", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.2.tgz", + "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.0.tgz", + "integrity": "sha512-4LuWrg7EKWgQaMJfnN+wcmbAW+VSsCmqGohftWjuct47bv8uE4n/nPpq4XjJPsxgq00GGG5J8dvBczp8uxScew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.4", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.43", + "@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/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "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.24.4", + "caniuse-lite": "^1.0.30001702", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "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/baseline-browser-mapping": { + "version": "2.8.25", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.25.tgz", + "integrity": "sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/browserslist": { + "version": "4.27.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", + "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", + "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.8.19", + "caniuse-lite": "^1.0.30001751", + "electron-to-chromium": "^1.5.238", + "node-releases": "^2.0.26", + "update-browserslist-db": "^1.1.4" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001754", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz", + "integrity": "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==", + "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/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/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/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.249", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.249.tgz", + "integrity": "sha512-5vcfL3BBe++qZ5kuFhD/p8WOM1N9m3nwvJPULJx+4xf2usSlZFJ0qoNYO2fOX4hi3ocuDcmDobtA+5SFr4OmBg==", + "dev": true, + "license": "ISC" + }, + "node_modules/enhanced-resolve": { + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/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/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "license": "MIT", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/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/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lightningcss": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", + "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", + "dev": true, + "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.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", + "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", + "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", + "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "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.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", + "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", + "cpu": [ + "x64" + ], + "dev": true, + "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.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", + "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", + "cpu": [ + "arm" + ], + "dev": true, + "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.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", + "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", + "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", + "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", + "cpu": [ + "x64" + ], + "dev": true, + "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.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", + "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", + "cpu": [ + "x64" + ], + "dev": true, + "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.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", + "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "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.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", + "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/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/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/marked": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.0.tgz", + "integrity": "sha512-KkDYEWEEiYJw/KC+DVm1zzlpMQSMIu6YRltkcCvwheCp8HWPXCk9JwOmHJKBlGfzcpzcIt6x3sMnTsRm/51oDg==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/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.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "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/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "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.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/react": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", + "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", + "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.0" + } + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/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/rollup": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.2.tgz", + "integrity": "sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.53.2", + "@rollup/rollup-android-arm64": "4.53.2", + "@rollup/rollup-darwin-arm64": "4.53.2", + "@rollup/rollup-darwin-x64": "4.53.2", + "@rollup/rollup-freebsd-arm64": "4.53.2", + "@rollup/rollup-freebsd-x64": "4.53.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.2", + "@rollup/rollup-linux-arm-musleabihf": "4.53.2", + "@rollup/rollup-linux-arm64-gnu": "4.53.2", + "@rollup/rollup-linux-arm64-musl": "4.53.2", + "@rollup/rollup-linux-loong64-gnu": "4.53.2", + "@rollup/rollup-linux-ppc64-gnu": "4.53.2", + "@rollup/rollup-linux-riscv64-gnu": "4.53.2", + "@rollup/rollup-linux-riscv64-musl": "4.53.2", + "@rollup/rollup-linux-s390x-gnu": "4.53.2", + "@rollup/rollup-linux-x64-gnu": "4.53.2", + "@rollup/rollup-linux-x64-musl": "4.53.2", + "@rollup/rollup-openharmony-arm64": "4.53.2", + "@rollup/rollup-win32-arm64-msvc": "4.53.2", + "@rollup/rollup-win32-ia32-msvc": "4.53.2", + "@rollup/rollup-win32-x64-gnu": "4.53.2", + "@rollup/rollup-win32-x64-msvc": "4.53.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tailwindcss": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.17.tgz", + "integrity": "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "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/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "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/vite": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.2.tgz", + "integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "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", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.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 + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "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/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/resumes/web-builder/package.json b/resumes/web-builder/package.json new file mode 100644 index 0000000..f1f306d --- /dev/null +++ b/resumes/web-builder/package.json @@ -0,0 +1,34 @@ +{ + "name": "web-builder", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview", + "lint": "tsc --noEmit" + }, + "keywords": [], + "author": "", + "license": "ISC", + "type": "module", + "dependencies": { + "gray-matter": "^4.0.3", + "marked": "^17.0.0", + "react": "^19.2.0", + "react-dom": "^19.2.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4.1.17", + "@types/marked": "^5.0.2", + "@types/react": "^19.2.2", + "@types/react-dom": "^19.2.2", + "@vitejs/plugin-react": "^5.1.0", + "autoprefixer": "^10.4.21", + "postcss": "^8.5.6", + "tailwindcss": "^4.1.17", + "typescript": "^5.9.3", + "vite": "^7.2.2" + } +} diff --git a/resumes/web-builder/postcss.config.js b/resumes/web-builder/postcss.config.js new file mode 100644 index 0000000..1c87846 --- /dev/null +++ b/resumes/web-builder/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + '@tailwindcss/postcss': {}, + autoprefixer: {}, + }, +} diff --git a/resumes/web-builder/public/robots.txt b/resumes/web-builder/public/robots.txt new file mode 100644 index 0000000..1f53798 --- /dev/null +++ b/resumes/web-builder/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / diff --git a/resumes/web-builder/src/App.tsx b/resumes/web-builder/src/App.tsx new file mode 100644 index 0000000..bacfe61 --- /dev/null +++ b/resumes/web-builder/src/App.tsx @@ -0,0 +1,112 @@ +import { useEffect, useState } from 'react'; +import { parseResumeContent } from './utils/parseResume'; +import type { ParsedResume } from './types/resume'; +import { ResumeHeader } from './components/ResumeHeader'; +import { ExperienceSection } from './components/ExperienceSection'; +import { SkillsSection } from './components/SkillsSection'; +import { EducationSection } from './components/EducationSection'; + +function App() { + const [resume, setResume] = useState(null); + const [error, setError] = useState(null); + + useEffect(() => { + // Load resume_content.md from public folder or embedded + fetch('/resume_content.md') + .then(res => res.text()) + .then(content => { + const parsed = parseResumeContent(content); + setResume(parsed); + }) + .catch(err => { + console.error('Failed to load resume:', err); + setError('Failed to load resume content.'); + }); + }, []); + + if (error) { + return ( +
+
+

{error}

+
+
+ ); + } + + if (!resume) { + return ( +
+
Loading...
+
+ ); + } + + const { data } = resume; + + return ( +
+
+ + + {data.summary && ( +
+

+ Professional Summary +

+

{data.summary}

+
+ )} + + + + + + {data.projects && data.projects.length > 0 && ( +
+

+ Projects +

+
+ {data.projects.map((project, index) => ( +
+

+ {project.link ? ( + + {project.name} + + ) : ( + project.name + )} +

+

{project.description}

+
+ ))} +
+
+ )} + + +
+
+ ); +} + +export default App; diff --git a/resumes/web-builder/src/components/EducationSection.tsx b/resumes/web-builder/src/components/EducationSection.tsx new file mode 100644 index 0000000..bcc91e0 --- /dev/null +++ b/resumes/web-builder/src/components/EducationSection.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import type { EducationItem } from '../types/resume'; +import { renderMarkdown } from '../utils/parseResume'; + +interface Props { + education: EducationItem[]; +} + +export const EducationSection: React.FC = ({ education }) => { + return ( +
+

+ Education +

+ +
+ {education.map((edu, index) => ( +
+

+ {edu.degree} +

+
+ {edu.institution} + {edu.location && | {edu.location}} + {edu.dates && | {edu.dates}} +
+ + {edu.description && ( +
+ )} +
+ ))} +
+
+ ); +}; diff --git a/resumes/web-builder/src/components/ExperienceSection.tsx b/resumes/web-builder/src/components/ExperienceSection.tsx new file mode 100644 index 0000000..1bdfd92 --- /dev/null +++ b/resumes/web-builder/src/components/ExperienceSection.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import type { ExperienceItem } from '../types/resume'; +import { renderMarkdown } from '../utils/parseResume'; + +interface Props { + experiences: ExperienceItem[]; +} + +export const ExperienceSection: React.FC = ({ experiences }) => { + return ( +
+

+ Experience +

+ +
+ {experiences.map((exp, index) => ( +
+

+ {exp.title} +

+
+ {exp.company} + {exp.location && | {exp.location}} + {exp.dates && | {exp.dates}} +
+ +
    + {exp.achievements.map((achievement, idx) => ( +
  • + ))} +
+
+ ))} +
+
+ ); +}; diff --git a/resumes/web-builder/src/components/ResumeHeader.tsx b/resumes/web-builder/src/components/ResumeHeader.tsx new file mode 100644 index 0000000..db37aab --- /dev/null +++ b/resumes/web-builder/src/components/ResumeHeader.tsx @@ -0,0 +1,90 @@ +import React from 'react'; +import type { ResumeHeader as ResumeHeaderType } from '../types/resume'; + +interface Props { + header: ResumeHeaderType; +} + +export const ResumeHeader: React.FC = ({ header }) => { + return ( +
+

+ {header.name} +

+

+ {header.title} +

+ +
+
+ 📍 + {header.location} +
+ + + + {header.phone && ( + + )} + + {header.linkedin && ( +
+ 🔗 + + LinkedIn + +
+ )} + + {header.github && ( +
+ 💻 + + GitHub + +
+ )} + + {header.website && ( +
+ 🌐 + + Website + +
+ )} +
+
+ ); +}; diff --git a/resumes/web-builder/src/components/SkillsSection.tsx b/resumes/web-builder/src/components/SkillsSection.tsx new file mode 100644 index 0000000..f2a8889 --- /dev/null +++ b/resumes/web-builder/src/components/SkillsSection.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import type { ResumeSkills } from '../types/resume'; + +interface Props { + skills: ResumeSkills; +} + +export const SkillsSection: React.FC = ({ skills }) => { + return ( +
+

+ Technical Skills +

+ +
+ {Object.entries(skills).map(([category, skillsList]) => ( +
+ + {category}: + + {skillsList} +
+ ))} +
+
+ ); +}; diff --git a/resumes/web-builder/src/index.css b/resumes/web-builder/src/index.css new file mode 100644 index 0000000..43c3eec --- /dev/null +++ b/resumes/web-builder/src/index.css @@ -0,0 +1,83 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* Global styles */ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* Print styles for browser print-to-PDF */ +@media print { + @page { + size: A4; + margin: 1.5cm; + } + + body { + background: white !important; + } + + .print\:hidden { + display: none !important; + } + + .print\:text-black { + color: black !important; + } + + .print\:text-gray-700 { + color: #374151 !important; + } + + .print\:bg-white { + background: white !important; + } + + .print\:shadow-none { + box-shadow: none !important; + } + + .print\:my-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + + .print\:border-gray-400 { + border-color: #9ca3af !important; + } + + /* Prevent page breaks inside sections */ + section { + page-break-inside: avoid; + } + + /* Keep headings with content */ + h2, h3 { + page-break-after: avoid; + } +} + +/* Markdown rendering styles */ +.achievement-bullet strong { + font-weight: 600; + color: #2C5F7F; +} + +.achievement-bullet em { + font-style: italic; +} + +.achievement-bullet a { + color: #2C5F7F; + text-decoration: underline; +} + +.achievement-bullet a:hover { + color: #1e4059; +} diff --git a/resumes/web-builder/src/main.tsx b/resumes/web-builder/src/main.tsx new file mode 100644 index 0000000..2339d59 --- /dev/null +++ b/resumes/web-builder/src/main.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App'; +import './index.css'; + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + +); diff --git a/resumes/web-builder/src/types/resume.ts b/resumes/web-builder/src/types/resume.ts new file mode 100644 index 0000000..074198c --- /dev/null +++ b/resumes/web-builder/src/types/resume.ts @@ -0,0 +1,62 @@ +// Resume data structure matching resume_content.md YAML schema + +export interface ResumeMetadata { + id: string; + targetRole: string; + targetCompany: string; + generatedDate: string; + language: 'en' | 'de'; + salaryTarget?: number; +} + +export interface ResumeHeader { + name: string; + title: string; + location: string; + email: string; + phone: string; + linkedin?: string; + github?: string; + website?: string; +} + +export interface ExperienceItem { + title: string; + company: string; + location: string; + dates: string; + achievements: string[]; // Markdown strings +} + +export interface EducationItem { + degree: string; + institution: string; + location: string; + dates: string; + description?: string; // Markdown string +} + +export interface ProjectItem { + name: string; + description: string; // Markdown string + link?: string; +} + +export interface ResumeSkills { + [category: string]: string; // e.g., "ML/AI Frameworks": "TensorFlow, PyTorch..." +} + +export interface ResumeData { + metadata: ResumeMetadata; + header: ResumeHeader; + summary: string; // Markdown string + experience: ExperienceItem[]; + skills: ResumeSkills; + education: EducationItem[]; + projects?: ProjectItem[]; +} + +export interface ParsedResume { + data: ResumeData; + rawContent: string; // Original markdown for reference +} diff --git a/resumes/web-builder/src/utils/parseResume.ts b/resumes/web-builder/src/utils/parseResume.ts new file mode 100644 index 0000000..f3daad8 --- /dev/null +++ b/resumes/web-builder/src/utils/parseResume.ts @@ -0,0 +1,178 @@ +import matter from 'gray-matter'; +import { marked } from 'marked'; +import type { ResumeData, ParsedResume, ExperienceItem, EducationItem, ProjectItem } from '../types/resume'; + +/** + * Parse resume_content.md file (YAML frontmatter + Markdown) + */ +export function parseResumeContent(fileContent: string): ParsedResume { + // Extract YAML frontmatter + const { data, content } = matter(fileContent); + + // Parse markdown sections + const sections = parseMarkdownSections(content); + + // Build structured resume data + const resumeData: ResumeData = { + metadata: data.metadata, + header: data.header, + summary: sections.summary || '', + experience: parseExperienceSection(sections.experience || ''), + skills: parseSkillsSection(sections.skills || ''), + education: parseEducationSection(sections.education || ''), + projects: sections.projects ? parseProjectsSection(sections.projects) : undefined, + }; + + return { + data: resumeData, + rawContent: fileContent, + }; +} + +/** + * Split markdown content into sections + */ +function parseMarkdownSections(content: string): Record { + const sections: Record = {}; + const lines = content.split('\n'); + let currentSection = 'summary'; + let currentContent: string[] = []; + + for (const line of lines) { + // Detect ## section headers + if (line.startsWith('## ')) { + // Save previous section + if (currentContent.length > 0) { + sections[currentSection] = currentContent.join('\n').trim(); + } + // Start new section + currentSection = line.replace('## ', '').toLowerCase().trim(); + currentContent = []; + } else if (line.startsWith('# Professional Summary')) { + currentSection = 'summary'; + currentContent = []; + } else { + currentContent.push(line); + } + } + + // Save last section + if (currentContent.length > 0) { + sections[currentSection] = currentContent.join('\n').trim(); + } + + return sections; +} + +/** + * Parse Experience section into structured items + */ +function parseExperienceSection(content: string): ExperienceItem[] { + const items: ExperienceItem[] = []; + const entries = content.split('\n### ').filter(e => e.trim()); + + for (const entry of entries) { + const lines = entry.split('\n').filter(l => l.trim()); + if (lines.length < 2) continue; + + const title = lines[0].replace('### ', '').trim(); + const meta = lines[1].replace(/\*\*/g, '').trim(); // Remove bold markers + const [company, location, dates] = meta.split('|').map(s => s.trim()); + + const achievements = lines + .slice(2) + .filter(l => l.startsWith('-')) + .map(l => l.replace(/^-\s*/, '').trim()); + + items.push({ + title, + company: company || '', + location: location || '', + dates: dates || '', + achievements, + }); + } + + return items; +} + +/** + * Parse Skills section into categories + */ +function parseSkillsSection(content: string): Record { + const skills: Record = {}; + const lines = content.split('\n').filter(l => l.trim() && l.includes(':')); + + for (const line of lines) { + const [category, skillsList] = line.split(':').map(s => s.replace(/\*\*/g, '').trim()); + if (category && skillsList) { + skills[category] = skillsList; + } + } + + return skills; +} + +/** + * Parse Education section into structured items + */ +function parseEducationSection(content: string): EducationItem[] { + const items: EducationItem[] = []; + const entries = content.split('\n### ').filter(e => e.trim()); + + for (const entry of entries) { + const lines = entry.split('\n').filter(l => l.trim()); + if (lines.length < 2) continue; + + const degree = lines[0].replace('### ', '').trim(); + const meta = lines[1].replace(/\*\*/g, '').trim(); + const [institution, location, dates] = meta.split('|').map(s => s.trim()); + + const description = lines.slice(2).join('\n').trim(); + + items.push({ + degree, + institution: institution || '', + location: location || '', + dates: dates || '', + description: description || undefined, + }); + } + + return items; +} + +/** + * Parse Projects section into structured items + */ +function parseProjectsSection(content: string): ProjectItem[] { + const items: ProjectItem[] = []; + const entries = content.split('\n### ').filter(e => e.trim()); + + for (const entry of entries) { + const lines = entry.split('\n').filter(l => l.trim()); + if (lines.length < 1) continue; + + const name = lines[0].replace('### ', '').trim(); + const description = lines.slice(1).join('\n').trim(); + + // Extract link if present + const linkMatch = description.match(/\[.*?\]\((.*?)\)/); + const link = linkMatch ? linkMatch[1] : undefined; + + items.push({ + name, + description, + link, + }); + } + + return items; +} + +/** + * Render markdown string to HTML + */ +export function renderMarkdown(markdown: string): string { + return marked.parse(markdown) as string; +} diff --git a/resumes/web-builder/tailwind.config.js b/resumes/web-builder/tailwind.config.js new file mode 100644 index 0000000..34eaa1c --- /dev/null +++ b/resumes/web-builder/tailwind.config.js @@ -0,0 +1,17 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: [ + "./index.html", + "./src/**/*.{js,ts,jsx,tsx}", + ], + theme: { + extend: { + colors: { + 'cv-blue': '#2C5F7F', + 'cv-gray': '#4A4A4A', + 'cv-light': '#F5F5F5', + } + }, + }, + plugins: [], +} diff --git a/resumes/web-builder/tsconfig.json b/resumes/web-builder/tsconfig.json new file mode 100644 index 0000000..3934b8f --- /dev/null +++ b/resumes/web-builder/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/resumes/web-builder/tsconfig.node.json b/resumes/web-builder/tsconfig.node.json new file mode 100644 index 0000000..42872c5 --- /dev/null +++ b/resumes/web-builder/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/resumes/web-builder/vite.config.ts b/resumes/web-builder/vite.config.ts new file mode 100644 index 0000000..06e3f2b --- /dev/null +++ b/resumes/web-builder/vite.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +export default defineConfig({ + plugins: [react()], + base: '/CV/', + build: { + outDir: 'dist', + assetsInlineLimit: 10000, + rollupOptions: { + output: { + manualChunks: undefined, + } + } + } +})