I've really done good on developing this Computer!
<!DOCTYPE html>
<br> * {<br> box-sizing: border-box;<br> }</p> <div class="highlight"><pre class="highlight plaintext"><code>body { margin: 0; min-height: 100vh; display: flex; align-items: center; justify-content: center; background: radial-gradient(circle at top, #19324a, #08131f 65%); font-family: Arial, Helvetica, sans-serif; color: white; } .computer { width: 900px; max-width: 95vw; background: linear-gradient(180deg, #c7cdd3, #9098a2); border-radius: 24px; padding: 20px; box-shadow: 0 20px 50px rgba(0,0,0,0.5), inset 0 3px 8px rgba(255,255,255,0.25); border: 3px solid #6f7880; } .monitor { background: #111; border-radius: 18px; padding: 18px; border: 10px solid #4b535b; box-shadow: inset 0 0 25px rgba(0,255,255,0.08); } .screen { min-height: 480px; border-radius: 12px; padding: 20px; background: linear-gradient(180deg, rgba(0,255,180,0.06), rgba(0,160,255,0.05)), #021118; border: 2px solid #1f6f7e; box-shadow: inset 0 0 30px rgba(0,255,200,0.08), 0 0 18px rgba(0,255,200,0.08); } .title-bar { display: flex; justify-content: space-between; align-items: center; background: linear-gradient(90deg, #1f9dff, #00d0ff); color: #021118; padding: 12px 14px; border-radius: 10px; font-weight: 700; margin-bottom: 16px; } .status-light { width: 14px; height: 14px; border-radius: 50%; background: #68ff7f; box-shadow: 0 0 12px #68ff7f; } .chat-area { display: grid; grid-template-columns: 1fr 260px; gap: 16px; } .chat-panel, .sound-panel { background: rgba(255,255,255,0.04); border: 1px solid rgba(0,255,255,0.15); border-radius: 14px; padding: 14px; backdrop-filter: blur(3px); } .messages { height: 250px; overflow-y: auto; background: rgba(0,0,0,0.25); border-radius: 10px; padding: 10px; margin-bottom: 12px; border: 1px solid rgba(0,255,255,0.12); } .msg { padding: 10px 12px; margin-bottom: 8px; border-radius: 12px; line-height: 1.4; word-wrap: break-word; } .msg.user { background: rgba(0, 210, 255, 0.15); border: 1px solid rgba(0, 210, 255, 0.25); } .msg.system { background: rgba(60, 255, 130, 0.1); border: 1px solid rgba(60, 255, 130, 0.2); color: #aaffc5; } .typing-box { display: flex; gap: 10px; margin-bottom: 10px; } .typing-box input { flex: 1; padding: 14px; border-radius: 10px; border: 2px solid #1a7c8f; background: #061c25; color: white; font-size: 16px; outline: none; } .typing-box input:focus { border-color: #43dfff; box-shadow: 0 0 10px rgba(67,223,255,0.3); } .typing-box button, .control-btn { padding: 12px 16px; border: none; border-radius: 10px; background: linear-gradient(180deg, #42d8ff, #1395d1); color: #04131a; font-weight: bold; cursor: pointer; transition: transform 0.15s ease, filter 0.15s ease; } .typing-box button:hover, .control-btn:hover { transform: translateY(-1px); filter: brightness(1.08); } .typing-box button:active, .control-btn:active { transform: translateY(1px); } .sound-panel h3 { margin-top: 0; margin-bottom: 12px; color: #7eefff; } .meter { width: 100%; height: 14px; border-radius: 999px; background: rgba(255,255,255,0.08); overflow: hidden; margin: 10px 0 16px; border: 1px solid rgba(255,255,255,0.08); } .meter-fill { width: 0%; height: 100%; background: linear-gradient(90deg, #47eaff, #8aff94); transition: width 0.08s linear; } .mini-text { font-size: 14px; color: #b7d9e3; line-height: 1.5; } .number-pad { margin-top: 16px; display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; } .pad-btn { padding: 14px 0; text-align: center; border-radius: 10px; background: rgba(255,255,255,0.08); border: 1px solid rgba(0,255,255,0.12); cursor: pointer; user-select: none; font-weight: bold; } .pad-btn:hover { background: rgba(0,255,255,0.12); } .footer-note { margin-top: 16px; font-size: 13px; color: #99b6bf; } </code></pre></div> <p>
Retro Computer Chat Box — Dial / Fax / Beep Typing Sounds
<div class="chat-area">
<div class="chat-panel">
<div class="messages" id="messages">
<div class="msg system">Computer ready. Start typing to hear dialing, beeps, and odd fax-machine sounds.</div>
</div>
<div class="typing-box">
<input
id="chatInput"
type="text"
placeholder="Type random words, numbers, or messages..."
autocomplete="off"
/>
<button id="sendBtn">Send</button>
</div>
<button class="control-btn" id="clearBtn">Clear Chat</button>
</div>
<div class="sound-panel">
<h3>Sound Activity</h3>
<div class="mini-text" id="soundLabel">Idle...</div>
<div class="meter">
<div class="meter-fill" id="meterFill"></div>
</div>
<div class="mini-text">
Letters trigger computer beeps.<br>
Numbers trigger phone-dial tones.<br>
Spaces and symbols can trigger strange fax-style sounds.
</div>
<div class="number-pad">
<div class="pad-btn">1</div>
<div class="pad-btn">2</div>
<div class="pad-btn">3</div>
<div class="pad-btn">4</div>
<div class="pad-btn">5</div>
<div class="pad-btn">6</div>
<div class="pad-btn">7</div>
<div class="pad-btn">8</div>
<div class="pad-btn">9</div>
<div class="pad-btn">*</div>
<div class="pad-btn">0</div>
<div class="pad-btn">#</div>
</div>
<div class="footer-note">
Click inside the page first, then type for sound.
</div>
</div>
</div>
</div>
</div>
<br>
const input = document.getElementById("chatInput");<br>
const sendBtn = document.getElementById("sendBtn");<br>
const clearBtn = document.getElementById("clearBtn");<br>
const messages = document.getElementById("messages");<br>
const soundLabel = document.getElementById("soundLabel");<br>
const meterFill = document.getElementById("meterFill");<br>
const padButtons = document.querySelectorAll(".pad-btn");</p>
<div class="highlight"><pre class="highlight plaintext"><code>let audioCtx;
let isAudioUnlocked = false;
function initAudio() {
if (!audioCtx) {
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
}
if (audioCtx.state === "suspended") {
audioCtx.resume();
}
isAudioUnlocked = true;
}
document.addEventListener("click", initAudio, { once: false });
document.addEventListener("keydown", initAudio, { once: false });
function updateMeter(level, label) {
meterFill.style.width = Math.max(0, Math.min(100, level)) + "%";
soundLabel.textContent = label;
clearTimeout(updateMeter._timer);
updateMeter._timer = setTimeout(() => {
meterFill.style.width = "0%";
soundLabel.textContent = "Idle...";
}, 120);
}
function makeOscillator(freq, type = "sine", volume = 0.04, duration = 0.08) {
if (!audioCtx) return;
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.type = type;
osc.frequency.setValueAtTime(freq, audioCtx.currentTime);
gain.gain.setValueAtTime(0.0001, audioCtx.currentTime);
gain.gain.exponentialRampToValueAtTime(volume, audioCtx.currentTime + 0.01);
gain.gain.exponentialRampToValueAtTime(0.0001, audioCtx.currentTime + duration);
osc.connect(gain);
gain.connect(audioCtx.destination);
osc.start();
osc.stop(audioCtx.currentTime + duration + 0.02);
}
function makeNoise(duration = 0.06, volume = 0.025) {
if (!audioCtx) return;
const bufferSize = audioCtx.sampleRate * duration;
const buffer = audioCtx.createBuffer(1, bufferSize, audioCtx.sampleRate);
const data = buffer.getChannelData(0);
for (let i = 0; i < bufferSize; i++) {
data[i] = (Math.random() * 2 - 1) * (1 - i / bufferSize);
}
const noise = audioCtx.createBufferSource();
const gain = audioCtx.createGain();
const filter = audioCtx.createBiquadFilter();
noise.buffer = buffer;
filter.type = "bandpass";
filter.frequency.value = 1800 + Math.random() * 1200;
filter.Q.value = 3;
gain.gain.value = volume;
noise.connect(filter);
filter.connect(gain);
gain.connect(audioCtx.destination);
noise.start();
}
const dtmfMap = {
"1": [697, 1209],
"2": [697, 1336],
"3": [697, 1477],
"4": [770, 1209],
"5": [770, 1336],
"6": [770, 1477],
"7": [852, 1209],
"8": [852, 1336],
"9": [852, 1477],
"*": [941, 1209],
"0": [941, 1336],
"#": [941, 1477]
};
function playDTMF(key) {
if (!audioCtx || !dtmfMap[key]) return;
const [f1, f2] = dtmfMap[key];
makeOscillator(f1, "sine", 0.03, 0.11);
makeOscillator(f2, "sine", 0.03, 0.11);
updateMeter(85, `Dial tone: ${key}`);
}
function playBeep(char) {
const base = 650 + (char.charCodeAt(0) % 12) * 35;
makeOscillator(base, "square", 0.02, 0.05);
updateMeter(55, `Computer beep: ${char}`);
}
function playFaxNoise() {
makeNoise(0.07, 0.03);
makeOscillator(1400 + Math.random() * 900, "sawtooth", 0.012, 0.06);
updateMeter(70, "Odd fax noise");
}
function playSpaceNoise() {
makeOscillator(420, "triangle", 0.012, 0.03);
updateMeter(35, "Soft system tick");
}
function handleTypedChar(char) {
if (!isAudioUnlocked) return;
if (/[0-9]/.test(char)) {
playDTMF(char);
} else if (/[*#]/.test(char)) {
playDTMF(char);
} else if (/[a-zA-Z]/.test(char)) {
playBeep(char);
} else if (char === " ") {
playSpaceNoise();
} else {
playFaxNoise();
}
}
input.addEventListener("keydown", (e) => {
if (e.key.length === 1) {
handleTypedChar(e.key);
} else if (e.key === "Backspace") {
makeOscillator(230, "triangle", 0.02, 0.04);
updateMeter(45, "Delete beep");
} else if (e.key === "Enter") {
e.preventDefault();
sendMessage();
}
});
function addMessage(text, type = "user") {
const div = document.createElement("div");
div.className = `msg ${type}`;
div.textContent = text;
messages.appendChild(div);
messages.scrollTop = messages.scrollHeight;
}
function sendMessage() {
const text = input.value.trim();
if (!text) return;
addMessage(text, "user");
input.value = "";
setTimeout(() => {
addMessage("Computer received your message.", "system");
}, 220);
if (isAudioUnlocked) {
makeOscillator(880, "square", 0.02, 0.05);
setTimeout(() => makeOscillator(1180, "square", 0.02, 0.05), 60);
updateMeter(90, "Message sent");
}
}
sendBtn.addEventListener("click", () => {
initAudio();
sendMessage();
});
clearBtn.addEventListener("click", () => {
messages.innerHTML = '<div class="msg system">Chat cleared. Start typing again.</div>';
if (isAudioUnlocked) {
makeOscillator(300, "triangle", 0.02, 0.05);
setTimeout(() => makeOscillator(220, "triangle", 0.02, 0.05), 60);
updateMeter(60, "System cleared");
}
});
padButtons.forEach(btn => {
btn.addEventListener("click", () => {
initAudio();
const value = btn.textContent.trim();
input.value += value;
input.focus();
handleTypedChar(value);
});
});
</code></pre></div>
<p>
Top comments (0)