1
0
Fork 0

sync colors

This commit is contained in:
koplenov 2026-04-05 05:47:03 +03:00
parent 73f0910d91
commit 41085f3c01
2 changed files with 141 additions and 126 deletions

View file

@ -4,15 +4,17 @@ const CyberSecurityArticle: React.FC = () => {
return ( return (
<> <>
<style>{` <style>{`
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=Share+Tech+Mono&display=swap');
:root { :root {
--bg-body: #0f1114; --bg-body: #0a0a0a;
--bg-card: #1a1d23; --bg-card: #0d0d22;
--bg-toc: #23272e; --bg-toc: #080818;
--text-main: #e3e6eb; --text-main: #cccccc;
--text-muted: #9ba3af; --text-muted: #888888;
--accent-blue: #4da3ff; --accent-blue: #00FFFF;
--accent-purple: #bb86fc; --accent-purple: #FF00FF;
--border-color: #30363d; --border-color: rgba(0,255,255,0.2);
} }
body { body {
@ -21,7 +23,7 @@ const CyberSecurityArticle: React.FC = () => {
} }
.wiki-wrapper { .wiki-wrapper {
font-family: 'Segoe UI', Roboto, sans-serif; font-family: 'Share Tech Mono', monospace;
background-color: var(--bg-body); background-color: var(--bg-body);
color: var(--text-main); color: var(--text-main);
margin: 0; margin: 0;
@ -34,42 +36,48 @@ const CyberSecurityArticle: React.FC = () => {
.wiki-container { .wiki-container {
background-color: var(--bg-card); background-color: var(--bg-card);
border: 1px solid var(--border-color); border: 1px solid rgba(0,255,255,0.15);
border-radius: 12px; border-radius: 12px;
padding: 40px; padding: 40px;
max-width: 1000px; max-width: 1000px;
width: 100%; width: 100%;
box-shadow: 0 10px 30px rgba(0,0,0,0.5); box-shadow: 0 0 40px rgba(0,255,255,0.08);
position: relative; position: relative;
} }
h1 { h1 {
font-size: 2.5em; font-size: 2.5em;
border-bottom: 1px solid var(--border-color); color: #00FFFF;
padding-bottom: 10px; border-bottom: 1px solid rgba(0,255,255,0.2);
padding-bottom: 10px;
margin-top: 0; margin-top: 0;
text-shadow: 0 0 20px rgba(0,255,255,0.3);
font-family: 'Orbitron', monospace;
} }
h2 { h2 {
font-size: 1.6em; font-size: 1.6em;
color: var(--accent-blue); color: #00FFFF;
border-bottom: 1px solid var(--border-color); border-bottom: 1px solid rgba(0,255,255,0.2);
margin-top: 2em; margin-top: 2em;
text-shadow: 0 0 10px rgba(0,255,255,0.2);
font-family: 'Orbitron', monospace;
} }
h3 { h3 {
font-size: 1.3em; font-size: 1.3em;
color: var(--accent-blue); color: #00FF41;
margin-top: 1.5em; margin-top: 1.5em;
font-family: 'Orbitron', monospace;
} }
a { a {
color: var(--accent-blue); color: #00FFFF;
text-decoration: none; text-decoration: none;
} }
a:hover { a:hover {
text-decoration: underline; text-decoration: underline;
} }
/* Инфобокс */ /* Инфобокс */
@ -77,19 +85,20 @@ const CyberSecurityArticle: React.FC = () => {
float: right; float: right;
width: 300px; width: 300px;
background-color: var(--bg-toc); background-color: var(--bg-toc);
border: 1px solid var(--border-color); border: 1px solid rgba(0,255,255,0.2);
border-radius: 8px; border-radius: 8px;
margin: 0 0 20px 20px; margin: 0 0 20px 20px;
padding: 10px; padding: 10px;
font-size: 0.9em; font-size: 0.9em;
box-shadow: 0 0 15px rgba(0,255,255,0.05);
} }
.infobox img { .infobox img {
width: 100%; width: 100%;
border-radius: 4px; border-radius: 4px;
display: block; display: block;
} }
.infobox-caption { .infobox-caption {
text-align: center; text-align: center;
padding-top: 8px; padding-top: 8px;
@ -107,12 +116,12 @@ const CyberSecurityArticle: React.FC = () => {
float: right; float: right;
border-radius: 4px; border-radius: 4px;
} }
.thumb img { .thumb img {
width: 100%; width: 100%;
display: block; display: block;
} }
.thumb-caption { .thumb-caption {
font-size: 0.85em; font-size: 0.85em;
padding: 5px; padding: 5px;
@ -125,13 +134,13 @@ const CyberSecurityArticle: React.FC = () => {
margin: 30px 0; margin: 30px 0;
width: 100%; width: 100%;
} }
.full-width-img img { .full-width-img img {
width: 100%; width: 100%;
max-height: 500px; max-height: 500px;
object-fit: cover; object-fit: cover;
border-radius: 8px; border-radius: 8px;
border: 1px solid var(--border-color); border: 1px solid rgba(0,255,255,0.2);
} }
.full-width-img figcaption { .full-width-img figcaption {
@ -146,11 +155,12 @@ const CyberSecurityArticle: React.FC = () => {
/* Оглавление */ /* Оглавление */
.toc { .toc {
background-color: var(--bg-toc); background-color: var(--bg-toc);
border: 1px solid var(--border-color); border: 1px solid rgba(0,255,255,0.2);
border-radius: 8px; border-radius: 8px;
padding: 15px; padding: 15px;
margin: 20px 0; margin: 20px 0;
display: inline-block; display: inline-block;
box-shadow: 0 0 10px rgba(0,255,255,0.05);
} }
.toc ul { .toc ul {
@ -166,7 +176,7 @@ const CyberSecurityArticle: React.FC = () => {
/* Источники */ /* Источники */
.sources { .sources {
margin-top: 50px; margin-top: 50px;
border-top: 1px solid var(--border-color); border-top: 1px solid rgba(0,255,255,0.2);
padding-top: 20px; padding-top: 20px;
} }
@ -180,11 +190,11 @@ const CyberSecurityArticle: React.FC = () => {
.wiki-container { .wiki-container {
padding: 20px; padding: 20px;
} }
h1 { h1 {
font-size: 1.8em; font-size: 1.8em;
} }
.infobox, .thumb { .infobox, .thumb {
float: none; float: none;
width: 100%; width: 100%;

View file

@ -310,7 +310,7 @@ const QUESTIONS_BASICS: Question[] = [
const styles: Record<string, React.CSSProperties> = { const styles: Record<string, React.CSSProperties> = {
container: { container: {
minHeight: '100vh', minHeight: '100vh',
backgroundColor: '#0f172a', backgroundColor: '#0a0a0a',
padding: '20px', padding: '20px',
fontFamily: 'system-ui, -apple-system, sans-serif', fontFamily: 'system-ui, -apple-system, sans-serif',
display: 'flex', display: 'flex',
@ -318,56 +318,59 @@ const styles: Record<string, React.CSSProperties> = {
alignItems: 'center' alignItems: 'center'
}, },
card: { card: {
backgroundColor: '#1e293b', backgroundColor: '#0d0d22',
borderRadius: '16px', borderRadius: '8px',
border: '1px solid #334155', border: '1px solid rgba(0,255,255,0.2)',
maxWidth: '600px', maxWidth: '600px',
width: '100%', width: '100%',
overflow: 'hidden', overflow: 'hidden',
boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.5)' boxShadow: '0 0 30px rgba(0,255,255,0.1)'
}, },
menu: { menu: {
textAlign: 'center', textAlign: 'center',
padding: '40px' padding: '40px'
}, },
menuTitle: { menuTitle: {
color: '#60a5fa', color: '#00FFFF',
fontSize: '32px', fontSize: '32px',
fontWeight: 'bold', fontWeight: 'bold',
marginBottom: '16px' marginBottom: '16px',
fontFamily: "'Orbitron', monospace"
}, },
menuSubtitle: { menuSubtitle: {
color: '#94a3b8', color: '#888',
marginBottom: '40px', marginBottom: '40px',
fontSize: '16px' fontSize: '16px',
fontFamily: "'Share Tech Mono', monospace"
}, },
menuButton: { menuButton: {
display: 'block', display: 'block',
width: '100%', width: '100%',
padding: '20px', padding: '20px',
marginBottom: '16px', marginBottom: '16px',
borderRadius: '12px', borderRadius: '6px',
border: '2px solid #475569', border: '1px solid rgba(0,255,255,0.3)',
backgroundColor: '#334155', backgroundColor: '#0a0a1a',
color: '#f8fafc', color: '#ccc',
fontSize: '18px', fontSize: '18px',
fontWeight: '600', fontWeight: '600',
cursor: 'pointer', cursor: 'pointer',
transition: 'all 0.2s', transition: 'all 0.2s',
textAlign: 'left', textAlign: 'left',
position: 'relative' position: 'relative',
fontFamily: "'Orbitron', monospace"
}, },
menuButtonCompleted: { menuButtonCompleted: {
borderColor: '#22c55e', borderColor: '#00FF41',
backgroundColor: 'rgba(34, 197, 94, 0.1)' backgroundColor: 'rgba(0,255,65,0.05)'
}, },
completedBadge: { completedBadge: {
position: 'absolute', position: 'absolute',
right: '20px', right: '20px',
top: '50%', top: '50%',
transform: 'translateY(-50%)', transform: 'translateY(-50%)',
backgroundColor: '#22c55e', backgroundColor: '#00FF41',
color: 'white', color: '#000',
width: '32px', width: '32px',
height: '32px', height: '32px',
borderRadius: '50%', borderRadius: '50%',
@ -375,46 +378,49 @@ const styles: Record<string, React.CSSProperties> = {
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
fontSize: '18px', fontSize: '18px',
boxShadow: '0 2px 8px rgba(34, 197, 94, 0.4)' boxShadow: '0 2px 8px rgba(0,255,65,0.4)'
}, },
header: { header: {
padding: '24px', padding: '24px',
borderBottom: '1px solid #334155', borderBottom: '1px solid rgba(0,255,255,0.15)',
backgroundColor: '#1e293b' backgroundColor: '#0d0d22'
}, },
progressBar: { progressBar: {
height: '4px', height: '4px',
backgroundColor: '#334155', backgroundColor: 'rgba(0,255,255,0.1)',
borderRadius: '2px', borderRadius: '2px',
marginBottom: '16px', marginBottom: '16px',
overflow: 'hidden' overflow: 'hidden'
}, },
progressFill: { progressFill: {
height: '100%', height: '100%',
backgroundColor: '#3b82f6', backgroundColor: '#00FFFF',
transition: 'width 0.3s ease' transition: 'width 0.3s ease'
}, },
meta: { meta: {
display: 'flex', display: 'flex',
justifyContent: 'space-between', justifyContent: 'space-between',
color: '#94a3b8', color: '#888',
fontSize: '14px', fontSize: '14px',
marginBottom: '8px' marginBottom: '8px',
fontFamily: "'Share Tech Mono', monospace"
}, },
title: { title: {
color: '#60a5fa', color: '#00FFFF',
fontSize: '20px', fontSize: '20px',
fontWeight: 'bold', fontWeight: 'bold',
marginBottom: '8px' marginBottom: '8px',
fontFamily: "'Orbitron', monospace"
}, },
scenario: { scenario: {
color: '#e2e8f0', color: '#ccc',
fontSize: '16px', fontSize: '16px',
lineHeight: '1.5', lineHeight: '1.5',
whiteSpace: 'pre-line' whiteSpace: 'pre-line',
fontFamily: "'Share Tech Mono', monospace"
}, },
hint: { hint: {
color: '#94a3b8', color: '#888',
fontSize: '13px', fontSize: '13px',
marginBottom: '12px', marginBottom: '12px',
fontStyle: 'italic' fontStyle: 'italic'
@ -427,10 +433,10 @@ const styles: Record<string, React.CSSProperties> = {
}, },
option: { option: {
padding: '16px', padding: '16px',
borderRadius: '12px', borderRadius: '6px',
border: '2px solid #475569', border: '1px solid rgba(0,255,255,0.2)',
backgroundColor: '#334155', backgroundColor: '#0a0a1a',
color: '#f1f5f9', color: '#ccc',
cursor: 'pointer', cursor: 'pointer',
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
@ -440,16 +446,16 @@ const styles: Record<string, React.CSSProperties> = {
fontSize: '15px' fontSize: '15px'
}, },
optionSelected: { optionSelected: {
borderColor: '#3b82f6', borderColor: '#FF00FF',
backgroundColor: '#2563eb' backgroundColor: 'rgba(255,0,255,0.1)'
}, },
optionCorrect: { optionCorrect: {
borderColor: '#22c55e', borderColor: '#00FF41',
backgroundColor: '#16a34a' backgroundColor: 'rgba(0,255,65,0.12)'
}, },
optionWrong: { optionWrong: {
borderColor: '#ef4444', borderColor: '#FF0040',
backgroundColor: '#dc2626' backgroundColor: 'rgba(255,0,64,0.12)'
}, },
optionDisabled: { optionDisabled: {
opacity: 0.6, opacity: 0.6,
@ -459,7 +465,8 @@ const styles: Record<string, React.CSSProperties> = {
width: '28px', width: '28px',
height: '28px', height: '28px',
borderRadius: '50%', borderRadius: '50%',
backgroundColor: 'rgba(0,0,0,0.3)', backgroundColor: 'rgba(0,255,255,0.1)',
color: '#00FFFF',
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
@ -469,14 +476,14 @@ const styles: Record<string, React.CSSProperties> = {
}, },
explanation: { explanation: {
padding: '24px', padding: '24px',
borderTop: '1px solid #334155', borderTop: '1px solid rgba(0,255,255,0.15)',
backgroundColor: 'rgba(0,0,0,0.2)' backgroundColor: 'rgba(0,0,0,0.3)'
}, },
explanationCorrect: { explanationCorrect: {
backgroundColor: 'rgba(22, 163, 74, 0.1)' backgroundColor: 'rgba(0,255,65,0.08)'
}, },
explanationWrong: { explanationWrong: {
backgroundColor: 'rgba(220, 38, 38, 0.1)' backgroundColor: 'rgba(255,0,64,0.08)'
}, },
resultTitle: { resultTitle: {
fontWeight: 'bold', fontWeight: 'bold',
@ -487,9 +494,10 @@ const styles: Record<string, React.CSSProperties> = {
gap: '8px' gap: '8px'
}, },
explanationText: { explanationText: {
color: '#cbd5e1', color: '#aaa',
lineHeight: '1.6', lineHeight: '1.6',
marginBottom: '12px' marginBottom: '12px',
fontFamily: "'Share Tech Mono', monospace"
}, },
tags: { tags: {
display: 'flex', display: 'flex',
@ -498,52 +506,57 @@ const styles: Record<string, React.CSSProperties> = {
marginBottom: '16px' marginBottom: '16px'
}, },
tag: { tag: {
backgroundColor: '#475569', backgroundColor: 'rgba(0,255,255,0.08)',
color: '#cbd5e1', color: '#00FFFF',
padding: '4px 10px', padding: '4px 10px',
borderRadius: '6px', borderRadius: '6px',
fontSize: '12px', fontSize: '12px',
fontFamily: 'monospace' fontFamily: 'monospace',
border: '1px solid rgba(0,255,255,0.3)'
}, },
analysis: { analysis: {
backgroundColor: 'rgba(0,0,0,0.3)', backgroundColor: 'rgba(0,0,0,0.3)',
padding: '12px', padding: '12px',
borderRadius: '8px', borderRadius: '8px',
fontSize: '13px', fontSize: '13px',
color: '#94a3b8', color: '#888',
marginBottom: '16px' marginBottom: '16px'
}, },
button: { button: {
width: '100%', width: '100%',
padding: '14px', padding: '14px',
borderRadius: '10px', borderRadius: '6px',
border: 'none', border: 'none',
backgroundColor: '#3b82f6', backgroundColor: '#00FFFF',
color: 'white', color: '#000',
fontWeight: 'bold', fontWeight: 'bold',
fontSize: '16px', fontSize: '16px',
cursor: 'pointer', cursor: 'pointer',
transition: 'background 0.2s' transition: 'background 0.2s',
fontFamily: "'Orbitron', monospace"
}, },
buttonDisabled: { buttonDisabled: {
backgroundColor: '#475569', backgroundColor: 'rgba(0,255,255,0.1)',
color: '#444',
cursor: 'not-allowed' cursor: 'not-allowed'
}, },
backButton: { backButton: {
marginTop: '20px', marginTop: '20px',
padding: '10px 20px', padding: '10px 20px',
backgroundColor: 'transparent', backgroundColor: 'transparent',
border: '1px solid #475569', border: '1px solid rgba(0,255,255,0.3)',
color: '#94a3b8', color: '#888',
borderRadius: '8px', borderRadius: '8px',
cursor: 'pointer', cursor: 'pointer',
fontSize: '14px' fontSize: '14px',
fontFamily: "'Orbitron', monospace"
}, },
completionStatus: { completionStatus: {
marginTop: '8px', marginTop: '8px',
fontSize: '14px', fontSize: '14px',
color: '#22c55e', color: '#00FF41',
fontWeight: 'bold' fontWeight: 'bold',
fontFamily: "'Share Tech Mono', monospace"
} }
}; };
@ -573,31 +586,31 @@ const Quiz: React.FC<QuizProps> = ({ questions, title, testId, onBack, onComplet
<h2 style={{ color: '#f8fafc', marginBottom: '8px' }}> <h2 style={{ color: '#f8fafc', marginBottom: '8px' }}>
{title} завершён! {title} завершён!
</h2> </h2>
{isPerfect && ( {isPerfect && (
<div style={{ <div style={{
backgroundColor: 'rgba(34, 197, 94, 0.2)', backgroundColor: 'rgba(0,255,65,0.1)',
border: '2px solid #22c55e', border: '1px solid #00FF41',
borderRadius: '12px', borderRadius: '12px',
padding: '12px', padding: '12px',
marginBottom: '20px', marginBottom: '20px',
color: '#4ade80', color: '#00FF41',
fontWeight: 'bold' fontWeight: 'bold'
}}> }}>
Все ответы правильные! Все ответы правильные!
</div> </div>
)} )}
<div style={{ <div style={{
fontSize: '56px', fontSize: '56px',
fontWeight: 'bold', fontWeight: 'bold',
color: '#60a5fa', color: '#00FFFF',
marginBottom: '8px' marginBottom: '8px'
}}> }}>
{percent}% {percent}%
</div> </div>
<div style={{ color: '#94a3b8', marginBottom: '32px' }}> <div style={{ color: '#888', marginBottom: '32px' }}>
Правильно: {score} из {questions.length} Правильно: {score} из {questions.length}
</div> </div>
@ -636,17 +649,9 @@ const Quiz: React.FC<QuizProps> = ({ questions, title, testId, onBack, onComplet
Пройти снова Пройти снова
</button> </button>
<button <button
onClick={onBack} onClick={onBack}
style={{ style={styles.backButton}
padding: '14px',
borderRadius: '10px',
border: '1px solid #475569',
backgroundColor: 'transparent',
color: '#94a3b8',
fontSize: '16px',
cursor: 'pointer'
}}
> >
В главное меню В главное меню
</button> </button>
@ -737,7 +742,7 @@ const Quiz: React.FC<QuizProps> = ({ questions, title, testId, onBack, onComplet
<div style={styles.card}> <div style={styles.card}>
<div style={styles.header}> <div style={styles.header}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '16px' }}> <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '16px' }}>
<span style={{ color: '#60a5fa', fontWeight: 'bold' }}>{title}</span> <span style={{ color: '#00FFFF', fontWeight: 'bold' }}>{title}</span>
<button onClick={onBack} style={{ ...styles.backButton, margin: 0 }}></button> <button onClick={onBack} style={{ ...styles.backButton, margin: 0 }}></button>
</div> </div>
<div style={styles.progressBar}> <div style={styles.progressBar}>
@ -778,7 +783,7 @@ const Quiz: React.FC<QuizProps> = ({ questions, title, testId, onBack, onComplet
}}> }}>
<div style={{ <div style={{
...styles.resultTitle, ...styles.resultTitle,
color: isCorrect ? '#4ade80' : '#f87171' color: isCorrect ? '#00FF41' : '#FF0040'
}}> }}>
<span>{isCorrect ? '✅' : '❌'}</span> <span>{isCorrect ? '✅' : '❌'}</span>
<span>{isCorrect ? 'Правильно!' : 'Ошибка'}</span> <span>{isCorrect ? 'Правильно!' : 'Ошибка'}</span>
@ -866,7 +871,7 @@ const MainMenu: React.FC<MainMenuProps> = ({ onSelect, completedTests }) => {
style={{ style={{
...styles.menuButton, ...styles.menuButton,
...(isCompleted ? styles.menuButtonCompleted : {}), ...(isCompleted ? styles.menuButtonCompleted : {}),
...(isHovered && !isCompleted ? { borderColor: test.color, transform: 'translateY(-2px)' } : {}) ...(isHovered && !isCompleted ? { borderColor: test.color || '#00FFFF', transform: 'translateY(-2px)' } : {})
}} }}
onMouseEnter={() => setHovered(index)} onMouseEnter={() => setHovered(index)}
onMouseLeave={() => setHovered(null)} onMouseLeave={() => setHovered(null)}
@ -879,7 +884,7 @@ const MainMenu: React.FC<MainMenuProps> = ({ onSelect, completedTests }) => {
<span>{test.title}</span> <span>{test.title}</span>
{isCompleted && <span style={{ color: '#22c55e' }}></span>} {isCompleted && <span style={{ color: '#22c55e' }}></span>}
</div> </div>
<div style={{ fontSize: '13px', color: '#94a3b8', marginTop: '4px', fontWeight: 'normal' }}> <div style={{ fontSize: '13px', color: '#888', marginTop: '4px', fontWeight: 'normal' }}>
{test.desc} {test.desc}
</div> </div>
{isCompleted && ( {isCompleted && (