From be8ff196e872776c5c0d7c968db070f528a806c9 Mon Sep 17 00:00:00 2001 From: matta Date: Tue, 1 Jul 2025 18:43:06 -0300 Subject: [PATCH 1/9] Tweaking cards and contents --- src/app/components/Card.tsx | 2 +- src/app/data/cardContent.ts | 30 +++++++++++++++++------------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/app/components/Card.tsx b/src/app/components/Card.tsx index 2678d5d..d7bc0c6 100644 --- a/src/app/components/Card.tsx +++ b/src/app/components/Card.tsx @@ -55,7 +55,7 @@ const Card: React.FC = ({ title, description, onClose, onExplore, but href={link.url} target="_blank" rel="noopener noreferrer" - className="text-white hover:text-white/80 text-base font-spartan-subtitle transition-colors uppercase underline underline-offset-2 decoration-white" + className="text-white hover:text-white/80 text-base font-spartan-subtitle transition-colors underline underline-offset-2 decoration-white" > {link.label} diff --git a/src/app/data/cardContent.ts b/src/app/data/cardContent.ts index 900bd6d..733362f 100644 --- a/src/app/data/cardContent.ts +++ b/src/app/data/cardContent.ts @@ -21,13 +21,13 @@ export interface CardContentMap { export const cardContent: CardContentMap = { temple: { - title: "The Phishing Dojo", + title: "Phishing Dojo", description: "Face the most notorious scam and phishing threats in the web3 ecosystem with the Phishing Dojo's immersive challenges. Can you spot them all?", - buttonText: "Enter the phishing dojo", + buttonText: "Enter the Phishing Dojo", links: [ { - label: "Enter the phishing dojo", - url: "https://phishing.therektgames.com/" + label: "Enter the Phishing Dojo", + url: "https://phishingdojo.com/" } ] }, @@ -49,7 +49,7 @@ export const cardContent: CardContentMap = { links: [ { label: "Learn & contribute", - url: "https://frameworks.securityalliance.org/" + url: "https://frameworks.securityalliance.dev" } ] }, @@ -58,22 +58,22 @@ export const cardContent: CardContentMap = { description: "We organize, coordinate and participate in conferences, workshops and hackathons. With a strong foothold in LATAM.", links: [ { - label: "Recent Events", + label: "Events archive", url: "https://lu.ma/theredguild" }, { - label: "Smart contract security course with cyfrin", + label: "Smart contract security course with Cyrin", url: "https://updraft.cyfrin.io/courses/security" }, { - label: "Undercover campaign in ethargentina", + label: "Undercover campaign at Ethereum Argentina", url: "https://blog.theredguild.org/you-were-not-pwned-the-red-guild-ethereum-argentina-2023/" } ] }, letters: { - title: "Security research & bug hunting", - description: "Independent reviews of smart contracts and web3 infrastructure that share Ethereum's ethos. We share learnings in public reports and blog posts.", + title: "Security Research & Advisories", + description: "Public investigations and technical posts like the Ethereum 7702 accounts deep dive, VSCode extensions audit, and the SLOVENLY COMET advisory.", buttonText: "Read our blog", links: [ { @@ -83,16 +83,20 @@ export const cardContent: CardContentMap = { ] }, flower: { - title: "Tooling", + title: "Open-Source Tooling", description: "We build open-source repositories to promote safer development environments.", links: [ { - label: "Web3 devcontainer", + label: "Web3 DevContainer", url: "https://github.com/theredguild/devcontainer" }, { - label: "devsecops toolkit", + label: "DevSecOps toolkit", url: "https://github.com/theredguild/DevSecOps-toolkit" + }, + { + label: "DevSecOOPS docs", + url: "https://devsecoops.theredguild.org/" } ] } From 13f900b0684f1320112090505b5a6f4fcc3d0d06 Mon Sep 17 00:00:00 2001 From: Ariel Vincennao Date: Tue, 1 Jul 2025 19:25:37 -0300 Subject: [PATCH 2/9] Improved clickable areas for Dojo gate svg on homepage --- src/app/components/Scene.tsx | 35 +++++++++++++++++++++++++++++++---- src/app/globals.css | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/app/components/Scene.tsx b/src/app/components/Scene.tsx index fafcbb2..d004419 100644 --- a/src/app/components/Scene.tsx +++ b/src/app/components/Scene.tsx @@ -121,7 +121,7 @@ const Scene: React.FC = ({ show, transitioning, onBack }) => { pointerEvents: transitioning ? 'none' : 'auto', }} > - {/* Cursor personalizado */} + {/* Scene cursor */} {customCursor.visible && isDesktop && (
= ({ show, transitioning, onBack }) => { {/* Temple */}
{ if (!activeElement) { setIsTempleHovered(true); } showSeeMoreCursor(); }} - onMouseLeave={() => { setIsTempleHovered(false); hideSeeMoreCursor(); }} - onClick={() => handleElementClick('temple', cardContent.temple)} + style={{position: 'relative'}} > + {/* Temple area hitboxes */} +
{ if (!activeElement) { setIsTempleHovered(true); } showSeeMoreCursor(); }} + onMouseLeave={() => { setIsTempleHovered(false); hideSeeMoreCursor(); }} + onClick={() => handleElementClick('temple', cardContent.temple)} + style={{ pointerEvents: 'auto', cursor: (!activeElement || isTempleHovered) ? 'pointer' : 'default' }} + /> +
{ if (!activeElement) { setIsTempleHovered(true); } showSeeMoreCursor(); }} + onMouseLeave={() => { setIsTempleHovered(false); hideSeeMoreCursor(); }} + onClick={() => handleElementClick('temple', cardContent.temple)} + style={{ pointerEvents: 'auto', cursor: (!activeElement || isTempleHovered) ? 'pointer' : 'default' }} + /> +
{ if (!activeElement) { setIsTempleHovered(true); } showSeeMoreCursor(); }} + onMouseLeave={() => { setIsTempleHovered(false); hideSeeMoreCursor(); }} + onClick={() => handleElementClick('temple', cardContent.temple)} + style={{ pointerEvents: 'auto', cursor: (!activeElement || isTempleHovered) ? 'pointer' : 'default' }} + /> +
{ if (!activeElement) { setIsTempleHovered(true); } showSeeMoreCursor(); }} + onMouseLeave={() => { setIsTempleHovered(false); hideSeeMoreCursor(); }} + onClick={() => handleElementClick('temple', cardContent.temple)} + style={{ pointerEvents: 'auto', cursor: (!activeElement || isTempleHovered) ? 'pointer' : 'default' }} + /> {isTempleHovered || activeElement === 'temple' ? ( Date: Wed, 8 Oct 2025 13:24:45 -0300 Subject: [PATCH 3/9] UI updates (#5) Co-authored-by: Ariel Vincennao --- eslint.config.mjs | 2 +- next.config.ts | 2 +- public/assets/letters-off.svg | 22 ------ public/assets/letters.svg | 14 ---- public/assets/lettersn-off.svg | 22 ++++++ public/assets/lettersn.svg | 14 ++++ src/app/components/BackgroundClouds.tsx | 6 +- src/app/components/MainContent.tsx | 71 +++++++------------ src/app/components/Navbar.tsx | 19 +++++ src/app/components/ParticlesDOM.tsx | 4 +- src/app/components/Scene.tsx | 23 +++--- .../components/SupportersCollaborators.tsx | 25 +++++++ src/app/contact/page.tsx | 48 ++++++------- src/app/globals.css | 3 +- src/app/initiatives/page.tsx | 2 +- src/app/layout.tsx | 3 - src/app/page.tsx | 26 ++++--- src/app/supporters/page.tsx | 20 ++++++ 18 files changed, 178 insertions(+), 148 deletions(-) delete mode 100644 public/assets/letters-off.svg delete mode 100644 public/assets/letters.svg create mode 100644 public/assets/lettersn-off.svg create mode 100644 public/assets/lettersn.svg create mode 100644 src/app/components/SupportersCollaborators.tsx create mode 100644 src/app/supporters/page.tsx diff --git a/eslint.config.mjs b/eslint.config.mjs index c85fb67..c30d3d9 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -13,4 +13,4 @@ const eslintConfig = [ ...compat.extends("next/core-web-vitals", "next/typescript"), ]; -export default eslintConfig; +export default eslintConfig; \ No newline at end of file diff --git a/next.config.ts b/next.config.ts index 8f6976e..18b2799 100644 --- a/next.config.ts +++ b/next.config.ts @@ -17,4 +17,4 @@ const nextConfig: NextConfig = { }, }; -export default nextConfig; +export default nextConfig; \ No newline at end of file diff --git a/public/assets/letters-off.svg b/public/assets/letters-off.svg deleted file mode 100644 index ece8992..0000000 --- a/public/assets/letters-off.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/public/assets/letters.svg b/public/assets/letters.svg deleted file mode 100644 index c618ac5..0000000 --- a/public/assets/letters.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/public/assets/lettersn-off.svg b/public/assets/lettersn-off.svg new file mode 100644 index 0000000..ef36358 --- /dev/null +++ b/public/assets/lettersn-off.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/assets/lettersn.svg b/public/assets/lettersn.svg new file mode 100644 index 0000000..f6e7152 --- /dev/null +++ b/public/assets/lettersn.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/app/components/BackgroundClouds.tsx b/src/app/components/BackgroundClouds.tsx index a0d3a95..761e84d 100644 --- a/src/app/components/BackgroundClouds.tsx +++ b/src/app/components/BackgroundClouds.tsx @@ -19,7 +19,7 @@ const BackgroundClouds = ({ onlyInScene }: BackgroundCloudsProps) => { alt="Cloud background" width={359} height={316} - className="object-contain absolute inset-0" + className="object-contain absolute inset-0 opacity-85" priority />
@@ -33,7 +33,7 @@ const BackgroundClouds = ({ onlyInScene }: BackgroundCloudsProps) => { alt="Cloud background" width={359} height={316} - className="object-contain absolute inset-0" + className="object-contain absolute inset-0 opacity-85" priority />
@@ -91,4 +91,4 @@ const BackgroundClouds = ({ onlyInScene }: BackgroundCloudsProps) => { ); }; -export default BackgroundClouds; \ No newline at end of file +export default BackgroundClouds; diff --git a/src/app/components/MainContent.tsx b/src/app/components/MainContent.tsx index 2a8989b..a0445e3 100644 --- a/src/app/components/MainContent.tsx +++ b/src/app/components/MainContent.tsx @@ -2,21 +2,10 @@ import React, { useRef, useState, useEffect } from 'react'; import Image from 'next/image'; -const TEXT = 'Advancing crypto security with research, tools and resources for the public good.'; -const COLOR_START = { r: 255, g: 255, b: 255 }; -const COLOR_END = { r: 247, g: 57, b: 47 }; // Rojo -const TRANSITION_SCROLL = 500; +const TRANSITION_SCROLL = 50; // Scroll para activar transición -function lerpColor(a: { r: number; g: number; b: number }, b: { r: number; g: number; b: number }, t: number) { - return { - r: Math.round(a.r + (b.r - a.r) * t), - g: Math.round(a.g + (b.g - a.g) * t), - b: Math.round(a.b + (b.b - a.b) * t), - }; -} - -const MainContent = ({ onSectionEnd }: { onSectionEnd: () => void }) => { - const [progress, setProgress] = useState(0); // 0 a 1 +const MainContent = ({ onSectionEnd, transitioning: parentTransitioning }: { onSectionEnd: () => void; transitioning?: boolean }) => { + const [, setProgress] = useState(0); // 0 a 1 const [transitioning, setTransitioning] = useState(false); const [blockScroll, setBlockScroll] = useState(false); const [showSection, setShowSection] = useState(true); @@ -37,7 +26,7 @@ const MainContent = ({ onSectionEnd }: { onSectionEnd: () => void }) => { setBlockScroll(false); window.scrollTo({ top: 0, behavior: 'auto' }); onSectionEnd(); - }, 400); + }, 500); // Match fade duration } }; window.addEventListener('scroll', handleScroll, { passive: true }); @@ -45,11 +34,11 @@ const MainContent = ({ onSectionEnd }: { onSectionEnd: () => void }) => { }, [transitioning, blockScroll, onSectionEnd]); useEffect(() => { - document.body.style.overflow = transitioning || blockScroll ? 'hidden' : ''; + document.body.style.overflow = (transitioning || blockScroll || parentTransitioning) ? 'hidden' : ''; return () => { document.body.style.overflow = ''; }; - }, [transitioning, blockScroll]); + }, [transitioning, blockScroll, parentTransitioning]); const lines = [ 'Advancing crypto security', @@ -73,9 +62,9 @@ const MainContent = ({ onSectionEnd }: { onSectionEnd: () => void }) => { alignItems: 'center', justifyContent: 'center', zIndex: 10, - opacity: transitioning ? 0 : 1, - transition: 'opacity 0.09s', - pointerEvents: transitioning ? 'none' : 'auto', + opacity: (transitioning || parentTransitioning) ? 0 : 1, + transition: 'opacity 0.5s ease-in-out', + pointerEvents: (transitioning || parentTransitioning) ? 'none' : 'auto', }} >
@@ -89,33 +78,23 @@ const MainContent = ({ onSectionEnd }: { onSectionEnd: () => void }) => { sizes="169px" />
-

+

- {lines.map((line, lineIndex) => { - const startIndex = TEXT.indexOf(line); - return ( -
- {line.split('').map((char, charIndex) => { - const index = startIndex + charIndex; - const t = Math.max(0, Math.min(1, progress * TEXT.length - index)); - const color = lerpColor(COLOR_START, COLOR_END, t); - const isActive = t >= 1; - return ( - - {char === ' ' ? '\u00A0' : char} - - ); - })} -
- ); - })} + {lines.map((line, lineIndex) => ( +
+ {line.split('').map((char, charIndex) => ( + + {char === ' ' ? '\u00A0' : char} + + ))} +
+ ))}

diff --git a/src/app/components/Navbar.tsx b/src/app/components/Navbar.tsx index a527ea0..c732210 100644 --- a/src/app/components/Navbar.tsx +++ b/src/app/components/Navbar.tsx @@ -51,6 +51,15 @@ const Navbar = () => { Initiatives +
  • + + Supporters + +
  • { Initiatives
  • +
  • + + Supporters + +
  • = ({ - countMobile = 24, - countDesktop = 48, + countMobile = 12, + countDesktop = 24, fadeIn = true, zIndexClass = 'z-20', }) => { diff --git a/src/app/components/Scene.tsx b/src/app/components/Scene.tsx index d004419..de50cf0 100644 --- a/src/app/components/Scene.tsx +++ b/src/app/components/Scene.tsx @@ -7,7 +7,6 @@ import TempleOff from "./assets/TempleOff"; import Temple from './assets/Temple'; import Card from './Card'; import { cardContent, CardContent } from '../data/cardContent'; -import ParticlesDOM from './ParticlesDOM'; interface SceneProps { show: boolean; @@ -117,7 +116,7 @@ const Scene: React.FC = ({ show, transitioning, onBack }) => { className={`scene-section-container h-screen relative${fadeOut ? ' fade-out-scene' : ''} ${customCursor.visible ? 'scene-see-more-cursor' : ''}`} style={{ opacity: transitioning ? 0 : 1, - transition: 'opacity 0.09s', + transition: 'opacity 0.5s ease-in-out', pointerEvents: transitioning ? 'none' : 'auto', }} > @@ -131,8 +130,6 @@ const Scene: React.FC = ({ show, transitioning, onBack }) => {
  • )}
    - {/* Animated DOM particles canvas */} - {/* Temple */}
    = ({ show, transitioning, onBack }) => { {/* Temple */}
    {/* Temple area hitboxes */} @@ -234,7 +231,7 @@ const Scene: React.FC = ({ show, transitioning, onBack }) => { alt="Light" fill priority - className={`object-contain transform origin-center transition-transform duration-300 ${(activeElement === 'leftLight') ? 'scale-180' : 'scale-160'} ${(isLeftLightHovered && !activeElement) ? 'brightness-125' : ''} ${activeElement && activeElement !== 'leftLight' ? 'opacity-15' : ''}`} + className={`object-contain transform origin-center transition-transform duration-300 ${(activeElement === 'leftLight') ? 'scale-175' : 'scale-160'} ${(isLeftLightHovered && !activeElement) ? 'brightness-125' : ''} ${activeElement && activeElement !== 'leftLight' ? 'opacity-15' : ''}`} />
    = ({ show, transitioning, onBack }) => { alt="Flower" fill priority - className={`object-contain${activeElement && activeElement !== 'flower' ? ' opacity-15 pointer-events-none' : ''} transition-transform duration-300 ${(activeElement === 'flower') ? 'scale-160 sm:scale-160 md:scale-160 lg:scale-160' : 'scale-140 sm:scale-140 md:scale-140 lg:scale-140'} ${(isFlowerHovered && !activeElement) ? 'brightness-125' : ''}`} + className={`object-contain${activeElement && activeElement !== 'flower' ? ' opacity-15 pointer-events-none' : ''} transition-transform duration-300 ${(activeElement === 'flower') ? 'scale-155 sm:scale-155 md:scale-155 lg:scale-155' : 'scale-140 sm:scale-140 md:scale-140 lg:scale-140'} ${(isFlowerHovered && !activeElement) ? 'brightness-125' : ''}`} onMouseEnter={() => !activeElement && setIsFlowerHovered(true)} onMouseLeave={() => setIsFlowerHovered(false)} onClick={() => handleElementClick('flower', cardContent.flower)} @@ -291,7 +288,7 @@ const Scene: React.FC = ({ show, transitioning, onBack }) => { alt="Tree" fill priority - className={`object-contain transform origin-center transition-transform duration-300 ${(activeElement === 'tree') ? 'scale-250' : 'scale-200'} ${(isTreeHovered && !activeElement) ? 'brightness-125' : ''} ${activeElement && activeElement !== 'tree' ? 'opacity-15' : ''}`} + className={`object-contain transform origin-center transition-transform duration-300 ${(activeElement === 'tree') ? 'scale-215' : 'scale-200'} ${(isTreeHovered && !activeElement) ? 'brightness-125' : ''} ${activeElement && activeElement !== 'tree' ? 'opacity-15' : ''}`} />
    = ({ show, transitioning, onBack }) => { alt="Lights" fill priority - className={`pointer-events-auto object-contain${activeElement && activeElement !== 'topRightLights' ? ' opacity-15 pointer-events-none' : ''} transform origin-center transition-transform duration-300 ${(activeElement === 'topRightLights') ? 'scale-180 sm:scale-180 md:scale-180 lg:scale-180' : 'scale-160 sm:scale-160 md:scale-160 lg:scale-160'} ${(isTopRightLightsHovered && !activeElement) ? 'brightness-125' : ''}`} + className={`pointer-events-auto object-contain${activeElement && activeElement !== 'topRightLights' ? ' opacity-15 pointer-events-none' : ''} transform origin-center transition-transform duration-300 ${(activeElement === 'topRightLights') ? 'scale-175 sm:scale-175 md:scale-175 lg:scale-175' : 'scale-160 sm:scale-160 md:scale-160 lg:scale-160'} ${(isTopRightLightsHovered && !activeElement) ? 'brightness-125' : ''}`} onMouseEnter={() => !activeElement && setIsTopRightLightsHovered(true)} onMouseLeave={() => setIsTopRightLightsHovered(false)} onClick={() => handleElementClick('topRightLights', cardContent.topRightLights)} @@ -321,14 +318,14 @@ const Scene: React.FC = ({ show, transitioning, onBack }) => {
    {/* Left Top Letters */} -
    -
    +
    +
    Letters
    { + return ( +
    + Supporters & Collaborators + +

    + The Red Guild works thanks to grants and donations - if you'd like to support our public-benefit work, get in touch. +

    +
    + ); +}; + +export default SupportersCollaborators; diff --git a/src/app/contact/page.tsx b/src/app/contact/page.tsx index a379cfd..11263f9 100644 --- a/src/app/contact/page.tsx +++ b/src/app/contact/page.tsx @@ -4,47 +4,41 @@ import Navbar from "../components/Navbar"; import BackgroundClouds from "../components/BackgroundClouds"; import ParticlesDOM from '../components/ParticlesDOM'; import XIcon from '../components/assets/XIcon'; +import Image from 'next/image'; export default function ContactPage() { return (
    - +

    Contact Us

    -
    -
    - {/* Social media */} - - - - - Letter + + {/* Email - Prominent position */} + + + {/* Social media icons */} + + {/* Supporters & Collaborators */} -
    - Supporters & Collaborators - -

    - The Red Guild works thanks to grants and donations - if you'd like to support our public-benefit work, get in touch. -

    -
    + {/* */}
    ); diff --git a/src/app/globals.css b/src/app/globals.css index cd36aa9..dcdd3d7 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,3 +1,4 @@ +@import url('https://fonts.googleapis.com/css2?family=Spartan:wght@400;500;600;700&display=swap'); /* Spartan font */ @import "tailwindcss"; :root { @@ -772,7 +773,7 @@ body::-webkit-scrollbar { .scene-see-more-cursor-label { font-family: 'Pixelify Sans', 'Pixelify', sans-serif; - font-size: 10px; + font-size: 14px; color: #fff; background: #222; border-radius: 6px; diff --git a/src/app/initiatives/page.tsx b/src/app/initiatives/page.tsx index a21de30..0a5da9c 100644 --- a/src/app/initiatives/page.tsx +++ b/src/app/initiatives/page.tsx @@ -15,7 +15,7 @@ export default function InitiativesPage() { return (
    - +

    Initiatives

    diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 5b29998..3c077ff 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -54,9 +54,6 @@ export default function RootLayout({ {/* Add any necessary meta tags here */} - - - { setTransitioning(true); setBlockScroll(true); @@ -27,26 +28,21 @@ export default function Home() { setBlockScroll(false); setUnmountScene(false); // Ensures Scene is mounted window.scrollTo({ top: 0, behavior: 'auto' }); - }, 200); + }, 500); // Match fade duration }; - // Return from Scene (Section2) to MainContent (Section1) + // Return from Scene (Section2) to MainContent (Section1) - Fade back const handleBackToSection1 = () => { setTransitioning(true); setBlockScroll(true); setTimeout(() => { setShowSection2(false); - setShowSection1(false); + setShowSection1(true); + setTransitioning(false); + setBlockScroll(false); + setUnmountScene(true); // Unmounts Scene after fade-out window.scrollTo({ top: 0, behavior: 'auto' }); - setTimeout(() => { - setShowSection1(true); - setTransitioning(false); - setBlockScroll(false); - }, 100); - setTimeout(() => { - setUnmountScene(true); // Unmounts Scene after fade-out - }, 300); // Wait for fade-out-scene duration - }, 200); + }, 500); // Match fade duration }; React.useEffect(() => { @@ -61,11 +57,13 @@ export default function Home() {
    + {/* Global particles that persist across all sections */} +
    setShowLoading(false)} /> - {showSection1 && } + {showSection1 && } {(showSection2 || (!unmountScene && transitioning)) && ( )} diff --git a/src/app/supporters/page.tsx b/src/app/supporters/page.tsx new file mode 100644 index 0000000..e7de5d3 --- /dev/null +++ b/src/app/supporters/page.tsx @@ -0,0 +1,20 @@ +'use client'; + +import Navbar from "../components/Navbar"; +import BackgroundClouds from "../components/BackgroundClouds"; +import ParticlesDOM from '../components/ParticlesDOM'; +import SupportersCollaborators from '../components/SupportersCollaborators'; + +export default function SupportersPage() { + return ( +
    + + + +
    + {/* Supporters & Collaborators Section */} + +
    +
    + ); +} From ce19896feefe8b5f7e8178a4a934745fcb289bfe Mon Sep 17 00:00:00 2001 From: "vercel[bot]" <35613825+vercel[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 13:14:10 -0300 Subject: [PATCH 4/9] Fix React Server Components RCE vulnerability (#9) > [!IMPORTANT] > This is an automatic PR generated by Vercel to help you with patching efforts. We can't guarantee it's comprehensive, and it may contain mistakes. Please review our [guidance](https://vercel.link/additional-checks) before merging these changes. A critical remote code execution (RCE) vulnerability in React Server Components, impacting frameworks such as Next.js, was identified in the project [landing-v2](https://vercel.com/theredguild/landing-v2). The vulnerability enables unauthenticated RCE on the server via insecure deserialization in the React Flight protocol. This issue is tracked under: - GitHub Security Advisory: [GHSA-9qr9-h5gf-34mp](https://github.com/vercel/next.js/security/advisories/GHSA-9qr9-h5gf-34mp) - React Advisory: [CVE-2025-55182](https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components) - Next.js Advisory: [CVE-2025-66478](https://nextjs.org/blog/CVE-2025-66478) This automated pull request upgrades the affected React and Next.js packages to patched versions that fully remediate the issue. [More Info](https://vercel.link/cve-2025-55182-automated-pr) | security@vercel.com Co-authored-by: Vercel --- package-lock.json | 80 +++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/package-lock.json b/package-lock.json index 94b0d34..73b6a3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.0", "dependencies": { "framer-motion": "^12.18.1", - "next": "15.3.3", + "next": "15.3.6", "react": "^19.0.0", "react-dom": "^19.0.0", "react-tsparticles": "^2.12.2", @@ -2517,9 +2517,9 @@ } }, "node_modules/@next/env": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.3.tgz", - "integrity": "sha512-OdiMrzCl2Xi0VTjiQQUK0Xh7bJHnOuET2s+3V+Y40WJBAXrJeGA3f+I8MZJ/YQ3mVGi5XGR1L66oFlgqXhQ4Vw==", + "version": "15.3.6", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.6.tgz", + "integrity": "sha512-/cK+QPcfRbDZxmI/uckT4lu9pHCfRIPBLqy88MhE+7Vg5hKrEYc333Ae76dn/cw2FBP2bR/GoK/4DU+U7by/Nw==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { @@ -2533,9 +2533,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.3.tgz", - "integrity": "sha512-WRJERLuH+O3oYB4yZNVahSVFmtxRNjNF1I1c34tYMoJb0Pve+7/RaLAJJizyYiFhjYNGHRAE1Ri2Fd23zgDqhg==", + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.5.tgz", + "integrity": "sha512-lM/8tilIsqBq+2nq9kbTW19vfwFve0NR7MxfkuSUbRSgXlMQoJYg+31+++XwKVSXk4uT23G2eF/7BRIKdn8t8w==", "cpu": [ "arm64" ], @@ -2549,9 +2549,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.3.tgz", - "integrity": "sha512-XHdzH/yBc55lu78k/XwtuFR/ZXUTcflpRXcsu0nKmF45U96jt1tsOZhVrn5YH+paw66zOANpOnFQ9i6/j+UYvw==", + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.5.tgz", + "integrity": "sha512-WhwegPQJ5IfoUNZUVsI9TRAlKpjGVK0tpJTL6KeiC4cux9774NYE9Wu/iCfIkL/5J8rPAkqZpG7n+EfiAfidXA==", "cpu": [ "x64" ], @@ -2565,9 +2565,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.3.tgz", - "integrity": "sha512-VZ3sYL2LXB8znNGcjhocikEkag/8xiLgnvQts41tq6i+wql63SMS1Q6N8RVXHw5pEUjiof+II3HkDd7GFcgkzw==", + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.5.tgz", + "integrity": "sha512-LVD6uMOZ7XePg3KWYdGuzuvVboxujGjbcuP2jsPAN3MnLdLoZUXKRc6ixxfs03RH7qBdEHCZjyLP/jBdCJVRJQ==", "cpu": [ "arm64" ], @@ -2581,9 +2581,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.3.tgz", - "integrity": "sha512-h6Y1fLU4RWAp1HPNJWDYBQ+e3G7sLckyBXhmH9ajn8l/RSMnhbuPBV/fXmy3muMcVwoJdHL+UtzRzs0nXOf9SA==", + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.5.tgz", + "integrity": "sha512-k8aVScYZ++BnS2P69ClK7v4nOu702jcF9AIHKu6llhHEtBSmM2zkPGl9yoqbSU/657IIIb0QHpdxEr0iW9z53A==", "cpu": [ "arm64" ], @@ -2597,9 +2597,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.3.tgz", - "integrity": "sha512-jJ8HRiF3N8Zw6hGlytCj5BiHyG/K+fnTKVDEKvUCyiQ/0r5tgwO7OgaRiOjjRoIx2vwLR+Rz8hQoPrnmFbJdfw==", + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.5.tgz", + "integrity": "sha512-2xYU0DI9DGN/bAHzVwADid22ba5d/xrbrQlr2U+/Q5WkFUzeL0TDR963BdrtLS/4bMmKZGptLeg6282H/S2i8A==", "cpu": [ "x64" ], @@ -2613,9 +2613,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.3.tgz", - "integrity": "sha512-HrUcTr4N+RgiiGn3jjeT6Oo208UT/7BuTr7K0mdKRBtTbT4v9zJqCDKO97DUqqoBK1qyzP1RwvrWTvU6EPh/Cw==", + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.5.tgz", + "integrity": "sha512-TRYIqAGf1KCbuAB0gjhdn5Ytd8fV+wJSM2Nh2is/xEqR8PZHxfQuaiNhoF50XfY90sNpaRMaGhF6E+qjV1b9Tg==", "cpu": [ "x64" ], @@ -2629,9 +2629,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.3.tgz", - "integrity": "sha512-SxorONgi6K7ZUysMtRF3mIeHC5aA3IQLmKFQzU0OuhuUYwpOBc1ypaLJLP5Bf3M9k53KUUUj4vTPwzGvl/NwlQ==", + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.5.tgz", + "integrity": "sha512-h04/7iMEUSMY6fDGCvdanKqlO1qYvzNxntZlCzfE8i5P0uqzVQWQquU1TIhlz0VqGQGXLrFDuTJVONpqGqjGKQ==", "cpu": [ "arm64" ], @@ -2645,9 +2645,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.3.tgz", - "integrity": "sha512-4QZG6F8enl9/S2+yIiOiju0iCTFd93d8VC1q9LZS4p/Xuk81W2QDjCFeoogmrWWkAD59z8ZxepBQap2dKS5ruw==", + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.5.tgz", + "integrity": "sha512-5fhH6fccXxnX2KhllnGhkYMndhOiLOLEiVGYjP2nizqeGWkN10sA9taATlXwake2E2XMvYZjjz0Uj7T0y+z1yw==", "cpu": [ "x64" ], @@ -7731,12 +7731,12 @@ "license": "MIT" }, "node_modules/next": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/next/-/next-15.3.3.tgz", - "integrity": "sha512-JqNj29hHNmCLtNvd090SyRbXJiivQ+58XjCcrC50Crb5g5u2zi7Y2YivbsEfzk6AtVI80akdOQbaMZwWB1Hthw==", + "version": "15.3.6", + "resolved": "https://registry.npmjs.org/next/-/next-15.3.6.tgz", + "integrity": "sha512-oI6D1zbbsh6JzzZFDCSHnnx6Qpvd1fSkVJu/5d8uluqnxzuoqtodVZjYvNovooznUq8udSAiKp7MbwlfZ8Gm6w==", "license": "MIT", "dependencies": { - "@next/env": "15.3.3", + "@next/env": "15.3.6", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", @@ -7751,14 +7751,14 @@ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.3.3", - "@next/swc-darwin-x64": "15.3.3", - "@next/swc-linux-arm64-gnu": "15.3.3", - "@next/swc-linux-arm64-musl": "15.3.3", - "@next/swc-linux-x64-gnu": "15.3.3", - "@next/swc-linux-x64-musl": "15.3.3", - "@next/swc-win32-arm64-msvc": "15.3.3", - "@next/swc-win32-x64-msvc": "15.3.3", + "@next/swc-darwin-arm64": "15.3.5", + "@next/swc-darwin-x64": "15.3.5", + "@next/swc-linux-arm64-gnu": "15.3.5", + "@next/swc-linux-arm64-musl": "15.3.5", + "@next/swc-linux-x64-gnu": "15.3.5", + "@next/swc-linux-x64-musl": "15.3.5", + "@next/swc-win32-arm64-msvc": "15.3.5", + "@next/swc-win32-x64-msvc": "15.3.5", "sharp": "^0.34.1" }, "peerDependencies": { diff --git a/package.json b/package.json index ea36306..82b4fbf 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "framer-motion": "^12.18.1", - "next": "15.3.3", + "next": "15.3.6", "react": "^19.0.0", "react-dom": "^19.0.0", "react-tsparticles": "^2.12.2", From 0545d67739a97b93f6adfd3e8f1086dd7f4be66c Mon Sep 17 00:00:00 2001 From: "vercel[bot]" <35613825+vercel[bot]@users.noreply.github.com> Date: Fri, 12 Dec 2025 12:38:37 -0300 Subject: [PATCH 5/9] Fix React Server Components CVE vulnerabilities (#10) > [!IMPORTANT] > This is an automatic PR generated by Vercel to help you patch known vulnerabilities related to CVE-2025-55182 (React2Shell), CVE-2025-55183, CVE-2025-55184, and CVE-2025-67779. We can't guarantee the PR is comprehensive, and it may contain mistakes. Not all projects are affected by all issues, but **patched versions are required to ensure full remediation**. Vercel has deployed WAF mitigations globally to help protect your application, but upgrading remains required for complete protection. This automated pull request updates your React, Next.js, and related Server Components packages to versions that fix **all currently known React Server Components vulnerabilities**, including the two newly discovered issues. See our [Security Bulletins](https://vercel.com/kb/bulletin/) for more information and reach out to security@vercel.com with any questions. Co-authored-by: Vercel --- package-lock.json | 16 ++++++++-------- package.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 73b6a3b..3c77e0c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.0", "dependencies": { "framer-motion": "^12.18.1", - "next": "15.3.6", + "next": "15.3.8", "react": "^19.0.0", "react-dom": "^19.0.0", "react-tsparticles": "^2.12.2", @@ -2517,9 +2517,9 @@ } }, "node_modules/@next/env": { - "version": "15.3.6", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.6.tgz", - "integrity": "sha512-/cK+QPcfRbDZxmI/uckT4lu9pHCfRIPBLqy88MhE+7Vg5hKrEYc333Ae76dn/cw2FBP2bR/GoK/4DU+U7by/Nw==", + "version": "15.3.8", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.8.tgz", + "integrity": "sha512-SAfHg0g91MQVMPioeFeDjE+8UPF3j3BvHjs8ZKJAUz1BG7eMPvfCKOAgNWJ6s1MLNeP6O2InKQRTNblxPWuq+Q==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { @@ -7731,12 +7731,12 @@ "license": "MIT" }, "node_modules/next": { - "version": "15.3.6", - "resolved": "https://registry.npmjs.org/next/-/next-15.3.6.tgz", - "integrity": "sha512-oI6D1zbbsh6JzzZFDCSHnnx6Qpvd1fSkVJu/5d8uluqnxzuoqtodVZjYvNovooznUq8udSAiKp7MbwlfZ8Gm6w==", + "version": "15.3.8", + "resolved": "https://registry.npmjs.org/next/-/next-15.3.8.tgz", + "integrity": "sha512-L+4c5Hlr84fuaNADZbB9+ceRX9/CzwxJ+obXIGHupboB/Q1OLbSUapFs4bO8hnS/E6zV/JDX7sG1QpKVR2bguA==", "license": "MIT", "dependencies": { - "@next/env": "15.3.6", + "@next/env": "15.3.8", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", diff --git a/package.json b/package.json index 82b4fbf..3bba85d 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "framer-motion": "^12.18.1", - "next": "15.3.6", + "next": "15.3.8", "react": "^19.0.0", "react-dom": "^19.0.0", "react-tsparticles": "^2.12.2", From b39dbe006ec187ce1eda28acd289f7a342b54754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Aereal=20Ae=C3=B3n?= <388605+mattaereal@users.noreply.github.com> Date: Wed, 18 Feb 2026 11:05:42 -0300 Subject: [PATCH 6/9] =?UTF-8?q?Updated=20and=20tested=20several=20fixes,?= =?UTF-8?q?=20improvements,=20new=20features=20and=20cate=E2=80=A6=20(#11)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …gories, including members, supporters. --- next.config.ts | 56 +- package-lock.json | 1598 +++++------------ package.json | 14 +- .../ethereum-foundation-official.svg | 19 + .../security-alliance-official.svg | 30 + public/assets/contact-section/wedf-logo.png | Bin 0 -> 29618 bytes src/app/components/Card.tsx | 103 +- src/app/components/MainContent.tsx | 61 +- src/app/components/MemberCard.tsx | 134 ++ src/app/components/MemberPreviewCard.tsx | 132 ++ src/app/components/Navbar.tsx | 518 ++++-- src/app/components/RadarChart.tsx | 136 ++ src/app/components/Scene.tsx | 42 +- src/app/components/SkillTree.tsx | 222 +++ .../components/SupportersCollaborators.tsx | 62 +- src/app/data/cardContent.ts | 8 +- src/app/data/membersConfig.ts | 623 +++++++ src/app/globals.css | 7 + src/app/initiatives/page.tsx | 37 +- src/app/layout.tsx | 12 +- src/app/members/page.tsx | 61 + 21 files changed, 2523 insertions(+), 1352 deletions(-) create mode 100644 public/assets/contact-section/ethereum-foundation-official.svg create mode 100644 public/assets/contact-section/security-alliance-official.svg create mode 100644 public/assets/contact-section/wedf-logo.png create mode 100644 src/app/components/MemberCard.tsx create mode 100644 src/app/components/MemberPreviewCard.tsx create mode 100644 src/app/components/RadarChart.tsx create mode 100644 src/app/components/SkillTree.tsx create mode 100644 src/app/data/membersConfig.ts create mode 100644 src/app/members/page.tsx diff --git a/next.config.ts b/next.config.ts index 18b2799..9cefb0b 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,15 +1,61 @@ import type { NextConfig } from "next"; +const securityHeaders = [ + { + key: "X-Frame-Options", + value: "DENY", + }, + { + key: "X-Content-Type-Options", + value: "nosniff", + }, + { + key: "Referrer-Policy", + value: "strict-origin-when-cross-origin", + }, + { + key: "Permissions-Policy", + value: "camera=(), microphone=(), geolocation=()", + }, + { + key: "Cross-Origin-Opener-Policy", + value: "same-origin", + }, + { + key: "Cross-Origin-Resource-Policy", + value: "same-site", + }, + { + key: "Strict-Transport-Security", + value: "max-age=63072000; includeSubDomains; preload", + }, +]; + const nextConfig: NextConfig = { - /* config options here */ + images: { + remotePatterns: [ + { + protocol: "https", + hostname: "github.com", + }, + { + protocol: "https", + hostname: "avatars.githubusercontent.com", + }, + ], + }, async headers() { return [ { - source: '/assets/:path*', + source: "/:path*", + headers: securityHeaders, + }, + { + source: "/assets/:path*", headers: [ { - key: 'Cache-Control', - value: 'public, max-age=31536000, immutable', + key: "Cache-Control", + value: "public, max-age=31536000, immutable", }, ], }, @@ -17,4 +63,4 @@ const nextConfig: NextConfig = { }, }; -export default nextConfig; \ No newline at end of file +export default nextConfig; diff --git a/package-lock.json b/package-lock.json index 3c77e0c..4e1dc5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,23 +8,23 @@ "name": "trg-page", "version": "0.1.0", "dependencies": { + "@tsparticles/engine": "^3.9.1", + "@tsparticles/react": "^3.0.0", "framer-motion": "^12.18.1", - "next": "15.3.8", + "next": "15.5.12", "react": "^19.0.0", "react-dom": "^19.0.0", - "react-tsparticles": "^2.12.2", - "stats.js": "^0.17.0", - "tsparticles": "^3.8.1" + "stats.js": "^0.17.0" }, "devDependencies": { - "@eslint/eslintrc": "^3", + "@eslint/eslintrc": "^3.3.3", "@svgr/webpack": "^8.1.0", "@tailwindcss/postcss": "^4", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", - "eslint": "^9", - "eslint-config-next": "15.3.3", + "eslint": "^9.39.2", + "eslint-config-next": "15.5.12", "tailwindcss": "^4", "typescript": "^5" } @@ -1814,9 +1814,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", - "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", "license": "MIT", "optional": true, "dependencies": { @@ -1835,9 +1835,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1867,9 +1867,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", "engines": { @@ -1877,13 +1877,13 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", - "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.6", + "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -1892,19 +1892,22 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz", - "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/core": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", - "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1915,9 +1918,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1927,7 +1930,7 @@ "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", + "js-yaml": "^4.1.1", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, @@ -1939,9 +1942,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.28.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.28.0.tgz", - "integrity": "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", "dev": true, "license": "MIT", "engines": { @@ -1952,9 +1955,9 @@ } }, "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1962,13 +1965,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", - "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.14.0", + "@eslint/core": "^0.17.0", "levn": "^0.4.1" }, "engines": { @@ -2041,10 +2044,20 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@img/colour": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.2.tgz", - "integrity": "sha512-OfXHZPppddivUJnqyKoi5YVeHRkkNE2zUFT2gbpKxp/JZCFYEYubnMg+gOp6lWfasPrTS+KPosKqdI+ELYVDtg==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", "cpu": [ "arm64" ], @@ -2060,13 +2073,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.1.0" + "@img/sharp-libvips-darwin-arm64": "1.2.4" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.2.tgz", - "integrity": "sha512-dYvWqmjU9VxqXmjEtjmvHnGqF8GrVjM2Epj9rJ6BUIXvk8slvNDJbhGFvIoXzkDhrJC2jUxNLz/GUjjvSzfw+g==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", "cpu": [ "x64" ], @@ -2082,13 +2095,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.1.0" + "@img/sharp-libvips-darwin-x64": "1.2.4" } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.1.0.tgz", - "integrity": "sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", "cpu": [ "arm64" ], @@ -2102,9 +2115,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.1.0.tgz", - "integrity": "sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", "cpu": [ "x64" ], @@ -2118,9 +2131,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.1.0.tgz", - "integrity": "sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", "cpu": [ "arm" ], @@ -2134,9 +2147,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.1.0.tgz", - "integrity": "sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", "cpu": [ "arm64" ], @@ -2150,9 +2163,9 @@ } }, "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.1.0.tgz", - "integrity": "sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", "cpu": [ "ppc64" ], @@ -2165,10 +2178,26 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.1.0.tgz", - "integrity": "sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", "cpu": [ "s390x" ], @@ -2182,9 +2211,9 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz", - "integrity": "sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", "cpu": [ "x64" ], @@ -2198,9 +2227,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.1.0.tgz", - "integrity": "sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", "cpu": [ "arm64" ], @@ -2214,9 +2243,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.1.0.tgz", - "integrity": "sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", "cpu": [ "x64" ], @@ -2230,9 +2259,9 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.2.tgz", - "integrity": "sha512-0DZzkvuEOqQUP9mo2kjjKNok5AmnOr1jB2XYjkaoNRwpAYMDzRmAqUIa1nRi58S2WswqSfPOWLNOr0FDT3H5RQ==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", "cpu": [ "arm" ], @@ -2248,13 +2277,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.1.0" + "@img/sharp-libvips-linux-arm": "1.2.4" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.2.tgz", - "integrity": "sha512-D8n8wgWmPDakc83LORcfJepdOSN6MvWNzzz2ux0MnIbOqdieRZwVYY32zxVx+IFUT8er5KPcyU3XXsn+GzG/0Q==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", "cpu": [ "arm64" ], @@ -2270,13 +2299,57 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.1.0" + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.2.tgz", - "integrity": "sha512-EGZ1xwhBI7dNISwxjChqBGELCWMGDvmxZXKjQRuqMrakhO8QoMgqCrdjnAqJq/CScxfRn+Bb7suXBElKQpPDiw==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", "cpu": [ "s390x" ], @@ -2292,13 +2365,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.1.0" + "@img/sharp-libvips-linux-s390x": "1.2.4" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.2.tgz", - "integrity": "sha512-sD7J+h5nFLMMmOXYH4DD9UtSNBD05tWSSdWAcEyzqW8Cn5UxXvsHAxmxSesYUsTOBmUnjtxghKDl15EvfqLFbQ==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", "cpu": [ "x64" ], @@ -2314,13 +2387,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.1.0" + "@img/sharp-libvips-linux-x64": "1.2.4" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.2.tgz", - "integrity": "sha512-NEE2vQ6wcxYav1/A22OOxoSOGiKnNmDzCYFOZ949xFmrWZOVII1Bp3NqVVpvj+3UeHMFyN5eP/V5hzViQ5CZNA==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", "cpu": [ "arm64" ], @@ -2336,13 +2409,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.1.0" + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.2.tgz", - "integrity": "sha512-DOYMrDm5E6/8bm/yQLCWyuDJwUnlevR8xtF8bs+gjZ7cyUNYXiSf/E8Kp0Ss5xasIaXSHzb888V1BE4i1hFhAA==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", "cpu": [ "x64" ], @@ -2358,20 +2431,20 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.1.0" + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.2.tgz", - "integrity": "sha512-/VI4mdlJ9zkaq53MbIG6rZY+QRN3MLbR6usYlgITEzi4Rpx5S6LFKsycOQjkOGmqTNmkIdLjEvooFKwww6OpdQ==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", "cpu": [ "wasm32" ], "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.4.3" + "@emnapi/runtime": "^1.7.0" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -2381,9 +2454,9 @@ } }, "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.2.tgz", - "integrity": "sha512-cfP/r9FdS63VA5k0xiqaNaEoGxBg9k7uE+RQGzuK9fHt7jib4zAVVseR9LsE4gJcNWgT6APKMNnCcnyOtmSEUQ==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", "cpu": [ "arm64" ], @@ -2400,9 +2473,9 @@ } }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.2.tgz", - "integrity": "sha512-QLjGGvAbj0X/FXl8n1WbtQ6iVBpWU7JO94u/P2M4a8CFYsvQi4GW2mRy/JqkRx0qpBzaOdKJKw8uc930EX2AHw==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", "cpu": [ "ia32" ], @@ -2419,9 +2492,9 @@ } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.2.tgz", - "integrity": "sha512-aUdT6zEYtDKCaxkofmmJDJYGCf0+pJg3eU9/oBuqvEeoB9dKI6ZLc/1iLJCTuJQDO4ptntAlkUmHgGjyuobZbw==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", "cpu": [ "x64" ], @@ -2517,15 +2590,15 @@ } }, "node_modules/@next/env": { - "version": "15.3.8", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.8.tgz", - "integrity": "sha512-SAfHg0g91MQVMPioeFeDjE+8UPF3j3BvHjs8ZKJAUz1BG7eMPvfCKOAgNWJ6s1MLNeP6O2InKQRTNblxPWuq+Q==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.12.tgz", + "integrity": "sha512-pUvdJN1on574wQHjaBfNGDt9Mz5utDSZFsIIQkMzPgNS8ZvT4H2mwOrOIClwsQOb6EGx5M76/CZr6G8i6pSpLg==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.3.3.tgz", - "integrity": "sha512-VKZJEiEdpKkfBmcokGjHu0vGDG+8CehGs90tBEy/IDoDDKGngeyIStt2MmE5FYNyU9BhgR7tybNWTAJY/30u+Q==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.12.tgz", + "integrity": "sha512-+ZRSDFTv4aC96aMb5E41rMjysx8ApkryevnvEYZvPZO52KvkqP5rNExLUXJFr9P4s0f3oqNQR6vopCZsPWKDcQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2533,9 +2606,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.3.5", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.5.tgz", - "integrity": "sha512-lM/8tilIsqBq+2nq9kbTW19vfwFve0NR7MxfkuSUbRSgXlMQoJYg+31+++XwKVSXk4uT23G2eF/7BRIKdn8t8w==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.12.tgz", + "integrity": "sha512-RnRjBtH8S8eXCpUNkQ+543DUc7ys8y15VxmFU9HRqlo9BG3CcBUiwNtF8SNoi2xvGCVJq1vl2yYq+3oISBS0Zg==", "cpu": [ "arm64" ], @@ -2549,9 +2622,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.3.5", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.5.tgz", - "integrity": "sha512-WhwegPQJ5IfoUNZUVsI9TRAlKpjGVK0tpJTL6KeiC4cux9774NYE9Wu/iCfIkL/5J8rPAkqZpG7n+EfiAfidXA==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.12.tgz", + "integrity": "sha512-nqa9/7iQlboF1EFtNhWxQA0rQstmYRSBGxSM6g3GxvxHxcoeqVXfGNr9stJOme674m2V7r4E3+jEhhGvSQhJRA==", "cpu": [ "x64" ], @@ -2565,9 +2638,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.3.5", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.5.tgz", - "integrity": "sha512-LVD6uMOZ7XePg3KWYdGuzuvVboxujGjbcuP2jsPAN3MnLdLoZUXKRc6ixxfs03RH7qBdEHCZjyLP/jBdCJVRJQ==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.12.tgz", + "integrity": "sha512-dCzAjqhDHwmoB2M4eYfVKqXs99QdQxNQVpftvP1eGVppamXh/OkDAwV737Zr0KPXEqRUMN4uCjh6mjO+XtF3Mw==", "cpu": [ "arm64" ], @@ -2581,9 +2654,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.3.5", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.5.tgz", - "integrity": "sha512-k8aVScYZ++BnS2P69ClK7v4nOu702jcF9AIHKu6llhHEtBSmM2zkPGl9yoqbSU/657IIIb0QHpdxEr0iW9z53A==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.12.tgz", + "integrity": "sha512-+fpGWvQiITgf7PUtbWY1H7qUSnBZsPPLyyq03QuAKpVoTy/QUx1JptEDTQMVvQhvizCEuNLEeghrQUyXQOekuw==", "cpu": [ "arm64" ], @@ -2597,9 +2670,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.3.5", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.5.tgz", - "integrity": "sha512-2xYU0DI9DGN/bAHzVwADid22ba5d/xrbrQlr2U+/Q5WkFUzeL0TDR963BdrtLS/4bMmKZGptLeg6282H/S2i8A==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.12.tgz", + "integrity": "sha512-jSLvgdRRL/hrFAPqEjJf1fFguC719kmcptjNVDJl26BnJIpjL3KH5h6mzR4mAweociLQaqvt4UyzfbFjgAdDcw==", "cpu": [ "x64" ], @@ -2613,9 +2686,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.3.5", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.5.tgz", - "integrity": "sha512-TRYIqAGf1KCbuAB0gjhdn5Ytd8fV+wJSM2Nh2is/xEqR8PZHxfQuaiNhoF50XfY90sNpaRMaGhF6E+qjV1b9Tg==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.12.tgz", + "integrity": "sha512-/uaF0WfmYqQgLfPmN6BvULwxY0dufI2mlN2JbOKqqceZh1G4hjREyi7pg03zjfyS6eqNemHAZPSoP84x17vo6w==", "cpu": [ "x64" ], @@ -2629,9 +2702,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.3.5", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.5.tgz", - "integrity": "sha512-h04/7iMEUSMY6fDGCvdanKqlO1qYvzNxntZlCzfE8i5P0uqzVQWQquU1TIhlz0VqGQGXLrFDuTJVONpqGqjGKQ==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.12.tgz", + "integrity": "sha512-xhsL1OvQSfGmlL5RbOmU+FV120urrgFpYLq+6U8C6KIym32gZT6XF/SDE92jKzzlPWskkbjOKCpqk5m4i8PEfg==", "cpu": [ "arm64" ], @@ -2645,9 +2718,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.3.5", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.5.tgz", - "integrity": "sha512-5fhH6fccXxnX2KhllnGhkYMndhOiLOLEiVGYjP2nizqeGWkN10sA9taATlXwake2E2XMvYZjjz0Uj7T0y+z1yw==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.12.tgz", + "integrity": "sha512-Z1Dh6lhFkxvBDH1FoW6OU/L6prYwPSlwjLiZkExIAh8fbP6iI/M7iGTQAJPYJ9YFlWobCZ1PHbchFhFYb2ADkw==", "cpu": [ "x64" ], @@ -2993,12 +3066,6 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "license": "Apache-2.0" - }, "node_modules/@swc/helpers": { "version": "0.5.15", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", @@ -3241,490 +3308,63 @@ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.8.tgz", "integrity": "sha512-7GmYk1n28teDHUjPlIx4Z6Z4hHEgvP5ZW2QS9ygnDAdI/myh3HTHjDqtSqgu1BpRoI4OiLx+fThAyA1JePoENA==", "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.8.tgz", - "integrity": "sha512-fou+U20j+Jl0EHwK92spoWISON2OBnCazIc038Xj2TdweYV33ZRkS9nwqiUi2d/Wba5xg5UoHfvynnb/UB49cQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/postcss": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.8.tgz", - "integrity": "sha512-vB/vlf7rIky+w94aWMw34bWW1ka6g6C3xIOdICKX2GC0VcLtL6fhlLiafF0DVIwa9V6EHz8kbWMkS2s2QvvNlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "@tailwindcss/node": "4.1.8", - "@tailwindcss/oxide": "4.1.8", - "postcss": "^8.4.41", - "tailwindcss": "4.1.8" - } - }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@tsparticles/basic": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/basic/-/basic-3.8.1.tgz", - "integrity": "sha512-my114zRmekT/+I2cGuEnHxlX5G/jO0iVtNnsxxlsgspXUTSY+fDixmrNF4UgFkuaIwd9Bv/yH+7S/4HE4qte7A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/matteobruni" - }, - { - "type": "github", - "url": "https://github.com/sponsors/tsparticles" - }, - { - "type": "buymeacoffee", - "url": "https://www.buymeacoffee.com/matteobruni" - } - ], - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1", - "@tsparticles/move-base": "3.8.1", - "@tsparticles/plugin-hex-color": "3.8.1", - "@tsparticles/plugin-hsl-color": "3.8.1", - "@tsparticles/plugin-rgb-color": "3.8.1", - "@tsparticles/shape-circle": "3.8.1", - "@tsparticles/updater-color": "3.8.1", - "@tsparticles/updater-opacity": "3.8.1", - "@tsparticles/updater-out-modes": "3.8.1", - "@tsparticles/updater-size": "3.8.1" - } - }, - "node_modules/@tsparticles/engine": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/engine/-/engine-3.8.1.tgz", - "integrity": "sha512-S8h10nuZfElY7oih//NUHnT5qf4v3/dnsU8CMs7dz5lBEGr3amrYrXk0V+YKPTIQwfdmJHUaSBoAqFiv4aEGIA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/matteobruni" - }, - { - "type": "github", - "url": "https://github.com/sponsors/tsparticles" - }, - { - "type": "buymeacoffee", - "url": "https://www.buymeacoffee.com/matteobruni" - } - ], - "hasInstallScript": true, - "license": "MIT" - }, - "node_modules/@tsparticles/interaction-external-attract": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-attract/-/interaction-external-attract-3.8.1.tgz", - "integrity": "sha512-GWzyj5MOzjb5pNWuqAueNZS2ilPcZ0isiqwcb0BjjpwfiGfL72UyIbNUDMLncsW+4jcwB4WyMsv/qOGDmAwVfQ==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/interaction-external-bounce": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-bounce/-/interaction-external-bounce-3.8.1.tgz", - "integrity": "sha512-tgVzsE3orneSeSUc1XhRD6Iqs8Rkm11iRdkncKSpNx4SI2eJWFPhwit2wIiHQ+IuvgCmM2DXRtLgEVeaux71zg==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/interaction-external-bubble": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-bubble/-/interaction-external-bubble-3.8.1.tgz", - "integrity": "sha512-edRVFybiVFd5vEjfEkHgrBTXfPTKc05EqCmRuOEd5gOll1ui0nPtknzj9JiLrPacQAJ7OgZKlHWYQb1u5Yy5Tw==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/interaction-external-connect": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-connect/-/interaction-external-connect-3.8.1.tgz", - "integrity": "sha512-DQ0nNB0VDSxFxeaJQvm91NDUU/UPoiHE+uUzyw5qSoWJEGTUOj/QkW0GuBinCo99i8MH/wLDqMS9nb+7ZejpUw==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/interaction-external-grab": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-grab/-/interaction-external-grab-3.8.1.tgz", - "integrity": "sha512-nPaHrazEr14CGokGGkFHYXZJTN3Inshe04uQNj+Rj4Lz9dAIqq8EFuSejp0g9lk2cTHWfVf4SK4r8+aJz9Ow4Q==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/interaction-external-pause": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-pause/-/interaction-external-pause-3.8.1.tgz", - "integrity": "sha512-W+6bjNDddtzlikwnfmk2G/GJsz4ZnoqvK0c63earvnPNUAJmkzrvmLS52JoaIOSyclOIeD4LmubT6IsQDv5ohA==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/interaction-external-push": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-push/-/interaction-external-push-3.8.1.tgz", - "integrity": "sha512-LgaXaBM5QXRCeYt3DzphEhE/OirEGnV4iJrXKGJ/FrYMH7kOao85rPmCtYQNYzIy6K0XstmATmTvFRziZ/M4VQ==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/interaction-external-remove": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-remove/-/interaction-external-remove-3.8.1.tgz", - "integrity": "sha512-mwo1DRJPIqzrWfs2G+kfQ5/HyM5j/soIj11zur3BkIlm9vdYIxUpA+hvO734oekSjJxY7YFmYUaqc4vC5TFE5w==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/interaction-external-repulse": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-repulse/-/interaction-external-repulse-3.8.1.tgz", - "integrity": "sha512-r0E828zrKIRHA27daItHtI9QEp1tO8d8dmF8Ld8+orn7q0+BKG+uGvNTYJFZ+hqR+lp5AkLOiThf7L2wLS9M1A==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/interaction-external-slow": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-slow/-/interaction-external-slow-3.8.1.tgz", - "integrity": "sha512-U4P6c9V6/fSDsWchD4oAYAIPHA/203LzQ7+792cMxa7YThza0VS7YyJUQ1PACjGMmfeKbE34/eoGPqESKakeLw==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/interaction-external-trail": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/interaction-external-trail/-/interaction-external-trail-3.8.1.tgz", - "integrity": "sha512-CUiTxCtTASYdqi55KpJ98IRnuLS+G66v+s1/dZeAE7F7wzL7tkcUBQ3hP1yzBpFmKsoYHJfz9nAfocAkgRb6hg==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/interaction-particles-attract": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/interaction-particles-attract/-/interaction-particles-attract-3.8.1.tgz", - "integrity": "sha512-lo5JAVdeh1tQq/7SDsIllNdyIJgF3hSquWLARUIwGolezD91bEmHp/rlhTscX5NrqiM3y7z3inJPhR0nP5kGeg==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/interaction-particles-collisions": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/interaction-particles-collisions/-/interaction-particles-collisions-3.8.1.tgz", - "integrity": "sha512-teqn1CZVoJkT/ubhkb4R/H1rnx7DoIeerHXS5uME+vrLIqzkn8QlWdEdTJ7PhdB+Ct2iYAeXCrJWwIqnKaAL3w==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/interaction-particles-links": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/interaction-particles-links/-/interaction-particles-links-3.8.1.tgz", - "integrity": "sha512-D+X7wEWyhfV7J0uDWf5vWDhxjfaNovNZW0BWscR9qSy8pl3hjRpv0sJ/QaQFscmK5SzVz28tUFDRLbH1aV5v/Q==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/move-base": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/move-base/-/move-base-3.8.1.tgz", - "integrity": "sha512-DNFRL1QT8ZQYLg3fIk74EbHJq5HGOq9CM2bCci9dDcdymvN4L7aWVFQavRiWDbi3y1EUW3+jeHSMbD3qHAfOeA==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/move-parallax": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/move-parallax/-/move-parallax-3.8.1.tgz", - "integrity": "sha512-umrIttaJGUgfxpnolbMU2BekoN4gw0RgcfVsWR7jzHErA7eTzdJ2mikbQFD+3/1DfTDgJOjWx+dy8a3G/bSsZg==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/plugin-absorbers": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/plugin-absorbers/-/plugin-absorbers-3.8.1.tgz", - "integrity": "sha512-Di2Gncl3tCOCkLr2xZH8qCTVop3ES1r4lnLGDfmWPwUoSwSAUDE1epXKuf/9aLgdCMe7B4v/BGIr3YKUtTO3ww==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/plugin-easing-quad": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/plugin-easing-quad/-/plugin-easing-quad-3.8.1.tgz", - "integrity": "sha512-+BiPNHgsNbbh0AhWKjrmJaAu5c37naqjbME8ZYl0BClI0AC5AzBUaezYRxECaLrdtHJvKrZXFMr6Q0sxjDc6QQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/matteobruni" - }, - { - "type": "github", - "url": "https://github.com/sponsors/tsparticles" - }, - { - "type": "buymeacoffee", - "url": "https://www.buymeacoffee.com/matteobruni" - } - ], - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/plugin-emitters": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/plugin-emitters/-/plugin-emitters-3.8.1.tgz", - "integrity": "sha512-PGldE3OHs1hsZM6a8qHpXvKIMhaWAqZNwq8v7FwgJGxikXVvYtkKSaWslTpID3hYvtB6+whKig2uWURmq2TUsg==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/plugin-emitters-shape-circle": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/plugin-emitters-shape-circle/-/plugin-emitters-shape-circle-3.8.1.tgz", - "integrity": "sha512-YmUzR5I0Yotadsz/UstDzhRAxEKkJBZ3SSF3y0TcP4t7CDyv5moMzi0W1bW/MeT7rt8d8RLYsS9qyOX/5a5DDw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/matteobruni" - }, - { - "type": "github", - "url": "https://github.com/sponsors/tsparticles" - }, - { - "type": "buymeacoffee", - "url": "https://www.buymeacoffee.com/matteobruni" - } - ], - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1", - "@tsparticles/plugin-emitters": "3.8.1" - } - }, - "node_modules/@tsparticles/plugin-emitters-shape-square": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/plugin-emitters-shape-square/-/plugin-emitters-shape-square-3.8.1.tgz", - "integrity": "sha512-hg8a9ZD3PPRuNW8y/jqrRS2J153DkVvAfSdsO+l2PASG8vYVaxzUD1kqAUknUhNZmhg3BvtwQp+ojCNaat5/Lg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/matteobruni" - }, - { - "type": "github", - "url": "https://github.com/sponsors/tsparticles" - }, - { - "type": "buymeacoffee", - "url": "https://www.buymeacoffee.com/matteobruni" - } - ], - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1", - "@tsparticles/plugin-emitters": "3.8.1" - } - }, - "node_modules/@tsparticles/plugin-hex-color": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/plugin-hex-color/-/plugin-hex-color-3.8.1.tgz", - "integrity": "sha512-AmgB7XIYBCvg5HcqYb19YpcjEx2k4DpU2e24n0rradDDeqKKcz7EWI/08FlAnDb5HUs1em63vaAanl1vdm3+OA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/matteobruni" - }, - { - "type": "github", - "url": "https://github.com/sponsors/tsparticles" - }, - { - "type": "buymeacoffee", - "url": "https://www.buymeacoffee.com/matteobruni" - } - ], - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/plugin-hsl-color": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/plugin-hsl-color/-/plugin-hsl-color-3.8.1.tgz", - "integrity": "sha512-Ja6oEX6yu0064e4a+Fv1TBJiG5y0hqWwoOKSqf/Ra/zo01ageOEvDVX70FOVSrP+iEPGPznKVNcZs1tEOOvO0g==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/matteobruni" - }, - { - "type": "github", - "url": "https://github.com/sponsors/tsparticles" - }, - { - "type": "buymeacoffee", - "url": "https://www.buymeacoffee.com/matteobruni" - } - ], - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/plugin-rgb-color": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/plugin-rgb-color/-/plugin-rgb-color-3.8.1.tgz", - "integrity": "sha512-xNLqnaFUYjU+7dCHQXjZdM4UojUAVorPVmXlYmkh1xmujLljEaFTwCg1UJVlNq+fXENIFkeaf3/XT0U/q0ZBTA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/matteobruni" - }, - { - "type": "github", - "url": "https://github.com/sponsors/tsparticles" - }, - { - "type": "buymeacoffee", - "url": "https://www.buymeacoffee.com/matteobruni" - } - ], - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/shape-circle": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/shape-circle/-/shape-circle-3.8.1.tgz", - "integrity": "sha512-dM/f+qcpd8/KfviuVuKiTS8KLDE/T7xxHK7EI2S49yPW6yrJJBXdL7T4N9/n/6PF+Wslcl+kf/eTDjEAI3WjNQ==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/shape-emoji": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/shape-emoji/-/shape-emoji-3.8.1.tgz", - "integrity": "sha512-xiXNZ/afdecengUXhOqgUwR+vysgaseVpzEjoGoliOMWq4WHWv+S6ujNfes2oz3x736mTlvKdXcEWRncSXaKWw==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/shape-image": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/shape-image/-/shape-image-3.8.1.tgz", - "integrity": "sha512-7Yi25uLXvcY5A6TzyVBjYPsTmeTrE+0a2YO8kdp3O7V9NRGCSfXKnPRFp+lNOTiQRRvOG+SSzx2G18dfc/jwQg==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/shape-line": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/shape-line/-/shape-line-3.8.1.tgz", - "integrity": "sha512-aXVKkpGLgi1hbU/JO+opzy3OTt6PfxWrhGZyI0ms3vdcRX9uYlq4GoNUoKPVfntjWzhecF+FNNZ9gqUG/+WZLQ==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/shape-polygon": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/shape-polygon/-/shape-polygon-3.8.1.tgz", - "integrity": "sha512-1pAx85NJbgmsOngl+ZAYH8vxwPJmoddjWCbWTD0wlp/x+2NRjn1iaGBKObPKLgwVzsAXb9qNHMsUX/x0C54svw==", + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@tsparticles/shape-square": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/shape-square/-/shape-square-3.8.1.tgz", - "integrity": "sha512-4cjDt6542dkc15zxG1VYT7ScgPXM3+5VGtwMfh5CYNBx+GZZ3R+XUo1Q66JadcqKcNdHXfMWbXCMxs0GaiTtSw==", + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.8.tgz", + "integrity": "sha512-fou+U20j+Jl0EHwK92spoWISON2OBnCazIc038Xj2TdweYV33ZRkS9nwqiUi2d/Wba5xg5UoHfvynnb/UB49cQ==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@tsparticles/shape-star": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/shape-star/-/shape-star-3.8.1.tgz", - "integrity": "sha512-wBxnawqan/ocguNxY6cOEXF+YVnLIUmGBlnVGYx/7U9E2UHuHEKkoumob4fUflKISjvj5eQLpm/E1eUfYMd6RA==", + "node_modules/@tailwindcss/postcss": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.8.tgz", + "integrity": "sha512-vB/vlf7rIky+w94aWMw34bWW1ka6g6C3xIOdICKX2GC0VcLtL6fhlLiafF0DVIwa9V6EHz8kbWMkS2s2QvvNlw==", + "dev": true, "license": "MIT", "dependencies": { - "@tsparticles/engine": "3.8.1" + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.1.8", + "@tailwindcss/oxide": "4.1.8", + "postcss": "^8.4.41", + "tailwindcss": "4.1.8" } }, - "node_modules/@tsparticles/shape-text": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/shape-text/-/shape-text-3.8.1.tgz", - "integrity": "sha512-PuEQobjHE5F/G2anv87b4K+wrBBuqE6H08Pm7BAb+qDl/LDmVZrrYrm4xl1DP07M/fhBJZpaBSgQ/m/5synSHw==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10.13.0" } }, - "node_modules/@tsparticles/slim": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/slim/-/slim-3.8.1.tgz", - "integrity": "sha512-b6JV8MrxMz0XYn0eBCI/Mq8VCRyeaWfUyQaQyxLiRd96xpBXCeULooJF+Eaz9it1sUI898a5QfvY8djNXs4OJw==", + "node_modules/@tsparticles/engine": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@tsparticles/engine/-/engine-3.9.1.tgz", + "integrity": "sha512-DpdgAhWMZ3Eh2gyxik8FXS6BKZ8vyea+Eu5BC4epsahqTGY9V3JGGJcXC6lRJx6cPMAx1A0FaQAojPF3v6rkmQ==", "funding": [ { "type": "github", @@ -3739,142 +3379,17 @@ "url": "https://www.buymeacoffee.com/matteobruni" } ], - "license": "MIT", - "dependencies": { - "@tsparticles/basic": "3.8.1", - "@tsparticles/engine": "3.8.1", - "@tsparticles/interaction-external-attract": "3.8.1", - "@tsparticles/interaction-external-bounce": "3.8.1", - "@tsparticles/interaction-external-bubble": "3.8.1", - "@tsparticles/interaction-external-connect": "3.8.1", - "@tsparticles/interaction-external-grab": "3.8.1", - "@tsparticles/interaction-external-pause": "3.8.1", - "@tsparticles/interaction-external-push": "3.8.1", - "@tsparticles/interaction-external-remove": "3.8.1", - "@tsparticles/interaction-external-repulse": "3.8.1", - "@tsparticles/interaction-external-slow": "3.8.1", - "@tsparticles/interaction-particles-attract": "3.8.1", - "@tsparticles/interaction-particles-collisions": "3.8.1", - "@tsparticles/interaction-particles-links": "3.8.1", - "@tsparticles/move-parallax": "3.8.1", - "@tsparticles/plugin-easing-quad": "3.8.1", - "@tsparticles/shape-emoji": "3.8.1", - "@tsparticles/shape-image": "3.8.1", - "@tsparticles/shape-line": "3.8.1", - "@tsparticles/shape-polygon": "3.8.1", - "@tsparticles/shape-square": "3.8.1", - "@tsparticles/shape-star": "3.8.1", - "@tsparticles/updater-life": "3.8.1", - "@tsparticles/updater-rotate": "3.8.1", - "@tsparticles/updater-stroke-color": "3.8.1" - } - }, - "node_modules/@tsparticles/updater-color": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/updater-color/-/updater-color-3.8.1.tgz", - "integrity": "sha512-HKrZzrF8YJ+TD+FdIwaWOPV565bkBhe+Ewj7CwKblG7H/SG+C6n1xIYobXkGP5pYkkQ+Cm1UV/Aq0Ih7sa+rJg==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/updater-destroy": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/updater-destroy/-/updater-destroy-3.8.1.tgz", - "integrity": "sha512-OMy8zZv3ujiaLw1i2BNWOhDgBPNnDiKlTwIP1mK0N9cYOplJkgaxmHOc7NhCndnLvZaYHqfN2bujLK2iBgNdbw==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/updater-life": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/updater-life/-/updater-life-3.8.1.tgz", - "integrity": "sha512-5rCFFKD7js1lKgTpKOLo2OfmisWp4qqMVUVR4bNPeR0Ne/dcwDbKDzWyYS2AMsvWv/gcTTtWiarRfAiVQ5HtNg==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/updater-opacity": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/updater-opacity/-/updater-opacity-3.8.1.tgz", - "integrity": "sha512-41dJ0T7df7AUFFkV9yU0buUfUwh+hLYcViXxkDy+6CJiiNCNZ4H404w1DTpBQLL4fbxUcDk9BXZLV7gkE2OfAw==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/updater-out-modes": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/updater-out-modes/-/updater-out-modes-3.8.1.tgz", - "integrity": "sha512-BY8WqQwoDFpgPybwTzBU2GnxtRkjWnGStqBnR53x5+f1j7geTSY6WjcOvl1W+IkjtwtjiifriwBl41EbqMrjdQ==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/updater-roll": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/updater-roll/-/updater-roll-3.8.1.tgz", - "integrity": "sha512-KYFTfMr8/M5pYBJFUFVrkogJURtKO5ogNSocOCf0v2QLMsbT5+OKNO7CLtxPZD98vTGRD3CHlt53/PF0tSesDA==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/updater-rotate": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/updater-rotate/-/updater-rotate-3.8.1.tgz", - "integrity": "sha512-gpI07H1+diuuUdhJsQ1RlfHSD3fzBJrjyuwGuoXgHmvKzak6EWKpYfUMOraH4Dm41m/4kJZelle4nST+NpIuoA==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/updater-size": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/updater-size/-/updater-size-3.8.1.tgz", - "integrity": "sha512-SC2ZxewtpwKadCalotK6x2YanxRO3hTMW1Rxzx9V2rcjAIgh/Nw49Vuithy2TDq8RtTc9rHDAPic2vMQ/lYQwA==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/updater-stroke-color": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/updater-stroke-color/-/updater-stroke-color-3.8.1.tgz", - "integrity": "sha512-rofHCf5oRHP2H+BTJ4D3r4mTqZtre3c8bsdJHATle26+gLpzbt6I1a83wAY8xnsQa1BNnRAfEsnb7GpdZ1vYaw==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/updater-tilt": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/updater-tilt/-/updater-tilt-3.8.1.tgz", - "integrity": "sha512-qMVd/sjrAds8m6vXFH5YKN8zrQR9SLdn5N5EvHx/JuKpOut4NhG85u8AEJL6ct1g7hY8Zj9kfi/dDSSovkaHhw==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } - }, - "node_modules/@tsparticles/updater-twinkle": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/updater-twinkle/-/updater-twinkle-3.8.1.tgz", - "integrity": "sha512-ETJ1zLYp4vjSjmXDiXXr0yW4Vw8sL6XixM0NPU3yx/dKCVi9SGVMlRymfkxJV+9jMuU/pUCCmRnIdDS7YrDGmw==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" - } + "hasInstallScript": true, + "license": "MIT" }, - "node_modules/@tsparticles/updater-wobble": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@tsparticles/updater-wobble/-/updater-wobble-3.8.1.tgz", - "integrity": "sha512-PkjVgeSkW0EebJQ9PdpwSMWU2fAvKsVSuH4KGmodYlgGkH0/zvKjMOPMEI6YRAor1/vF1soFyLYp9Vax7Ae13g==", - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1" + "node_modules/@tsparticles/react": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@tsparticles/react/-/react-3.0.0.tgz", + "integrity": "sha512-hjGEtTT1cwv6BcjL+GcVgH++KYs52bIuQGW3PWv7z3tMa8g0bd6RI/vWSLj7p//NZ3uTjEIeilYIUPBh7Jfq/Q==", + "peerDependencies": { + "@tsparticles/engine": "^3.0.2", + "react": ">=16.8.0", + "react-dom": ">=16.8.0" } }, "node_modules/@tybys/wasm-util": { @@ -3940,21 +3455,20 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.34.0.tgz", - "integrity": "sha512-QXwAlHlbcAwNlEEMKQS2RCgJsgXrTJdjXT08xEgbPFa2yYQgVjBymxP5DrfrE7X7iodSzd9qBUHUycdyVJTW1w==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.0.tgz", + "integrity": "sha512-lRyPDLzNCuae71A3t9NEINBiTn7swyOhvUj3MyUOxb8x6g6vPEFoOU+ZRmGMusNC3X3YMhqMIX7i8ShqhT74Pw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.34.0", - "@typescript-eslint/type-utils": "8.34.0", - "@typescript-eslint/utils": "8.34.0", - "@typescript-eslint/visitor-keys": "8.34.0", - "graphemer": "^1.4.0", - "ignore": "^7.0.0", + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.56.0", + "@typescript-eslint/type-utils": "8.56.0", + "@typescript-eslint/utils": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0", + "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3964,9 +3478,9 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.34.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "@typescript-eslint/parser": "^8.56.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { @@ -3980,17 +3494,17 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.34.0.tgz", - "integrity": "sha512-vxXJV1hVFx3IXz/oy2sICsJukaBrtDEQSBiV48/YIV5KWjX1dO+bcIr/kCPrW6weKXvsaGKFNlwH0v2eYdRRbA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.0.tgz", + "integrity": "sha512-IgSWvLobTDOjnaxAfDTIHaECbkNlAlKv2j5SjpB2v7QHKv1FIfjwMy8FsDbVfDX/KjmCmYICcw7uGaXLhtsLNg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.34.0", - "@typescript-eslint/types": "8.34.0", - "@typescript-eslint/typescript-estree": "8.34.0", - "@typescript-eslint/visitor-keys": "8.34.0", - "debug": "^4.3.4" + "@typescript-eslint/scope-manager": "8.56.0", + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4000,20 +3514,20 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.34.0.tgz", - "integrity": "sha512-iEgDALRf970/B2YExmtPMPF54NenZUf4xpL3wsCRx/lgjz6ul/l13R81ozP/ZNuXfnLCS+oPmG7JIxfdNYKELw==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.0.tgz", + "integrity": "sha512-M3rnyL1vIQOMeWxTWIW096/TtVP+8W3p/XnaFflhmcFp+U4zlxUxWj4XwNs6HbDeTtN4yun0GNTTDBw/SvufKg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.34.0", - "@typescript-eslint/types": "^8.34.0", - "debug": "^4.3.4" + "@typescript-eslint/tsconfig-utils": "^8.56.0", + "@typescript-eslint/types": "^8.56.0", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4023,18 +3537,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.34.0.tgz", - "integrity": "sha512-9Ac0X8WiLykl0aj1oYQNcLZjHgBojT6cW68yAgZ19letYu+Hxd0rE0veI1XznSSst1X5lwnxhPbVdwjDRIomRw==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.0.tgz", + "integrity": "sha512-7UiO/XwMHquH+ZzfVCfUNkIXlp/yQjjnlYUyYz7pfvlK3/EyyN6BK+emDmGNyQLBtLGaYrTAI6KOw8tFucWL2w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.34.0", - "@typescript-eslint/visitor-keys": "8.34.0" + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4045,9 +3559,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.34.0.tgz", - "integrity": "sha512-+W9VYHKFIzA5cBeooqQxqNriAP0QeQ7xTiDuIOr71hzgffm3EL2hxwWBIIj4GuofIbKxGNarpKqIq6Q6YrShOA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.0.tgz", + "integrity": "sha512-bSJoIIt4o3lKXD3xmDh9chZcjCz5Lk8xS7Rxn+6l5/pKrDpkCwtQNQQwZ2qRPk7TkUYhrq3WPIHXOXlbXP0itg==", "dev": true, "license": "MIT", "engines": { @@ -4058,20 +3572,21 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.34.0.tgz", - "integrity": "sha512-n7zSmOcUVhcRYC75W2pnPpbO1iwhJY3NLoHEtbJwJSNlVAZuwqu05zY3f3s2SDWWDSo9FdN5szqc73DCtDObAg==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.0.tgz", + "integrity": "sha512-qX2L3HWOU2nuDs6GzglBeuFXviDODreS58tLY/BALPC7iu3Fa+J7EOTwnX9PdNBxUI7Uh0ntP0YWGnxCkXzmfA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.34.0", - "@typescript-eslint/utils": "8.34.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0", + "@typescript-eslint/utils": "8.56.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4081,14 +3596,14 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.34.0.tgz", - "integrity": "sha512-9V24k/paICYPniajHfJ4cuAWETnt7Ssy+R0Rbcqo5sSFr3QEZ/8TSoUi9XeXVBGXCaLtwTOKSLGcInCAvyZeMA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.0.tgz", + "integrity": "sha512-DBsLPs3GsWhX5HylbP9HNG15U0bnwut55Lx12bHB9MpXxQ+R5GC8MwQe+N1UFXxAeQDvEsEDY6ZYwX03K7Z6HQ==", "dev": true, "license": "MIT", "engines": { @@ -4100,22 +3615,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.34.0.tgz", - "integrity": "sha512-rOi4KZxI7E0+BMqG7emPSK1bB4RICCpF7QD3KCLXn9ZvWoESsOMlHyZPAHyG04ujVplPaHbmEvs34m+wjgtVtg==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.0.tgz", + "integrity": "sha512-ex1nTUMWrseMltXUHmR2GAQ4d+WjkZCT4f+4bVsps8QEdh0vlBsaCokKTPlnqBFqqGaxilDNJG7b8dolW2m43Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.34.0", - "@typescript-eslint/tsconfig-utils": "8.34.0", - "@typescript-eslint/types": "8.34.0", - "@typescript-eslint/visitor-keys": "8.34.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" + "@typescript-eslint/project-service": "8.56.0", + "@typescript-eslint/tsconfig-utils": "8.56.0", + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0", + "debug": "^4.4.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4125,49 +3639,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -4185,16 +3669,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.34.0.tgz", - "integrity": "sha512-8L4tWatGchV9A1cKbjaavS6mwYwp39jql8xUmIIKJdm+qiaeHy5KMKlBrf30akXAWBzn2SqKsNOtSENWUwg7XQ==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.0.tgz", + "integrity": "sha512-RZ3Qsmi2nFGsS+n+kjLAYDPVlrzf7UhTffrDIKr+h2yzAlYP/y5ZulU0yeDEPItos2Ph46JAL5P/On3pe7kDIQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.34.0", - "@typescript-eslint/types": "8.34.0", - "@typescript-eslint/typescript-estree": "8.34.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.56.0", + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4204,19 +3688,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.34.0.tgz", - "integrity": "sha512-qHV7pW7E85A0x6qyrFn+O+q1k1p3tQCsqIZ1KZ5ESLXY57aTvUd3/a4rdPTeXisvhXn2VQG0VSKUqs8KHF2zcA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.0.tgz", + "integrity": "sha512-q+SL+b+05Ud6LbEE35qe4A99P+htKTKVbyiNEe45eCbJFyh/HVK9QXwlrbz+Q4L8SOW4roxSVwXYj4DMBT7Ieg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.34.0", - "eslint-visitor-keys": "^4.2.0" + "@typescript-eslint/types": "8.56.0", + "eslint-visitor-keys": "^5.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4226,6 +3710,19 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.0.tgz", + "integrity": "sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@unrs/resolver-binding-darwin-arm64": { "version": "1.7.12", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.7.12.tgz", @@ -4876,17 +4373,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -5013,25 +4499,11 @@ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, - "node_modules/color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", - "license": "MIT", - "optional": true, - "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, - "engines": { - "node": ">=12.5.0" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -5044,20 +4516,9 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "devOptional": true, + "dev": true, "license": "MIT" }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "license": "MIT", - "optional": true, - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, "node_modules/commander": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", @@ -5287,9 +4748,9 @@ } }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -5358,9 +4819,9 @@ } }, "node_modules/detect-libc": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "devOptional": true, "license": "Apache-2.0", "engines": { @@ -5724,33 +5185,32 @@ } }, "node_modules/eslint": { - "version": "9.28.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.28.0.tgz", - "integrity": "sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.20.0", - "@eslint/config-helpers": "^0.2.1", - "@eslint/core": "^0.14.0", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.28.0", - "@eslint/plugin-kit": "^0.3.1", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.3.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -5785,13 +5245,13 @@ } }, "node_modules/eslint-config-next": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.3.3.tgz", - "integrity": "sha512-QJLv/Ouk2vZnxL4b67njJwTLjTf7uZRltI0LL4GERYR4qMF5z08+gxkfODAeaK7TiC6o+cER91bDaEnwrTWV6Q==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.5.12.tgz", + "integrity": "sha512-ktW3XLfd+ztEltY5scJNjxjHwtKWk6vU2iwzZqSN09UsbBmMeE/cVlJ1yESg6Yx5LW7p/Z8WzUAgYXGLEmGIpg==", "dev": true, "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "15.3.3", + "@next/eslint-plugin-next": "15.5.12", "@rushstack/eslint-patch": "^1.10.3", "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", @@ -6501,13 +5961,6 @@ "dev": true, "license": "ISC" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -6672,13 +6125,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "license": "MIT", - "optional": true - }, "node_modules/is-async-function": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", @@ -7112,9 +6558,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -7639,9 +7085,9 @@ } }, "node_modules/minizlib": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", - "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", "dev": true, "license": "MIT", "dependencies": { @@ -7651,22 +7097,6 @@ "node": ">= 18" } }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/motion-dom": { "version": "12.18.1", "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.18.1.tgz", @@ -7731,15 +7161,13 @@ "license": "MIT" }, "node_modules/next": { - "version": "15.3.8", - "resolved": "https://registry.npmjs.org/next/-/next-15.3.8.tgz", - "integrity": "sha512-L+4c5Hlr84fuaNADZbB9+ceRX9/CzwxJ+obXIGHupboB/Q1OLbSUapFs4bO8hnS/E6zV/JDX7sG1QpKVR2bguA==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.12.tgz", + "integrity": "sha512-Fi/wQ4Etlrn60rz78bebG1i1SR20QxvV8tVp6iJspjLUSHcZoeUXCt+vmWoEcza85ElZzExK/jJ/F6SvtGktjA==", "license": "MIT", "dependencies": { - "@next/env": "15.3.8", - "@swc/counter": "0.1.3", + "@next/env": "15.5.12", "@swc/helpers": "0.5.15", - "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" @@ -7751,19 +7179,19 @@ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.3.5", - "@next/swc-darwin-x64": "15.3.5", - "@next/swc-linux-arm64-gnu": "15.3.5", - "@next/swc-linux-arm64-musl": "15.3.5", - "@next/swc-linux-x64-gnu": "15.3.5", - "@next/swc-linux-x64-musl": "15.3.5", - "@next/swc-win32-arm64-msvc": "15.3.5", - "@next/swc-win32-x64-msvc": "15.3.5", - "sharp": "^0.34.1" + "@next/swc-darwin-arm64": "15.5.12", + "@next/swc-darwin-x64": "15.5.12", + "@next/swc-linux-arm64-gnu": "15.5.12", + "@next/swc-linux-arm64-musl": "15.5.12", + "@next/swc-linux-x64-gnu": "15.5.12", + "@next/swc-linux-x64-musl": "15.5.12", + "@next/swc-win32-arm64-msvc": "15.5.12", + "@next/swc-win32-x64-msvc": "15.5.12", + "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", - "@playwright/test": "^1.41.2", + "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", @@ -8242,34 +7670,6 @@ "dev": true, "license": "MIT" }, - "node_modules/react-tsparticles": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/react-tsparticles/-/react-tsparticles-2.12.2.tgz", - "integrity": "sha512-/nrEbyL8UROXKIMXe+f+LZN2ckvkwV2Qa+GGe/H26oEIc+wq/ybSG9REDwQiSt2OaDQGu0MwmA4BKmkL6wAWcA==", - "deprecated": "@tsparticles/react is the new version, please use that", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/matteobruni" - }, - { - "type": "github", - "url": "https://github.com/sponsors/tsparticles" - }, - { - "type": "buymeacoffee", - "url": "https://www.buymeacoffee.com/matteobruni" - } - ], - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "tsparticles-engine": "^2.12.0" - }, - "peerDependencies": { - "react": ">=16" - } - }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -8523,9 +7923,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "devOptional": true, "license": "ISC", "bin": { @@ -8585,16 +7985,16 @@ } }, "node_modules/sharp": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.2.tgz", - "integrity": "sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", "hasInstallScript": true, "license": "Apache-2.0", "optional": true, "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.4", - "semver": "^7.7.2" + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -8603,27 +8003,30 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.2", - "@img/sharp-darwin-x64": "0.34.2", - "@img/sharp-libvips-darwin-arm64": "1.1.0", - "@img/sharp-libvips-darwin-x64": "1.1.0", - "@img/sharp-libvips-linux-arm": "1.1.0", - "@img/sharp-libvips-linux-arm64": "1.1.0", - "@img/sharp-libvips-linux-ppc64": "1.1.0", - "@img/sharp-libvips-linux-s390x": "1.1.0", - "@img/sharp-libvips-linux-x64": "1.1.0", - "@img/sharp-libvips-linuxmusl-arm64": "1.1.0", - "@img/sharp-libvips-linuxmusl-x64": "1.1.0", - "@img/sharp-linux-arm": "0.34.2", - "@img/sharp-linux-arm64": "0.34.2", - "@img/sharp-linux-s390x": "0.34.2", - "@img/sharp-linux-x64": "0.34.2", - "@img/sharp-linuxmusl-arm64": "0.34.2", - "@img/sharp-linuxmusl-x64": "0.34.2", - "@img/sharp-wasm32": "0.34.2", - "@img/sharp-win32-arm64": "0.34.2", - "@img/sharp-win32-ia32": "0.34.2", - "@img/sharp-win32-x64": "0.34.2" + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" } }, "node_modules/shebang-command": { @@ -8725,16 +8128,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "license": "MIT", - "optional": true, - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, "node_modules/snake-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", @@ -8782,14 +8175,6 @@ "node": ">= 0.4" } }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/string.prototype.includes": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", @@ -9026,17 +8411,16 @@ } }, "node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.9.tgz", + "integrity": "sha512-BTLcK0xsDh2+PUe9F6c2TlRp4zOOBMTkoQHQIWSIzI0R7KG46uEwq4OPk2W7bZcprBMsuaeFsqwYr7pjh6CuHg==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", + "minizlib": "^3.1.0", "yallist": "^5.0.0" }, "engines": { @@ -9044,14 +8428,14 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "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.4.4", - "picomatch": "^4.0.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { "node": ">=12.0.0" @@ -9061,11 +8445,14 @@ } }, "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", - "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", + "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" }, @@ -9076,9 +8463,9 @@ } }, "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -9102,9 +8489,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", "dev": true, "license": "MIT", "engines": { @@ -9133,63 +8520,6 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, - "node_modules/tsparticles": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/tsparticles/-/tsparticles-3.8.1.tgz", - "integrity": "sha512-8hrG4dZMg5xxJEJ6ZA6qwdQUQjtguI+VCtl1kvp2QlgmX6qvegv0jizO3gKKUZ9QAwprIW57YeA7UTPvFvxYWw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/matteobruni" - }, - { - "type": "github", - "url": "https://github.com/sponsors/tsparticles" - }, - { - "type": "buymeacoffee", - "url": "https://www.buymeacoffee.com/matteobruni" - } - ], - "license": "MIT", - "dependencies": { - "@tsparticles/engine": "3.8.1", - "@tsparticles/interaction-external-trail": "3.8.1", - "@tsparticles/plugin-absorbers": "3.8.1", - "@tsparticles/plugin-emitters": "3.8.1", - "@tsparticles/plugin-emitters-shape-circle": "3.8.1", - "@tsparticles/plugin-emitters-shape-square": "3.8.1", - "@tsparticles/shape-text": "3.8.1", - "@tsparticles/slim": "3.8.1", - "@tsparticles/updater-destroy": "3.8.1", - "@tsparticles/updater-roll": "3.8.1", - "@tsparticles/updater-tilt": "3.8.1", - "@tsparticles/updater-twinkle": "3.8.1", - "@tsparticles/updater-wobble": "3.8.1" - } - }, - "node_modules/tsparticles-engine": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/tsparticles-engine/-/tsparticles-engine-2.12.0.tgz", - "integrity": "sha512-ZjDIYex6jBJ4iMc9+z0uPe7SgBnmb6l+EJm83MPIsOny9lPpetMsnw/8YJ3xdxn8hV+S3myTpTN1CkOVmFv0QQ==", - "deprecated": "starting from tsparticles v3 the packages are now moved to @tsparticles/package-name instead of tsparticles-package-name", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/matteobruni" - }, - { - "type": "github", - "url": "https://github.com/sponsors/tsparticles" - }, - { - "type": "buymeacoffee", - "url": "https://www.buymeacoffee.com/matteobruni" - } - ], - "hasInstallScript": true, - "license": "MIT" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index 3bba85d..b42c973 100644 --- a/package.json +++ b/package.json @@ -9,23 +9,23 @@ "lint": "next lint" }, "dependencies": { + "@tsparticles/engine": "^3.9.1", + "@tsparticles/react": "^3.0.0", "framer-motion": "^12.18.1", - "next": "15.3.8", + "next": "15.5.12", "react": "^19.0.0", "react-dom": "^19.0.0", - "react-tsparticles": "^2.12.2", - "stats.js": "^0.17.0", - "tsparticles": "^3.8.1" + "stats.js": "^0.17.0" }, "devDependencies": { - "@eslint/eslintrc": "^3", + "@eslint/eslintrc": "^3.3.3", "@svgr/webpack": "^8.1.0", "@tailwindcss/postcss": "^4", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", - "eslint": "^9", - "eslint-config-next": "15.3.3", + "eslint": "^9.39.2", + "eslint-config-next": "15.5.12", "tailwindcss": "^4", "typescript": "^5" } diff --git a/public/assets/contact-section/ethereum-foundation-official.svg b/public/assets/contact-section/ethereum-foundation-official.svg new file mode 100644 index 0000000..d22a55f --- /dev/null +++ b/public/assets/contact-section/ethereum-foundation-official.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/public/assets/contact-section/security-alliance-official.svg b/public/assets/contact-section/security-alliance-official.svg new file mode 100644 index 0000000..1b348cc --- /dev/null +++ b/public/assets/contact-section/security-alliance-official.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/assets/contact-section/wedf-logo.png b/public/assets/contact-section/wedf-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..72ca57b2477f1e6d359ba958c5e49e66ea0ad4fe GIT binary patch literal 29618 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�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 literal 0 HcmV?d00001 diff --git a/src/app/components/Card.tsx b/src/app/components/Card.tsx index d7bc0c6..820d859 100644 --- a/src/app/components/Card.tsx +++ b/src/app/components/Card.tsx @@ -9,19 +9,56 @@ interface CardProps { onExplore: () => void; buttonText?: string; links?: CardLink[]; + variant?: 'default' | 'ethos'; } -const Card: React.FC = ({ title, description, onClose, onExplore, buttonText, links }) => { +const toSafeExternalUrl = (value: string): string | null => { + try { + const parsed = new URL(value); + if (parsed.protocol === 'https:' || parsed.protocol === 'http:') { + return parsed.toString(); + } + return null; + } catch { + return null; + } +}; + +const Card: React.FC = ({ + title, + description, + onClose, + onExplore, + buttonText, + links, + variant = 'default', +}) => { + const isEthos = variant === 'ethos'; + return ( -
    -
    -
    -
    +
    +
    +
    + {isEthos && ( +
    + )} +
    {onClose && ( )} -

    {title}

    -

    +

    {title}

    +

    + {description} +

    {links && links.length > 0 ? ( -
    - {links.map((link, idx) => ( - - {link.label} - - ))} +
    + {links.map((link, idx) => { + const safeUrl = toSafeExternalUrl(link.url); + if (!safeUrl) { + return null; + } + + return ( + + {link.label} + + ); + })}
    ) : ( = ({ title, description, onClose, onExplore, but e.preventDefault(); onExplore(); }} - className="text-white hover:text-white/80 text-base font-spartan-subtitle transition-colors uppercase underline underline-offset-2 decoration-white mt-6" + className={`font-spartan-subtitle transition-colors uppercase underline underline-offset-2 mt-6 ${ + isEthos + ? 'text-white/90 hover:text-white text-sm decoration-white/60' + : 'text-white hover:text-white/80 text-base decoration-white' + }`} > {buttonText || "Explore"} @@ -79,4 +128,4 @@ const Card: React.FC = ({ title, description, onClose, onExplore, but ); }; -export default Card; \ No newline at end of file +export default Card; diff --git a/src/app/components/MainContent.tsx b/src/app/components/MainContent.tsx index a0445e3..58d917f 100644 --- a/src/app/components/MainContent.tsx +++ b/src/app/components/MainContent.tsx @@ -2,10 +2,24 @@ import React, { useRef, useState, useEffect } from 'react'; import Image from 'next/image'; -const TRANSITION_SCROLL = 50; // Scroll para activar transición +const TRANSITION_SCROLL = 500; +const COLOR_START = { r: 255, g: 255, b: 255 }; +const COLOR_END = { r: 247, g: 57, b: 47 }; + +function lerpColor( + a: { r: number; g: number; b: number }, + b: { r: number; g: number; b: number }, + t: number +) { + return { + r: Math.round(a.r + (b.r - a.r) * t), + g: Math.round(a.g + (b.g - a.g) * t), + b: Math.round(a.b + (b.b - a.b) * t), + }; +} const MainContent = ({ onSectionEnd, transitioning: parentTransitioning }: { onSectionEnd: () => void; transitioning?: boolean }) => { - const [, setProgress] = useState(0); // 0 a 1 + const [progress, setProgress] = useState(0); const [transitioning, setTransitioning] = useState(false); const [blockScroll, setBlockScroll] = useState(false); const [showSection, setShowSection] = useState(true); @@ -45,6 +59,7 @@ const MainContent = ({ onSectionEnd, transitioning: parentTransitioning }: { onS ' with research, tools and resources', ' for the public good.' ]; + const text = lines.join(''); if (!showSection) return null; @@ -78,23 +93,33 @@ const MainContent = ({ onSectionEnd, transitioning: parentTransitioning }: { onS sizes="169px" />
    -

    +

    - {lines.map((line, lineIndex) => ( -
    - {line.split('').map((char, charIndex) => ( - - {char === ' ' ? '\u00A0' : char} - - ))} -
    - ))} + {lines.map((line, lineIndex) => { + const startIndex = text.indexOf(line); + return ( +
    + {line.split('').map((char, charIndex) => { + const index = startIndex + charIndex; + const t = Math.max(0, Math.min(1, progress * text.length - index)); + const color = lerpColor(COLOR_START, COLOR_END, t); + const isActive = t >= 1; + return ( + + {char === ' ' ? '\u00A0' : char} + + ); + })} +
    + ); + })}

    diff --git a/src/app/components/MemberCard.tsx b/src/app/components/MemberCard.tsx new file mode 100644 index 0000000..66b45dd --- /dev/null +++ b/src/app/components/MemberCard.tsx @@ -0,0 +1,134 @@ +import React from "react"; +import Image from "next/image"; + +import { MemberProfile } from "../data/membersConfig"; +import RadarChart from "./RadarChart"; +import SkillTree from "./SkillTree"; + +interface MemberCardProps { + member: MemberProfile; +} + +const toSafeExternalUrl = (value?: string): string | null => { + if (!value) { + return null; + } + + try { + const parsed = new URL(value); + if (parsed.protocol === "https:" || parsed.protocol === "http:") { + return parsed.toString(); + } + return null; + } catch { + return null; + } +}; + +const MemberCard: React.FC = ({ member }) => { + const initials = + member.alias + .split(" ") + .map((part) => part[0]) + .join("") + .slice(0, 2) + .toUpperCase() || member.name.slice(0, 2).toUpperCase(); + const fallbackGithubAvatar = member.githubUsername + ? `https://github.com/${encodeURIComponent(member.githubUsername)}.png?size=256` + : undefined; + const avatarUrl = + toSafeExternalUrl(member.avatar) || toSafeExternalUrl(fallbackGithubAvatar); + + return ( +
    +
    +
    +
    +
    +
    +
    + {avatarUrl ? ( + {member.name} + ) : ( +
    + {initials} +
    + )} +
    +
    +
    +
    {member.name}
    +
    + {member.alias} +
    +
    {member.title}
    +
    +
    + +
    + + Level {member.level} + + + {member.className} + +
    + +

    {member.bio}

    + +
      + {member.highlights.map((item) => ( +
    • + + {item} +
    • + ))} +
    + +
    + {member.specialties.map((item) => ( + + {item} + + ))} +
    +
    + +
    + + +
    +
    +

    + Radix Chart +

    + Capability Mesh +
    +
    + +
    +
    + {member.radar.map((stat) => ( +
    + {stat.label} + {stat.value} +
    + ))} +
    +
    +
    +
    +
    + ); +}; + +export default MemberCard; diff --git a/src/app/components/MemberPreviewCard.tsx b/src/app/components/MemberPreviewCard.tsx new file mode 100644 index 0000000..ee356d1 --- /dev/null +++ b/src/app/components/MemberPreviewCard.tsx @@ -0,0 +1,132 @@ +import Image from "next/image"; +import React from "react"; + +import { MemberProfile } from "../data/membersConfig"; +import RadarChart from "./RadarChart"; + +interface MemberPreviewCardProps { + member: MemberProfile; + isActive: boolean; + onSelect: () => void; +} + +const toSafeExternalUrl = (value?: string): string | null => { + if (!value) { + return null; + } + + try { + const parsed = new URL(value); + if (parsed.protocol === "https:" || parsed.protocol === "http:") { + return parsed.toString(); + } + return null; + } catch { + return null; + } +}; + +const MemberPreviewCard: React.FC = ({ + member, + isActive, + onSelect, +}) => { + const initials = + member.alias + .split(" ") + .map((part) => part[0]) + .join("") + .slice(0, 2) + .toUpperCase() || member.name.slice(0, 2).toUpperCase(); + const fallbackGithubAvatar = member.githubUsername + ? `https://github.com/${encodeURIComponent(member.githubUsername)}.png?size=256` + : undefined; + const avatarUrl = + toSafeExternalUrl(member.avatar) || toSafeExternalUrl(fallbackGithubAvatar); + const socials = [ + { key: "github", label: "GH", href: toSafeExternalUrl(member.socials?.github) }, + { key: "x", label: "X", href: toSafeExternalUrl(member.socials?.x) }, + { key: "linkedin", label: "IN", href: toSafeExternalUrl(member.socials?.linkedin) }, + { key: "website", label: "WEB", href: toSafeExternalUrl(member.socials?.website) }, + ]; + + return ( +
    +
    + + +
    + {socials.map((social) => + social.href ? ( + + {social.label} + + ) : ( + + {social.label} + + ) + )} +
    +
    + ); +}; + +export default MemberPreviewCard; diff --git a/src/app/components/Navbar.tsx b/src/app/components/Navbar.tsx index c732210..372c199 100644 --- a/src/app/components/Navbar.tsx +++ b/src/app/components/Navbar.tsx @@ -3,11 +3,17 @@ import Image from "next/image"; import Link from "next/link"; import { usePathname } from "next/navigation"; -import React, { useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; const Navbar = () => { const pathname = usePathname(); const [isMenuOpen, setIsMenuOpen] = useState(false); + const [isAboutOpen, setIsAboutOpen] = useState(false); + const [isMobileAboutOpen, setIsMobileAboutOpen] = useState(false); + const [isEthosOpen, setIsEthosOpen] = useState(false); + const closeAboutTimeoutRef = useRef | null>(null); + + const isAboutActive = pathname === "/members"; const toggleMenu = () => { setIsMenuOpen(!isMenuOpen); @@ -15,147 +21,395 @@ const Navbar = () => { const closeMenu = () => { setIsMenuOpen(false); + setIsAboutOpen(false); + setIsMobileAboutOpen(false); + }; + + const clearAboutCloseTimer = () => { + if (closeAboutTimeoutRef.current) { + clearTimeout(closeAboutTimeoutRef.current); + closeAboutTimeoutRef.current = null; + } + }; + + const openAboutMenu = () => { + clearAboutCloseTimer(); + setIsAboutOpen(true); + }; + + const scheduleAboutClose = () => { + clearAboutCloseTimer(); + closeAboutTimeoutRef.current = setTimeout(() => { + setIsAboutOpen(false); + }, 220); }; + const openEthos = () => { + setIsEthosOpen(true); + setIsAboutOpen(false); + setIsMobileAboutOpen(false); + setIsMenuOpen(false); + }; + + const closeEthos = () => { + setIsEthosOpen(false); + }; + + useEffect(() => { + if (!isEthosOpen) { + return; + } + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === "Escape") { + setIsEthosOpen(false); + } + }; + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, [isEthosOpen]); + + useEffect(() => { + return () => { + clearAboutCloseTimer(); + }; + }, []); + return ( -
    +
    + )} + + + {isEthosOpen && ( +
    +
    +
    - Contact - - - - - {/* Mobile Hamburger Button */} - - - {/* Mobile Menu Overlay */} - {isMenuOpen && ( -
    -
    e.stopPropagation()}> -
      -
    • - - Home - -
    • -
    • - - Initiatives - -
    • -
    • - - Supporters - -
    • -
    • - - Blog - -
    • -
    • - - Contact - -
    • -
    +
    + +
    +

    + About the Guild +

    +

    Our Ethos

    +

    + The Red Guild is a security collective devoted to protecting the open crypto ecosystem. + We move like a guild: research, education, and open-source tooling built in public for the + benefit of the community. +

    +

    + Our work blends adversarial rigor with public-good intent. We investigate threats, teach + defenders, and ship practical tools that raise the baseline for everyone. +

    + +
    +
    +

    What we do

    +
      +
    • Security research, advisories, and investigations
    • +
    • Education programs, workshops, and awareness campaigns
    • +
    • Open-source tooling for safer development
    • +
    +
    +
    +

    How we work

    +
      +
    • Community-first collaboration and open knowledge
    • +
    • Responsible disclosure and transparent reporting
    • +
    • Iterative practice, shared playbooks, repeatable wins
    • +
    +
    +
    +
    )} - + ); }; -export default Navbar; \ No newline at end of file +export default Navbar; diff --git a/src/app/components/RadarChart.tsx b/src/app/components/RadarChart.tsx new file mode 100644 index 0000000..d9b93bb --- /dev/null +++ b/src/app/components/RadarChart.tsx @@ -0,0 +1,136 @@ +import React from "react"; + +import { MemberStat } from "../data/membersConfig"; + +interface RadarChartProps { + stats: MemberStat[]; + size?: number; + showLabels?: boolean; +} + +const RadarChart: React.FC = ({ stats, size = 220, showLabels = true }) => { + if (!stats.length) { + return null; + } + + const isCompact = !showLabels || size <= 96; + const padding = showLabels ? 24 : 14; + const center = size / 2; + const radius = size / 2 - padding; + const angleStep = (Math.PI * 2) / stats.length; + const maxValue = 100; + const pointRadius = isCompact ? Math.max(0.9, size * 0.012) : 3; + const pointStroke = isCompact ? 0.55 : 1; + const axisStroke = isCompact ? 0.7 : 1; + const polygonStroke = isCompact ? 1.15 : 2; + + const buildPolygon = (ratio: number) => + stats + .map((_, index) => { + const angle = -Math.PI / 2 + index * angleStep; + const r = radius * ratio; + const x = center + Math.cos(angle) * r; + const y = center + Math.sin(angle) * r; + return `${x.toFixed(2)},${y.toFixed(2)}`; + }) + .join(" "); + + const dataPolygon = stats + .map((stat, index) => { + const angle = -Math.PI / 2 + index * angleStep; + const r = (stat.value / maxValue) * radius; + const x = center + Math.cos(angle) * r; + const y = center + Math.sin(angle) * r; + return `${x.toFixed(2)},${y.toFixed(2)}`; + }) + .join(" "); + + const labelRadius = radius + 14; + + return ( + + ); +}; + +export default RadarChart; diff --git a/src/app/components/Scene.tsx b/src/app/components/Scene.tsx index de50cf0..a5d49a8 100644 --- a/src/app/components/Scene.tsx +++ b/src/app/components/Scene.tsx @@ -69,6 +69,19 @@ const Scene: React.FC = ({ show, transitioning, onBack }) => { }; }, [show, transitioning, onBack]); + React.useEffect(() => { + if (!activeCard) return; + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + setActiveCard(null); + setActiveElement(null); + setIsTempleHovered(false); + } + }; + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, [activeCard]); + // Handle custom cursor useEffect(() => { if (!customCursor.visible || !isDesktop) return; @@ -245,21 +258,20 @@ const Scene: React.FC = ({ show, transitioning, onBack }) => {
    {activeCard && ( - <> -
    -
    -
    e.stopPropagation()}> - -
    +
    +
    +
    e.stopPropagation()}> +
    - +
    )} {/* Bottom Left Flower */} @@ -340,4 +352,4 @@ const Scene: React.FC = ({ show, transitioning, onBack }) => { ); }; -export default Scene; \ No newline at end of file +export default Scene; diff --git a/src/app/components/SkillTree.tsx b/src/app/components/SkillTree.tsx new file mode 100644 index 0000000..23bffab --- /dev/null +++ b/src/app/components/SkillTree.tsx @@ -0,0 +1,222 @@ +import React, { useMemo, useState } from "react"; + +import { CareerPathNode, SkillTier } from "../data/membersConfig"; + +const MAX_LEVEL = 5; +const HEXAGON_CLIP_PATH = "polygon(25% 5%, 75% 5%, 100% 50%, 75% 95%, 25% 95%, 0 50%)"; +const SKILL_EMOJIS = ["🛡️", "🧠", "⚙️", "🔍", "🧪", "📡", "🧰", "🛰️", "🗝️", "🚀"]; + +type SkillBadge = { + id: string; + label: string; + description: string; + level: number; + requires: string[]; + emoji: string; +}; + +interface SkillTreeProps { + tiers: SkillTier[]; + careerPath?: CareerPathNode[]; +} + +interface LevelPipsProps { + level: number; + compact?: boolean; +} + +const normalizeRequires = (requires?: string | string[]): string[] => { + if (!requires) { + return []; + } + const values = Array.isArray(requires) ? requires : [requires]; + return values.map((value) => value.trim()).filter(Boolean); +}; + +const LevelPips: React.FC = ({ level, compact = false }) => ( + + {Array.from({ length: MAX_LEVEL }).map((_, index) => { + const active = index < level; + return ( + + ); + })} + +); + +const SkillTree: React.FC = ({ tiers, careerPath }) => { + const badges = useMemo(() => { + if (careerPath && careerPath.length > 0) { + return careerPath.map((node, index) => ({ + id: node.id, + label: node.label, + description: node.description, + level: node.level, + requires: normalizeRequires(node.requires), + emoji: SKILL_EMOJIS[index % SKILL_EMOJIS.length], + })); + } + + let emojiIndex = 0; + + return tiers.flatMap((tier, tierIndex) => + tier.nodes.map((node, nodeIndex) => { + const previousTier = tiers[tierIndex - 1]; + const previousNode = + previousTier?.nodes[Math.min(nodeIndex, previousTier.nodes.length - 1)]; + + const fallback: SkillBadge = { + id: `${tier.label}-${node.label}`, + label: node.label, + description: + node.description || + (tierIndex === 0 + ? `${node.label} is part of the core foundation every guild member starts with.` + : `${node.label} is developed during the ${tier.label.toLowerCase()} stage.`), + level: node.level, + requires: node.requires ? [node.requires] : previousNode ? [previousNode.label] : [], + emoji: SKILL_EMOJIS[emojiIndex % SKILL_EMOJIS.length], + }; + + emojiIndex += 1; + return fallback; + }) + ); + }, [careerPath, tiers]); + + const [activeBadgeId, setActiveBadgeId] = useState(badges[0]?.id || ""); + + const badgeById = useMemo(() => { + const map = new Map(); + badges.forEach((badge) => map.set(badge.id, badge)); + return map; + }, [badges]); + + const badgeByLabel = useMemo(() => { + const map = new Map(); + badges.forEach((badge) => { + if (!map.has(badge.label.toLowerCase())) { + map.set(badge.label.toLowerCase(), badge); + } + }); + return map; + }, [badges]); + + const activeBadge = badgeById.get(activeBadgeId) || badges[0] || null; + + const activeDependencies = (activeBadge?.requires || []).map((requiredLabel) => { + const requiredBadge = badgeByLabel.get(requiredLabel.toLowerCase()); + return { + label: requiredLabel, + level: requiredBadge?.level || 0, + }; + }); + + return ( +
    +
    +

    + Career Badges +

    + Compact View +
    + +
    + {badges.map((badge) => { + const isActive = activeBadge?.id === badge.id; + + return ( + + ); + })} +
    + +
    + {activeBadge ? ( +
    +
    +

    + {activeBadge.label} +

    + +
    + +

    + {activeBadge.description} +

    + +
    +

    + Dependencies +

    + {activeDependencies.length > 0 ? ( +
    + {activeDependencies.map((dependency) => ( + + {dependency.label} + + + ))} +
    + ) : ( +

    + None +

    + )} +
    +
    + ) : ( +
    +

    + No skill badges configured. +

    +
    + )} +
    +
    + ); +}; + +export default SkillTree; diff --git a/src/app/components/SupportersCollaborators.tsx b/src/app/components/SupportersCollaborators.tsx index 73c0aad..9f3bdfb 100644 --- a/src/app/components/SupportersCollaborators.tsx +++ b/src/app/components/SupportersCollaborators.tsx @@ -5,14 +5,62 @@ import Image from 'next/image'; const SupportersCollaborators: React.FC = () => { return ( -
    - Supporters & Collaborators -
    - - Ethereum Foundation +
    +
    +
    +
    +

    + About the Guild +

    +

    Supporters & Collaborators

    +

    + We collaborate with aligned organizations that support The Red Guild through grants, + shared security initiatives, and ecosystem efforts focused on public-benefit outcomes. +

    +
    +
    +

    diff --git a/src/app/data/cardContent.ts b/src/app/data/cardContent.ts index 733362f..32c71a7 100644 --- a/src/app/data/cardContent.ts +++ b/src/app/data/cardContent.ts @@ -44,12 +44,16 @@ export const cardContent: CardContentMap = { }, topRightLights: { title: "Security Frameworks", - description: "A curated resource full of best practices and potential pitfalls in crypto security, collaborating with industry experts at the Security Alliance (SEAL).", + description: "A curated resource full of best practices and potential pitfalls in crypto security, collaborating with industry experts at Security Alliance (SEAL).", buttonText: "Learn & contribute", links: [ { label: "Learn & contribute", url: "https://frameworks.securityalliance.dev" + }, + { + label: "Security Alliance (SEAL)", + url: "https://www.securityalliance.org/" } ] }, @@ -100,4 +104,4 @@ export const cardContent: CardContentMap = { } ] } -}; \ No newline at end of file +}; diff --git a/src/app/data/membersConfig.ts b/src/app/data/membersConfig.ts new file mode 100644 index 0000000..5688030 --- /dev/null +++ b/src/app/data/membersConfig.ts @@ -0,0 +1,623 @@ +export type MemberStat = { + label: string; + value: number; +}; + +export type SkillNode = { + label: string; + level: number; + description?: string; + icon?: string; + requires?: string; +}; + +export type SkillTier = { + label: string; + nodes: SkillNode[]; +}; + +export type CareerPathNode = { + id: string; + label: string; + level: number; + description: string; + stage: string; + requires?: string | string[]; + icon?: string; +}; + +export type MemberSocials = { + github?: string; + x?: string; + linkedin?: string; + website?: string; +}; + +export type MemberProfile = { + id: string; + name: string; + alias: string; + title: string; + level: number; + className: string; + bio: string; + highlights: string[]; + specialties: string[]; + radar: MemberStat[]; + skillTree: SkillTier[]; + careerPath?: CareerPathNode[]; + githubUsername?: string; + socials?: MemberSocials; + avatar?: string; +}; + +export const members: MemberProfile[] = [ + { + id: "mattaereal", + name: "Matías Aereal Aeón", + alias: "matta", + title: "Security Knowmad", + level: 5, + className: "Founder", + githubUsername: "mattaereal", + avatar: "https://github.com/mattaereal.png?size=256", + socials: { + github: "https://github.com/mattaereal", + x: "https://x.com/mattaereal", + }, + bio: "LatAm-first security educator coordinating threat intel and frontline awareness. Builds playbooks and turns incidents into learnable quests.", + highlights: [ + "Leads public phishing response drills", + "Maintains guild threat intel feeds", + "Runs security workshops across LATAM", + ], + specialties: ["Gamified Education", "Stage Presence", "Barefoot Walker", "Paranoid", "SEAL: Initiative Lead", "SEAL: Technical Council", "Producer"], + radar: [ + { label: "SOCIAL", value: 84 }, + { label: "SECURITY", value: 72 }, + { label: "DEVELOPMENT", value: 60 }, + { label: "EDUCATION", value: 92 }, + { label: "OPERATIONS", value: 78 }, + { label: "ART", value: 70 }, + ], + skillTree: [ + { + label: "Core", + nodes: [ + { + label: "Threat Modeling", + level: 4, + description: "Maps likely attacker behavior and prioritizes defensive controls.", + icon: "/assets/lights.svg", + }, + { + label: "Community Signals", + level: 3, + description: "Reads social and onchain indicators to detect active scam waves.", + icon: "/assets/lettersn.svg", + }, + ], + }, + { + label: "Paths", + nodes: [ + { + label: "Playbook Design", + level: 3, + description: "Turns incidents into reusable responder guides for distributed teams.", + icon: "/assets/tree.svg", + requires: "Threat Modeling", + }, + { + label: "Phishing Triage", + level: 2, + description: "Classifies malicious campaigns and routes evidence quickly.", + icon: "/assets/flower.svg", + requires: "Community Signals", + }, + ], + }, + { + label: "Mastery", + nodes: [ + { + label: "Public Awareness", + level: 4, + description: "Designs outreach that helps users avoid real-world social engineering.", + icon: "/assets/sun.svg", + requires: "Playbook Design", + }, + { + label: "Incident Command", + level: 3, + description: "Coordinates multi-team response and communication during incidents.", + icon: "/assets/temple.svg", + requires: "Phishing Triage", + }, + ], + }, + ], + careerPath: [ + { + id: "matta-programming-basics", + label: "Programming Basics", + level: 2, + description: "Technical baseline needed to evaluate attack vectors and tooling behavior.", + stage: "Foundation", + icon: "/assets/temple.svg", + }, + { + id: "matta-threat-modeling", + label: "Threat Modeling", + level: 4, + description: "Prioritizes attacker paths and defensive controls for community-facing systems.", + stage: "Foundation", + requires: "Programming Basics", + icon: "/assets/lights.svg", + }, + { + id: "matta-signal-analysis", + label: "Signal Analysis", + level: 3, + description: "Interprets social and onchain signals to identify likely phishing campaigns.", + stage: "Practice", + requires: "Threat Modeling", + icon: "/assets/lettersn.svg", + }, + { + id: "matta-phishing-triage", + label: "Phishing Triage", + level: 2, + description: "Validates reports and routes actionable evidence to the right responders.", + stage: "Practice", + requires: "Signal Analysis", + icon: "/assets/flower.svg", + }, + { + id: "matta-playbook-design", + label: "Playbook Design", + level: 3, + description: "Converts incidents into repeatable response drills and guidance.", + stage: "Leadership", + requires: ["Threat Modeling", "Phishing Triage"], + icon: "/assets/tree.svg", + }, + { + id: "matta-incident-command", + label: "Incident Command", + level: 3, + description: "Coordinates cross-team communication and tactical incident decisions.", + stage: "Leadership", + requires: "Playbook Design", + icon: "/assets/sun.svg", + }, + ], + }, + { + id: "tincho", + name: "Martin Abbatemarco", + alias: "tincho", + title: "Ethereum Security Researcher", + level: 5, + className: "Founder", + githubUsername: "tinchoabbate", + avatar: "https://github.com/tinchoabbate.png?size=256", + socials: { + github: "https://github.com/tinchoabbate", + x: "https://x.com/tinchoabbate", + }, + bio: "Original creator of DamnVulnerableDefi and co-creator of the Phishing Dojo.", + highlights: [ + "Designs adversarial simulations", + "Maintains exploit testing harnesses", + "Writes post-incident advisories", + ], + specialties: ["Smart contracts", "Ethereum", "Auditing"], + radar: [ + { label: "SOCIAL", value: 52 }, + { label: "SECURITY", value: 94 }, + { label: "DEVELOPMENT", value: 88 }, + { label: "EDUCATION", value: 66 }, + { label: "OPERATIONS", value: 50 }, + { label: "ART", value: 40 }, + ], + skillTree: [ + { + label: "Core", + nodes: [ + { + label: "Programming Fundamentals", + level: 4, + description: "Solid grounding in software engineering and systems behavior.", + icon: "/assets/temple.svg", + }, + { + label: "Opcode Craft", + level: 4, + description: "Reads and reasons about low-level EVM execution semantics.", + icon: "/assets/lights.svg", + requires: "Programming Fundamentals", + }, + ], + }, + { + label: "Paths", + nodes: [ + { + label: "Reverse Engineering", + level: 4, + description: "Dissects unknown behavior to reconstruct exploitable logic paths.", + icon: "/assets/tree.svg", + requires: "Programming Fundamentals", + }, + { + label: "Protocol Forensics", + level: 4, + description: "Analyzes incidents post-mortem to isolate root causes and impact.", + icon: "/assets/lettersn.svg", + requires: "Opcode Craft", + }, + ], + }, + { + label: "Mastery", + nodes: [ + { + label: "EVM Edge Cases", + level: 4, + description: "Finds edge-condition bugs and undefined execution assumptions.", + icon: "/assets/sun.svg", + requires: "Reverse Engineering", + }, + { + label: "Disclosure Strategy", + level: 3, + description: "Packages findings into safe, coordinated and actionable disclosures.", + icon: "/assets/flower.svg", + requires: "Protocol Forensics", + }, + ], + }, + ], + careerPath: [ + { + id: "tincho-programming-fundamentals", + label: "Programming Fundamentals", + level: 4, + description: "Deep software engineering baseline for low-level system analysis.", + stage: "Foundation", + icon: "/assets/temple.svg", + }, + { + id: "tincho-solidity-internals", + label: "Solidity Internals", + level: 4, + description: "Understands compiler output and contract behavior across toolchains.", + stage: "Foundation", + requires: "Programming Fundamentals", + icon: "/assets/lights.svg", + }, + { + id: "tincho-reverse-engineering", + label: "Reverse Engineering", + level: 4, + description: "Reconstructs behavior from bytecode and artifacts under adversarial conditions.", + stage: "Research", + requires: "Programming Fundamentals", + icon: "/assets/tree.svg", + }, + { + id: "tincho-protocol-forensics", + label: "Protocol Forensics", + level: 4, + description: "Builds root-cause narratives from exploit traces and protocol internals.", + stage: "Research", + requires: ["Solidity Internals", "Reverse Engineering"], + icon: "/assets/lettersn.svg", + }, + { + id: "tincho-evm-edge-cases", + label: "EVM Edge Cases", + level: 4, + description: "Discovers brittle assumptions in unusual execution and state transitions.", + stage: "Mastery", + requires: "Protocol Forensics", + icon: "/assets/sun.svg", + }, + { + id: "tincho-disclosure-strategy", + label: "Disclosure Strategy", + level: 3, + description: "Shapes findings into coordinated, safe and practical public guidance.", + stage: "Mastery", + requires: "Protocol Forensics", + icon: "/assets/flower.svg", + }, + ], + }, + { + id: "dantesito", + name: "Dante Martinez", + alias: "dantesito", + title: "Permanent Intern", + level: 1, + className: "Core contributor", + githubUsername: "d4rm5", + avatar: "https://github.com/d4rm5.png?size=256", + socials: { + github: "https://github.com/d4rm5", + x: "https://x.com/dantesito", + }, + bio: "Builds open-source tooling and research pipelines for safer development. Obsessed with repeatable, transparent security work.", + highlights: [ + "Maintains open-source security kits", + "Builds safe dev environments", + "Creates audit automation routines", + ], + specialties: ["DevSecOps", "Tooling", "Research Ops"], + radar: [ + { label: "SOCIAL", value: 63 }, + { label: "SECURITY", value: 72 }, + { label: "DEVELOPMENT", value: 74 }, + { label: "EDUCATION", value: 58 }, + { label: "OPERATIONS", value: 71 }, + { label: "ART", value: 46 }, + ], + skillTree: [ + { + label: "Core", + nodes: [ + { + label: "Automation Craft", + level: 3, + description: "Builds reliable scripts and task runners for security operations.", + icon: "/assets/lights.svg", + }, + { + label: "Pipeline Design", + level: 3, + description: "Designs CI and analysis pipelines with clear security gates.", + icon: "/assets/tree.svg", + }, + ], + }, + { + label: "Paths", + nodes: [ + { + label: "Tooling Forge", + level: 4, + description: "Ships shared tooling that helps contributors audit faster and safer.", + icon: "/assets/temple.svg", + requires: "Automation Craft", + }, + { + label: "Safe Environments", + level: 3, + description: "Hardens local and cloud environments used for research and testing.", + icon: "/assets/flower.svg", + requires: "Pipeline Design", + }, + ], + }, + { + label: "Mastery", + nodes: [ + { + label: "Open Source Ops", + level: 4, + description: "Maintains community tooling with quality controls and release discipline.", + icon: "/assets/lettersn.svg", + requires: "Tooling Forge", + }, + { + label: "Research Synthesis", + level: 3, + description: "Converts scattered technical signals into practical guild guidance.", + icon: "/assets/sun.svg", + requires: "Safe Environments", + }, + ], + }, + ], + careerPath: [ + { + id: "dante-programming-basics", + label: "Programming Basics", + level: 2, + description: "Core coding fluency for secure automation and reproducible workflows.", + stage: "Foundation", + icon: "/assets/temple.svg", + }, + { + id: "dante-pipeline-design", + label: "Pipeline Design", + level: 3, + description: "Builds CI and analysis pipelines with clear security constraints.", + stage: "Foundation", + requires: "Programming Basics", + icon: "/assets/tree.svg", + }, + { + id: "dante-automation-craft", + label: "Automation Craft", + level: 3, + description: "Turns repetitive security workflows into dependable tooling.", + stage: "Practice", + requires: "Programming Basics", + icon: "/assets/lights.svg", + }, + { + id: "dante-safe-environments", + label: "Safe Environments", + level: 3, + description: "Hardens local and cloud environments for safer testing and research.", + stage: "Practice", + requires: "Pipeline Design", + icon: "/assets/flower.svg", + }, + { + id: "dante-tooling-forge", + label: "Tooling Forge", + level: 4, + description: "Ships internal and public tooling that speeds up security operations.", + stage: "Delivery", + requires: ["Automation Craft", "Safe Environments"], + icon: "/assets/temple.svg", + }, + { + id: "dante-research-synthesis", + label: "Research Synthesis", + level: 3, + description: "Converts fragmented technical findings into usable team guidance.", + stage: "Delivery", + requires: "Tooling Forge", + icon: "/assets/sun.svg", + }, + ], + }, + { + id: "manut0r", + name: "Manuel Marquez", + alias: "Manut0r", + title: "Lead Developer", + level: 1, + className: "Lead", + githubUsername: "marquezmanu", + avatar: "https://github.com/marquezmanu.png?size=256", + socials: { + github: "https://github.com/marquezmanu", + x: "https://x.com/manut0r", + linkedin: "https://www.linkedin.com/in/manut0r", + website: "https://manut0r.dev", + }, + bio: "Lead developer for the Phishing Dojo. Focused on software development and front-end execution with strong UI/UX interface design for security education products.", + highlights: [ + "Leads Phishing Dojo feature implementation", + "Builds maintainable front-end architecture", + "Owns UI/UX quality and interaction polish", + ], + specialties: ["Software Development", "Front-end Engineering", "UI/UX Interfaces", "Product Delivery"], + radar: [ + { label: "SOCIAL", value: 62 }, + { label: "SECURITY", value: 52 }, + { label: "DEVELOPMENT", value: 84 }, + { label: "EDUCATION", value: 60 }, + { label: "OPERATIONS", value: 78 }, + { label: "ART", value: 86 }, + ], + skillTree: [ + { + label: "Core", + nodes: [ + { + label: "Software Development", + level: 4, + description: "Builds production-ready features with clean architecture and shipping discipline.", + icon: "/assets/temple.svg", + }, + { + label: "Front-end Engineering", + level: 4, + description: "Delivers scalable client-side systems and component libraries.", + icon: "/assets/tree.svg", + requires: "Software Development", + }, + ], + }, + { + label: "Paths", + nodes: [ + { + label: "UI Systems", + level: 4, + description: "Designs coherent visual systems for product consistency and speed.", + icon: "/assets/lights.svg", + requires: "Front-end Engineering", + }, + { + label: "UX Flow Design", + level: 4, + description: "Refines user journeys to reduce friction and improve comprehension.", + icon: "/assets/flower.svg", + requires: "Front-end Engineering", + }, + ], + }, + { + label: "Mastery", + nodes: [ + { + label: "Interaction Craft", + level: 4, + description: "Builds intuitive interactions and responsive feedback loops.", + icon: "/assets/lettersn.svg", + requires: "UI Systems", + }, + { + label: "Phishing Dojo Delivery", + level: 4, + description: "Owns implementation quality of the Dojo learning experience.", + icon: "/assets/sun.svg", + requires: "UX Flow Design", + }, + ], + }, + ], + careerPath: [ + { + id: "manut0r-programming-basics", + label: "Programming Basics", + level: 3, + description: "Technical baseline for scalable software and interface systems.", + stage: "Foundation", + icon: "/assets/temple.svg", + }, + { + id: "manut0r-software-development", + label: "Software Development", + level: 4, + description: "Builds robust features and maintainable application architecture.", + stage: "Foundation", + requires: "Programming Basics", + icon: "/assets/tree.svg", + }, + { + id: "manut0r-frontend-engineering", + label: "Front-end Engineering", + level: 4, + description: "Turns product requirements into reliable and reusable web interfaces.", + stage: "Practice", + requires: "Software Development", + icon: "/assets/lights.svg", + }, + { + id: "manut0r-ui-systems", + label: "UI Systems", + level: 4, + description: "Creates cohesive visual systems and component patterns.", + stage: "Practice", + requires: "Front-end Engineering", + icon: "/assets/lettersn.svg", + }, + { + id: "manut0r-ux-interfaces", + label: "UX Interfaces", + level: 4, + description: "Designs intuitive interface behavior and user task flows.", + stage: "Leadership", + requires: ["Front-end Engineering", "UI Systems"], + icon: "/assets/flower.svg", + }, + { + id: "manut0r-phishing-dojo-lead", + label: "Phishing Dojo Lead", + level: 4, + description: "Leads front-end and experience delivery for the Phishing Dojo platform.", + stage: "Leadership", + requires: "UX Interfaces", + icon: "/assets/sun.svg", + }, + ], + }, +]; diff --git a/src/app/globals.css b/src/app/globals.css index dcdd3d7..0831f0a 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -748,6 +748,13 @@ body::-webkit-scrollbar { font-size: 0.875rem; } +.font-manrope-body { + font-family: var(--font-manrope), 'Spartan', sans-serif; + font-weight: 500; + line-height: 1.4; + letter-spacing: 0.01em; +} + /* Pixelify Sans class for active characters */ .font-pixelify-sans { font-family: var(--font-pixelify-sans); diff --git a/src/app/initiatives/page.tsx b/src/app/initiatives/page.tsx index 0a5da9c..d6a0028 100644 --- a/src/app/initiatives/page.tsx +++ b/src/app/initiatives/page.tsx @@ -12,13 +12,45 @@ export default function InitiativesPage() { console.log('Explorar clickeado:', title); }; + const totalInitiatives = Object.keys(cardContent).length; + return (

    -

    Initiatives

    +
    +
    +
    +

    + About the Guild +

    +

    Initiatives

    +

    + Our initiatives turn security knowledge into practical impact: training, tooling, + research, and public resources that anyone can use to harden crypto systems. +

    + +
    +
    +

    What is active now

    +

    + {totalInitiatives} active lines of work, from adversarial training grounds to + open-source safety tooling and long-form technical advisories. +

    +
    +
    +

    How to engage

    +

    + Pick an initiative below to access challenges, documentation, event archives, or + code repositories and join the work where it is happening. +

    +
    +
    +
    +
    +
    {Object.entries(cardContent).map(([key, content]) => (
    handleExplore(content.title)} />
    @@ -38,4 +71,4 @@ export default function InitiativesPage() {
    ); -} \ No newline at end of file +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 3c077ff..aa5071b 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,5 +1,5 @@ import type { Metadata } from "next"; -import { Inter, Pixelify_Sans } from "next/font/google"; +import { Inter, Pixelify_Sans, Manrope } from "next/font/google"; import "./globals.css"; const inter = Inter({ @@ -14,6 +14,12 @@ const pixelifySans = Pixelify_Sans({ variable: "--font-pixelify-sans", }); +const manrope = Manrope({ + subsets: ["latin"], + weight: ["400", "500", "600", "700"], + variable: "--font-manrope", +}); + const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || "http://localhost:3000"; const ogImage = "https://opengraph.b-cdn.net/production/images/e40efc77-0740-4c48-b3f8-f8cc5c1d5720.png?token=I0ecXikVP-poYNtEyFMuJyPRCVQ6JdgFd7tHAt_3iJk&height=730&width=1200&expires=33286790432"; @@ -56,11 +62,11 @@ export default function RootLayout({ {children} ); -} \ No newline at end of file +} diff --git a/src/app/members/page.tsx b/src/app/members/page.tsx new file mode 100644 index 0000000..a3302ef --- /dev/null +++ b/src/app/members/page.tsx @@ -0,0 +1,61 @@ +'use client'; + +import React, { useMemo, useState } from "react"; + +import Navbar from "../components/Navbar"; +import BackgroundClouds from "../components/BackgroundClouds"; +import ParticlesDOM from "../components/ParticlesDOM"; +import MemberCard from "../components/MemberCard"; +import MemberPreviewCard from "../components/MemberPreviewCard"; +import { members } from "../data/membersConfig"; + +export default function MembersPage() { + const [selectedMemberId, setSelectedMemberId] = useState(members[0]?.id || ""); + + const selectedMember = useMemo( + () => members.find((member) => member.id === selectedMemberId) || members[0], + [selectedMemberId] + ); + + return ( +
    + + + +
    +
    +

    + The Red Guild Roster +

    +

    + Members +

    +

    + Contributors presented as playable profiles: a mix of ethos, skills, + and tactical focus. Please, don't take this too seriously. +

    +

    + Select a member card to open the full profile. +

    +
    + +
    + {members.map((member) => ( + setSelectedMemberId(member.id)} + /> + ))} +
    + + {selectedMember && ( +
    + +
    + )} +
    +
    + ); +} From 621dfb7ec953bc296c40f4313a0d6b20fc7906f7 Mon Sep 17 00:00:00 2001 From: matta Date: Fri, 20 Feb 2026 04:02:33 +0000 Subject: [PATCH 7/9] Updated data, and fixed a clicking error on cards --- src/app/components/MemberCard.tsx | 8 +- src/app/components/MemberPreviewCard.tsx | 14 +- src/app/components/RadarChart.tsx | 16 +- src/app/components/SkillTree.tsx | 2 +- src/app/data/membersConfig.ts | 499 ++++++++++++----------- 5 files changed, 305 insertions(+), 234 deletions(-) diff --git a/src/app/components/MemberCard.tsx b/src/app/components/MemberCard.tsx index 66b45dd..543d109 100644 --- a/src/app/components/MemberCard.tsx +++ b/src/app/components/MemberCard.tsx @@ -116,11 +116,13 @@ const MemberCard: React.FC = ({ member }) => {
    -
    +
    {member.radar.map((stat) => (
    - {stat.label} - {stat.value} + {stat.label} + + {stat.value} +
    ))}
    diff --git a/src/app/components/MemberPreviewCard.tsx b/src/app/components/MemberPreviewCard.tsx index ee356d1..33c6b42 100644 --- a/src/app/components/MemberPreviewCard.tsx +++ b/src/app/components/MemberPreviewCard.tsx @@ -52,6 +52,15 @@ const MemberPreviewCard: React.FC = ({ return (
    { + if (event.key === "Enter" || event.key === " ") { + event.preventDefault(); + onSelect(); + } + }} className={`relative w-full max-w-[320px] overflow-hidden rounded-2xl border p-2.5 text-left transition-all ${ isActive ? "border-[#f7392f]/70 bg-[#1a1111]/92 shadow-[0_0_24px_rgba(247,57,47,0.22)]" @@ -59,7 +68,7 @@ const MemberPreviewCard: React.FC = ({ }`} >
    - +
    {socials.map((social) => @@ -111,6 +120,7 @@ const MemberPreviewCard: React.FC = ({ href={social.href} target="_blank" rel="noopener noreferrer" + onClick={(event) => event.stopPropagation()} className="inline-flex items-center rounded-md border border-white/14 bg-white/5 px-1.5 py-0.5 text-[9px] uppercase tracking-[0.12em] font-pixelify-sans text-white/75 transition-colors hover:text-[color:var(--color-primary)] hover:border-[color:var(--color-primary)]/40" > {social.label} diff --git a/src/app/components/RadarChart.tsx b/src/app/components/RadarChart.tsx index d9b93bb..d05a003 100644 --- a/src/app/components/RadarChart.tsx +++ b/src/app/components/RadarChart.tsx @@ -8,6 +8,20 @@ interface RadarChartProps { showLabels?: boolean; } +const RADAR_LABEL_ABBREVIATIONS: Record = { + SOCIAL: "SOC", + EDUCATION: "EDU", + ART: "ART", + DEVELOPMENT: "DEV", + OPERATIONS: "OPS", + SECURITY: "SEC", +}; + +const toRadarLabel = (label: string): string => { + const normalized = label.trim().toUpperCase(); + return RADAR_LABEL_ABBREVIATIONS[normalized] || normalized.slice(0, 3); +}; + const RadarChart: React.FC = ({ stats, size = 220, showLabels = true }) => { if (!stats.length) { return null; @@ -125,7 +139,7 @@ const RadarChart: React.FC = ({ stats, size = 220, showLabels = fontFamily="Spartan, sans-serif" letterSpacing="0.08em" > - {stat.label.toUpperCase()} + {toRadarLabel(stat.label)} ); })} diff --git a/src/app/components/SkillTree.tsx b/src/app/components/SkillTree.tsx index 23bffab..9fc3cb1 100644 --- a/src/app/components/SkillTree.tsx +++ b/src/app/components/SkillTree.tsx @@ -193,7 +193,7 @@ const SkillTree: React.FC = ({ tiers, careerPath }) => { {activeDependencies.map((dependency) => ( {dependency.label} diff --git a/src/app/data/membersConfig.ts b/src/app/data/membersConfig.ts index 5688030..ee8531d 100644 --- a/src/app/data/membersConfig.ts +++ b/src/app/data/membersConfig.ts @@ -65,35 +65,44 @@ export const members: MemberProfile[] = [ github: "https://github.com/mattaereal", x: "https://x.com/mattaereal", }, - bio: "LatAm-first security educator coordinating threat intel and frontline awareness. Builds playbooks and turns incidents into learnable quests.", + bio: "Systems engineer and former developer with deep security background in reverse engineering, red teaming, pentesting, and peer review. Leads strategy, operations, and partnerships while staying obsessive about Linux hardening and OPSEC.", highlights: [ - "Leads public phishing response drills", - "Maintains guild threat intel feeds", - "Runs security workshops across LATAM", + "Leads business, operations, and multi-team security direction", + "Runs deep technical reviews from exploit paths to architecture flaws", + "Designs strict OPSEC setups and Linux-first security workflows", + ], + specialties: [ + "Security Leadership", + "Reverse Engineering", + "Red Teaming & Pentesting", + "Peer Review", + "Linux & Sysadmin", + "OPSEC", + "EVM Bytecode", + "Artist Producer", ], - specialties: ["Gamified Education", "Stage Presence", "Barefoot Walker", "Paranoid", "SEAL: Initiative Lead", "SEAL: Technical Council", "Producer"], radar: [ - { label: "SOCIAL", value: 84 }, - { label: "SECURITY", value: 72 }, - { label: "DEVELOPMENT", value: 60 }, - { label: "EDUCATION", value: 92 }, - { label: "OPERATIONS", value: 78 }, - { label: "ART", value: 70 }, + { label: "SOCIAL", value: 94 }, + { label: "SECURITY", value: 98 }, + { label: "DEVELOPMENT", value: 72 }, + { label: "EDUCATION", value: 81 }, + { label: "OPERATIONS", value: 97 }, + { label: "ART", value: 84 }, ], skillTree: [ { label: "Core", nodes: [ { - label: "Threat Modeling", - level: 4, - description: "Maps likely attacker behavior and prioritizes defensive controls.", + label: "Security Foundations", + level: 5, + description: "Applies attacker mindset and defensive depth across systems and teams.", icon: "/assets/lights.svg", }, { - label: "Community Signals", - level: 3, - description: "Reads social and onchain indicators to detect active scam waves.", + label: "Linux & Sysadmin Ops", + level: 5, + description: "Builds resilient systems using hardening-first operational practices.", icon: "/assets/lettersn.svg", }, ], @@ -102,18 +111,18 @@ export const members: MemberProfile[] = [ label: "Paths", nodes: [ { - label: "Playbook Design", - level: 3, - description: "Turns incidents into reusable responder guides for distributed teams.", + label: "Reverse Engineering", + level: 5, + description: "Dissects unknown behavior and reconstructs root exploit mechanics.", icon: "/assets/tree.svg", - requires: "Threat Modeling", + requires: "Security Foundations", }, { - label: "Phishing Triage", - level: 2, - description: "Classifies malicious campaigns and routes evidence quickly.", + label: "Red Teaming & Pentesting", + level: 5, + description: "Validates security posture through offensive assessments and simulation.", icon: "/assets/flower.svg", - requires: "Community Signals", + requires: "Linux & Sysadmin Ops", }, ], }, @@ -121,74 +130,82 @@ export const members: MemberProfile[] = [ label: "Mastery", nodes: [ { - label: "Public Awareness", - level: 4, - description: "Designs outreach that helps users avoid real-world social engineering.", + label: "EVM Bytecode Analysis", + level: 5, + description: "Works at low-level execution detail to analyze contract behavior deeply.", icon: "/assets/sun.svg", - requires: "Playbook Design", + requires: "Reverse Engineering", }, { - label: "Incident Command", - level: 3, - description: "Coordinates multi-team response and communication during incidents.", + label: "Security Leadership", + level: 5, + description: "Bridges technical depth with execution, management, and business goals.", icon: "/assets/temple.svg", - requires: "Phishing Triage", + requires: "Red Teaming & Pentesting", }, ], }, ], careerPath: [ { - id: "matta-programming-basics", - label: "Programming Basics", - level: 2, - description: "Technical baseline needed to evaluate attack vectors and tooling behavior.", + id: "matta-linux-ops", + label: "Arch Linux BTW", + level: 4, + description: "Applies sysadmin discipline and hardening practices across environments.", stage: "Foundation", - icon: "/assets/temple.svg", + icon: "/assets/lights.svg", }, { - id: "matta-threat-modeling", - label: "Threat Modeling", + id: "matta-opsec", + label: "OpSec", level: 4, - description: "Prioritizes attacker paths and defensive controls for community-facing systems.", + description: "Builds and maintains strict personal and organizational operational security.", stage: "Foundation", - requires: "Programming Basics", - icon: "/assets/lights.svg", + requires: "Arch Linux BTW", + icon: "/assets/temple.svg", }, { - id: "matta-signal-analysis", - label: "Signal Analysis", - level: 3, - description: "Interprets social and onchain signals to identify likely phishing campaigns.", + id: "matta-reverse-engineering", + label: "Reverse Engineering", + level: 3.5, + description: "Investigates internals, flaws, and exploit chains under real constraints.", stage: "Practice", - requires: "Threat Modeling", + requires: "Arch Linux BTW", icon: "/assets/lettersn.svg", }, { - id: "matta-phishing-triage", - label: "Phishing Triage", - level: 2, - description: "Validates reports and routes actionable evidence to the right responders.", + id: "matta-social-engineering", + label: "Social Engineering", + level: 5, + description: "Understands manipulation patterns and designs defenses against human-layer attacks.", stage: "Practice", - requires: "Signal Analysis", + requires: "OpSec", + icon: "/assets/flower.svg", + }, + { + id: "matta-redteam-pentest", + label: "Red Teaming", + level: 5, + description: "Stress-tests organizations through adversarial simulation and review.", + stage: "Mastery", + requires: ["Reverse Engineering", "Social Engineering"], icon: "/assets/flower.svg", }, { - id: "matta-playbook-design", - label: "Playbook Design", + id: "matta-singing", + label: "Singing", level: 3, - description: "Converts incidents into repeatable response drills and guidance.", - stage: "Leadership", - requires: ["Threat Modeling", "Phishing Triage"], + description: "Performs vocally and channels artistic expression into team culture.", + stage: "Identity", icon: "/assets/tree.svg", }, { - id: "matta-incident-command", - label: "Incident Command", - level: 3, - description: "Coordinates cross-team communication and tactical incident decisions.", + id: "matta-security-leadership", + label: "Leadership", + level: 4, + description: "Aligns people, operations, and technical direction across the organization.", stage: "Leadership", - requires: "Playbook Design", + requires: ["Red Teaming", "OpSec"], icon: "/assets/sun.svg", }, ], @@ -206,37 +223,44 @@ export const members: MemberProfile[] = [ github: "https://github.com/tinchoabbate", x: "https://x.com/tinchoabbate", }, - bio: "Original creator of DamnVulnerableDefi and co-creator of the Phishing Dojo.", + bio: "Systems engineer focused on Web3 internals: gas economics, EVM behavior, Solidity risk patterns, and Ethereum security research. Introverted profile with high technical precision and strong musical artistry.", highlights: [ - "Designs adversarial simulations", - "Maintains exploit testing harnesses", - "Writes post-incident advisories", + "Deep-dives EVM and gas behavior under adversarial scenarios", + "Leads Solidity-focused review and exploit simulation work", + "Brings exceptional musicianship and creative discipline", + ], + specialties: [ + "Solidity (5/5)", + "Ethereum Internals", + "Gas & EVM Analysis", + "Smart Contract Auditing", + "Security Research", + "Music Artist", ], - specialties: ["Smart contracts", "Ethereum", "Auditing"], radar: [ - { label: "SOCIAL", value: 52 }, - { label: "SECURITY", value: 94 }, - { label: "DEVELOPMENT", value: 88 }, - { label: "EDUCATION", value: 66 }, - { label: "OPERATIONS", value: 50 }, - { label: "ART", value: 40 }, + { label: "SOCIAL", value: 59 }, + { label: "SECURITY", value: 95 }, + { label: "DEVELOPMENT", value: 79 }, + { label: "EDUCATION", value: 81 }, + { label: "OPERATIONS", value: 64 }, + { label: "ART", value: 92 }, ], skillTree: [ { label: "Core", nodes: [ { - label: "Programming Fundamentals", - level: 4, - description: "Solid grounding in software engineering and systems behavior.", + label: "Ethereum Internals", + level: 5, + description: "Understands account model, execution context, and protocol mechanics.", icon: "/assets/temple.svg", }, { - label: "Opcode Craft", - level: 4, - description: "Reads and reasons about low-level EVM execution semantics.", + label: "Solidity Security", + level: 5, + description: "Reviews contract design and implementation with exploit-aware mindset.", icon: "/assets/lights.svg", - requires: "Programming Fundamentals", + requires: "Ethereum Internals", }, ], }, @@ -244,18 +268,18 @@ export const members: MemberProfile[] = [ label: "Paths", nodes: [ { - label: "Reverse Engineering", - level: 4, - description: "Dissects unknown behavior to reconstruct exploitable logic paths.", + label: "Gas & EVM Trace Analysis", + level: 5, + description: "Analyzes costs, traces, and execution flows at opcode-level depth.", icon: "/assets/tree.svg", - requires: "Programming Fundamentals", + requires: "Ethereum Internals", }, { - label: "Protocol Forensics", + label: "Smart Contract Peer Review", level: 4, - description: "Analyzes incidents post-mortem to isolate root causes and impact.", + description: "Performs rigorous review cycles and communicates actionable fixes.", icon: "/assets/lettersn.svg", - requires: "Opcode Craft", + requires: "Solidity Security", }, ], }, @@ -263,18 +287,18 @@ export const members: MemberProfile[] = [ label: "Mastery", nodes: [ { - label: "EVM Edge Cases", + label: "On-chain Incident Forensics", level: 4, - description: "Finds edge-condition bugs and undefined execution assumptions.", + description: "Reconstructs exploit narratives from traces, state changes, and context.", icon: "/assets/sun.svg", - requires: "Reverse Engineering", + requires: "Gas & EVM Trace Analysis", }, { label: "Disclosure Strategy", - level: 3, - description: "Packages findings into safe, coordinated and actionable disclosures.", + level: 4, + description: "Translates deep findings into safe, practical advisory guidance.", icon: "/assets/flower.svg", - requires: "Protocol Forensics", + requires: "Smart Contract Peer Review", }, ], }, @@ -282,56 +306,64 @@ export const members: MemberProfile[] = [ careerPath: [ { id: "tincho-programming-fundamentals", - label: "Programming Fundamentals", + label: "Coding Basics", level: 4, - description: "Deep software engineering baseline for low-level system analysis.", + description: "Systems-engineering base used for tooling and protocol-level analysis.", stage: "Foundation", icon: "/assets/temple.svg", }, { - id: "tincho-solidity-internals", - label: "Solidity Internals", + id: "tincho-ethereum-internals", + label: "Ethereum Core", level: 4, - description: "Understands compiler output and contract behavior across toolchains.", + description: "Strong understanding of EVM execution and chain-level behavior.", stage: "Foundation", - requires: "Programming Fundamentals", + requires: "Coding Basics", icon: "/assets/lights.svg", }, { - id: "tincho-reverse-engineering", - label: "Reverse Engineering", - level: 4, - description: "Reconstructs behavior from bytecode and artifacts under adversarial conditions.", - stage: "Research", - requires: "Programming Fundamentals", + id: "tincho-opsec", + label: "OpSec", + level: 3, + description: "Maintains practical personal and operational security hygiene.", + stage: "Foundation", + requires: "Coding Basics", + icon: "/assets/temple.svg", + }, + { + id: "tincho-solidity-security", + label: "Solidity Security", + level: 5, + description: "Top-tier smart contract review and exploit pattern recognition.", + stage: "Practice", + requires: "Ethereum Core", icon: "/assets/tree.svg", }, { - id: "tincho-protocol-forensics", - label: "Protocol Forensics", - level: 4, - description: "Builds root-cause narratives from exploit traces and protocol internals.", - stage: "Research", - requires: ["Solidity Internals", "Reverse Engineering"], + id: "tincho-code-review", + label: "Code Review", + level: 5, + description: "Performs deep technical review and delivers actionable remediation guidance.", + stage: "Mastery", + requires: ["Ethereum Core", "Solidity Security"], icon: "/assets/lettersn.svg", }, { - id: "tincho-evm-edge-cases", - label: "EVM Edge Cases", + id: "tincho-musical-artistry", + label: "Music Producer", level: 4, - description: "Discovers brittle assumptions in unusual execution and state transitions.", - stage: "Mastery", - requires: "Protocol Forensics", - icon: "/assets/sun.svg", + description: "Strong music production craft that complements his technical identity.", + stage: "Identity", + icon: "/assets/flower.svg", }, { - id: "tincho-disclosure-strategy", - label: "Disclosure Strategy", - level: 3, - description: "Shapes findings into coordinated, safe and practical public guidance.", - stage: "Mastery", - requires: "Protocol Forensics", - icon: "/assets/flower.svg", + id: "tincho-gamification", + label: "Gamification", + level: 5, + description: "Designs high-impact, challenge-based learning experiences for security.", + stage: "Leadership", + requires: ["Code Review", "OpSec"], + icon: "/assets/tree.svg", }, ], }, @@ -340,43 +372,49 @@ export const members: MemberProfile[] = [ name: "Dante Martinez", alias: "dantesito", title: "Permanent Intern", - level: 1, - className: "Core contributor", + level: 2, + className: "Core Contributor", githubUsername: "d4rm5", avatar: "https://github.com/d4rm5.png?size=256", socials: { github: "https://github.com/d4rm5", x: "https://x.com/dantesito", }, - bio: "Builds open-source tooling and research pipelines for safer development. Obsessed with repeatable, transparent security work.", + bio: "Youngest member of the team and currently studying systems engineering. Building base capability across front-end, back-end, and security while contributing where needed.", highlights: [ - "Maintains open-source security kits", - "Builds safe dev environments", - "Creates audit automation routines", + "Growing in front-end, back-end, and security fundamentals", + "Supports implementation tasks across product and research", + "Focused on learning speed and consistency", + ], + specialties: [ + "Systems Engineering Student", + "Front-end Basics", + "Back-end Basics", + "Security Basics", + "Team Support", ], - specialties: ["DevSecOps", "Tooling", "Research Ops"], radar: [ - { label: "SOCIAL", value: 63 }, - { label: "SECURITY", value: 72 }, - { label: "DEVELOPMENT", value: 74 }, - { label: "EDUCATION", value: 58 }, - { label: "OPERATIONS", value: 71 }, - { label: "ART", value: 46 }, + { label: "SOCIAL", value: 70 }, + { label: "SECURITY", value: 49 }, + { label: "DEVELOPMENT", value: 58 }, + { label: "EDUCATION", value: 55 }, + { label: "OPERATIONS", value: 52 }, + { label: "ART", value: 22 }, ], skillTree: [ { label: "Core", nodes: [ { - label: "Automation Craft", - level: 3, - description: "Builds reliable scripts and task runners for security operations.", + label: "Programming Fundamentals", + level: 2, + description: "Core coding foundation for practical engineering growth.", icon: "/assets/lights.svg", }, { - label: "Pipeline Design", - level: 3, - description: "Designs CI and analysis pipelines with clear security gates.", + label: "Systems Fundamentals", + level: 2, + description: "Builds understanding of system behavior, components, and constraints.", icon: "/assets/tree.svg", }, ], @@ -385,18 +423,18 @@ export const members: MemberProfile[] = [ label: "Paths", nodes: [ { - label: "Tooling Forge", - level: 4, - description: "Ships shared tooling that helps contributors audit faster and safer.", + label: "Front-end Basics", + level: 2, + description: "Implements core UI components and simple interface behaviors.", icon: "/assets/temple.svg", - requires: "Automation Craft", + requires: "Programming Fundamentals", }, { - label: "Safe Environments", - level: 3, - description: "Hardens local and cloud environments used for research and testing.", + label: "Back-end Basics", + level: 2, + description: "Builds simple APIs and handles data flow with supervision.", icon: "/assets/flower.svg", - requires: "Pipeline Design", + requires: "Programming Fundamentals", }, ], }, @@ -404,18 +442,18 @@ export const members: MemberProfile[] = [ label: "Mastery", nodes: [ { - label: "Open Source Ops", - level: 4, - description: "Maintains community tooling with quality controls and release discipline.", + label: "Security Basics", + level: 2, + description: "Applies entry-level secure development and hygiene practices.", icon: "/assets/lettersn.svg", - requires: "Tooling Forge", + requires: "Back-end Basics", }, { - label: "Research Synthesis", + label: "Execution Consistency", level: 3, - description: "Converts scattered technical signals into practical guild guidance.", + description: "Delivers reliable outcomes while learning across disciplines.", icon: "/assets/sun.svg", - requires: "Safe Environments", + requires: "Front-end Basics", }, ], }, @@ -423,55 +461,55 @@ export const members: MemberProfile[] = [ careerPath: [ { id: "dante-programming-basics", - label: "Programming Basics", + label: "Coding Basics", level: 2, - description: "Core coding fluency for secure automation and reproducible workflows.", + description: "Foundational coding ability for real project contribution.", stage: "Foundation", icon: "/assets/temple.svg", }, { - id: "dante-pipeline-design", - label: "Pipeline Design", - level: 3, - description: "Builds CI and analysis pipelines with clear security constraints.", + id: "dante-systems-fundamentals", + label: "Systems Basics", + level: 2, + description: "Develops systems-engineering fundamentals across stack layers.", stage: "Foundation", - requires: "Programming Basics", + requires: "Coding Basics", icon: "/assets/tree.svg", }, { - id: "dante-automation-craft", - label: "Automation Craft", - level: 3, - description: "Turns repetitive security workflows into dependable tooling.", + id: "dante-frontend-basics", + label: "Front-end Basics", + level: 2, + description: "Builds simple UIs and interactions with growing confidence.", stage: "Practice", - requires: "Programming Basics", + requires: "Coding Basics", icon: "/assets/lights.svg", }, { - id: "dante-safe-environments", - label: "Safe Environments", - level: 3, - description: "Hardens local and cloud environments for safer testing and research.", + id: "dante-backend-basics", + label: "Back-end Basics", + level: 2, + description: "Implements basic server logic and API integration flows.", stage: "Practice", - requires: "Pipeline Design", + requires: "Coding Basics", icon: "/assets/flower.svg", }, { - id: "dante-tooling-forge", - label: "Tooling Forge", - level: 4, - description: "Ships internal and public tooling that speeds up security operations.", + id: "dante-security-basics", + label: "Security Basics", + level: 2, + description: "Learns defensive practices and secure engineering fundamentals.", stage: "Delivery", - requires: ["Automation Craft", "Safe Environments"], + requires: ["Front-end Basics", "Back-end Basics"], icon: "/assets/temple.svg", }, { - id: "dante-research-synthesis", - label: "Research Synthesis", + id: "dante-team-contribution", + label: "Teamwork", level: 3, - description: "Converts fragmented technical findings into usable team guidance.", + description: "Contributes consistently while growing toward deeper specialization.", stage: "Delivery", - requires: "Tooling Forge", + requires: "Security Basics", icon: "/assets/sun.svg", }, ], @@ -481,8 +519,8 @@ export const members: MemberProfile[] = [ name: "Manuel Marquez", alias: "Manut0r", title: "Lead Developer", - level: 1, - className: "Lead", + level: 4, + className: "Lead Developer", githubUsername: "marquezmanu", avatar: "https://github.com/marquezmanu.png?size=256", socials: { @@ -491,20 +529,27 @@ export const members: MemberProfile[] = [ linkedin: "https://www.linkedin.com/in/manut0r", website: "https://manut0r.dev", }, - bio: "Lead developer for the Phishing Dojo. Focused on software development and front-end execution with strong UI/UX interface design for security education products.", + bio: "Developer with 14 years of experience, specialized in front-end engineering, UI systems, and product execution. Strong social collaborator and currently leveling up security understanding.", highlights: [ - "Leads Phishing Dojo feature implementation", - "Builds maintainable front-end architecture", - "Owns UI/UX quality and interaction polish", + "Owns front-end architecture and interface delivery quality", + "Builds scalable UI systems and smooth product flows", + "Actively learning security concepts for safer product decisions", + ], + specialties: [ + "Front-end Engineering", + "UI Architecture", + "UX Flows", + "Product Delivery", + "Team Collaboration", + "Security Learner", ], - specialties: ["Software Development", "Front-end Engineering", "UI/UX Interfaces", "Product Delivery"], radar: [ - { label: "SOCIAL", value: 62 }, - { label: "SECURITY", value: 52 }, - { label: "DEVELOPMENT", value: 84 }, - { label: "EDUCATION", value: 60 }, - { label: "OPERATIONS", value: 78 }, - { label: "ART", value: 86 }, + { label: "SOCIAL", value: 86 }, + { label: "SECURITY", value: 38 }, + { label: "DEVELOPMENT", value: 95 }, + { label: "EDUCATION", value: 67 }, + { label: "OPERATIONS", value: 80 }, + { label: "ART", value: 26 }, ], skillTree: [ { @@ -512,14 +557,14 @@ export const members: MemberProfile[] = [ nodes: [ { label: "Software Development", - level: 4, - description: "Builds production-ready features with clean architecture and shipping discipline.", + level: 5, + description: "Delivers robust application features with production discipline.", icon: "/assets/temple.svg", }, { label: "Front-end Engineering", - level: 4, - description: "Delivers scalable client-side systems and component libraries.", + level: 5, + description: "Builds high-quality web interfaces and maintainable component systems.", icon: "/assets/tree.svg", requires: "Software Development", }, @@ -530,15 +575,15 @@ export const members: MemberProfile[] = [ nodes: [ { label: "UI Systems", - level: 4, - description: "Designs coherent visual systems for product consistency and speed.", + level: 5, + description: "Creates coherent design systems for consistency and delivery speed.", icon: "/assets/lights.svg", requires: "Front-end Engineering", }, { label: "UX Flow Design", level: 4, - description: "Refines user journeys to reduce friction and improve comprehension.", + description: "Optimizes end-to-end user journeys to reduce friction.", icon: "/assets/flower.svg", requires: "Front-end Engineering", }, @@ -555,9 +600,9 @@ export const members: MemberProfile[] = [ requires: "UI Systems", }, { - label: "Phishing Dojo Delivery", - level: 4, - description: "Owns implementation quality of the Dojo learning experience.", + label: "Product Delivery", + level: 5, + description: "Executes interface quality from concept to production release.", icon: "/assets/sun.svg", requires: "UX Flow Design", }, @@ -567,55 +612,55 @@ export const members: MemberProfile[] = [ careerPath: [ { id: "manut0r-programming-basics", - label: "Programming Basics", - level: 3, - description: "Technical baseline for scalable software and interface systems.", + label: "Coding Basics", + level: 5, + description: "Long-term coding experience across real-world product cycles.", stage: "Foundation", icon: "/assets/temple.svg", }, { id: "manut0r-software-development", - label: "Software Development", - level: 4, + label: "Software Dev", + level: 5, description: "Builds robust features and maintainable application architecture.", stage: "Foundation", - requires: "Programming Basics", + requires: "Coding Basics", icon: "/assets/tree.svg", }, { id: "manut0r-frontend-engineering", - label: "Front-end Engineering", - level: 4, + label: "Front-end Dev", + level: 5, description: "Turns product requirements into reliable and reusable web interfaces.", stage: "Practice", - requires: "Software Development", + requires: "Software Dev", icon: "/assets/lights.svg", }, { id: "manut0r-ui-systems", label: "UI Systems", - level: 4, + level: 5, description: "Creates cohesive visual systems and component patterns.", stage: "Practice", - requires: "Front-end Engineering", + requires: "Front-end Dev", icon: "/assets/lettersn.svg", }, { id: "manut0r-ux-interfaces", - label: "UX Interfaces", + label: "UX Flows", level: 4, description: "Designs intuitive interface behavior and user task flows.", - stage: "Leadership", - requires: ["Front-end Engineering", "UI Systems"], + stage: "Mastery", + requires: "Front-end Dev", icon: "/assets/flower.svg", }, { - id: "manut0r-phishing-dojo-lead", - label: "Phishing Dojo Lead", - level: 4, - description: "Leads front-end and experience delivery for the Phishing Dojo platform.", + id: "manut0r-product-delivery", + label: "Delivery Lead", + level: 5, + description: "Leads end-to-end interface delivery with product and engineering alignment.", stage: "Leadership", - requires: "UX Interfaces", + requires: ["UI Systems", "UX Flows"], icon: "/assets/sun.svg", }, ], From 04122dcf452a95a6066a203a9aa409e54629f12e Mon Sep 17 00:00:00 2001 From: matta Date: Fri, 20 Feb 2026 04:52:04 +0000 Subject: [PATCH 8/9] Reorg of sections, normalization, and contributors impl --- src/app/components/ContributorMiniCard.tsx | 113 +++++++++ src/app/components/Navbar.tsx | 226 +++++++----------- .../components/SupportersCollaborators.tsx | 39 ++- src/app/contributors/page.tsx | 84 +++++++ src/app/data/cardContent.ts | 18 +- src/app/data/membersConfig.ts | 76 +++++- src/app/ethos/page.tsx | 56 +++++ src/app/initiatives/page.tsx | 55 +++-- src/app/members/page.tsx | 2 +- src/app/supporters/page.tsx | 4 +- 10 files changed, 486 insertions(+), 187 deletions(-) create mode 100644 src/app/components/ContributorMiniCard.tsx create mode 100644 src/app/contributors/page.tsx create mode 100644 src/app/ethos/page.tsx diff --git a/src/app/components/ContributorMiniCard.tsx b/src/app/components/ContributorMiniCard.tsx new file mode 100644 index 0000000..56cabe6 --- /dev/null +++ b/src/app/components/ContributorMiniCard.tsx @@ -0,0 +1,113 @@ +import Image from "next/image"; +import React from "react"; + +import { ContributorProfile } from "../data/membersConfig"; + +interface ContributorMiniCardProps { + contributor: ContributorProfile; +} + +const toSafeExternalUrl = (value?: string): string | null => { + if (!value) { + return null; + } + + try { + const parsed = new URL(value); + if (parsed.protocol === "https:" || parsed.protocol === "http:") { + return parsed.toString(); + } + return null; + } catch { + return null; + } +}; + +const ContributorMiniCard: React.FC = ({ contributor }) => { + const initials = + contributor.alias + .split(" ") + .map((part) => part[0]) + .join("") + .slice(0, 2) + .toUpperCase() || contributor.name.slice(0, 2).toUpperCase(); + + const fallbackGithubAvatar = contributor.githubUsername + ? `https://github.com/${encodeURIComponent(contributor.githubUsername)}.png?size=256` + : undefined; + const avatarUrl = + toSafeExternalUrl(contributor.avatar) || toSafeExternalUrl(fallbackGithubAvatar); + + return ( +
    +
    + +
    +
    +
    +
    + {avatarUrl ? ( + {contributor.name} + ) : ( +
    + {initials} +
    + )} +
    + +
    +

    + {contributor.alias} +

    +

    + {contributor.title} +

    +
    +

    + {contributor.className} +

    + + Lv {contributor.level} + +
    +
    +
    + +
    +

    + Projects +

    +
    + {contributor.projects.slice(0, 3).map((project) => ( +

    + {project} +

    + ))} +
    +
    +
    + +
    +

    + Participation Score +

    +

    + {contributor.participationScore} +

    +
    +
    +
    + ); +}; + +export default ContributorMiniCard; diff --git a/src/app/components/Navbar.tsx b/src/app/components/Navbar.tsx index 372c199..16ed852 100644 --- a/src/app/components/Navbar.tsx +++ b/src/app/components/Navbar.tsx @@ -8,12 +8,11 @@ import React, { useEffect, useRef, useState } from "react"; const Navbar = () => { const pathname = usePathname(); const [isMenuOpen, setIsMenuOpen] = useState(false); - const [isAboutOpen, setIsAboutOpen] = useState(false); - const [isMobileAboutOpen, setIsMobileAboutOpen] = useState(false); - const [isEthosOpen, setIsEthosOpen] = useState(false); - const closeAboutTimeoutRef = useRef | null>(null); + const [isWhoOpen, setIsWhoOpen] = useState(false); + const [isMobileWhoOpen, setIsMobileWhoOpen] = useState(false); + const closeWhoTimeoutRef = useRef | null>(null); - const isAboutActive = pathname === "/members"; + const isWhoActive = pathname === "/members" || pathname === "/contributors"; const toggleMenu = () => { setIsMenuOpen(!isMenuOpen); @@ -21,56 +20,32 @@ const Navbar = () => { const closeMenu = () => { setIsMenuOpen(false); - setIsAboutOpen(false); - setIsMobileAboutOpen(false); + setIsWhoOpen(false); + setIsMobileWhoOpen(false); }; - const clearAboutCloseTimer = () => { - if (closeAboutTimeoutRef.current) { - clearTimeout(closeAboutTimeoutRef.current); - closeAboutTimeoutRef.current = null; + const clearWhoCloseTimer = () => { + if (closeWhoTimeoutRef.current) { + clearTimeout(closeWhoTimeoutRef.current); + closeWhoTimeoutRef.current = null; } }; - const openAboutMenu = () => { - clearAboutCloseTimer(); - setIsAboutOpen(true); + const openWhoMenu = () => { + clearWhoCloseTimer(); + setIsWhoOpen(true); }; - const scheduleAboutClose = () => { - clearAboutCloseTimer(); - closeAboutTimeoutRef.current = setTimeout(() => { - setIsAboutOpen(false); + const scheduleWhoClose = () => { + clearWhoCloseTimer(); + closeWhoTimeoutRef.current = setTimeout(() => { + setIsWhoOpen(false); }, 220); }; - const openEthos = () => { - setIsEthosOpen(true); - setIsAboutOpen(false); - setIsMobileAboutOpen(false); - setIsMenuOpen(false); - }; - - const closeEthos = () => { - setIsEthosOpen(false); - }; - - useEffect(() => { - if (!isEthosOpen) { - return; - } - const handleKeyDown = (event: KeyboardEvent) => { - if (event.key === "Escape") { - setIsEthosOpen(false); - } - }; - window.addEventListener("keydown", handleKeyDown); - return () => window.removeEventListener("keydown", handleKeyDown); - }, [isEthosOpen]); - useEffect(() => { return () => { - clearAboutCloseTimer(); + clearWhoCloseTimer(); }; }, []); @@ -89,7 +64,6 @@ const Navbar = () => {
    - {/* Desktop Menu */}
    • { Supporters
    • +
    • - {isAboutOpen && ( + {isWhoOpen && (
      - setIsAboutOpen(false)} + onClick={() => setIsWhoOpen(false)} className="text-left text-xs text-white/80 transition-all duration-300 hover:text-[color:var(--color-primary)] hover:glitch-effect focus-visible:text-[color:var(--color-primary)] focus-visible:outline-none" > Members + setIsWhoOpen(false)} + className="text-left text-xs text-white/80 transition-all duration-300 hover:text-[color:var(--color-primary)] hover:glitch-effect focus-visible:text-[color:var(--color-primary)] focus-visible:outline-none" + > + Contributors +
      )}
    • + +
    • + + Our Ethos + +
    • +
    • { Blog
    • +
    • {
    - {/* Mobile Hamburger Button */} - {/* Mobile Menu Overlay */} {isMenuOpen && (
    {
  • - {isMobileAboutOpen && ( + {isMobileWhoOpen && (
    - { > Members + + Contributors +
    )}
  • +
  • + + Our Ethos + +
  • {
  • )} - - {isEthosOpen && ( -
    -
    -
    -
    - -
    -

    - About the Guild -

    -

    Our Ethos

    -

    - The Red Guild is a security collective devoted to protecting the open crypto ecosystem. - We move like a guild: research, education, and open-source tooling built in public for the - benefit of the community. -

    -

    - Our work blends adversarial rigor with public-good intent. We investigate threats, teach - defenders, and ship practical tools that raise the baseline for everyone. -

    - -
    -
    -

    What we do

    -
      -
    • Security research, advisories, and investigations
    • -
    • Education programs, workshops, and awareness campaigns
    • -
    • Open-source tooling for safer development
    • -
    -
    -
    -

    How we work

    -
      -
    • Community-first collaboration and open knowledge
    • -
    • Responsible disclosure and transparent reporting
    • -
    • Iterative practice, shared playbooks, repeatable wins
    • -
    -
    -
    -
    -
    -
    - )} ); }; -export default Navbar; +export default Navbar; diff --git a/src/app/components/SupportersCollaborators.tsx b/src/app/components/SupportersCollaborators.tsx index 9f3bdfb..48befdc 100644 --- a/src/app/components/SupportersCollaborators.tsx +++ b/src/app/components/SupportersCollaborators.tsx @@ -5,20 +5,37 @@ import Image from 'next/image'; const SupportersCollaborators: React.FC = () => { return ( -
    -
    -
    -
    -

    - About the Guild +

    +
    +

    + About the Guild +

    +

    + Supporters & Collaborators +

    +

    + We collaborate with aligned organizations that support The Red Guild through grants, + shared security initiatives, and ecosystem efforts focused on public-benefit outcomes. +

    +
    + +
    +
    +

    Aligned partners

    +

    + Foundations, security alliances, and public-interest groups helping sustain research, + tooling, and education for a safer ecosystem.

    -

    Supporters & Collaborators

    -

    - We collaborate with aligned organizations that support The Red Guild through grants, - shared security initiatives, and ecosystem efforts focused on public-benefit outcomes. +

    +
    +

    Support model

    +

    + Grants, donations, and collaborative programs that keep public-benefit security work + active and broadly accessible.

    -
    +
    +
    + [...contributors] + .sort((a, b) => b.participationScore - a.participationScore) + .slice(0, 10), + [] + ); + const totalParticipation2026 = useMemo( + () => contributors.reduce((sum, contributor) => sum + contributor.participationScore, 0), + [] + ); + + return ( +
    + + + + +
    +
    +

    + Who +

    +

    + Contributors +

    +

    + Community contributors who collaborated with The Red Guild on specific projects. +

    +
    + +
    +
    +

    + Contributor Roster +

    +
    + {contributors.map((contributor) => ( + + ))} +
    +
    + + +
    +
    +
    + ); +} diff --git a/src/app/data/cardContent.ts b/src/app/data/cardContent.ts index 32c71a7..e6ebb7b 100644 --- a/src/app/data/cardContent.ts +++ b/src/app/data/cardContent.ts @@ -70,19 +70,27 @@ export const cardContent: CardContentMap = { url: "https://updraft.cyfrin.io/courses/security" }, { - label: "Undercover campaign at Ethereum Argentina", - url: "https://blog.theredguild.org/you-were-not-pwned-the-red-guild-ethereum-argentina-2023/" + label: "Security awareness campaign at Devconnect", + url: "https://blog.theredguild.org/against-all-odds-security-awareness-campaign-at-devconnect/" } ] }, letters: { title: "Security Research & Advisories", description: "Public investigations and technical posts like the Ethereum 7702 accounts deep dive, VSCode extensions audit, and the SLOVENLY COMET advisory.", - buttonText: "Read our blog", + buttonText: "Read our research", links: [ { - label: "Read our blog", - url: "https://blog.theredguild.org/" + label: "One Time Pwnage (SEAL Radar)", + url: "https://www.securityalliance.org/news/2025-03-slovenly-comet" + }, + { + label: "VSCode internals: escaping containers", + url: "https://blog.theredguild.org/leveraging-vscode-internals-to-escape-containers/" + }, + { + label: "Devcontainer security research (Part II)", + url: "https://blog.theredguild.org/where-do-you-run-your-code-part-ii-2/" } ] }, diff --git a/src/app/data/membersConfig.ts b/src/app/data/membersConfig.ts index ee8531d..3ba2402 100644 --- a/src/app/data/membersConfig.ts +++ b/src/app/data/membersConfig.ts @@ -51,6 +51,20 @@ export type MemberProfile = { avatar?: string; }; +export type ContributorProfile = { + id: string; + name: string; + alias: string; + title: string; + className: string; + level: number; + projects: string[]; + participationScore: number; + githubUsername?: string; + socials?: MemberSocials; + avatar?: string; +}; + export const members: MemberProfile[] = [ { id: "mattaereal", @@ -60,7 +74,7 @@ export const members: MemberProfile[] = [ level: 5, className: "Founder", githubUsername: "mattaereal", - avatar: "https://github.com/mattaereal.png?size=256", + avatar: "https://github.com/mattaereal.png?size=256&cb=20260220", socials: { github: "https://github.com/mattaereal", x: "https://x.com/mattaereal", @@ -666,3 +680,63 @@ export const members: MemberProfile[] = [ ], }, ]; + +export const contributors: ContributorProfile[] = [ + { + id: "eugenioclrc-contrib", + name: "Eugenio CLRC", + alias: "eugenioclrc", + title: "Contributor", + className: "Contributor", + level: 3, + projects: [ + "Devcon 24' CTF", + "Ekoparty 25 Village", + ], + participationScore: 82, + githubUsername: "eugenioclrc", + avatar: "https://github.com/eugenioclrc.png?size=256", + socials: { + github: "https://github.com/eugenioclrc", + }, + }, + { + id: "anon-node-01", + name: "Anonymous Contributor", + alias: "anon-node-01", + title: "Contributor", + className: "Anonymous", + level: 2, + projects: [ + "Devcon 24' CTF", + "Phishing Dojo QA", + ], + participationScore: 61, + }, + { + id: "anon-village-02", + name: "Anonymous Contributor", + alias: "anon-village-02", + title: "Contributor", + className: "Anonymous", + level: 3, + projects: [ + "Ekoparty 25 Village", + "Workshop Ops Support", + ], + participationScore: 74, + }, + { + id: "anon-research-03", + name: "Anonymous Contributor", + alias: "anon-research-03", + title: "Contributor", + className: "Anonymous", + level: 2, + projects: [ + "Threat Intel Triage", + "Security Advisories Drafting", + ], + participationScore: 57, + }, +]; diff --git a/src/app/ethos/page.tsx b/src/app/ethos/page.tsx new file mode 100644 index 0000000..74ad5a2 --- /dev/null +++ b/src/app/ethos/page.tsx @@ -0,0 +1,56 @@ +'use client'; + +import React from "react"; + +import Navbar from "../components/Navbar"; +import BackgroundClouds from "../components/BackgroundClouds"; +import ParticlesDOM from "../components/ParticlesDOM"; + +export default function EthosPage() { + return ( +
    + + + + +
    +
    +

    + About the Guild +

    +

    + Our Ethos +

    +

    + The Red Guild is a security collective devoted to protecting the open crypto ecosystem. + We move like a guild: research, education, and open-source tooling built in public for the + benefit of the community. +

    +

    + Our work blends adversarial rigor with public-good intent. We investigate threats, teach + defenders, and ship practical tools that raise the baseline for everyone. +

    +
    + +
    +
    +

    What we do

    +
      +
    • Security research, advisories, and investigations
    • +
    • Education programs, workshops, and awareness campaigns
    • +
    • Open-source tooling for safer development
    • +
    +
    +
    +

    How we work

    +
      +
    • Community-first collaboration and open knowledge
    • +
    • Responsible disclosure and transparent reporting
    • +
    • Iterative practice, shared playbooks, repeatable wins
    • +
    +
    +
    +
    +
    + ); +} diff --git a/src/app/initiatives/page.tsx b/src/app/initiatives/page.tsx index d6a0028..f24f722 100644 --- a/src/app/initiatives/page.tsx +++ b/src/app/initiatives/page.tsx @@ -19,37 +19,36 @@ export default function InitiativesPage() { -
    -
    -
    -
    -

    - About the Guild +

    +
    +

    + About the Guild +

    +

    + Initiatives +

    +

    + Our initiatives turn security knowledge into practical impact: training, tooling, + research, and public resources that anyone can use to harden crypto systems. +

    +
    + +
    +
    +

    What is active now

    +

    + {totalInitiatives} active lines of work, from adversarial training grounds to + open-source safety tooling and long-form technical advisories.

    -

    Initiatives

    -

    - Our initiatives turn security knowledge into practical impact: training, tooling, - research, and public resources that anyone can use to harden crypto systems. +

    +
    +

    How to engage

    +

    + Pick an initiative below to access challenges, documentation, event archives, or + code repositories and join the work where it is happening.

    - -
    -
    -

    What is active now

    -

    - {totalInitiatives} active lines of work, from adversarial training grounds to - open-source safety tooling and long-form technical advisories. -

    -
    -
    -

    How to engage

    -

    - Pick an initiative below to access challenges, documentation, event archives, or - code repositories and join the work where it is happening. -

    -
    -
    -
    +
    {Object.entries(cardContent).map(([key, content]) => ( diff --git a/src/app/members/page.tsx b/src/app/members/page.tsx index a3302ef..4e07d6c 100644 --- a/src/app/members/page.tsx +++ b/src/app/members/page.tsx @@ -16,7 +16,6 @@ export default function MembersPage() { () => members.find((member) => member.id === selectedMemberId) || members[0], [selectedMemberId] ); - return (
    @@ -55,6 +54,7 @@ export default function MembersPage() {
    )} +
    ); diff --git a/src/app/supporters/page.tsx b/src/app/supporters/page.tsx index e7de5d3..a161047 100644 --- a/src/app/supporters/page.tsx +++ b/src/app/supporters/page.tsx @@ -7,11 +7,11 @@ import SupportersCollaborators from '../components/SupportersCollaborators'; export default function SupportersPage() { return ( -
    +
    -
    +
    {/* Supporters & Collaborators Section */}
    From 988250f7cb22cb7fa0e2265cf6afb6e445ee5a65 Mon Sep 17 00:00:00 2001 From: matta Date: Fri, 20 Feb 2026 05:04:04 +0000 Subject: [PATCH 9/9] Improved contact page --- src/app/contact/page.tsx | 93 +++++++++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 26 deletions(-) diff --git a/src/app/contact/page.tsx b/src/app/contact/page.tsx index 11263f9..392970c 100644 --- a/src/app/contact/page.tsx +++ b/src/app/contact/page.tsx @@ -1,45 +1,86 @@ 'use client'; +import Link from "next/link"; + import Navbar from "../components/Navbar"; import BackgroundClouds from "../components/BackgroundClouds"; import ParticlesDOM from '../components/ParticlesDOM'; -import XIcon from '../components/assets/XIcon'; -import Image from 'next/image'; export default function ContactPage() { return ( -
    +
    -
    -

    Contact Us

    - - {/* Email - Prominent position */} -
    - - hello@theredguild.org +
    + - {/* Social media icons */} -
    -
    - - - - - GitHub - - - Blog - +
    +
    +

    Emergency channels

    + +
    +
    +

    Include in your message

    +
      +
    • Name
    • +
    • Handle
    • +
    • Organization
    • +
    • Email
    • +
    - - {/* Supporters & Collaborators */} - {/* */}
    ); -} \ No newline at end of file +}