Files
motif/play.html
T
b1rdmania 0b952424c3 Add iOS audio unlock banner to play page
Shows "Tap to enable audio on iOS" banner on iOS devices.
Hides automatically once audio is unlocked via button or play.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 16:41:15 +00:00

383 lines
11 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<title>Wario Synth - Game Boy Midi Synthesis Engine</title>
<meta name="description" content="Tap to play this Gameboy tune" />
<!-- OpenGraph / Social Media Preview -->
<meta property="og:title" content="Wario Synth 16-Bit Midi" />
<meta property="og:description" content="Turn any song into a Game Boy version" />
<meta property="og:image" content="https://motif-self.vercel.app/wariosynthlogo.png" />
<meta property="og:image:width" content="1180" />
<meta property="og:image:height" content="912" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://motif-self.vercel.app/play" />
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Wario Synth 16-Bit Midi" />
<meta name="twitter:description" content="Turn any song into a Game Boy version" />
<meta name="twitter:image" content="https://motif-self.vercel.app/wariosynthlogo.png" />
<style>
/* Local Pixel Font */
@font-face {
font-family: 'Press Start 2P';
src: url('/fonts/PressStart2P.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
:root {
/* Game Boy palette - light mode (authentic LCD) */
--gb-lightest: #E0E8C8; /* Screen background */
--gb-light: #A8B89A; /* Surface/cards */
--gb-medium: #6B7B5A; /* Dim text, borders */
--gb-dark: #3A4A2A; /* Text */
--gb-darkest: #1D2A1D; /* Darkest accents */
/* Semantic mapping - LIGHT background, DARK text */
--color-bg: #C8D8B0;
--color-surface: #A8B89A;
--color-border: var(--gb-dark);
--color-text: var(--gb-darkest);
--color-text-dim: var(--gb-medium);
--spacing-unit: 8px;
--pixel-border: 4px;
}
* {
box-sizing: border-box;
image-rendering: pixelated;
}
body {
margin: 0;
padding: calc(var(--spacing-unit) * 3);
background: var(--color-bg);
color: var(--color-text);
font-family: 'Press Start 2P', monospace;
line-height: 2;
font-size: 10px;
-webkit-font-smoothing: none;
-moz-osx-font-smoothing: unset;
}
/* LCD Screen Effect - subtle on light bg */
body::before {
content: '';
position: fixed;
inset: 0;
background: repeating-linear-gradient(
0deg,
rgba(0, 0, 0, 0.03) 0px,
rgba(0, 0, 0, 0.03) 2px,
transparent 2px,
transparent 4px
);
pointer-events: none;
z-index: 9999;
}
.container {
max-width: 600px;
margin: 0 auto;
}
/* Hero header */
.hero {
text-align: center;
margin: 0 0 calc(var(--spacing-unit) * 3) 0;
padding: calc(var(--spacing-unit) * 2);
border: var(--pixel-border) solid var(--gb-dark);
background: var(--color-surface);
}
.hero h1 {
color: var(--gb-darkest);
margin: 0;
font-size: 16px;
font-weight: normal;
letter-spacing: 0.05em;
text-transform: uppercase;
}
/* Main card */
.player-card {
background: var(--gb-dark);
padding: calc(var(--spacing-unit) * 3);
border: var(--pixel-border) solid var(--gb-darkest);
}
/* Song title */
.song-title {
margin: 0 0 calc(var(--spacing-unit) * 2) 0;
font-size: 14px;
line-height: 1.8;
font-weight: normal;
color: var(--gb-lightest);
word-break: break-word;
}
.song-artist {
display: none;
margin-top: calc(var(--spacing-unit) * -1);
margin-bottom: calc(var(--spacing-unit) * 2);
font-size: 8px;
color: var(--gb-medium);
}
/* Buttons */
button {
background: var(--color-surface);
color: var(--color-text);
border: var(--pixel-border) solid var(--gb-dark);
padding: 12px 16px;
border-radius: 0;
cursor: pointer;
font-family: 'Press Start 2P', monospace;
font-size: 8px;
text-transform: uppercase;
box-shadow:
inset -3px -3px 0 var(--gb-medium),
inset 3px 3px 0 var(--gb-lightest);
transition: none;
}
button:hover:not(:disabled) {
background: var(--gb-lightest);
color: var(--gb-darkest);
}
button:active:not(:disabled) {
box-shadow: inset 3px 3px 0 var(--gb-medium);
}
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
button.primary {
background: var(--gb-dark);
color: var(--gb-lightest);
border-color: var(--gb-darkest);
box-shadow:
inset -3px -3px 0 var(--gb-darkest),
inset 3px 3px 0 var(--gb-medium);
}
button.primary:hover:not(:disabled) {
background: var(--gb-darkest);
color: var(--gb-lightest);
}
/* Play button container */
.play-container {
display: flex;
justify-content: center;
margin: calc(var(--spacing-unit) * 2) 0;
}
.play-container button {
min-width: 200px;
padding: 14px 20px;
font-size: 10px;
}
/* Progress bar */
.progress-container {
margin-top: calc(var(--spacing-unit) * 2);
padding-top: calc(var(--spacing-unit) * 2);
border-top: 2px solid var(--gb-light);
}
.progress-time {
display: flex;
justify-content: space-between;
margin-bottom: calc(var(--spacing-unit));
font-size: 8px;
color: var(--gb-light);
}
.progress-bar-wrapper {
position: relative;
height: 20px;
display: flex;
align-items: center;
background: var(--gb-darkest);
border: 2px solid var(--gb-light);
padding: 4px;
}
.progress-bar {
width: 100%;
height: 8px;
-webkit-appearance: none;
appearance: none;
background: transparent;
outline: none;
cursor: pointer;
position: relative;
z-index: 2;
}
.progress-bar::-webkit-slider-runnable-track {
height: 8px;
background: var(--gb-darkest);
}
.progress-bar::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 12px;
height: 12px;
background: var(--gb-lightest);
cursor: pointer;
border: none;
}
.progress-bar::-moz-range-track {
height: 8px;
background: var(--gb-darkest);
}
.progress-bar::-moz-range-thumb {
width: 12px;
height: 12px;
background: var(--gb-lightest);
cursor: pointer;
border: none;
border-radius: 0;
}
.progress-fill {
position: absolute;
left: 4px;
top: 50%;
transform: translateY(-50%);
height: 8px;
background: var(--gb-light);
pointer-events: none;
z-index: 1;
width: 0%;
}
/* CTA link (inside card) */
.cta-link-inline {
margin-top: calc(var(--spacing-unit) * 2);
padding-top: calc(var(--spacing-unit) * 2);
border-top: 2px solid var(--gb-light);
text-align: center;
}
.cta-link-inline a {
display: inline-block;
color: var(--gb-lightest);
text-decoration: none;
font-size: 10px;
padding: 12px 20px;
border: var(--pixel-border) solid var(--gb-light);
background: var(--gb-dark);
box-shadow:
inset -3px -3px 0 var(--gb-darkest),
inset 3px 3px 0 var(--gb-medium);
}
.cta-link-inline a:hover {
background: var(--gb-darkest);
color: var(--gb-lightest);
}
/* iOS audio unlock banner */
.ios-audio-banner {
margin-top: calc(var(--spacing-unit) * 2);
padding: calc(var(--spacing-unit) * 2);
border-top: 2px solid var(--gb-light);
display: none; /* toggled by JS */
text-align: center;
}
.ios-audio-banner p {
font-size: 8px;
color: var(--gb-light);
margin: 0 0 calc(var(--spacing-unit)) 0;
line-height: 2;
}
.ios-audio-banner button {
background: var(--gb-lightest);
color: var(--gb-darkest);
border: var(--pixel-border) solid var(--gb-light);
padding: 12px 20px;
font-size: 10px;
}
/* Footer */
.footer {
margin-top: calc(var(--spacing-unit) * 4);
text-align: center;
font-size: 8px;
color: var(--gb-dark);
}
.footer a {
color: var(--gb-darkest);
text-decoration: underline;
}
</style>
</head>
<body>
<div class="container">
<div class="hero">
<h1>WARIO SYNTH</h1>
</div>
<div class="player-card">
<!-- Song Title -->
<h2 id="songTitle" class="song-title">Loading...</h2>
<div id="songArtist" class="song-artist"></div>
<!-- Play/Pause Control -->
<div class="play-container">
<button id="playToggleBtn" class="primary" disabled>
Play
</button>
</div>
<!-- Progress Bar -->
<div class="progress-container" id="playProgressContainer">
<div class="progress-time" id="playTimeRow">
<span id="playCurrentTime">0:00</span>
<span id="playDuration"></span>
</div>
<div class="progress-bar-wrapper">
<input id="playProgressBar" class="progress-bar" type="range" min="0" max="100" value="0" step="0.1" />
<div id="playProgressFill" class="progress-fill"></div>
</div>
</div>
<!-- iOS Audio Unlock -->
<div id="iosAudioBanner" class="ios-audio-banner">
<p>Tap to enable audio on iOS</p>
<button id="enableAudioBtn" type="button">Enable Audio</button>
</div>
<!-- CTA -->
<div class="cta-link-inline">
<a id="generateOwn" href="/">Generate your own</a>
</div>
</div>
<div class="footer">
Wario Synth Engine - by <a href="https://x.com/b1rdmania" target="_blank" rel="noopener">Birdmania</a>
</div>
</div>
<script type="module" src="/src/play.ts"></script>
</body>
</html>