levkin.ca/relay/relay.js
ilia b9a601894d Add levkin.ca design concepts (Spec, Slab, Relay, Vault).
Four static landing-page options with Vite build, cal booking, and links to sibling sites.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-20 22:34:48 -04:00

59 lines
1.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const MESSAGES = [
{
morse: '·−·−− · ·−·−− ·−· · ·−·−− · ·−·−− ·−· · ·−·−− ·−−−',
text: 'Levkin builds production software for teams under pressure. Custom systems, automation, enterprise tooling.',
},
{
morse: ' ·−·−− · ·−·−− ·−· · ·−·−− ·−−− · ·−·−− ·−· · ·−·−− · ·−·−− ·−· · ·−·−− ·−−−',
text: 'Error handling required. Documentation required. Tests before live data. Scope creep rejected.',
},
];
const morseEl = document.getElementById('morse');
const decodedEl = document.getElementById('decoded');
const btn = document.getElementById('decode-btn');
let idx = 0;
let typing = false;
function typeMorse(text, cb) {
typing = true;
morseEl.textContent = '';
let i = 0;
const tick = () => {
if (i < text.length) {
morseEl.textContent += text[i];
i++;
setTimeout(tick, 35 + Math.random() * 40);
} else {
typing = false;
cb?.();
}
};
tick();
}
function showMessage() {
const msg = MESSAGES[idx % MESSAGES.length];
decodedEl.classList.add('hidden');
typeMorse(msg.morse, () => {
btn.disabled = false;
btn.textContent = 'Decode ↵';
});
btn._pending = msg;
}
btn.addEventListener('click', () => {
if (typing) return;
if (btn._pending && decodedEl.classList.contains('hidden')) {
decodedEl.textContent = btn._pending.text;
decodedEl.classList.remove('hidden');
btn.textContent = 'Next signal →';
btn._pending = null;
return;
}
idx++;
showMessage();
});
showMessage();