Files
motif/play.html
T
b1rdmania 778f2a1aaa Match /play landing UX to main page.
Updates layout and styling to reuse main MOTIF hierarchy and components.
2025-12-26 17:15:49 +00:00

298 lines
8.3 KiB
HTML
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.
<!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>MOTIF - Play</title>
<meta name="description" content="Play a shared MOTIF chiptune and generate your own." />
<!-- OpenGraph / Social Media Preview -->
<meta property="og:title" content="MOTIF" />
<meta property="og:description" content="Procedural Music Synthesis from MIDI" />
<meta property="og:image" content="/chiptune_blog_piece_1000x.webp" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<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="MOTIF" />
<meta name="twitter:description" content="Procedural Music Synthesis from MIDI" />
<meta name="twitter:image" content="/chiptune_blog_piece_1000x.webp" />
<style>
:root {
--color-bg: #0a0a0a;
--color-surface: #141414;
--color-surface-elevated: #1a1a1a;
--color-border: #2a2a2a;
--color-text: #e8e8e8;
--color-text-dim: #999;
--color-accent-primary: #00ff88;
--color-accent-secondary: #ffaa44;
--spacing-unit: 8px;
--radius: 8px;
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.5);
--shadow-md: 0 4px 16px rgba(0, 0, 0, 0.6);
--shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.7);
--glow-primary: 0 0 20px rgba(0, 255, 136, 0.3);
--glow-secondary: 0 0 20px rgba(255, 170, 68, 0.3);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: calc(var(--spacing-unit) * 3);
background:
radial-gradient(1000px 600px at 50% -150px, rgba(0, 255, 136, 0.12), transparent 60%),
radial-gradient(800px 600px at 110% 20%, rgba(255, 170, 68, 0.08), transparent 55%),
var(--color-bg);
color: var(--color-text);
font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
.container {
max-width: 960px;
margin: 0 auto;
}
h1.page-title {
color: var(--color-accent-primary);
text-align: center;
margin: 0 0 calc(var(--spacing-unit) * 3) 0;
font-size: 2em;
font-weight: 700;
letter-spacing: 0.05em;
text-shadow: var(--glow-primary);
}
.tagline {
text-align: center;
margin: 0 0 calc(var(--spacing-unit) * 3) 0;
color: var(--color-text-dim);
}
.section {
margin-top: calc(var(--spacing-unit) * 5);
}
.section-header {
margin: 0 0 calc(var(--spacing-unit) * 2) 0;
}
.section-title {
margin: 0;
font-size: 13px;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--color-text);
}
.section-subtitle {
margin: calc(var(--spacing-unit) / 2) 0 0 0;
font-size: 13px;
color: var(--color-text-dim);
}
.divider {
height: 1px;
margin: 0 0 calc(var(--spacing-unit) * 3) 0;
background: linear-gradient(90deg, transparent, var(--color-border), transparent);
}
#status {
margin: calc(var(--spacing-unit) * 2) 0 0 0;
padding: calc(var(--spacing-unit) * 2);
background: var(--color-surface);
border-left: 3px solid var(--color-accent-primary);
border-radius: var(--radius);
box-shadow: var(--shadow-md);
font-size: 14px;
min-height: 24px;
}
button {
background: var(--color-surface);
color: var(--color-text);
border: 1px solid var(--color-border);
padding: calc(var(--spacing-unit) * 1.5) calc(var(--spacing-unit) * 3);
border-radius: var(--radius);
cursor: pointer;
font-family: inherit;
font-size: 14px;
font-weight: 500;
transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: var(--shadow-sm);
}
button:hover:not(:disabled) {
background: var(--color-surface-elevated);
transform: translateY(-1px);
border-color: #444;
box-shadow: var(--shadow-md);
}
button:active:not(:disabled) {
transform: translateY(0);
box-shadow: var(--shadow-sm);
}
button:disabled {
opacity: 0.4;
cursor: not-allowed;
}
button.primary {
background: var(--color-accent-secondary);
color: #000;
border-color: rgba(255, 170, 68, 0.6);
font-weight: 700;
}
button.primary:hover:not(:disabled) {
box-shadow: var(--glow-secondary), var(--shadow-md);
}
.motif-stage {
background: var(--color-surface-elevated);
padding: calc(var(--spacing-unit) * 3);
border-radius: var(--radius);
border: 1px solid rgba(255, 170, 68, 0.2);
box-shadow: var(--shadow-lg), var(--glow-secondary);
}
.motif-grid {
display: flex;
flex-direction: column;
gap: 16px;
}
.motif-header {
margin-bottom: 6px;
}
.motif-title {
margin: 0;
color: var(--color-accent-secondary);
text-shadow: 0 0 18px rgba(255, 170, 68, 0.15);
font-size: 16px;
font-weight: 700;
}
.motif-kicker {
font-size: 0.85em;
color: #b6b6b6;
margin: 6px 0 0 0;
max-width: 70ch;
}
.motif-controls {
display: flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
}
.motif-controls button.primary {
flex: 1;
min-width: 180px;
padding: 12px 16px;
}
.volume-control {
margin-top: 0;
display: flex;
align-items: center;
gap: 10px;
flex: 1;
min-width: 200px;
}
.volume-control label {
font-size: 0.85em;
color: #aaa;
min-width: 55px;
}
input[type="range"] {
flex: 1;
margin: 0;
}
.actions {
margin-top: calc(var(--spacing-unit) * 2);
display: flex;
gap: 12px;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
}
.actions a {
color: rgba(0, 255, 136, 0.85);
text-decoration: none;
font-size: 13px;
}
.actions a:hover {
text-decoration: underline;
}
.backpill {
margin-left: auto;
font-size: 13px;
color: rgba(255, 255, 255, 0.65);
}
</style>
</head>
<body>
<div class="container">
<h1 class="page-title">MOTIF</h1>
<p class="tagline">Shared chiptune player</p>
<div class="section">
<div class="section-header">
<h3 class="section-title">Synthesis Engine</h3>
<p class="section-subtitle">The same Game Boy/NES render you hear on the main page.</p>
</div>
<div class="divider"></div>
<div class="motif-stage">
<div class="motif-grid">
<div class="motif-header">
<h2 class="motif-title" id="title">Loading…</h2>
<p class="motif-kicker">Tap play to run the shared MIDI through MOTIFs synth engine.</p>
</div>
<div class="motif-controls">
<button id="playBtn" class="primary" disabled>Play</button>
<button id="stopBtn" disabled>Stop</button>
<div class="volume-control">
<label for="volume">Volume</label>
<input id="volume" type="range" min="0" max="1" step="0.01" value="0.35" />
</div>
<span class="backpill" id="shareHint">/play</span>
</div>
<div id="status">Loading…</div>
<div class="actions">
<a id="generateOwn" href="/">Generate your own</a>
<a href="/" aria-label="Back to MOTIF home">Home</a>
</div>
</div>
</div>
</div>
</div>
<script type="module" src="/src/play.ts"></script>
</body>
</html>