diff options
| author | Yuval Adam <_@yuv.al> | 2025-03-07 13:12:43 +0100 |
|---|---|---|
| committer | Yuval Adam <_@yuv.al> | 2025-03-07 13:12:43 +0100 |
| commit | a6fac18fb89d7268ac5ce1026f3bffd2e9f275a7 (patch) | |
| tree | 08d2763d51951557da24399464941f9581dfb657 | |
| parent | a5e22c91da6d4e0fdf8505229fc2fa2ee0808d94 (diff) | |
Initial fatter design and copy
| -rw-r--r-- | public/img/morse-pattern.svg | 29 | ||||
| -rw-r--r-- | public/vite.svg | 1 | ||||
| -rw-r--r-- | src/pages/HomePage.tsx | 123 | ||||
| -rw-r--r-- | src/pages/chart/ChartPage.tsx | 51 | ||||
| -rw-r--r-- | src/styles.css | 856 |
5 files changed, 1000 insertions, 60 deletions
diff --git a/public/img/morse-pattern.svg b/public/img/morse-pattern.svg new file mode 100644 index 0000000..d7eacb3 --- /dev/null +++ b/public/img/morse-pattern.svg @@ -0,0 +1,29 @@ +<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"> + <defs> + <pattern id="morse-pattern" patternUnits="userSpaceOnUse" width="100" height="100"> + <!-- Dots --> + <circle cx="10" cy="10" r="2" fill="#ffffff" /> + <circle cx="50" cy="10" r="2" fill="#ffffff" /> + <circle cx="90" cy="10" r="2" fill="#ffffff" /> + <circle cx="10" cy="50" r="2" fill="#ffffff" /> + <circle cx="50" cy="50" r="2" fill="#ffffff" /> + <circle cx="90" cy="50" r="2" fill="#ffffff" /> + <circle cx="10" cy="90" r="2" fill="#ffffff" /> + <circle cx="50" cy="90" r="2" fill="#ffffff" /> + <circle cx="90" cy="90" r="2" fill="#ffffff" /> + + <!-- Dashes --> + <rect x="20" y="30" width="15" height="3" fill="#ffffff" /> + <rect x="60" y="30" width="15" height="3" fill="#ffffff" /> + <rect x="20" y="70" width="15" height="3" fill="#ffffff" /> + <rect x="60" y="70" width="15" height="3" fill="#ffffff" /> + + <!-- Diagonal dashes --> + <rect x="25" y="15" width="15" height="3" transform="rotate(45 25 15)" fill="#ffffff" /> + <rect x="75" y="65" width="15" height="3" transform="rotate(45 75 65)" fill="#ffffff" /> + <rect x="25" y="65" width="15" height="3" transform="rotate(-45 25 65)" fill="#ffffff" /> + <rect x="75" y="15" width="15" height="3" transform="rotate(-45 75 15)" fill="#ffffff" /> + </pattern> + </defs> + <rect width="100" height="100" fill="url(#morse-pattern)" /> +</svg> diff --git a/public/vite.svg b/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
\ No newline at end of file diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx index 6a8c9c7..f7f65dd 100644 --- a/src/pages/HomePage.tsx +++ b/src/pages/HomePage.tsx @@ -18,6 +18,7 @@ const HomePage = () => { const [options, setOptions] = useState<string[]>([]); const [wpm, setWpm] = useState(20); const [showHints, setShowHints] = useState(false); + const [showHowToPlay, setShowHowToPlay] = useState(false); const actxRef = useRef<any>(null); const optionButtonsRef = useRef<Array<HTMLButtonElement | null>>([null, null, null, null]); @@ -234,10 +235,63 @@ const HomePage = () => { { !gameStarted ? ( <div id="startScreen"> - <p>Learn Morse code the fun way!</p> - <button id="startButton" className="start-button" onClick={startGame}>Start</button> - <div className="chart-link"> - <Link to="/chart">View Morse Code Chart</Link> + <div className="hero-content"> + <h2>Master Morse Code Through Play</h2> + <p>Morse Hero turns learning Morse code into an engaging game. Listen to the signals, identify the characters, and improve your skills with every round.</p> + + <div className="feature-grid"> + <div className="feature-item"> + <div className="feature-icon">🎮</div> + <h3>Interactive Learning</h3> + <p>Learn by doing with our interactive game format</p> + </div> + <div className="feature-item"> + <div className="feature-icon">🔊</div> + <h3>Audio Recognition</h3> + <p>Train your ear to recognize Morse code sounds</p> + </div> + <div className="feature-item"> + <div className="feature-icon">📈</div> + <h3>Track Progress</h3> + <p>See your improvement with each practice session</p> + </div> + <div className="feature-item"> + <div className="feature-icon">âš¡</div> + <h3>Adjustable Speed</h3> + <p>Set your own pace as you build your skills</p> + </div> + </div> + + <div className="cta-container"> + <button id="startButton" className="start-button" onClick={startGame}> + Start Playing + <span className="button-morse">· − · − ·</span> + </button> + <button className="how-to-play-button" onClick={() => setShowHowToPlay(!showHowToPlay)}> + {showHowToPlay ? 'Hide Instructions' : 'How to Play'} + </button> + </div> + + {showHowToPlay && ( + <div className="how-to-play"> + <h3>How to Play Morse Hero</h3> + <ol> + <li>Listen to the Morse code sound played</li> + <li>Select the correct character from the four options</li> + <li>Use keyboard keys that match the displayed characters for faster play</li> + <li>Enable hints if you need help seeing the Morse patterns</li> + <li>Adjust the speed to match your skill level</li> + </ol> + <div className="morse-fact"> + <h4>Did You Know?</h4> + <p>Morse code was developed by Samuel Morse and Alfred Vail in the 1830s and revolutionized long-distance communication.</p> + </div> + </div> + )} + + <div className="chart-link"> + <Link to="/chart">View Morse Code Chart</Link> + </div> </div> </div> ) : ( @@ -255,6 +309,13 @@ const HomePage = () => { </div> <div className="game-container"> + <div className="game-instructions"> + <p>Listen to the Morse code and select the correct character</p> + <button className="replay-button" onClick={() => playMorseCode(currentChar)}> + <span className="replay-icon">↻</span> Replay Sound + </button> + </div> + <div className="options"> {options.map((option, index) => ( <button @@ -272,19 +333,21 @@ const HomePage = () => { </div> <div className="settings"> - <label htmlFor="wpmSelect">Speed:</label> - <select - id="wpmSelect" - value={wpm} - onChange={(e) => setWpm(parseInt(e.target.value))} - > - <option value="10">10 WPM</option> - <option value="15">15 WPM</option> - <option value="20">20 WPM</option> - <option value="25">25 WPM</option> - <option value="30">30 WPM</option> - </select> - <div className="hint-setting"> + <div className="setting-group"> + <label htmlFor="wpmSelect">Speed:</label> + <select + id="wpmSelect" + value={wpm} + onChange={(e) => setWpm(parseInt(e.target.value))} + > + <option value="10">10 WPM</option> + <option value="15">15 WPM</option> + <option value="20">20 WPM</option> + <option value="25">25 WPM</option> + <option value="30">30 WPM</option> + </select> + </div> + <div className="setting-group hint-setting"> <input type="checkbox" id="hintMode" @@ -294,6 +357,11 @@ const HomePage = () => { /> <label htmlFor="hintMode">Show Hints</label> </div> + <button className="reset-button" onClick={resetGame}>New Game</button> + </div> + + <div className="keyboard-tip"> + <p>Pro Tip: Use your keyboard to select options faster!</p> </div> </div> </div> @@ -301,9 +369,24 @@ const HomePage = () => { } <footer className="footer"> - <p>Need help? View the <Link to="/chart">Morse Code Chart</Link>. </p> - <p>Created with <a href="https://www.mastercw.com/cw.js/">CW.js</a>. For a complete and professional - Morse Code training solution visit <a href="https://www.mastercw.com">Master CW</a>.</p> + <div className="footer-content"> + <div className="footer-section"> + <h3>About Morse Code</h3> + <p>Morse code is a method of transmitting text as a series of on-off tones, lights, or clicks that can be understood by a skilled listener without specialized equipment.</p> + </div> + <div className="footer-section"> + <h3>Quick Links</h3> + <ul> + <li><Link to="/chart">Morse Code Chart</Link></li> + <li><a href="https://en.wikipedia.org/wiki/Morse_code" target="_blank" rel="noopener noreferrer">Learn More</a></li> + </ul> + </div> + </div> + <div className="footer-bottom"> + <p>Created with <a href="https://www.mastercw.com/cw.js/">CW.js</a>. For a complete and professional + Morse Code training solution visit <a href="https://www.mastercw.com">Master CW</a>.</p> + <p>© {new Date().getFullYear()} Morse Hero - Practice Morse Code the Fun Way</p> + </div> </footer> </div > ); diff --git a/src/pages/chart/ChartPage.tsx b/src/pages/chart/ChartPage.tsx index e8bf7bc..0492265 100644 --- a/src/pages/chart/ChartPage.tsx +++ b/src/pages/chart/ChartPage.tsx @@ -83,7 +83,24 @@ const ChartPage = () => { <h1 className="title-link"> <Link to="/" style={{ color: 'inherit', textDecoration: 'inherit' }}>Morse Hero</Link> </h1> - <h2>Morse Code Chart</h2> + + <div className="page-intro"> + <h2>Morse Code Reference Chart</h2> + <p>Click on any character to hear its Morse code sound. Practice recognizing these patterns to improve your Morse code skills.</p> + </div> + + <div className="morse-info-card"> + <h3>Understanding Morse Code</h3> + <p>Morse code uses dots (·) and dashes (−) to represent letters, numbers, and special characters. A dash is three times as long as a dot. The space between parts of the same letter is one dot length, between letters is three dot lengths, and between words is seven dot lengths.</p> + <div className="morse-tips"> + <h4>Memorization Tips</h4> + <ul> + <li>E (·) and T (−) are the most common letters in English and have the shortest codes</li> + <li>Letters with similar sounds often have related patterns (e.g., S and O: S = ··· and O = −−−)</li> + <li>Practice regularly with common words to build muscle memory</li> + </ul> + </div> + </div> <div className="chart-section"> <h2>Letters</h2> @@ -120,15 +137,39 @@ const ChartPage = () => { ))} </div> </div> + + <div className="morse-history"> + <h3>History of Morse Code</h3> + <div className="history-content"> + <p>Morse code was developed in the 1830s by Samuel Morse and Alfred Vail for use with the telegraph. It revolutionized long-distance communication and remained the standard for telegraph communication for over 160 years.</p> + <p>The original Morse code was slightly different from what we use today. The International Morse Code, which is the standard now, was created in 1865 to accommodate languages other than English.</p> + <p>Though largely replaced by newer technologies, Morse code remains important in aviation, amateur radio, and emergencies where other communication systems might fail.</p> + </div> + </div> <div className="back-link"> - <Link to="/">Back to Morse Hero</Link> + <Link to="/">Back to Morse Hero Game</Link> </div> <footer className="footer"> - <p>Click on any character to hear its Morse code sound.</p> - <p>Created with <a href="https://www.mastercw.com/cw.js/">CW.js</a>. For a complete and professional - Morse Code training solution visit <a href="https://www.mastercw.com">Master CW</a>.</p> + <div className="footer-content"> + <div className="footer-section"> + <h3>About Morse Code</h3> + <p>Morse code is a method of transmitting text as a series of on-off tones, lights, or clicks that can be understood by a skilled listener without specialized equipment.</p> + </div> + <div className="footer-section"> + <h3>Quick Links</h3> + <ul> + <li><Link to="/">Morse Hero Game</Link></li> + <li><a href="https://en.wikipedia.org/wiki/Morse_code" target="_blank" rel="noopener noreferrer">Learn More</a></li> + </ul> + </div> + </div> + <div className="footer-bottom"> + <p>Created with <a href="https://www.mastercw.com/cw.js/">CW.js</a>. For a complete and professional + Morse Code training solution visit <a href="https://www.mastercw.com">Master CW</a>.</p> + <p>© {new Date().getFullYear()} Morse Hero - Practice Morse Code the Fun Way</p> + </div> </footer> </div> ); diff --git a/src/styles.css b/src/styles.css index 50ebaea..b2a0e62 100644 --- a/src/styles.css +++ b/src/styles.css @@ -21,6 +21,11 @@ --shadow-lg: 0 15px 30px rgba(0, 0, 0, 0.2); --transition-fast: 0.2s ease; --transition-normal: 0.3s ease; + --card-bg: rgba(52, 73, 94, 0.6); + --card-border: rgba(255, 255, 255, 0.1); + --header-height: 70px; + --footer-height: 100px; + --glow-color: rgba(243, 156, 18, 0.6); } * { @@ -34,6 +39,7 @@ body { margin: 0; padding: 0; background: radial-gradient(ellipse at top, var(--bg-dark) 0%, var(--bg-darker) 100%); + background-attachment: fixed; color: var(--text-light); min-height: 100vh; display: flex; @@ -42,14 +48,31 @@ body { justify-content: center; font-size: 18px; line-height: 1.6; + position: relative; + overflow-x: hidden; +} + +body::before { + content: ""; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: url('/img/morse-pattern.svg') repeat; + opacity: 0.03; + z-index: -1; + pointer-events: none; } .container { - max-width: 900px; + max-width: 1000px; margin: 0 auto; padding: 30px 20px; text-align: center; width: 100%; + position: relative; + z-index: 1; } button { @@ -63,6 +86,7 @@ button { outline: none; position: relative; overflow: hidden; + box-shadow: var(--shadow-md); } button::after { @@ -81,16 +105,44 @@ button:hover::after { opacity: 1; } +button:active { + transform: translateY(2px); + box-shadow: var(--shadow-sm); +} + .title-link { text-decoration: none; transition: all var(--transition-normal); position: relative; display: inline-block; + font-size: 3rem; + font-weight: 700; + margin-bottom: 1rem; + color: var(--text-light); + text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); + letter-spacing: 2px; } .title-link:hover { color: var(--secondary-color); - text-shadow: 0 0 15px rgba(243, 156, 18, 0.6); + text-shadow: 0 0 15px var(--glow-color); +} + +.title-link::after { + content: ""; + position: absolute; + bottom: -5px; + left: 50%; + transform: translateX(-50%); + width: 0; + height: 3px; + background: var(--secondary-color); + transition: width var(--transition-normal); + box-shadow: 0 0 10px var(--glow-color); +} + +.title-link:hover::after { + width: 80%; } .footer { @@ -99,42 +151,12 @@ button:hover::after { text-align: center; font-size: 16px; color: var(--text-dim); - width: 100%; border-top: 1px solid rgba(255, 255, 255, 0.1); -} - -.footer a { - color: var(--primary-color); - text-decoration: none; - font-weight: bold; - transition: color var(--transition-normal); - position: relative; -} - -.footer a::after { - content: ''; - position: absolute; width: 100%; - transform: scaleX(0); - height: 2px; - bottom: -2px; - left: 0; - background-color: var(--primary-color); - transform-origin: bottom right; - transition: transform 0.3s ease-out; -} - -.footer a:hover { - color: var(--secondary-color); -} - -.footer a:hover::after { - transform: scaleX(1); - transform-origin: bottom left; + background: linear-gradient(to top, rgba(26, 37, 48, 0.8), transparent); + backdrop-filter: blur(5px); } -/* Morse Hero Main Styles */ - h1 { font-size: 5.5em; margin-top: 0.5rem; @@ -910,4 +932,770 @@ body.game-active #startScreen { transform: scaleX(1); transform-origin: bottom left; background-color: var(--secondary-color); +} + +.option-button { + background: linear-gradient(145deg, var(--primary-color), var(--primary-dark)); + color: white; + border-radius: var(--border-radius-md); + font-size: 36px; + padding: 20px; + margin: 10px; + width: calc(50% - 20px); + height: 120px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + position: relative; + overflow: hidden; + transition: all var(--transition-normal); + border: 1px solid rgba(255, 255, 255, 0.1); + box-shadow: var(--shadow-md), inset 0 1px rgba(255, 255, 255, 0.15); +} + +.option-button:hover { + transform: translateY(-3px); + box-shadow: var(--shadow-lg), inset 0 1px rgba(255, 255, 255, 0.15); +} + +.option-button:active { + transform: translateY(1px); + box-shadow: var(--shadow-sm), inset 0 1px rgba(255, 255, 255, 0.15); +} + +.option-button.correct { + background: linear-gradient(145deg, var(--success-color), var(--success-dark)); + animation: correct-pulse 1s infinite; +} + +.option-button.incorrect { + background: linear-gradient(145deg, var(--accent-color), var(--accent-dark)); + animation: incorrect-shake 0.5s; +} + +/* Start screen styles */ +#startScreen { + max-width: 600px; + margin: 0 auto; + padding: 30px; + background: var(--card-bg); + border-radius: var(--border-radius-lg); + box-shadow: var(--shadow-lg); + border: 1px solid var(--card-border); + backdrop-filter: blur(10px); + animation: fadeIn 0.8s ease-out; +} + +#startScreen p { + font-size: 1.3rem; + margin-bottom: 1.5rem; + color: var(--text-light); + line-height: 1.6; +} + +.start-button { + background: linear-gradient(145deg, var(--secondary-color), var(--secondary-dark)); + color: white; + font-size: 1.5rem; + padding: 15px 40px; + border-radius: var(--border-radius-md); + margin: 20px 0; + position: relative; + overflow: hidden; + transition: all var(--transition-normal); + box-shadow: var(--shadow-md), 0 0 15px rgba(243, 156, 18, 0.3); +} + +.start-button:hover { + transform: translateY(-3px) scale(1.05); + box-shadow: var(--shadow-lg), 0 0 20px rgba(243, 156, 18, 0.5); +} + +.start-button:active { + transform: translateY(1px); +} + +.chart-link { + margin-top: 20px; +} + +.chart-link a { + color: var(--text-light); + text-decoration: none; + font-weight: 600; + transition: all var(--transition-normal); + position: relative; + padding: 5px 10px; + border-radius: var(--border-radius-sm); +} + +.chart-link a::after { + content: ""; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 2px; + background: var(--primary-color); + transform: scaleX(0); + transform-origin: right; + transition: transform var(--transition-normal); +} + +.chart-link a:hover { + color: var(--primary-color); +} + +.chart-link a:hover::after { + transform: scaleX(1); + transform-origin: left; +} + +/* Game area styles */ +#gameArea { + animation: fadeIn 0.5s ease-out; +} + +.game-container { + background: var(--card-bg); + border-radius: var(--border-radius-lg); + padding: 30px; + margin: 20px 0; + box-shadow: var(--shadow-lg); + border: 1px solid var(--card-border); + backdrop-filter: blur(10px); +} + +/* Chart page styles */ +.chart-section { + background: var(--card-bg); + border-radius: var(--border-radius-lg); + padding: 30px; + margin: 30px 0; + box-shadow: var(--shadow-lg); + border: 1px solid var(--card-border); + backdrop-filter: blur(10px); + animation: fadeIn 0.5s ease-out; +} + +.chart-section h2 { + margin-bottom: 20px; + color: var(--secondary-color); + font-weight: 600; + position: relative; + display: inline-block; +} + +.chart-section h2::after { + content: ""; + position: absolute; + bottom: -5px; + left: 50%; + transform: translateX(-50%); + width: 50px; + height: 3px; + background: var(--secondary-color); + border-radius: 3px; +} + +/* New animations */ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes correct-pulse { + 0% { + box-shadow: 0 0 0 0 rgba(46, 204, 113, 0.4); + } + + 70% { + box-shadow: 0 0 0 15px rgba(46, 204, 113, 0); + } + + 100% { + box-shadow: 0 0 0 0 rgba(46, 204, 113, 0); + } +} + +@keyframes incorrect-shake { + + 0%, + 100% { + transform: translateX(0); + } + + 20%, + 60% { + transform: translateX(-5px); + } + + 40%, + 80% { + transform: translateX(5px); + } +} + +/* Media queries for responsiveness */ +@media (max-width: 768px) { + .title-link { + font-size: 2.5rem; + } + + .option-button { + font-size: 28px; + height: 100px; + } + + .chart-section { + padding: 20px; + } +} + +@media (max-width: 480px) { + .title-link { + font-size: 2rem; + } + + .option-button { + font-size: 24px; + height: 90px; + width: calc(50% - 10px); + margin: 5px; + } + + .start-button { + font-size: 1.2rem; + padding: 12px 30px; + } +} + +/* Hero content styles */ +.hero-content { + text-align: center; +} + +.hero-content h2 { + font-size: 1.8rem; + margin-bottom: 1rem; + color: var(--secondary-color); + font-weight: 600; +} + +.hero-content > p { + font-size: 1.2rem; + margin-bottom: 2rem; + max-width: 80%; + margin-left: auto; + margin-right: auto; +} + +/* Feature grid */ +.feature-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 20px; + margin: 30px 0; +} + +.feature-item { + background: rgba(255, 255, 255, 0.05); + border-radius: var(--border-radius-md); + padding: 20px; + transition: all var(--transition-normal); + border: 1px solid rgba(255, 255, 255, 0.05); +} + +.feature-item:hover { + transform: translateY(-5px); + box-shadow: var(--shadow-md); + background: rgba(255, 255, 255, 0.1); + border-color: rgba(255, 255, 255, 0.1); +} + +.feature-icon { + font-size: 2rem; + margin-bottom: 10px; +} + +.feature-item h3 { + font-size: 1.2rem; + margin-bottom: 10px; + color: var(--primary-color); +} + +.feature-item p { + font-size: 0.9rem; + color: var(--text-dim); +} + +/* CTA container */ +.cta-container { + display: flex; + flex-direction: column; + align-items: center; + gap: 15px; + margin: 30px 0; +} + +.button-morse { + display: block; + font-size: 0.8rem; + margin-top: 5px; + opacity: 0.8; +} + +.how-to-play-button { + background: transparent; + color: var(--text-light); + border: 1px solid rgba(255, 255, 255, 0.2); + padding: 10px 20px; + border-radius: var(--border-radius-md); + font-size: 1rem; + transition: all var(--transition-normal); +} + +.how-to-play-button:hover { + background: rgba(255, 255, 255, 0.1); + border-color: rgba(255, 255, 255, 0.3); +} + +/* How to play section */ +.how-to-play { + background: rgba(255, 255, 255, 0.05); + border-radius: var(--border-radius-md); + padding: 20px; + margin: 20px 0; + border: 1px solid rgba(255, 255, 255, 0.1); + animation: fadeIn 0.5s ease-out; +} + +.how-to-play h3 { + font-size: 1.3rem; + margin-bottom: 15px; + color: var(--primary-color); +} + +.how-to-play ol { + text-align: left; + padding-left: 30px; + margin-bottom: 20px; +} + +.how-to-play li { + margin-bottom: 10px; + color: var(--text-light); +} + +.morse-fact { + background: rgba(52, 152, 219, 0.1); + border-radius: var(--border-radius-sm); + padding: 15px; + border-left: 3px solid var(--primary-color); + text-align: left; +} + +.morse-fact h4 { + color: var(--primary-color); + margin-bottom: 5px; + font-size: 1.1rem; +} + +.morse-fact p { + font-size: 0.9rem; + color: var(--text-dim); +} + +/* Game instructions */ +.game-instructions { + margin-bottom: 20px; + padding-bottom: 20px; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); +} + +.game-instructions p { + margin-bottom: 15px; +} + +.replay-button { + background: linear-gradient(145deg, var(--primary-color), var(--primary-dark)); + color: white; + padding: 8px 15px; + border-radius: var(--border-radius-sm); + font-size: 0.9rem; + display: inline-flex; + align-items: center; + gap: 8px; +} + +.replay-icon { + font-size: 1.2rem; +} + +/* Settings styles */ +.settings { + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; + gap: 20px; + margin-top: 20px; + padding-top: 20px; + border-top: 1px solid rgba(255, 255, 255, 0.1); +} + +.setting-group { + display: flex; + align-items: center; + gap: 10px; +} + +.reset-button { + background: linear-gradient(145deg, var(--accent-color), var(--accent-dark)); + color: white; + padding: 8px 15px; + border-radius: var(--border-radius-sm); + font-size: 0.9rem; +} + +.keyboard-tip { + margin-top: 20px; + font-size: 0.9rem; + color: var(--text-dim); + font-style: italic; +} + +/* Enhanced footer */ +.footer { + margin-top: 60px; + padding: 40px 20px 20px; +} + +.footer-content { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + gap: 30px; + margin-bottom: 30px; + text-align: left; +} + +.footer-section { + flex: 1; + min-width: 250px; +} + +.footer-section h3 { + font-size: 1.2rem; + margin-bottom: 15px; + color: var(--text-light); + position: relative; + display: inline-block; +} + +.footer-section h3::after { + content: ""; + position: absolute; + bottom: -5px; + left: 0; + width: 30px; + height: 2px; + background: var(--primary-color); +} + +.footer-section p { + color: var(--text-dim); + line-height: 1.6; +} + +.footer-section ul { + list-style: none; + padding: 0; +} + +.footer-section li { + margin-bottom: 10px; +} + +.footer-section a { + color: var(--primary-color); + text-decoration: none; + transition: all var(--transition-normal); + position: relative; +} + +.footer-section a::after { + content: ''; + position: absolute; + width: 100%; + transform: scaleX(0); + height: 1px; + bottom: -2px; + left: 0; + background-color: var(--primary-color); + transform-origin: bottom right; + transition: transform 0.3s ease-out; +} + +.footer-section a:hover { + color: var(--secondary-color); +} + +.footer-section a:hover::after { + transform: scaleX(1); + transform-origin: bottom left; +} + +.footer-bottom { + padding-top: 20px; + border-top: 1px solid rgba(255, 255, 255, 0.1); + text-align: center; +} + +.footer-bottom p { + margin-bottom: 10px; +} + +.footer-bottom a { + color: var(--primary-color); + text-decoration: none; + font-weight: 600; + transition: color var(--transition-normal); +} + +.footer-bottom a:hover { + color: var(--secondary-color); +} + +/* Media queries for responsiveness */ +@media (max-width: 768px) { + .feature-grid { + grid-template-columns: 1fr; + } + + .footer-content { + flex-direction: column; + } + + .hero-content > p { + max-width: 100%; + } +} + +/* Chart page specific styles */ +.page-intro { + text-align: center; + margin-bottom: 30px; +} + +.page-intro h2 { + font-size: 2rem; + color: var(--secondary-color); + margin-bottom: 15px; + font-weight: 600; +} + +.page-intro p { + font-size: 1.1rem; + max-width: 700px; + margin: 0 auto; + color: var(--text-dim); +} + +.morse-info-card { + background: var(--card-bg); + border-radius: var(--border-radius-lg); + padding: 30px; + margin: 30px 0; + box-shadow: var(--shadow-lg); + border: 1px solid var(--card-border); + backdrop-filter: blur(10px); + animation: fadeIn 0.5s ease-out; + text-align: left; +} + +.morse-info-card h3 { + font-size: 1.5rem; + margin-bottom: 15px; + color: var(--primary-color); +} + +.morse-info-card p { + line-height: 1.7; + margin-bottom: 20px; +} + +.morse-tips { + background: rgba(255, 255, 255, 0.05); + border-radius: var(--border-radius-md); + padding: 20px; + border-left: 3px solid var(--secondary-color); +} + +.morse-tips h4 { + color: var(--secondary-color); + margin-bottom: 15px; + font-size: 1.2rem; +} + +.morse-tips ul { + padding-left: 20px; +} + +.morse-tips li { + margin-bottom: 10px; + color: var(--text-dim); +} + +.morse-history { + background: var(--card-bg); + border-radius: var(--border-radius-lg); + padding: 30px; + margin: 30px 0; + box-shadow: var(--shadow-lg); + border: 1px solid var(--card-border); + backdrop-filter: blur(10px); + animation: fadeIn 0.5s ease-out; + text-align: left; +} + +.morse-history h3 { + font-size: 1.5rem; + margin-bottom: 20px; + color: var(--primary-color); + text-align: center; +} + +.history-content { + display: flex; + flex-direction: column; + gap: 15px; +} + +.history-content p { + line-height: 1.7; + color: var(--text-dim); +} + +.morse-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); + gap: 15px; + margin: 20px 0; +} + +.morse-item { + background: rgba(255, 255, 255, 0.05); + border-radius: var(--border-radius-md); + padding: 15px 10px; + cursor: pointer; + transition: all var(--transition-normal); + border: 1px solid rgba(255, 255, 255, 0.05); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + position: relative; + overflow: hidden; +} + +.morse-item:hover { + transform: translateY(-3px); + background: rgba(255, 255, 255, 0.1); + box-shadow: var(--shadow-md); + border-color: rgba(255, 255, 255, 0.1); +} + +.morse-item.playing { + background: rgba(52, 152, 219, 0.2); + border-color: var(--primary-color); + box-shadow: 0 0 15px rgba(52, 152, 219, 0.3); + animation: pulse 1s infinite; +} + +.morse-item .character { + font-size: 1.8rem; + font-weight: 600; + margin-bottom: 5px; +} + +.morse-item .morse { + font-size: 1rem; + color: var(--text-dim); + letter-spacing: 1px; +} + +.back-link { + margin: 40px 0; + text-align: center; +} + +.back-link a { + display: inline-block; + background: linear-gradient(145deg, var(--primary-color), var(--primary-dark)); + color: white; + padding: 12px 25px; + border-radius: var(--border-radius-md); + text-decoration: none; + font-weight: 600; + transition: all var(--transition-normal); + box-shadow: var(--shadow-md); +} + +.back-link a:hover { + transform: translateY(-3px); + box-shadow: var(--shadow-lg); +} + +.back-link a:active { + transform: translateY(1px); + box-shadow: var(--shadow-sm); +} + +@media (max-width: 768px) { + .morse-grid { + grid-template-columns: repeat(auto-fill, minmax(70px, 1fr)); + gap: 10px; + } + + .morse-item .character { + font-size: 1.5rem; + } + + .morse-item .morse { + font-size: 0.9rem; + } + + .morse-info-card, + .morse-history, + .chart-section { + padding: 20px; + } +} + +@media (max-width: 480px) { + .morse-grid { + grid-template-columns: repeat(auto-fill, minmax(60px, 1fr)); + gap: 8px; + } + + .morse-item { + padding: 10px 5px; + } + + .morse-item .character { + font-size: 1.3rem; + } + + .morse-item .morse { + font-size: 0.8rem; + } }
\ No newline at end of file |
