Files
motif/index.html
T
b1rdmania 6e61aef35a Redesign UI with Game Boy retro aesthetic
- Add classic LCD green color palette (#9BBC0F, #8BAC0F, #306230, #0F380F)
- Switch to Press Start 2P pixel font
- Add scanline overlay effect for CRT feel
- Style buttons with chunky 4px borders and inset shadows
- Remove all border-radius for pixel-perfect look
- Update hero, controls, results table, and player sections

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:49:04 +00:00

1222 lines
40 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, user-scalable=no">
<title>WARIO SYNTH - Retro Game Console Music</title>
<!-- OpenGraph / Social Media Preview -->
<meta property="og:title" content="WARIO SYNTH">
<meta property="og:description" content="Turn any song into retro game console music">
<meta property="og:image" content="/wario.png">
<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">
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="WARIO SYNTH">
<meta name="twitter:description" content="Turn any song into retro game console music">
<meta name="twitter:image" content="/wario.png">
<!-- General Meta -->
<meta name="description" content="WARIO SYNTH - Transform any song into retro Gameboy-style game console music. Search, preview MIDI, and generate chiptune versions.">
<!-- Pixel Font -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap" rel="stylesheet">
<style>
/* Design System: Game Boy DMG - Classic LCD greens */
:root {
/* Game Boy LCD palette */
--gb-lightest: #9BBC0F;
--gb-light: #8BAC0F;
--gb-dark: #306230;
--gb-darkest: #0F380F;
/* Console colors */
--gb-shell: #C4CFA1;
--gb-shell-dark: #8B956D;
--gb-purple: #442176;
--gb-red: #AB2E41;
/* Semantic mapping */
--color-bg: var(--gb-darkest);
--color-surface: var(--gb-dark);
--color-surface-elevated: #1a3a1a;
--color-border: var(--gb-light);
--color-text: var(--gb-lightest);
--color-text-dim: var(--gb-light);
--color-accent-primary: var(--gb-lightest);
--color-accent-secondary: var(--gb-light);
--spacing-unit: 8px;
--radius: 0px; /* Pixel-perfect, no rounding */
--pixel-border: 4px;
}
* {
box-sizing: border-box;
image-rendering: pixelated;
}
body {
font-family: 'Press Start 2P', monospace;
background: var(--color-bg);
color: var(--color-text);
margin: 0;
padding: calc(var(--spacing-unit) * 3);
line-height: 2;
font-size: 10px;
-webkit-font-smoothing: none;
-moz-osx-font-smoothing: unset;
}
/* LCD Screen Effect */
body::before {
content: '';
position: fixed;
inset: 0;
background: repeating-linear-gradient(
0deg,
rgba(0, 0, 0, 0.1) 0px,
rgba(0, 0, 0, 0.1) 2px,
transparent 2px,
transparent 4px
);
pointer-events: none;
z-index: 9999;
}
.container {
max-width: 960px;
margin: 0 auto;
}
.hero {
text-align: center;
margin: 0 0 calc(var(--spacing-unit) * 4) 0;
position: relative;
padding: calc(var(--spacing-unit) * 2);
border: var(--pixel-border) solid var(--gb-light);
background: var(--gb-dark);
}
.hero h1 {
color: var(--gb-lightest);
margin: 0;
font-size: 20px;
font-weight: normal;
letter-spacing: 0.05em;
text-transform: uppercase;
}
.hero .tagline {
margin: calc(var(--spacing-unit) * 2) 0 0 0;
color: var(--gb-light);
font-size: 8px;
}
.faq-link {
background: var(--gb-dark);
border: var(--pixel-border) solid var(--gb-light);
color: var(--gb-lightest);
padding: 8px 12px;
border-radius: 0;
box-shadow:
inset -4px -4px 0 var(--gb-darkest),
inset 4px 4px 0 var(--gb-light);
font-size: 8px;
}
.faq-link:hover:not(:disabled) {
background: var(--gb-light);
color: var(--gb-darkest);
}
.faq-top {
position: absolute;
top: calc(var(--spacing-unit) * 2);
right: calc(var(--spacing-unit) * 2);
}
/* FAQ modal */
.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.65);
display: none;
align-items: center;
justify-content: center;
padding: 20px;
z-index: 1000;
}
.modal-backdrop.open { display: flex; }
.modal {
width: min(720px, 100%);
background: rgba(20,20,20,0.98);
border: 1px solid rgba(255,255,255,0.12);
border-radius: 12px;
box-shadow: 0 30px 120px rgba(0,0,0,0.75);
overflow: hidden;
}
.modal header {
display: flex;
align-items: center;
gap: 12px;
padding: 14px 16px;
border-bottom: 1px solid rgba(255,255,255,0.08);
}
.modal header h3 {
margin: 0;
font-size: 14px;
letter-spacing: 0.08em;
text-transform: uppercase;
color: rgba(255,255,255,0.9);
}
.modal header .faq-header-links {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.modal header .faq-header-links a {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 10px;
border-radius: 999px;
border: 1px solid rgba(255,255,255,0.12);
background: rgba(0,0,0,0.18);
color: rgba(255,255,255,0.82);
text-decoration: none;
font-size: 12px;
line-height: 1;
box-shadow: none;
transition: border-color 120ms ease, box-shadow 120ms ease, background 120ms ease;
}
.modal header .faq-header-links a:hover {
border-color: rgba(255,255,255,0.22);
box-shadow: 0 10px 30px rgba(0,0,0,0.45);
background: rgba(0,0,0,0.28);
}
.modal header .faq-header-links a:focus-visible {
outline: none;
box-shadow: 0 0 0 3px rgba(0,255,136,0.25), 0 12px 34px rgba(0,0,0,0.55);
border-color: rgba(0,255,136,0.45);
}
.modal header .faq-header-links .dot {
width: 6px;
height: 6px;
border-radius: 999px;
background: rgba(0,255,136,0.85);
box-shadow: 0 0 14px rgba(0,255,136,0.22);
flex: 0 0 auto;
}
.modal header .faq-header-links .label {
display: inline-flex;
align-items: baseline;
gap: 6px;
white-space: nowrap;
}
.modal header .faq-header-links .handle {
color: rgba(0,255,136,0.9);
font-weight: 600;
}
@media (max-width: 480px) {
.modal header {
gap: 10px;
padding: 12px 12px;
}
.modal header .faq-header-links a {
padding: 6px 9px;
font-size: 12px;
}
}
.modal header .spacer { margin-left: auto; }
.modal header button {
padding: 8px 10px;
border-radius: 10px;
background: rgba(255,255,255,0.06);
border: 1px solid rgba(255,255,255,0.12);
box-shadow: none;
}
.modal main {
padding: 14px 16px 16px 16px;
}
.faq-grid {
display: grid;
grid-template-columns: 1fr;
gap: 12px;
}
.faq-item {
border: 1px solid rgba(255,255,255,0.08);
border-radius: 12px;
padding: 12px 12px;
background: rgba(0,0,0,0.18);
}
.faq-item h4 {
margin: 0 0 6px 0;
font-size: 13px;
color: rgba(0,255,136,0.9);
}
.faq-item p {
margin: 0;
color: rgba(255,255,255,0.75);
font-size: 13px;
line-height: 1.45;
}
.faq-item code {
font-size: 12px;
color: rgba(255,255,255,0.85);
}
.controls {
margin: calc(var(--spacing-unit) * 3) auto calc(var(--spacing-unit) * 2) auto;
display: flex;
gap: calc(var(--spacing-unit) * 1.5);
align-items: stretch;
justify-content: center;
max-width: 720px;
}
.controls.locked {
opacity: 0.35;
}
/* Chunky 8-bit buttons */
button {
background: var(--gb-dark);
color: var(--gb-lightest);
border: var(--pixel-border) solid var(--gb-light);
padding: 12px 16px;
border-radius: 0;
cursor: pointer;
font-family: 'Press Start 2P', monospace;
font-size: 8px;
text-transform: uppercase;
box-shadow:
inset -4px -4px 0 var(--gb-darkest),
inset 4px 4px 0 var(--gb-light);
transition: none;
}
button:hover:not(:disabled) {
background: var(--gb-light);
color: var(--gb-darkest);
box-shadow:
inset 4px 4px 0 var(--gb-darkest),
inset -4px -4px 0 var(--gb-lightest);
}
button:active:not(:disabled) {
box-shadow:
inset 4px 4px 0 var(--gb-darkest);
}
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
button.primary {
background: var(--gb-lightest);
color: var(--gb-darkest);
border-color: var(--gb-lightest);
box-shadow:
inset -4px -4px 0 var(--gb-light),
inset 4px 4px 0 #c5d82f;
}
button.primary:hover:not(:disabled) {
background: var(--gb-light);
color: var(--gb-darkest);
}
/* Search button */
#searchBtn {
padding: 14px 20px;
font-size: 10px;
}
/* Status bar - like a Game Boy dialog box */
#status {
margin: calc(var(--spacing-unit) * 3) 0;
padding: calc(var(--spacing-unit) * 2);
background: var(--gb-dark);
border: var(--pixel-border) solid var(--gb-light);
font-size: 8px;
min-height: 24px;
}
/* Text input - Game Boy style */
input[type="text"] {
flex: 1;
background: var(--gb-darkest);
color: var(--gb-lightest);
border: var(--pixel-border) solid var(--gb-light);
padding: 12px 14px;
border-radius: 0;
font-family: 'Press Start 2P', monospace;
font-size: 10px;
box-shadow: inset 4px 4px 0 rgba(0,0,0,0.3);
}
input[type="text"]:focus {
outline: none;
border-color: var(--gb-lightest);
background: var(--gb-dark);
}
input[type="text"]::placeholder {
color: var(--gb-dark);
}
.results-section {
margin: 30px 0;
display: none;
}
.results-section.visible {
display: block;
}
.results-section.collapsed {
opacity: 0.55;
transition: opacity 160ms ease;
}
.results-section.collapsed:hover {
opacity: 1;
}
.chooser-helper {
margin-top: calc(var(--spacing-unit) * 2);
padding: calc(var(--spacing-unit) * 2);
background: var(--gb-dark);
border: var(--pixel-border) solid var(--gb-light);
}
.chooser-helper h4 {
margin: 0 0 8px 0;
font-size: 8px;
text-transform: uppercase;
color: var(--gb-lightest);
}
.chooser-helper p {
margin: 0;
font-size: 8px;
color: var(--gb-light);
line-height: 2;
}
/* Results table - Game Boy menu style */
.results-table {
width: 100%;
border-collapse: collapse;
margin: calc(var(--spacing-unit) * 2) 0;
background: var(--gb-dark);
border: var(--pixel-border) solid var(--gb-light);
}
.results-table th,
.results-table td {
padding: 12px 16px;
text-align: left;
border-bottom: 2px solid var(--gb-darkest);
font-size: 8px;
}
.results-table th {
background: var(--gb-darkest);
color: var(--gb-lightest);
font-weight: normal;
text-transform: uppercase;
}
.results-table .source-col {
width: 100px;
text-align: center;
}
.results-table .duration-col {
width: 80px;
text-align: right;
}
.results-table .action-col {
width: 120px;
text-align: right;
}
.results-table tbody tr {
cursor: pointer;
}
.results-table tbody tr:hover {
background: var(--gb-darkest);
}
.results-table tbody tr:last-child td {
border-bottom: none;
}
.results-table tr.selected {
background: var(--gb-light);
color: var(--gb-darkest);
}
.results-table tr.selected td {
color: var(--gb-darkest);
}
.results-table tr.selected td:first-child {
padding-left: 12px;
}
/* Selection arrow indicator */
.results-table tr.selected td:first-child::before {
content: '▶ ';
}
@media (max-width: 640px) {
.results-table th,
.results-table td {
padding: 10px 12px;
font-size: 7px;
}
.results-table .source-col {
display: none;
}
.results-table .duration-col {
width: 60px;
}
.results-table .action-col {
width: 90px;
}
}
.results-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: calc(var(--spacing-unit) * 2);
flex-wrap: wrap;
margin: 0 0 calc(var(--spacing-unit) * 2) 0;
}
.results-header h3 { margin: 0; }
.confidence-bar {
width: 60px;
height: 4px;
background: var(--gb-darkest);
overflow: hidden;
}
.confidence-fill {
height: 100%;
background: var(--gb-lightest);
}
/* Selected source card - Game Boy cartridge style */
.selected-card {
margin-top: calc(var(--spacing-unit) * 3);
padding: calc(var(--spacing-unit) * 3);
background: var(--gb-dark);
border: var(--pixel-border) solid var(--gb-light);
}
.selected-title {
margin: 0;
font-size: 12px;
line-height: 2;
font-weight: normal;
color: var(--gb-lightest);
}
.selected-meta {
margin: 12px 0 0 0;
font-size: 8px;
color: var(--gb-light);
}
.selected-actions {
display: flex;
gap: 12px;
margin-top: 16px;
flex-wrap: wrap;
}
.selected-actions .primary {
flex: 1;
min-width: 160px;
padding: 14px 16px;
}
.selected-actions button:not(.primary) {
flex: 1;
min-width: 140px;
}
.selected-support {
display: flex;
gap: 16px;
align-items: center;
flex-wrap: wrap;
margin-top: 16px;
}
.selected-support .linklike {
background: transparent;
border: none;
padding: 0;
box-shadow: none;
color: var(--gb-lightest);
cursor: pointer;
font-size: 8px;
text-decoration: underline;
}
.selected-support .linklike:hover {
color: var(--gb-light);
}
.preview-inline {
display: inline-flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
}
.preview-state {
font-size: 8px;
color: var(--gb-light);
display: none;
}
/* Copy link button */
#copyLinkBtn {
padding: 12px 16px;
}
#copyLinkBtn:hover:not(:disabled) {
background: var(--gb-light);
color: var(--gb-darkest);
}
.engine-line {
margin-top: 14px;
color: rgba(255,255,255,0.72);
font-size: 13px;
}
details.details-toggle {
margin-top: 12px;
}
details.details-toggle summary {
cursor: pointer;
color: rgba(255,255,255,0.7);
font-size: 12px;
list-style: none;
}
details.details-toggle summary::-webkit-details-marker { display: none; }
.selected-details {
margin-top: 8px;
font-size: 12px;
color: rgba(255,255,255,0.58);
}
.footer {
margin-top: calc(var(--spacing-unit) * 6);
display: flex;
justify-content: center;
gap: calc(var(--spacing-unit) * 1.5);
flex-wrap: wrap;
}
.player-section {
margin: 30px 0;
display: none;
}
.player-section.visible {
display: block;
}
.player-controls {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin: 20px 0;
}
.player-box {
background: var(--color-surface);
padding: calc(var(--spacing-unit) * 3);
border: 1px solid var(--color-border);
border-radius: var(--radius);
box-shadow: var(--shadow-md);
transition: transform 150ms ease, box-shadow 150ms ease;
}
.player-box:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
}
.player-box h4 {
margin: 0 0 calc(var(--spacing-unit)) 0;
color: var(--color-accent-primary);
font-size: 15px;
font-weight: 600;
}
.player-box p {
font-size: 13px;
color: var(--color-text-dim);
margin: 0 0 calc(var(--spacing-unit) * 2) 0;
}
.player-box button {
width: 100%;
margin: calc(var(--spacing-unit)) 0 0 0;
}
.player-box button:first-of-type {
margin-top: 0;
}
.player-info {
background: var(--color-surface);
padding: calc(var(--spacing-unit) * 3);
margin: calc(var(--spacing-unit) * 3) 0;
border-left: 3px solid var(--color-accent-primary);
border-radius: var(--radius);
box-shadow: var(--shadow-md);
}
.player-info h4 {
margin: 0 0 calc(var(--spacing-unit)) 0;
color: var(--color-text);
font-size: 16px;
}
.player-info p {
margin: 0;
font-size: 13px;
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);
}
.preview-controls {
display: flex;
gap: calc(var(--spacing-unit) * 1.5);
align-items: center;
flex-wrap: wrap;
padding: calc(var(--spacing-unit) * 3);
background: var(--color-surface);
border-radius: var(--radius);
border: 1px solid var(--color-border);
box-shadow: var(--shadow-sm);
}
.preview-controls button.preview-play {
flex: 1;
min-width: 160px;
}
.preview-controls button.next-result {
margin-left: 0;
}
.preview-controls .preview-actions {
margin-left: auto;
display: inline-flex;
gap: calc(var(--spacing-unit) * 1.25);
align-items: center;
}
.preview-controls .volume-control {
flex: 1;
min-width: 200px;
margin-top: 0;
}
@media (max-width: 768px) {
.preview-controls {
flex-direction: column;
align-items: stretch;
}
.preview-controls .preview-actions {
margin-left: 0;
width: 100%;
display: flex;
flex-direction: column;
}
}
.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-controls {
display: flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
}
.motif-controls button {
flex-shrink: 0;
}
.motif-controls button.primary {
flex: 1;
min-width: 180px;
padding: 12px 16px;
font-weight: 700;
}
.motif-controls button.primary:hover {
box-shadow: 0 16px 60px rgba(255, 170, 68, 0.15);
border-color: rgba(255, 170, 68, 0.55);
}
.motif-controls .volume-control {
flex: 1;
min-width: 200px;
margin-top: 0;
}
.motif-controls .volume-control label {
font-size: 0.85em;
min-width: 55px;
}
/* iOS audio unlock (Motif) */
.ios-audio-banner {
margin-top: calc(var(--spacing-unit) * 2);
padding: calc(var(--spacing-unit) * 2);
border-radius: var(--radius);
border: 1px solid rgba(255, 170, 68, 0.22);
background: rgba(0, 0, 0, 0.25);
box-shadow: var(--shadow-sm);
display: none; /* toggled by JS */
}
.ios-audio-banner .row {
display: flex;
gap: calc(var(--spacing-unit) * 1.5);
align-items: center;
flex-wrap: wrap;
}
.ios-audio-banner .copy {
font-size: 12px;
color: var(--color-text-dim);
line-height: 1.35;
flex: 1;
min-width: 220px;
}
.ios-audio-banner .copy strong {
color: var(--color-text);
font-weight: 600;
}
.ios-audio-banner .state {
margin-top: calc(var(--spacing-unit) * 1);
font-size: 12px;
color: rgba(255, 170, 68, 0.85);
display: none;
}
.ios-audio-banner button {
padding: calc(var(--spacing-unit) * 1.25) calc(var(--spacing-unit) * 2);
border-radius: var(--radius);
border: 1px solid rgba(255, 170, 68, 0.35);
background: rgba(255, 170, 68, 0.12);
color: var(--color-text);
box-shadow: var(--shadow-sm);
font-weight: 600;
}
.ios-audio-banner button:hover:not(:disabled) {
border-color: rgba(255, 170, 68, 0.55);
box-shadow: var(--glow-secondary), var(--shadow-md);
}
.motif-kicker {
font-size: 0.85em;
color: #b6b6b6;
margin: 0 0 10px 0;
max-width: 70ch;
}
.try-next {
margin-top: 14px;
width: 100%;
}
.try-next button {
width: 100%;
}
.volume-control {
margin-top: 10px;
display: flex;
align-items: center;
gap: 10px;
position: relative;
}
.volume-control label {
font-size: 0.9em;
color: #aaa;
}
.volume-control input[type="range"] {
flex: 1;
margin: 0;
}
.motif-progress-container {
margin-top: 8px;
padding-top: 16px;
border-top: 1px solid rgba(255, 170, 68, 0.15);
}
.progress-time {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
font-size: 0.85em;
color: #8f8f8f;
}
.progress-bar-wrapper {
position: relative;
height: 44px;
display: flex;
align-items: center;
padding: calc(var(--spacing-unit) * 2) 0;
}
.progress-bar {
width: 100%;
height: 6px;
-webkit-appearance: none;
appearance: none;
background: transparent;
border-radius: 3px;
outline: none;
cursor: pointer;
position: relative;
z-index: 2;
}
.progress-bar::-webkit-slider-runnable-track {
height: 6px;
background: rgba(255, 255, 255, 0.1);
border-radius: 3px;
}
.progress-bar::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 20px;
height: 20px;
border-radius: 50%;
background: var(--color-accent-secondary);
cursor: pointer;
box-shadow: 0 0 8px rgba(255, 170, 68, 0.6), var(--shadow-sm);
margin-top: -7px;
transition: transform 100ms ease;
}
.progress-bar:active::-webkit-slider-thumb {
transform: scale(1.15);
}
.progress-bar::-moz-range-track {
height: 6px;
background: rgba(255, 255, 255, 0.1);
border-radius: 3px;
}
.progress-bar::-moz-range-thumb {
width: 20px;
height: 20px;
border-radius: 50%;
background: var(--color-accent-secondary);
cursor: pointer;
border: none;
box-shadow: 0 0 8px rgba(255, 170, 68, 0.6), var(--shadow-sm);
}
.progress-fill {
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
height: 6px;
background: linear-gradient(90deg, var(--color-accent-secondary), rgba(255, 170, 68, 0.5));
border-radius: 3px;
pointer-events: none;
z-index: 1;
width: 0%;
transition: width 0.1s linear;
}
/* Use on your website */
.embed-card {
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius);
padding: calc(var(--spacing-unit) * 3);
box-shadow: var(--shadow-md);
}
.embed-row {
display: flex;
gap: calc(var(--spacing-unit) * 1.5);
align-items: flex-start;
flex-wrap: wrap;
}
.embed-row button {
flex-shrink: 0;
}
.codeblock {
flex: 1;
min-width: 260px;
margin: 0;
padding: calc(var(--spacing-unit) * 2);
border-radius: calc(var(--radius) + 2px);
background: rgba(0,0,0,0.35);
border: 1px solid rgba(255,255,255,0.08);
overflow: auto;
box-shadow: var(--shadow-sm);
}
.codeblock code {
font-size: 12px;
color: rgba(255,255,255,0.85);
white-space: pre;
}
.embed-hint {
margin-top: calc(var(--spacing-unit) * 1.5);
color: var(--color-text-dim);
font-size: 12px;
}
.embed-hint strong {
color: var(--color-text);
font-weight: 600;
}
.copy-toast {
margin-left: auto;
font-size: 12px;
color: rgba(0,255,136,0.85);
display: none;
}
.engine-selector {
margin-top: 10px;
font-size: 0.9em;
}
.engine-selector label {
color: #aaa;
display: block;
margin-bottom: 5px;
}
.engine-selector select {
background: #333;
color: #e0e0e0;
border: 1px solid #555;
padding: 5px 10px;
font-family: inherit;
width: 100%;
}
</style>
</head>
<body>
<div class="container">
<div class="hero">
<button id="faqBtn" class="faq-link faq-top" type="button">FAQ</button>
<h1>WARIO SYNTH</h1>
<p class="tagline"><strong>Turn any song into retro game console music</strong></p>
</div>
<div class="controls">
<input type="text" id="songInput" placeholder="Search for a song…" />
<button id="searchBtn" class="primary">Search</button>
</div>
<div id="status">Ready. Enter a song name to search for MIDI files.</div>
<div id="resultsSection" class="results-section">
<div id="chooseHelper" class="chooser-helper" style="display:none;">
<h4>Choosing a MIDI source</h4>
<p>
Different MIDI files capture songs differently. Some will produce better results than others.<br />
Pick a source, generate, and if it sounds off, try another.
</p>
</div>
<div class="results-header">
<h3>Search Results</h3>
</div>
<table id="resultsTable" class="results-table">
<thead>
<tr>
<th>Song</th>
<th class="source-col">Source</th>
<th class="duration-col">Length</th>
<th class="action-col">Action</th>
</tr>
</thead>
<tbody id="resultsBody">
</tbody>
</table>
</div>
<div id="playerSection" class="player-section">
<div id="selectedCard" class="selected-card">
<h2 id="selectedTitle" class="selected-title">No source selected</h2>
<div id="selectedMeta" class="selected-meta">Search for a song, then choose a source to use.</div>
<!-- selected_pre_generate only -->
<div id="selectedExpectation" class="selected-meta" style="margin-top: 8px; color: rgba(255,255,255,0.62);">
Some MIDI files work better than others. If the result sounds off, try another source.
</div>
<div class="selected-actions" id="preGenActions">
<button id="motifBtn" class="primary" disabled>Generate music</button>
</div>
<div class="selected-support" id="preGenSupport">
<div class="preview-inline">
<button id="previewBtn" type="button" class="linklike" disabled>Preview original MIDI</button>
<span id="previewState" class="preview-state">Previewing…</span>
<button id="previewStopBtn" type="button" class="linklike" style="display:none;">Stop preview</button>
</div>
<button id="chooseDifferentBtn" type="button" class="linklike">Choose a different source</button>
</div>
<div id="iosAudioBanner" class="ios-audio-banner" aria-live="polite">
<div class="row">
<div class="copy">
<strong>iOS Safari:</strong> tap once to enable audio, then press <strong>Generate music</strong>.
</div>
<button id="enableAudioBtn" type="button">Enable Audio</button>
</div>
<div id="iosAudioState" class="state">Audio: …</div>
</div>
<!-- generated only: artifact playback + sharing -->
<div id="generatedBlock" style="display:none;">
<div class="engine-line" id="generatedTransform">
Reimagined as classic game-console music<br />
using the Wario Synthesis Engine.
</div>
<div style="display:flex; justify-content:center; margin-top: 14px; margin-bottom: 14px;">
<button id="playPauseBtn" class="primary" type="button">Play</button>
</div>
<div class="motif-progress-container" id="motifProgressContainer" style="display: none;">
<div class="progress-time">
<span id="motifCurrentTime">0:00</span>
<span id="motifDuration">0:00</span>
</div>
<div class="progress-bar-wrapper">
<input type="range" id="motifProgressBar" class="progress-bar" min="0" max="100" value="0" step="0.1" />
<div class="progress-fill" id="motifProgressFill"></div>
</div>
</div>
<div class="volume-control" id="generatedVolumeRow" style="margin-top: 14px; opacity: 0.75;">
<label for="motifVolume" style="min-width: auto;">Volume</label>
<input type="range" id="motifVolume" min="0" max="1" step="0.01" value="0.8" />
</div>
<div style="margin-top: 14px;">
<button id="copyLinkBtn" type="button" disabled>Copy link</button>
</div>
</div>
<details class="details-toggle" id="detailsToggle">
<summary>Details</summary>
<div id="selectedDetails" class="selected-details"></div>
</details>
</div>
<div class="section" id="embedSection" data-not-live="true" style="display:none;">
<div class="section-header">
<h3 class="section-title">Use on your website <span style="color: rgba(255,255,255,0.5); font-weight: 500;">(Coming soon)</span></h3>
<p class="section-subtitle">Embeddable widget + multiple synth engines.</p>
</div>
<div class="divider"></div>
<div class="embed-card" style="opacity:0.55; filter: grayscale(20%); position:relative;">
<div style="position:absolute; inset:0; background: linear-gradient(90deg, rgba(0,0,0,0.35), rgba(0,0,0,0)); pointer-events:none;"></div>
<div class="embed-row">
<pre class="codeblock"><code id="embedCode">&lt;iframe src=&quot;...&quot;&gt;&lt;/iframe&gt;</code></pre>
<div style="display:flex; flex-direction:column; gap: calc(var(--spacing-unit) * 1.5);">
<button id="copyEmbedBtn" class="primary" type="button" disabled>Copy embed</button>
<span id="copyToast" class="copy-toast">Copied</span>
</div>
</div>
<div class="embed-hint">
<strong>Note:</strong> This is not live yet. Well ship a dedicated <code>/embed</code> widget + style presets next.
</div>
</div>
</div>
</div>
</div>
<div class="footer">
<button id="faqBtnFooter" class="faq-link" type="button">FAQ</button>
<button id="newSearchBtn" class="faq-link" type="button">New search</button>
</div>
<div id="faqModalBackdrop" class="modal-backdrop" role="dialog" aria-modal="true" aria-labelledby="faqTitle">
<div class="modal" role="document">
<header>
<h3 id="faqTitle">FAQ</h3>
<nav class="faq-header-links" aria-label="FAQ links">
<a href="https://x.com/b1rdmania" target="_blank" rel="noopener noreferrer" aria-label="Open @b1rdmania on X">
<span class="dot" aria-hidden="true"></span>
<span class="label"><span class="handle">@b1rdmania</span><span aria-hidden="true">X</span></span>
</a>
<a href="https://github.com/b1rdmania/motif" target="_blank" rel="noopener noreferrer" aria-label="Open the WARIO SYNTH GitHub repository">
<span class="dot" aria-hidden="true"></span>
<span class="label">GitHub</span>
</a>
</nav>
<div class="spacer"></div>
<button id="faqCloseBtn" type="button">Close</button>
</header>
<main>
<div class="faq-grid">
<div class="faq-item">
<h4>What is WARIO SYNTH?</h4>
<p>Turn any song into retro <strong>Gameboy-style</strong> synth using the Wario Synthesis Engine. Search a track, preview the MIDI, hit Generate.</p>
</div>
<div class="faq-item">
<h4>How does it work?</h4>
<p>We scrape MIDI files from the web, analyse the structure (melody, bass, chords), then resynthesise with the <strong>Wario Synthesis Engine</strong>. Light touch and runs in any browser through <strong>Web Audio</strong>.</p>
</div>
<div class="faq-item">
<h4>Why "Enable Audio" on iPhone?</h4>
<p>Apple blocks sound until you tap something. Just hit the button once — you're good. Still silent? Check your ringer switch isn't on mute.</p>
</div>
<div class="faq-item">
<h4>Ps. I love Claude Code.</h4>
<img src="/wario.png" alt="Wario moment" style="margin-top: 8px; border-radius: 8px; max-width: 100%; opacity: 0.85;" />
</div>
</div>
</main>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>