fix: complete blame form buttons with styling and functionality

- Added missing CSS styles for all buttons (submit-btn, generate-btn, nuclear-option)
- Implemented full JavaScript functionality for form submission, apology generation, and nuclear option
- Added sound effects using Web Audio API
- Improved form layout and sidebar styling
- Added responsive design improvements
- Fixed visual issues with rage-meter, shit-list, and footer elements
- Added interactive features: auto-blame, clear log, sound toggle, easter egg
This commit is contained in:
2026-03-02 11:51:33 -05:00
parent 67530fa5d5
commit 700708ed5e

View File

@@ -96,6 +96,16 @@
padding: 5px; padding: 5px;
animation: warning-blink 1s infinite; animation: warning-blink 1s infinite;
} }
.dustin-face {
font-size: 3em;
margin-bottom: 10px;
animation: face-shake 3s infinite;
}
@keyframes face-shake {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(5deg); }
75% { transform: rotate(-5deg); }
}
@keyframes warning-blink { @keyframes warning-blink {
0%, 100% { opacity: 1; } 0%, 100% { opacity: 1; }
50% { opacity: 0.5; } 50% { opacity: 0.5; }
@@ -197,6 +207,60 @@
.stat-value.yellow { .stat-value.yellow {
color: var(--terminal-yellow); color: var(--terminal-yellow);
} }
.rage-meter {
height: 10px;
background: rgba(255, 0, 0, 0.2);
border-radius: 5px;
margin-top: 10px;
overflow: hidden;
}
.rage-fill {
height: 100%;
background: linear-gradient(90deg, var(--terminal-red), var(--terminal-amber));
border-radius: 5px;
transition: width 0.5s ease;
}
.shit-list {
margin-top: 20px;
padding-top: 15px;
border-top: 1px solid var(--terminal-green);
}
.shit-list-title {
color: var(--terminal-yellow);
font-weight: bold;
margin-bottom: 10px;
font-size: 1.1em;
}
.shit-item {
padding: 8px 0;
border-bottom: 1px dashed rgba(0, 255, 0, 0.3);
color: var(--terminal-text);
font-size: 0.9em;
}
.shit-item:last-child {
border-bottom: none;
}
.footer {
text-align: center;
margin-top: 30px;
padding-top: 20px;
border-top: 1px solid var(--terminal-green);
color: var(--terminal-cyan);
font-size: 0.9em;
}
.footer p {
margin: 10px 0;
}
.easter-egg {
color: var(--terminal-magenta);
cursor: pointer;
text-decoration: underline;
margin-top: 15px;
display: inline-block;
}
.easter-egg:hover {
color: var(--terminal-red);
}
.main-content { .main-content {
display: grid; display: grid;
grid-template-columns: 1fr; grid-template-columns: 1fr;
@@ -223,6 +287,20 @@
max-height: 600px; max-height: 600px;
} }
} }
.sidebar {
background: rgba(0, 0, 0, 0.8);
border: 2px solid var(--terminal-green);
padding: 20px;
border-radius: 5px;
display: flex;
flex-direction: column;
gap: 20px;
}
@media (min-width: 768px) {
.sidebar {
padding: 25px;
}
}
.log-header { .log-header {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -267,6 +345,122 @@
background: var(--terminal-cyan); background: var(--terminal-cyan);
color: var(--terminal-bg); color: var(--terminal-bg);
} }
.control-btn.danger {
border-color: var(--terminal-red);
color: var(--terminal-red);
}
.control-btn.danger:hover {
background: var(--terminal-red);
color: var(--terminal-bg);
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
color: var(--terminal-yellow);
margin-bottom: 8px;
font-weight: bold;
}
.form-group select,
.form-group textarea {
width: 100%;
background: rgba(0, 0, 0, 0.7);
border: 1px solid var(--terminal-green);
color: var(--terminal-text);
font-family: 'IBM Plex Mono', monospace;
padding: 10px;
border-radius: 3px;
font-size: 0.9em;
}
.form-group select:focus,
.form-group textarea:focus {
outline: none;
border-color: var(--terminal-cyan);
box-shadow: 0 0 10px var(--terminal-cyan);
}
.form-group textarea {
min-height: 100px;
resize: vertical;
}
.blame-generator, .apology-generator {
background: rgba(0, 0, 0, 0.7);
border: 2px solid var(--terminal-green);
padding: 20px;
border-radius: 5px;
margin-bottom: 20px;
}
.blame-title, .apology-title {
color: var(--terminal-red);
font-weight: bold;
text-align: center;
margin-bottom: 15px;
font-size: 1.2em;
text-transform: uppercase;
letter-spacing: 1px;
border-bottom: 1px solid var(--terminal-green);
padding-bottom: 10px;
}
.apology-title {
color: var(--terminal-magenta);
}
.apology-display {
background: rgba(0, 0, 0, 0.9);
border: 1px solid var(--terminal-magenta);
padding: 15px;
border-radius: 3px;
min-height: 80px;
margin-bottom: 15px;
font-style: italic;
color: var(--terminal-text);
}
.submit-btn, .generate-btn, .nuclear-option {
background: var(--terminal-bg);
border: 2px solid var(--terminal-red);
color: var(--terminal-red);
padding: 12px 20px;
cursor: pointer;
font-family: 'IBM Plex Mono', monospace;
font-weight: bold;
border-radius: 5px;
transition: all 0.3s;
width: 100%;
margin-top: 15px;
text-transform: uppercase;
letter-spacing: 1px;
}
.submit-btn:hover {
background: var(--terminal-red);
color: var(--terminal-bg);
box-shadow: 0 0 15px var(--terminal-red);
}
.generate-btn {
border-color: var(--terminal-magenta);
color: var(--terminal-magenta);
}
.generate-btn:hover {
background: var(--terminal-magenta);
color: var(--terminal-bg);
box-shadow: 0 0 15px var(--terminal-magenta);
}
.nuclear-option {
border-color: var(--terminal-amber);
color: var(--terminal-amber);
font-size: 1.1em;
padding: 15px;
margin-top: 20px;
animation: nuclear-pulse 2s infinite;
}
.nuclear-option:hover {
background: var(--terminal-amber);
color: var(--terminal-bg);
box-shadow: 0 0 20px var(--terminal-amber);
animation: none;
}
@keyframes nuclear-pulse {
0%, 100% { box-shadow: 0 0 10px var(--terminal-amber); }
50% { box-shadow: 0 0 25px var(--terminal-amber); }
}
.incident { .incident {
margin-bottom: 15px; margin-bottom: 15px;
padding: 15px; padding: 15px;
@@ -381,7 +575,267 @@
<p class="easter-egg" id="easter-egg">Click here if you actually like Dustin (you monster)</p> <p class="easter-egg" id="easter-egg">Click here if you actually like Dustin (you monster)</p>
</div> </div>
<script> <script>
// JavaScript functionality as previously defined... document.addEventListener('DOMContentLoaded', function() {
// DOM Elements
const blameForm = document.getElementById('blame-form');
const generateApologyBtn = document.getElementById('generate-apology');
const nuclearOptionBtn = document.getElementById('nuclear-option');
const autoAddBtn = document.getElementById('auto-add');
const clearLogBtn = document.getElementById('clear-log');
const soundToggle = document.getElementById('sound-toggle');
const logContainer = document.getElementById('log');
const totalFuckups = document.getElementById('total-fuckups');
const apologiesCount = document.getElementById('apologies-count');
const hoursWasted = document.getElementById('hours-wasted');
const apologyDisplay = document.getElementById('apology-display');
const sincerityLevel = document.getElementById('sincerity-level');
const easterEgg = document.getElementById('easter-egg');
// State
let soundEnabled = true;
let fuckupCount = 1247;
let apologyCount = 42;
let hoursCount = 3728;
// Incident templates
const incidents = [
"Dustin forgot to renew the SSL certificate — again.",
"Dustin scheduled the database backup during peak hours.",
"Dustin 'accidentally' pushed to production on a Friday afternoon.",
"Dustin's 'quick fix' broke the entire login system.",
"Dustin used the CEO's account to test the new spam filter.",
"Dustin thought 'rm -rf /' was a good way to free up disk space.",
"Dustin set the password policy to 'password123' for 'convenience'.",
"Dustin uploaded the customer database to a public GitHub repo.",
"Dustin replied to a phishing email with admin credentials.",
"Dustin thought blockchain would solve our inventory tracking issues."
];
// Apology templates
const apologies = [
"My bad, I thought that was the test environment. Whoops!",
"In my defense, the documentation was unclear. And by unclear, I mean non-existent.",
"That was a feature, not a bug. You just don't understand my vision.",
"It worked on my machine. Must be a you problem.",
"I was following industry best practices. From 1998.",
"The AI told me to do it. Can't argue with the algorithm, right?",
"I was trying to be proactive. Turns out, proactivity causes outages.",
"It's not my fault — the system was designed to fail. I just... helped.",
"I was optimizing for scalability. Current scalability: zero.",
"Look, we all make mistakes. Mine just happen to take down entire systems."
];
// Sound effects
function playSound(type) {
if (!soundEnabled) return;
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
switch(type) {
case 'blame':
oscillator.frequency.setValueAtTime(440, audioContext.currentTime);
oscillator.type = 'sawtooth';
gainNode.gain.setValueAtTime(0.1, audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.5);
oscillator.start();
oscillator.stop(audioContext.currentTime + 0.5);
break;
case 'apology':
oscillator.frequency.setValueAtTime(220, audioContext.currentTime);
oscillator.type = 'sine';
gainNode.gain.setValueAtTime(0.05, audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 1);
oscillator.start();
oscillator.stop(audioContext.currentTime + 1);
break;
case 'nuclear':
oscillator.frequency.setValueAtTime(55, audioContext.currentTime);
oscillator.frequency.exponentialRampToValueAtTime(880, audioContext.currentTime + 2);
oscillator.type = 'square';
gainNode.gain.setValueAtTime(0.2, audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 2);
oscillator.start();
oscillator.stop(audioContext.currentTime + 2);
break;
}
}
// Add incident to log
function addIncident(text, severity = 'critical') {
const incident = document.createElement('div');
incident.className = 'incident';
const timestamp = new Date().toLocaleTimeString();
const severityColors = {
minor: 'var(--terminal-green)',
warning: 'var(--terminal-yellow)',
critical: 'var(--terminal-red)',
apocalyptic: 'var(--terminal-magenta)'
};
incident.innerHTML = `
<div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
<strong style="color: ${severityColors[severity]}">[${severity.toUpperCase()}]</strong>
<span style="color: var(--terminal-cyan); font-size: 0.9em;">${timestamp}</span>
</div>
<div>${text}</div>
`;
logContainer.insertBefore(incident, logContainer.firstChild);
// Limit log to 20 items
if (logContainer.children.length > 20) {
logContainer.removeChild(logContainer.lastChild);
}
// Update stats
fuckupCount++;
hoursCount += Math.floor(Math.random() * 5) + 1;
updateStats();
// Play sound
playSound('blame');
}
// Update statistics display
function updateStats() {
totalFuckups.textContent = fuckupCount.toLocaleString();
apologiesCount.textContent = apologyCount;
hoursWasted.textContent = hoursCount.toLocaleString();
}
// Generate random apology
function generateApology() {
const apology = apologies[Math.floor(Math.random() * apologies.length)];
const sincerity = Math.floor(Math.random() * 101);
apologyDisplay.textContent = `"${apology}"`;
sincerityLevel.textContent = `${sincerity}%`;
apologyCount++;
updateStats();
// Play sound
playSound('apology');
// Visual feedback
apologyDisplay.style.animation = 'none';
setTimeout(() => {
apologyDisplay.style.animation = 'fadeIn 0.5s';
}, 10);
}
// Nuclear option
function activateNuclearOption() {
if (!confirm("🚨 WARNING: This will fire Dustin permanently! 🚨\n\nAre you absolutely sure? (This action cannot be undone and will probably make things worse)")) {
return;
}
// Clear the log
logContainer.innerHTML = '';
// Add nuclear incident
addIncident("🚨 NUCLEAR OPTION ACTIVATED: DUSTIN HAS BEEN TERMINATED 🚨", 'apocalyptic');
addIncident("System stability: CRITICAL - Without Dustin to blame, reality is collapsing", 'apocalyptic');
addIncident("Paradox detected: If Dustin is fired, who do we blame for firing Dustin?", 'apocalyptic');
// Update stats dramatically
fuckupCount += 1000;
hoursCount += 500;
updateStats();
// Play nuclear sound
playSound('nuclear');
// Visual effects
document.body.style.animation = 'none';
setTimeout(() => {
document.body.style.animation = 'shake 0.5s';
}, 10);
// Disable nuclear button
nuclearOptionBtn.disabled = true;
nuclearOptionBtn.textContent = "🚨 DUSTIN TERMINATED 🚨";
nuclearOptionBtn.style.opacity = '0.5';
nuclearOptionBtn.style.cursor = 'not-allowed';
}
// Event Listeners
blameForm.addEventListener('submit', function(e) {
e.preventDefault();
const severity = document.getElementById('severity').value;
const description = document.getElementById('description').value.trim();
if (!description) {
alert("Please describe Dustin's mess-up. Be creative!");
return;
}
addIncident(description, severity);
// Reset form
document.getElementById('description').value = '';
document.getElementById('severity').value = 'critical';
// Visual feedback
blameForm.style.animation = 'none';
setTimeout(() => {
blameForm.style.animation = 'fadeIn 0.5s';
}, 10);
});
generateApologyBtn.addEventListener('click', generateApology);
nuclearOptionBtn.addEventListener('click', activateNuclearOption);
autoAddBtn.addEventListener('click', function() {
const randomIncident = incidents[Math.floor(Math.random() * incidents.length)];
const severities = ['minor', 'warning', 'critical', 'apocalyptic'];
const randomSeverity = severities[Math.floor(Math.random() * severities.length)];
addIncident(randomIncident, randomSeverity);
});
clearLogBtn.addEventListener('click', function() {
if (confirm("Clear the entire incident log? (Dustin probably suggested this)")) {
logContainer.innerHTML = '';
addIncident("Incident log cleared. This was definitely Dustin's idea.", 'warning');
}
});
soundToggle.addEventListener('click', function() {
soundEnabled = !soundEnabled;
soundToggle.textContent = soundEnabled ? "🔊 Sound: ON" : "🔇 Sound: OFF";
});
easterEgg.addEventListener('click', function() {
alert("You monster! Dustin actually appreciates your support.\n\nHe's still at fault for everything, but thanks for trying.");
addIncident("Someone actually clicked the 'like Dustin' button. Investigation required.", 'critical');
});
// Add shake animation for nuclear option
const style = document.createElement('style');
style.textContent = `
@keyframes shake {
0%, 100% { transform: translateX(0); }
10%, 30%, 50%, 70%, 90% { transform: translateX(-10px); }
20%, 40%, 60%, 80% { transform: translateX(10px); }
}
`;
document.head.appendChild(style);
// Initialize with some incidents
setTimeout(() => {
addIncident("System initialized. Ready to blame Dustin for everything.", 'warning');
addIncident("Dustin already blamed for today's coffee machine outage.", 'minor');
addIncident("Dustin suspected in DNS resolution issues. Investigation ongoing.", 'critical');
}, 1000);
});
</script> </script>
</body> </body>
</html> </html>