“Mamma Mia! - Tech Dashboard” is a professional theater production control system designed for managing live musical performances. The application provides scene-by-scene audio playback control, keyboard shortcuts for quick navigation, and visual feedback systems optimized for technical theater operations. Built with theatrical workflow in mind, it features panic stop functionality, auto-advance capabilities, and an aesthetically pleasing Mediterranean theme.
production/
├── index.html # Complete theater tech dashboard (461 lines)
└── audio/
└── placeholder.txt # Audio assets directory (scene1.mp3 - scene10.mp3 expected)
The application is specifically designed for the ABBA musical “Mamma Mia!” with structured acts and scenes:
body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 50%, #90caf9 100%);
min-height: 100vh;
padding: 20px;
position: relative;
overflow-x: hidden;
}
h1 {
font-size: 3.5rem;
text-align: center;
color: #f57f17; /* Warm Mediterranean gold */
margin-bottom: 30px;
font-weight: 300;
letter-spacing: -1px;
}
/* Subtle vine decorations for Greek island atmosphere */
body::before,
body::after {
content: '🌿';
position: fixed;
font-size: 100px;
opacity: 0.06;
color: #4caf50;
transform: rotate(-30deg);
z-index: -1;
}
.vine-decoration {
position: fixed;
font-size: 80px;
opacity: 0.05;
color: #66bb6a;
z-index: -1;
}
/* Rainbow color coding for 10 scenes */
.scene-box[data-scene="0"] { border-left-color: #e91e63; } /* Pink */
.scene-box[data-scene="1"] { border-left-color: #9c27b0; } /* Purple */
.scene-box[data-scene="2"] { border-left-color: #673ab7; } /* Deep Purple */
.scene-box[data-scene="3"] { border-left-color: #3f51b5; } /* Indigo */
.scene-box[data-scene="4"] { border-left-color: #2196f3; } /* Blue */
.scene-box[data-scene="5"] { border-left-color: #00bcd4; } /* Cyan */
.scene-box[data-scene="6"] { border-left-color: #009688; } /* Teal */
.scene-box[data-scene="7"] { border-left-color: #4caf50; } /* Green */
.scene-box[data-scene="8"] { border-left-color: #ff9800; } /* Orange */
.scene-box[data-scene="9"] { border-left-color: #ff5722; } /* Deep Orange */
.scene-box.highlighted {
box-shadow: 0 0 20px rgba(245, 127, 23, 0.5), 0 0 40px rgba(245, 127, 23, 0.2);
transform: translateY(-2px) scale(1.01);
background: rgba(255, 253, 250, 0.95);
}
const audioElements = document.querySelectorAll('audio');
const playButtons = document.querySelectorAll('.play-button');
function togglePlay(sceneIndex) {
const audio = audioElements[sceneIndex];
const button = playButtons[sceneIndex];
if (audio.paused) {
// Stop all other audio first
stopAllAudio();
// Play selected track
audio.play();
button.innerHTML = '⏸';
button.classList.add('playing');
// Set up auto-advance functionality
audio.addEventListener('ended', function() {
button.innerHTML = '▶';
button.classList.remove('playing');
// Auto-advance to next scene after 1 second
autoAdvanceTimeout = setTimeout(() => {
if (currentScene < totalScenes - 1) {
highlightScene(currentScene + 1);
}
}, 1000);
}, { once: true });
} else {
audio.pause();
button.innerHTML = '▶';
button.classList.remove('playing');
clearTimeout(autoAdvanceTimeout);
}
}
function stopAllAudio() {
audioElements.forEach((audio, index) => {
audio.pause();
audio.currentTime = 0; /* Reset to beginning */
playButtons[index].innerHTML = '▶';
playButtons[index].classList.remove('playing');
});
clearTimeout(autoAdvanceTimeout);
}
function showPanicOverlay() {
const overlay = document.getElementById('panic-overlay');
overlay.style.display = 'block';
setTimeout(() => {
overlay.style.display = 'none';
}, 1500); /* Display for 1.5 seconds */
}
document.addEventListener('keydown', function(e) {
switch(e.key) {
case '.': /* Period = Next Scene */
e.preventDefault();
if (currentScene < totalScenes - 1) {
highlightScene(currentScene + 1);
}
break;
case ',': /* Comma = Previous Scene */
e.preventDefault();
if (currentScene > 0) {
highlightScene(currentScene - 1);
}
break;
case ' ': /* Space = Play/Pause Current */
e.preventDefault();
togglePlay(currentScene);
break;
case 'Escape': /* ESC = Emergency Stop All */
e.preventDefault();
stopAllAudio();
showPanicOverlay();
break;
}
});
function highlightScene(index) {
// Remove all existing highlights
sceneBoxes.forEach(box => box.classList.remove('highlighted'));
// Add highlight to target scene
if (index >= 0 && index < totalScenes) {
sceneBoxes[index].classList.add('highlighted');
currentScene = index;
updateProgressIndicator();
// Smooth scroll to bring scene into view
sceneBoxes[index].scrollIntoView({
behavior: 'smooth',
block: 'center'
});
}
}
function updateProgressIndicator() {
document.getElementById('current-scene').textContent = currentScene + 1;
}
.play-button {
width: 44px;
height: 44px;
border-radius: 50%;
background: #f57f17; /* Mediterranean gold */
border: none;
color: white;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
font-size: 1.1rem;
}
.play-button:hover {
background: #e65100; /* Darker on hover */
transform: scale(1.05);
}
.play-button.playing {
background: #d32f2f; /* Red when playing */
}
<div class="scene-box" data-scene="0">
<div class="scene-info">Act One - Prologue</div>
<div class="song-title">I Have a Dream</div>
<div class="audio-player">
<button class="play-button" onclick="togglePlay(0)">▶</button>
<audio src="/audio/scene1.mp3"></audio>
</div>
<div class="actors">Imogen Roome</div>
</div>
// Auto-advance after audio ends
audio.addEventListener('ended', function() {
button.innerHTML = '▶';
button.classList.remove('playing');
// 1-second delay before advancing to next scene
autoAdvanceTimeout = setTimeout(() => {
if (currentScene < totalScenes - 1) {
highlightScene(currentScene + 1);
}
}, 1000);
}, { once: true });
.progress-indicator {
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(255, 255, 255, 0.95);
padding: 12px 24px;
border-radius: 24px;
font-weight: 400;
color: #5d4037;
font-size: 0.9rem;
}
.keyboard-hint {
position: fixed;
bottom: 65px;
right: 20px;
background: rgba(255, 255, 255, 0.9);
padding: 8px 14px;
border-radius: 6px;
font-size: 0.75rem;
color: #5d4037;
font-weight: 400;
}
.panic-overlay {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(211, 47, 47, 0.95); /* Emergency red */
color: white;
padding: 30px 50px;
border-radius: 8px;
font-size: 1.5rem;
font-weight: 500;
display: none;
z-index: 1000;
}
.scene-box {
background: rgba(252, 252, 253, 0.9);
border-radius: 12px;
padding: 25px 30px;
transition: all 0.3s ease;
position: relative;
min-height: 140px;
width: 100%;
border-left: 5px solid;
}
let currentScene = 0;
const totalScenes = 10;
let autoAdvanceTimeout;
// Efficient DOM queries
const sceneBoxes = document.querySelectorAll('.scene-box');
const audioElements = document.querySelectorAll('audio');
const playButtons = document.querySelectorAll('.play-button');
The Mamma Mia! Tech Dashboard represents an excellent implementation of theatrical production control technology, successfully combining artistic aesthetics with professional operational requirements. The comprehensive keyboard controls, emergency systems, and seamless audio management create a reliable tool for live theater production.
Technical Rating: 8.8/10
The application successfully demonstrates how web technology can be effectively applied to live theater production, creating tools that enhance rather than complicate the artistic process.