<!-- Prompt to Performance - Complete Single Block Version -->
<style>
.perf-container { font-family: Helvetica, Arial, sans-serif; max-width: 100%; margin: 20px auto; padding: 20px; background: #fff; }
.perf-header { text-align: center; margin-bottom: 30px; border-bottom: 1px solid #ddd; padding-bottom: 20px; }
.perf-title { font-size: 24px; font-weight: bold; letter-spacing: 2px; text-transform: uppercase; }
.perf-subtitle { color: #666; margin-top: 10px; }
.perf-main { display: grid; grid-template-columns: 1fr 1fr; gap: 30px; }
.perf-section { padding: 20px; }
.perf-input-section { border-right: 1px solid #ddd; }
.perf-output-section { background: #fafafa; }
.perf-section-title { font-size: 18px; font-weight: bold; margin-bottom: 15px; text-transform: uppercase; }
.perf-textarea { width: 100%; height: 120px; padding: 15px; border: 1px solid #ccc; font-family: inherit; resize: vertical; }
.perf-textarea:focus { outline: none; border-color: #000; }
.perf-controls { margin: 20px 0; display: flex; gap: 10px; flex-wrap: wrap; }
.perf-btn { background: #000; color: #fff; border: none; padding: 10px 20px; cursor: pointer; text-transform: uppercase; font-size: 12px; }
.perf-btn:hover { background: #333; }
.perf-btn.secondary { background: #fff; color: #000; border: 1px solid #000; }
.perf-btn.secondary:hover { background: #f5f5f5; }
.perf-canvas { width: 100%; height: 300px; background: #000; border: 1px solid #ccc; position: relative; overflow: hidden; }
.perf-laser { position: absolute; background: #fff; opacity: 0.8; }
.perf-laser.beam { height: 2px; box-shadow: 0 0 10px #fff; }
.perf-laser.line { width: 1px; box-shadow: 0 0 8px #fff; }
.perf-laser.dot { width: 4px; height: 4px; border-radius: 50%; box-shadow: 0 0 15px #fff; }
.perf-status { margin-top: 15px; padding: 10px; background: #f0f0f0; border-left: 3px solid #000; font-size: 14px; }
.perf-monologue { margin-top: 15px; padding: 15px; background: #f8f8f8; border-left: 3px solid #333; display: none; font-style: italic; line-height: 1.6; }
.perf-voice-status { margin-top: 10px; text-align: center; padding: 8px; background: #f0f0f0; font-size: 12px; color: #666; }
.perf-voice-status.speaking { background: #e8f5e8; color: #2d5a2d; }
.perf-stats { display: flex; gap: 20px; margin: 15px 0; font-size: 14px; }
.perf-stat { display: flex; flex-direction: column; }
.perf-stat-label { font-size: 11px; text-transform: uppercase; color: #666; }
.perf-stat-value { font-size: 18px; font-weight: bold; }
@keyframes laser-pulse { 0%, 100% { opacity: 0.6; } 50% { opacity: 1; } }
@keyframes laser-sweep { 0% { transform: scaleX(0); } 100% { transform: scaleX(1); } }
@media (max-width: 768px) { .perf-main { grid-template-columns: 1fr; } .perf-input-section { border-right: none; border-bottom: 1px solid #ddd; padding-bottom: 20px; } }
</style>
<div class="perf-container">
<div class="perf-header">
<div class="perf-title">Prompt → Performance</div>
<div class="perf-subtitle">Transform text into laser lighting with voice performance</div>
</div>
<div class="perf-main">
<div class="perf-section perf-input-section">
<div class="perf-section-title">Text Input</div>
<textarea class="perf-textarea" id="perfInput" placeholder="Enter your creative prompt here... Brilliant laser beams cut through darkness, creating patterns of light and shadow..."></textarea>
<div class="perf-controls">
<button class="perf-btn" onclick="createLaserShow()">Create Laser Show</button>
<button class="perf-btn" onclick="createMonologue()">Create Performance</button>
<button class="perf-btn secondary" onclick="stopAll()">Stop</button>
</div>
<div class="perf-stats">
<div class="perf-stat">
<div class="perf-stat-label">Words</div>
<div class="perf-stat-value" id="perfWordCount">0</div>
</div>
<div class="perf-stat">
<div class="perf-stat-label">Lasers</div>
<div class="perf-stat-value" id="perfLaserCount">0</div>
</div>
<div class="perf-stat">
<div class="perf-stat-label">Status</div>
<div class="perf-stat-value" id="perfStatus">Ready</div>
</div>
</div>
</div>
<div class="perf-section perf-output-section">
<div class="perf-section-title">Performance Output</div>
<div class="perf-canvas" id="perfCanvas"></div>
<div class="perf-monologue" id="perfMonologue">
<strong>Generated Performance:</strong>
<div id="perfMonologueText"></div>
</div>
<div class="perf-voice-status" id="perfVoiceStatus">Voice system ready</div>
<div class="perf-status" id="perfStatusDisplay">Ready for input. Enter text to generate performance.</div>
</div>
</div>
</div>
<script>
let perfCurrentSpeech = null;
let perfVoices = [];
let perfSelectedVoice = null;
let perfProcessing = false;
// Initialize voices
if (window.speechSynthesis) {
speechSynthesis.onvoiceschanged = function() {
perfVoices = speechSynthesis.getVoices();
perfSelectedVoice = perfVoices.find(v => v.lang.startsWith('en')) || perfVoices[0];
};
}
// Update word count
document.getElementById('perfInput').addEventListener('input', function() {
const words = this.value.trim().split(/\s+/).filter(w => w.length > 0);
document.getElementById('perfWordCount').textContent = words.length;
document.getElementById('perfStatusDisplay').textContent = words.length > 0 ? 'Text ready for performance.' : 'Ready for input.';
});
// Create laser effects
function createPerfLasers(text) {
const canvas = document.getElementById('perfCanvas');
canvas.innerHTML = '';
const words = text.split(/\s+/).filter(w => w.length > 0);
const laserCount = Math.min(12, Math.max(3, words.length));
for (let i = 0; i < laserCount; i++) {
const laser = document.createElement('div');
laser.className = 'perf-laser';
const types = ['beam', 'line', 'dot'];
const type = types[Math.floor(Math.random() * types.length)];
laser.classList.add(type);
const x = Math.random() * (canvas.offsetWidth - 50);
const y = Math.random() * (canvas.offsetHeight - 50);
laser.style.left = x + 'px';
laser.style.top = y + 'px';
if (type === 'beam') {
laser.style.width = (60 + Math.random() * 120) + 'px';
} else if (type === 'line') {
laser.style.height = (40 + Math.random() * 80) + 'px';
}
const hue = Math.random() * 360;
laser.style.filter = `hue-rotate(${hue}deg)`;
laser.style.animation = `laser-pulse ${2 + Math.random() * 2}s ease-in-out infinite`;
laser.style.animationDelay = (Math.random() * 2) + 's';
canvas.appendChild(laser);
}
return laserCount;
}
// Generate simple monologue
function generatePerfMonologue(text) {
const words = text.toLowerCase().split(/\s+/);
const keyWords = words.filter(w => w.length > 4).slice(0, 3);
let monologue = "In this moment of creation, I witness ";
if (keyWords.length > 0) {
monologue += `the essence of ${keyWords[0]}. `;
} else {
monologue += "the power of imagination. ";
}
monologue += "Light and shadow dance together, creating patterns that speak to the soul. ";
if (keyWords.length > 1) {
monologue += `Each ${keyWords[1]} becomes a messenger of deeper meaning, `;
}
monologue += "weaving together the visible and invisible into one magnificent performance. ";
if (keyWords.length > 2) {
monologue += `The ${keyWords[2]} reminds us that beauty exists in the spaces between certainty and mystery. `;
}
monologue += "This performance speaks to the very essence of what it means to create, to express, to exist in this universe of infinite possibility.";
return monologue;
}
// Speech function
function perfSpeak(text) {
if (!window.speechSynthesis) return;
if (perfCurrentSpeech) {
speechSynthesis.cancel();
}
const processedText = text.replace(/\./g, '... ').replace(/,/g, ', ');
perfCurrentSpeech = new SpeechSynthesisUtterance(processedText);
if (perfSelectedVoice) {
perfCurrentSpeech.voice = perfSelectedVoice;
}
perfCurrentSpeech.volume = 0.8;
perfCurrentSpeech.rate = 0.7;
perfCurrentSpeech.pitch = 1.0;
perfCurrentSpeech.onstart = function() {
document.getElementById('perfVoiceStatus').textContent = 'Speaking performance...';
document.getElementById('perfVoiceStatus').className = 'perf-voice-status speaking';
};
perfCurrentSpeech.onend = function() {
document.getElementById('perfVoiceStatus').textContent = 'Performance complete';
document.getElementById('perfVoiceStatus').className = 'perf-voice-status';
perfCurrentSpeech = null;
};
speechSynthesis.speak(perfCurrentSpeech);
}
// Create laser show (no voice)
function createLaserShow() {
const text = document.getElementById('perfInput').value.trim();
if (!text || perfProcessing) return;
perfProcessing = true;
document.getElementById('perfStatus').textContent = 'Creating';
document.getElementById('perfMonologue').style.display = 'none';
if (perfCurrentSpeech) {
speechSynthesis.cancel();
perfCurrentSpeech = null;
}
const laserCount = createPerfLasers(text);
document.getElementById('perfLaserCount').textContent = laserCount;
setTimeout(function() {
document.getElementById('perfStatus').textContent = 'Active';
document.getElementById('perfStatusDisplay').textContent = `Silent laser show with ${laserCount} effects.`;
document.getElementById('perfVoiceStatus').textContent = 'Laser show - visual only';
perfProcessing = false;
}, 1000);
}
// Create full performance
function createMonologue() {
const text = document.getElementById('perfInput').value.trim();
if (!text || perfProcessing) return;
perfProcessing = true;
document.getElementById('perfStatus').textContent = 'Creating';
const monologue = generatePerfMonologue(text);
document.getElementById('perfMonologueText').textContent = monologue;
document.getElementById('perfMonologue').style.display = 'block';
const laserCount = createPerfLasers(text);
document.getElementById('perfLaserCount').textContent = laserCount;
setTimeout(function() {
perfSpeak(monologue);
document.getElementById('perfStatus').textContent = 'Active';
document.getElementById('perfStatusDisplay').textContent = `Performance created with ${laserCount} laser effects and voice.`;
perfProcessing = false;
}, 1500);
}
// Stop all
function stopAll() {
if (perfCurrentSpeech) {
speechSynthesis.cancel();
perfCurrentSpeech = null;
}
document.getElementById('perfStatus').textContent = 'Stopped';
document.getElementById('perfVoiceStatus').textContent = 'Stopped';
document.getElementById('perfVoiceStatus').className = 'perf-voice-status';
document.getElementById('perfMonologue').style.display = 'none';
perfProcessing = false;
}
// Initialize word count
document.getElementById('perfInput').dispatchEvent(new Event('input'));
</script>