|
7 | 7 | <div class="container"> |
8 | 8 | <div class="hero-content"> |
9 | 9 | <div class="hero-text"> |
10 | | - <h1 class="hero-title" id="terminal-name"></h1> |
11 | | - <h2 class="hero-subtitle" id="terminal-headline"></h2> |
12 | | - <p class="hero-description" id="terminal-bio"></p> |
13 | | - <div class="hero-buttons" id="hero-buttons" style="opacity: 0; transition: opacity 0.5s ease-in;"> |
| 10 | + <h1 class="hero-title typewriter" id="terminal-name">{{ site.data.profile.name }}</h1> |
| 11 | + <h2 class="hero-subtitle typewriter-delay-1" id="terminal-headline">{{ site.data.profile.headline }}</h2> |
| 12 | + <p class="hero-description typewriter-delay-2" id="terminal-bio">{{ site.data.profile.bio }}</p> |
| 13 | + <div class="hero-buttons fade-in-after-typing"> |
14 | 14 | <a href="{{ site.data.profile.contact.github }}" class="btn btn-primary github-btn" target="_blank"> |
15 | 15 | <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor" style="margin-right: 8px;"> |
16 | 16 | <path d="M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z"/> |
@@ -92,58 +92,69 @@ <h3>Connect</h3> |
92 | 92 | </section> |
93 | 93 |
|
94 | 94 | <style> |
95 | | - .hero-title, .hero-subtitle, .hero-description { |
96 | | - min-height: 1.2em; |
| 95 | + /* CSS-based typewriter effect */ |
| 96 | + .typewriter { |
| 97 | + overflow: hidden; |
| 98 | + border-right: 2px solid var(--gold-primary); |
| 99 | + white-space: nowrap; |
| 100 | + margin: 0 auto; |
| 101 | + letter-spacing: 0.05em; |
| 102 | + animation: |
| 103 | + typing 2s steps(30, end), |
| 104 | + blink-caret 0.75s step-end infinite; |
| 105 | + animation-fill-mode: forwards; |
97 | 106 | } |
98 | | -</style> |
99 | | - |
100 | | -<script> |
101 | | - // Terminal typewriter effect with single cursor |
102 | | - const nameText = "{{ site.data.profile.name }}"; |
103 | | - const headlineText = "{{ site.data.profile.headline }}"; |
104 | | - const bioText = "{{ site.data.profile.bio }}"; |
105 | 107 |
|
106 | | - const texts = [ |
107 | | - { element: document.getElementById('terminal-name'), text: nameText, speed: 80 }, |
108 | | - { element: document.getElementById('terminal-headline'), text: headlineText, speed: 60 }, |
109 | | - { element: document.getElementById('terminal-bio'), text: bioText, speed: 40 } |
110 | | - ]; |
| 108 | + .typewriter-delay-1 { |
| 109 | + overflow: hidden; |
| 110 | + border-right: 2px solid var(--gold-primary); |
| 111 | + white-space: nowrap; |
| 112 | + margin: 0 auto; |
| 113 | + letter-spacing: 0.05em; |
| 114 | + width: 0; |
| 115 | + animation: |
| 116 | + typing 1.5s steps(40, end) 2.2s, |
| 117 | + blink-caret 0.75s step-end infinite 2.2s; |
| 118 | + animation-fill-mode: forwards; |
| 119 | + } |
111 | 120 |
|
112 | | - let currentTextIndex = 0; |
113 | | - let charIndex = 0; |
114 | | - const cursor = '<span class="terminal-cursor">_</span>'; |
| 121 | + .typewriter-delay-2 { |
| 122 | + overflow: hidden; |
| 123 | + border-right: 2px solid var(--gold-primary); |
| 124 | + white-space: nowrap; |
| 125 | + margin: 0 auto; |
| 126 | + letter-spacing: 0.05em; |
| 127 | + width: 0; |
| 128 | + animation: |
| 129 | + typing 3s steps(60, end) 4s, |
| 130 | + blink-caret 0.75s step-end infinite 4s, |
| 131 | + remove-caret 0s 7s forwards; |
| 132 | + animation-fill-mode: forwards; |
| 133 | + } |
115 | 134 |
|
116 | | - function typeWriter() { |
117 | | - if (currentTextIndex >= texts.length) { |
118 | | - // All text typed, remove cursor and show buttons |
119 | | - texts[texts.length - 1].element.innerHTML = texts[texts.length - 1].element.innerHTML.replace(cursor, ''); |
120 | | - document.getElementById('hero-buttons').style.opacity = '1'; |
121 | | - return; |
122 | | - } |
123 | | - |
124 | | - const current = texts[currentTextIndex]; |
125 | | - |
126 | | - if (charIndex < current.text.length) { |
127 | | - // Type current character |
128 | | - current.element.innerHTML = current.text.substring(0, charIndex + 1) + cursor; |
129 | | - charIndex++; |
130 | | - setTimeout(typeWriter, current.speed); |
131 | | - } else { |
132 | | - // Finished current element, move to next |
133 | | - current.element.innerHTML = current.text; // Remove cursor from completed element |
134 | | - currentTextIndex++; |
135 | | - charIndex = 0; |
136 | | - setTimeout(typeWriter, 300); // Pause between elements |
137 | | - } |
| 135 | + @keyframes typing { |
| 136 | + from { width: 0; } |
| 137 | + to { width: 100%; } |
138 | 138 | } |
139 | 139 |
|
140 | | - // Start typing when page loads |
141 | | - if (document.readyState === 'loading') { |
142 | | - document.addEventListener('DOMContentLoaded', () => setTimeout(typeWriter, 500)); |
143 | | - } else { |
144 | | - setTimeout(typeWriter, 500); |
| 140 | + @keyframes blink-caret { |
| 141 | + from, to { border-color: transparent; } |
| 142 | + 50% { border-color: var(--gold-primary); } |
145 | 143 | } |
146 | | -</script> |
| 144 | + |
| 145 | + @keyframes remove-caret { |
| 146 | + to { border-right: none; } |
| 147 | + } |
| 148 | + |
| 149 | + .fade-in-after-typing { |
| 150 | + opacity: 0; |
| 151 | + animation: fade-in 0.5s ease-in 7.2s forwards; |
| 152 | + } |
| 153 | + |
| 154 | + @keyframes fade-in { |
| 155 | + to { opacity: 1; } |
| 156 | + } |
| 157 | +</style> |
147 | 158 |
|
148 | 159 | <script> |
149 | 160 | // Fetch live GitHub contributions count |
|
0 commit comments