1
0
Fork 0

added cyber menu

This commit is contained in:
koplenov 2026-04-05 05:32:27 +03:00
parent 87f07afc27
commit 0f8a089188
2 changed files with 845 additions and 0 deletions

483
src/cases/CybersecMenu.css Normal file
View file

@ -0,0 +1,483 @@
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;700;900&family=Share+Tech+Mono&display=swap');
.csm-root {
--csm-green: #00FF41;
--csm-magenta: #FF00FF;
--csm-cyan: #00FFFF;
--csm-orange: #FF6600;
--csm-bg: #0a0a0a;
font-family: 'Orbitron', monospace;
background: var(--csm-bg);
color: white;
overflow: hidden;
height: 100%;
width: 100%;
position: relative;
min-height: 100vh;
}
#csm-canvas {
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
z-index: 0;
pointer-events: none;
}
.csm-grid-overlay {
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
background-image:
linear-gradient(rgba(0,255,255,0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(0,255,255,0.03) 1px, transparent 1px);
background-size: 50px 50px;
pointer-events: none;
z-index: 1;
}
.csm-scanlines {
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
background: repeating-linear-gradient(
0deg,
rgba(0,0,0,0.15),
rgba(0,0,0,0.15) 1px,
transparent 1px,
transparent 2px
);
pointer-events: none;
z-index: 1000;
animation: csm-scanlineFlicker 0.1s infinite;
}
@keyframes csm-scanlineFlicker {
0%, 100% { opacity: 1; }
50% { opacity: 0.98; }
}
.csm-noise {
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
pointer-events: none;
z-index: 999;
opacity: 0.03;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
}
/* Corner decorations */
.csm-corner {
position: absolute;
width: 100px;
height: 100px;
border: 1px solid rgba(0,255,255,0.2);
z-index: 5;
}
.csm-tl { top: 20px; left: 20px; border-right: none; border-bottom: none; }
.csm-tr { top: 20px; right: 20px; border-left: none; border-bottom: none; }
.csm-bl { bottom: 20px; left: 20px; border-right: none; border-top: none; }
.csm-br { bottom: 20px; right: 20px; border-left: none; border-top: none; }
/* Main container */
.csm-main-container {
position: relative;
z-index: 10;
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
/* Header */
.csm-header {
position: absolute;
top: 30px;
left: 50%;
transform: translateX(-50%);
text-align: center;
z-index: 20;
}
.csm-header h1 {
font-size: 2.5rem;
font-weight: 900;
text-transform: uppercase;
letter-spacing: 8px;
background: linear-gradient(90deg, var(--csm-cyan), var(--csm-magenta), var(--csm-green));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-shadow: 0 0 30px rgba(0,255,255,0.5);
animation: csm-titlePulse 3s ease-in-out infinite;
transition: text-shadow 0.1s;
}
.csm-subtitle {
font-family: 'Share Tech Mono', monospace;
font-size: 0.9rem;
color: var(--csm-green);
letter-spacing: 4px;
margin-top: 10px;
opacity: 0.8;
}
@keyframes csm-titlePulse {
0%, 100% { filter: brightness(1); }
50% { filter: brightness(1.3); }
}
/* Character */
.csm-character-container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 15;
}
.csm-hacker-svg {
width: 400px;
height: 500px;
filter: drop-shadow(0 0 20px rgba(0,255,65,0.3));
animation: csm-characterFloat 4s ease-in-out infinite;
}
@keyframes csm-characterFloat {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-15px); }
}
.csm-tablet-glow { animation: csm-tabletPulse 2s ease-in-out infinite; }
@keyframes csm-tabletPulse {
0%, 100% { opacity: 0.6; }
50% { opacity: 1; }
}
.csm-eye-glow { animation: csm-eyePulse 3s ease-in-out infinite; }
@keyframes csm-eyePulse {
0%, 100% { opacity: 0.7; }
50% { opacity: 1; }
}
.csm-code-text {
font-family: 'Share Tech Mono', monospace;
font-size: 8px;
fill: var(--csm-green);
animation: csm-codeFlicker 0.1s infinite;
}
@keyframes csm-codeFlicker {
0%, 100% { opacity: 0.8; }
50% { opacity: 1; }
}
/* Right Side Menu */
.csm-right-menu {
position: absolute;
right: 40px;
top: 50%;
transform: translateY(-50%);
display: flex;
flex-direction: column;
gap: 25px;
z-index: 20;
}
.csm-menu-item {
position: relative;
cursor: pointer;
transition: all 0.2s ease;
}
.csm-hexagon {
width: 70px;
height: 80px;
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.csm-hexagon-bg {
position: absolute;
width: 100%;
height: 100%;
fill: none;
stroke: var(--csm-cyan);
stroke-width: 2;
filter: drop-shadow(0 0 10px var(--csm-cyan));
transition: all 0.2s ease;
}
.csm-hexagon:hover .csm-hexagon-bg {
stroke: var(--csm-magenta);
filter: drop-shadow(0 0 20px var(--csm-magenta));
transform: scale(1.15) translateX(-8px);
}
.csm-hexagon-icon {
position: relative;
z-index: 2;
font-size: 28px;
transition: all 0.2s ease;
}
.csm-hexagon:hover .csm-hexagon-icon {
transform: scale(1.15) translateX(-8px);
}
.csm-menu-item:hover {
animation: csm-glitch 0.3s ease;
}
@keyframes csm-glitch {
0% { transform: translate(0); }
20% { transform: translate(-2px, 2px); }
40% { transform: translate(-2px, -2px); }
60% { transform: translate(2px, 2px); }
80% { transform: translate(2px, -2px); }
100% { transform: translate(0); }
}
/* Tooltip */
.csm-tooltip {
position: absolute;
right: 90px;
top: 50%;
transform: translateY(-50%);
background: rgba(10,10,10,0.95);
border: 1px solid var(--csm-cyan);
padding: 12px 18px;
border-radius: 4px;
min-width: 220px;
opacity: 0;
visibility: hidden;
transition: all 0.2s ease;
pointer-events: none;
}
.csm-tooltip::after {
content: '';
position: absolute;
right: -8px;
top: 50%;
transform: translateY(-50%);
border-width: 8px 0 8px 8px;
border-style: solid;
border-color: transparent transparent transparent var(--csm-cyan);
}
.csm-menu-item:hover .csm-tooltip {
opacity: 1;
visibility: visible;
right: 100px;
}
.csm-tooltip-title {
font-size: 0.85rem;
font-weight: 700;
color: var(--csm-cyan);
margin-bottom: 5px;
text-transform: uppercase;
letter-spacing: 2px;
}
.csm-tooltip-desc {
font-family: 'Share Tech Mono', monospace;
font-size: 0.75rem;
color: #aaa;
line-height: 1.4;
}
/* Level colors */
.csm-level-1:hover .csm-hexagon-bg { stroke: var(--csm-green); filter: drop-shadow(0 0 20px var(--csm-green)); }
.csm-level-1:hover .csm-hexagon-icon { color: var(--csm-green); }
.csm-level-1 .csm-tooltip { border-color: var(--csm-green); }
.csm-level-1 .csm-tooltip::after { border-left-color: var(--csm-green); }
.csm-level-1 .csm-tooltip-title { color: var(--csm-green); }
.csm-level-2:hover .csm-hexagon-bg { stroke: var(--csm-orange); filter: drop-shadow(0 0 20px var(--csm-orange)); }
.csm-level-2:hover .csm-hexagon-icon { color: var(--csm-orange); }
.csm-level-2 .csm-tooltip { border-color: var(--csm-orange); }
.csm-level-2 .csm-tooltip::after { border-left-color: var(--csm-orange); }
.csm-level-2 .csm-tooltip-title { color: var(--csm-orange); }
.csm-level-3:hover .csm-hexagon-bg { stroke: var(--csm-magenta); filter: drop-shadow(0 0 20px var(--csm-magenta)); }
.csm-level-3:hover .csm-hexagon-icon { color: var(--csm-magenta); }
.csm-level-3 .csm-tooltip { border-color: var(--csm-magenta); }
.csm-level-3 .csm-tooltip::after { border-left-color: var(--csm-magenta); }
.csm-level-3 .csm-tooltip-title { color: var(--csm-magenta); }
.csm-level-4:hover .csm-hexagon-bg { stroke: var(--csm-cyan); filter: drop-shadow(0 0 20px var(--csm-cyan)); }
.csm-level-4:hover .csm-hexagon-icon { color: var(--csm-cyan); }
.csm-level-4 .csm-tooltip { border-color: var(--csm-cyan); }
.csm-level-4 .csm-tooltip::after { border-left-color: var(--csm-cyan); }
.csm-level-4 .csm-tooltip-title { color: var(--csm-cyan); }
.csm-deepfake:hover .csm-hexagon-bg { stroke: #FF0040; filter: drop-shadow(0 0 20px #FF0040); }
.csm-deepfake:hover .csm-hexagon-icon { color: #FF0040; }
.csm-deepfake .csm-tooltip { border-color: #FF0040; }
.csm-deepfake .csm-tooltip::after { border-left-color: #FF0040; }
.csm-deepfake .csm-tooltip-title { color: #FF0040; }
/* Bottom Container */
.csm-bottom-container {
position: absolute;
bottom: 50px;
left: 0;
right: 0;
display: flex;
justify-content: space-between;
padding: 0 80px;
z-index: 20;
}
.csm-bottom-block {
position: relative;
cursor: pointer;
transition: all 0.2s ease;
}
.csm-block-shape {
width: 120px;
height: 60px;
background: rgba(10,10,10,0.9);
border: 2px solid var(--csm-cyan);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
position: relative;
transition: all 0.2s ease;
}
.csm-block-shape::before {
content: '';
position: absolute;
inset: -4px;
border-radius: 10px;
border: 1px solid var(--csm-cyan);
opacity: 0;
transition: all 0.2s ease;
}
.csm-bottom-block:hover .csm-block-shape {
border-color: var(--csm-magenta);
box-shadow: 0 0 30px rgba(255,0,255,0.5);
transform: scale(1.05);
}
.csm-bottom-block:hover .csm-block-shape::before {
opacity: 1;
border-color: var(--csm-magenta);
animation: csm-pulseRing 1.5s ease-out infinite;
}
@keyframes csm-pulseRing {
0% { transform: scale(1); opacity: 0.8; }
100% { transform: scale(1.3); opacity: 0; }
}
.csm-block-icon {
font-size: 24px;
color: var(--csm-cyan);
transition: all 0.2s ease;
}
.csm-bottom-block:hover .csm-block-icon { color: var(--csm-magenta); }
.csm-block-text {
font-size: 0.9rem;
font-weight: 700;
letter-spacing: 3px;
color: white;
}
.csm-block-tooltip {
position: absolute;
bottom: 75px;
left: 50%;
transform: translateX(-50%);
background: rgba(10,10,10,0.95);
border: 1px solid var(--csm-cyan);
padding: 10px 15px;
border-radius: 4px;
white-space: nowrap;
opacity: 0;
visibility: hidden;
transition: all 0.2s ease;
font-family: 'Share Tech Mono', monospace;
font-size: 0.8rem;
color: #aaa;
}
.csm-block-tooltip::after {
content: '';
position: absolute;
bottom: -8px;
left: 50%;
transform: translateX(-50%);
border-width: 8px 8px 0;
border-style: solid;
border-color: var(--csm-cyan) transparent transparent;
}
.csm-bottom-block:hover .csm-block-tooltip {
opacity: 1;
visibility: visible;
bottom: 85px;
border-color: var(--csm-magenta);
}
.csm-bottom-block:hover .csm-block-tooltip::after {
border-top-color: var(--csm-magenta);
}
/* Notification */
.csm-notification {
position: fixed;
top: 100px;
left: 50%;
transform: translateX(-50%);
background: rgba(10,10,10,0.95);
border: 2px solid var(--csm-green);
padding: 20px 40px;
border-radius: 4px;
z-index: 10000;
text-align: center;
box-shadow: 0 0 30px rgba(0,255,65,0.5);
animation: csm-notifIn 0.3s ease;
}
.csm-notification.csm-notif-out {
animation: csm-notifOut 0.3s ease forwards;
}
.csm-notif-title {
font-family: 'Orbitron', monospace;
font-size: 1.1rem;
font-weight: 700;
color: var(--csm-green);
margin-bottom: 8px;
letter-spacing: 2px;
}
.csm-notif-message {
font-family: 'Share Tech Mono', monospace;
font-size: 0.9rem;
color: #aaa;
}
@keyframes csm-notifIn {
from { opacity: 0; transform: translateX(-50%) translateY(-20px); }
to { opacity: 1; transform: translateX(-50%) translateY(0); }
}
@keyframes csm-notifOut {
from { opacity: 1; transform: translateX(-50%) translateY(0); }
to { opacity: 0; transform: translateX(-50%) translateY(-20px); }
}
/* Responsive */
@media (max-width: 1024px) {
.csm-hacker-svg { width: 300px; height: 375px; }
.csm-right-menu { right: 20px; gap: 15px; }
.csm-hexagon { width: 55px; height: 63px; }
.csm-hexagon-icon { font-size: 22px; }
.csm-tooltip { min-width: 180px; padding: 10px 14px; }
.csm-header h1 { font-size: 1.8rem; }
}
@media (max-width: 768px) {
.csm-header h1 { font-size: 1.4rem; letter-spacing: 4px; }
.csm-hacker-svg { width: 220px; height: 275px; }
.csm-right-menu { right: 10px; gap: 10px; }
.csm-hexagon { width: 45px; height: 52px; }
.csm-hexagon-icon { font-size: 18px; }
.csm-tooltip { display: none; }
.csm-bottom-container { padding: 0 30px; bottom: 30px; }
.csm-block-shape { width: 90px; height: 50px; }
.csm-block-text { font-size: 0.7rem; }
}

362
src/cases/CybersecMenu.tsx Normal file
View file

@ -0,0 +1,362 @@
import React, { useEffect, useRef, useState, useCallback } from 'react';
import './CybersecMenu.css';
interface Notification {
id: number;
title: string;
message: string;
removing: boolean;
}
const CybersecMenu: React.FC = () => {
const canvasRef = useRef<HTMLCanvasElement>(null);
const animFrameRef = useRef<number>(0);
const smokeOffsetRef = useRef(0);
const titleRef = useRef<HTMLHeadingElement>(null);
const [notification, setNotification] = useState<Notification | null>(null);
const notifIdRef = useRef(0);
const notifTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const showNotification = useCallback((title: string, message: string) => {
if (notifTimerRef.current) clearTimeout(notifTimerRef.current);
const id = ++notifIdRef.current;
setNotification({ id, title, message, removing: false });
notifTimerRef.current = setTimeout(() => {
setNotification(prev => prev?.id === id ? { ...prev, removing: true } : prev);
setTimeout(() => setNotification(prev => prev?.id === id ? null : prev), 300);
}, 3000);
}, []);
const selectLevel = useCallback((level: number | string) => {
const levelNames: Record<string | number, string> = {
1: 'Phishing Fake emails & links',
2: 'Skimming ATM/card fraud',
3: 'Password cracking Brute force & dictionary',
4: 'Social engineering Manipulation',
'deepfake': 'Voice deepfake AI-generated speech',
};
showNotification(`>> LEVEL ${level} SELECTED`, levelNames[level]);
}, [showNotification]);
const openWiki = useCallback(() => {
showNotification('>> ACCESSING WIKI', 'Security knowledge base loading...');
}, [showNotification]);
const openQuiz = useCallback(() => {
showNotification('>> INITIATING QUIZ', 'Test your skills module loading...');
}, [showNotification]);
// Keyboard navigation
useEffect(() => {
const handleKey = (e: KeyboardEvent) => {
const map: Record<string, () => void> = {
'1': () => selectLevel(1),
'2': () => selectLevel(2),
'3': () => selectLevel(3),
'4': () => selectLevel(4),
'5': () => selectLevel('deepfake'),
'w': openWiki, 'W': openWiki,
'q': openQuiz, 'Q': openQuiz,
};
map[e.key]?.();
};
window.addEventListener('keydown', handleKey);
return () => window.removeEventListener('keydown', handleKey);
}, [selectLevel, openWiki, openQuiz]);
// Glitch effect on title
useEffect(() => {
const interval = setInterval(() => {
if (Math.random() > 0.9 && titleRef.current) {
const rx = (Math.random() * 10 - 5).toFixed(1);
const rx2 = (Math.random() * 10 - 5).toFixed(1);
titleRef.current.style.textShadow = `${rx}px 0 #FF0040, ${rx2}px 0 #00FFFF`;
setTimeout(() => {
if (titleRef.current) titleRef.current.style.textShadow = '0 0 30px rgba(0,255,255,0.5)';
}, 100);
}
}, 2000);
return () => clearInterval(interval);
}, []);
// Particle canvas
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext('2d');
if (!ctx) return;
const resize = () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
};
resize();
const COLORS = ['#00FF41', '#FF00FF', '#00FFFF', '#FF6600'];
class Particle {
x = 0; y = 0; size = 0; speedX = 0; speedY = 0;
opacity = 0; color = ''; life = 0; maxLife = 0;
constructor() { this.reset(); }
reset() {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.size = Math.random() * 3 + 1;
this.speedX = (Math.random() - 0.5) * 0.5;
this.speedY = (Math.random() - 0.5) * 0.5;
this.opacity = Math.random() * 0.5 + 0.1;
this.color = COLORS[Math.floor(Math.random() * COLORS.length)];
this.life = 0;
this.maxLife = Math.random() * 200 + 100;
}
update() {
this.x += this.speedX;
this.y += this.speedY;
this.life++;
if (this.x < 0) this.x = canvas.width;
if (this.x > canvas.width) this.x = 0;
if (this.y < 0) this.y = canvas.height;
if (this.y > canvas.height) this.y = 0;
if (this.life > this.maxLife) this.reset();
}
draw() {
ctx.save();
ctx.globalAlpha = this.opacity * (1 - this.life / this.maxLife);
ctx.fillStyle = this.color;
ctx.shadowBlur = 10;
ctx.shadowColor = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}
}
const count = Math.min(80, Math.floor((canvas.width * canvas.height) / 15000));
let particles = Array.from({ length: count }, () => new Particle());
const onVis = () => {
if (document.hidden) { cancelAnimationFrame(animFrameRef.current); }
else { animate(); }
};
document.addEventListener('visibilitychange', onVis);
const onResize = () => { resize(); particles = Array.from({ length: Math.min(80, Math.floor((canvas.width * canvas.height) / 15000)) }, () => new Particle()); };
window.addEventListener('resize', onResize);
function drawSmoke() {
smokeOffsetRef.current += 0.2;
const so = smokeOffsetRef.current;
const layerColors = ['#00FF41', '#FF00FF', '#00FFFF'];
for (let layer = 0; layer < 3; layer++) {
ctx.save();
ctx.globalAlpha = 0.03 - layer * 0.008;
const grad = ctx.createRadialGradient(
canvas.width * 0.3 + Math.sin(so * 0.01 + layer) * 200,
canvas.height * 0.5 + Math.cos(so * 0.015 + layer) * 100,
0,
canvas.width * 0.5, canvas.height * 0.5,
canvas.width * 0.8
);
grad.addColorStop(0, layerColors[layer]);
grad.addColorStop(1, '#0a0a0a');
ctx.fillStyle = grad;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.restore();
}
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawSmoke();
particles.forEach(p => { p.update(); p.draw(); });
ctx.save();
ctx.strokeStyle = 'rgba(0,255,255,0.05)';
ctx.lineWidth = 0.5;
for (let i = 0; i < particles.length; i++) {
for (let j = i + 1; j < particles.length; j++) {
const dx = particles[i].x - particles[j].x;
const dy = particles[i].y - particles[j].y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 100) {
ctx.globalAlpha = (1 - dist / 100) * 0.2;
ctx.beginPath();
ctx.moveTo(particles[i].x, particles[i].y);
ctx.lineTo(particles[j].x, particles[j].y);
ctx.stroke();
}
}
}
ctx.restore();
animFrameRef.current = requestAnimationFrame(animate);
}
animate();
return () => {
cancelAnimationFrame(animFrameRef.current);
window.removeEventListener('resize', onResize);
document.removeEventListener('visibilitychange', onVis);
};
}, []);
const menuItems = [
{ level: 1 as number | string, cls: 'csm-level-1', icon: '🔒', title: 'Level 1', desc: 'Phishing Fake emails & links' },
{ level: 2 as number | string, cls: 'csm-level-2', icon: '⌨️', title: 'Level 2', desc: 'Skimming ATM/card fraud' },
{ level: 3 as number | string, cls: 'csm-level-3', icon: '🖥️', title: 'Level 3', desc: 'Password cracking Brute force & dictionary' },
{ level: 4 as number | string, cls: 'csm-level-4', icon: '🛡️', title: 'Level 4', desc: 'Social engineering Manipulation' },
{ level: 'deepfake', cls: 'csm-deepfake', icon: '🎭', title: 'Deepfake', desc: 'Voice deepfake AI-generated speech' },
];
return (
<div className="csm-root">
<canvas ref={canvasRef} id="csm-canvas" />
<div className="csm-grid-overlay" />
<div className="csm-scanlines" />
<div className="csm-noise" />
<div className="csm-corner csm-tl" />
<div className="csm-corner csm-tr" />
<div className="csm-corner csm-bl" />
<div className="csm-corner csm-br" />
<div className="csm-main-container">
{/* Header */}
<div className="csm-header">
<h1 ref={titleRef}>CYBERSEC TRAINING</h1>
<div className="csm-subtitle">[ TACTICAL SECURITY SIMULATION ]</div>
</div>
{/* Character */}
<div className="csm-character-container">
<svg className="csm-hacker-svg" viewBox="0 0 400 500" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="csm-hoodGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style={{stopColor:'#1a1a1a',stopOpacity:1}}/>
<stop offset="100%" style={{stopColor:'#0d0d0d',stopOpacity:1}}/>
</linearGradient>
<linearGradient id="csm-maskGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style={{stopColor:'#2a2a2a',stopOpacity:1}}/>
<stop offset="50%" style={{stopColor:'#1a1a1a',stopOpacity:1}}/>
<stop offset="100%" style={{stopColor:'#0a0a0a',stopOpacity:1}}/>
</linearGradient>
<filter id="csm-glow">
<feGaussianBlur stdDeviation="3" result="coloredBlur"/>
<feMerge><feMergeNode in="coloredBlur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="csm-strongGlow">
<feGaussianBlur stdDeviation="5" result="coloredBlur"/>
<feMerge><feMergeNode in="coloredBlur"/><feMergeNode in="coloredBlur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
{/* Hood/Head Silhouette */}
<path d="M200 80 C 150 80, 100 120, 90 180 C 85 210, 85 250, 95 290 C 100 320, 110 350, 130 370 L 130 420 C 130 440, 150 450, 200 450 C 250 450, 270 440, 270 420 L 270 370 C 290 350, 300 320, 305 290 C 315 250, 315 210, 310 180 C 300 120, 250 80, 200 80 Z"
fill="url(#csm-hoodGrad)" stroke="#00FF41" strokeWidth="2" filter="url(#csm-glow)"/>
{/* Hood Inner Shadow */}
<path d="M200 100 C 165 100, 130 130, 125 170 C 122 190, 122 220, 128 250 C 132 270, 140 290, 155 305 L 155 350 C 155 365, 170 375, 200 375 C 230 375, 245 365, 245 350 L 245 305 C 260 290, 268 270, 272 250 C 278 220, 278 190, 275 170 C 270 130, 235 100, 200 100 Z"
fill="#0a0a0a"/>
{/* Goggles/Mask */}
<rect x="125" y="200" width="150" height="70" rx="15"
fill="url(#csm-maskGrad)" stroke="#00FFFF" strokeWidth="2" filter="url(#csm-glow)"/>
{/* Goggle Lenses */}
<ellipse cx="165" cy="235" rx="28" ry="22" fill="#000" stroke="#00FFFF" strokeWidth="1.5"/>
<ellipse cx="235" cy="235" rx="28" ry="22" fill="#000" stroke="#00FFFF" strokeWidth="1.5"/>
{/* Glowing Eyes */}
<circle cx="165" cy="235" r="8" fill="#00FF41" className="csm-eye-glow" filter="url(#csm-strongGlow)"/>
<circle cx="235" cy="235" r="8" fill="#00FF41" className="csm-eye-glow" filter="url(#csm-strongGlow)"/>
{/* Eye Details */}
<circle cx="167" cy="233" r="3" fill="#fff" opacity="0.8"/>
<circle cx="237" cy="233" r="3" fill="#fff" opacity="0.8"/>
{/* Goggle Frame Details */}
<line x1="193" y1="220" x2="207" y2="220" stroke="#00FFFF" strokeWidth="2"/>
<line x1="193" y1="235" x2="207" y2="235" stroke="#00FFFF" strokeWidth="2"/>
<line x1="193" y1="250" x2="207" y2="250" stroke="#00FFFF" strokeWidth="2"/>
{/* Goggle Side Lights */}
<rect x="115" y="225" width="8" height="20" rx="2" fill="#FF00FF" filter="url(#csm-glow)" opacity="0.8"/>
<rect x="277" y="225" width="8" height="20" rx="2" fill="#FF00FF" filter="url(#csm-glow)" opacity="0.8"/>
{/* Shoulders/Torso */}
<path d="M80 380 C 60 390, 40 420, 30 480 L 30 500 L 370 500 L 370 480 C 360 420, 340 390, 320 380 C 280 360, 240 355, 200 355 C 160 355, 120 360, 80 380 Z"
fill="#0d0d0d" stroke="#00FF41" strokeWidth="1.5" opacity="0.6"/>
{/* Jacket Details */}
<path d="M200 355 L 200 500" stroke="#00FF41" strokeWidth="1" opacity="0.3"/>
<path d="M120 380 L 150 500" stroke="#00FF41" strokeWidth="1" opacity="0.2"/>
<path d="M280 380 L 250 500" stroke="#00FF41" strokeWidth="1" opacity="0.2"/>
{/* Collar */}
<path d="M150 340 C 150 340, 200 360, 250 340 L 260 370 C 260 370, 200 395, 140 370 Z"
fill="#1a1a1a" stroke="#00FFFF" strokeWidth="1"/>
{/* Holographic Tablet */}
<g transform="translate(220, 400) rotate(-10)">
<rect x="0" y="0" width="100" height="70" rx="5"
fill="rgba(0,20,40,0.9)" stroke="#00FF41" strokeWidth="2" className="csm-tablet-glow"/>
<rect x="5" y="5" width="90" height="60" rx="3" fill="rgba(0,10,20,0.95)"/>
<line x1="10" y1="12" x2="50" y2="12" stroke="#00FF41" strokeWidth="1.5" opacity="0.9"/>
<line x1="10" y1="20" x2="70" y2="20" stroke="#00FF41" strokeWidth="1.5" opacity="0.7"/>
<line x1="10" y1="28" x2="45" y2="28" stroke="#00FF41" strokeWidth="1.5" opacity="0.8"/>
<line x1="10" y1="36" x2="60" y2="36" stroke="#00FF41" strokeWidth="1.5" opacity="0.6"/>
<line x1="10" y1="44" x2="40" y2="44" stroke="#00FF41" strokeWidth="1.5" opacity="0.9"/>
<line x1="10" y1="52" x2="55" y2="52" stroke="#00FF41" strokeWidth="1.5" opacity="0.7"/>
<text x="55" y="58" className="csm-code-text" fontSize="6">01001</text>
<ellipse cx="50" cy="75" rx="45" ry="8" fill="url(#csm-hoodGrad)" opacity="0.3" filter="url(#csm-glow)"/>
</g>
{/* Hand */}
<ellipse cx="230" cy="445" rx="15" ry="12" fill="#1a1a1a" stroke="#00FF41" strokeWidth="1" opacity="0.8"/>
{/* Circuit Patterns */}
<path d="M120 150 L 140 150 L 145 160" stroke="#00FFFF" strokeWidth="0.5" fill="none" opacity="0.4"/>
<path d="M280 150 L 260 150 L 255 160" stroke="#00FFFF" strokeWidth="0.5" fill="none" opacity="0.4"/>
<circle cx="145" cy="160" r="2" fill="#00FFFF" opacity="0.5"/>
<circle cx="255" cy="160" r="2" fill="#00FFFF" opacity="0.5"/>
{/* Chin/Mouth */}
<path d="M175 290 C 175 290, 200 300, 225 290 L 225 305 C 225 305, 200 315, 175 305 Z"
fill="#0a0a0a" stroke="#00FF41" strokeWidth="0.5" opacity="0.5"/>
</svg>
</div>
{/* Right Side Menu */}
<div className="csm-right-menu">
{menuItems.map(item => (
<div key={String(item.level)} className={`csm-menu-item ${item.cls}`} onClick={() => selectLevel(item.level)}>
<div className="csm-hexagon">
<svg className="csm-hexagon-bg" viewBox="0 0 70 80">
<polygon points="35,2 66,20 66,58 35,76 4,58 4,20"/>
</svg>
<span className="csm-hexagon-icon">{item.icon}</span>
</div>
<div className="csm-tooltip">
<div className="csm-tooltip-title">{item.title}</div>
<div className="csm-tooltip-desc">{item.desc}</div>
</div>
</div>
))}
</div>
{/* Bottom Container */}
<div className="csm-bottom-container">
<div className="csm-bottom-block" onClick={openWiki}>
<div className="csm-block-shape">
<span className="csm-block-icon">📖</span>
<span className="csm-block-text">WIKI</span>
</div>
<div className="csm-block-tooltip">Security knowledge base</div>
</div>
<div className="csm-bottom-block" onClick={openQuiz}>
<div className="csm-block-shape">
<span className="csm-block-icon"></span>
<span className="csm-block-text">QUIZ</span>
</div>
<div className="csm-block-tooltip">Test your skills</div>
</div>
</div>
</div>
{/* Notification */}
{notification && (
<div className={`csm-notification ${notification.removing ? 'csm-notif-out' : ''}`}>
<div className="csm-notif-title">{notification.title}</div>
<div className="csm-notif-message">{notification.message}</div>
</div>
)}
</div>
);
};
export default CybersecMenu;