Files
motif/index.html
T
b1rdmania e22ec74a14 Match FAQ style to Version History (dark bg, light text)
More consistent and easier to read.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 11:14:30 +00:00

1299 lines
40 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, user-scalable=no">
<title>Wario Synth - Game Boy Midi Synthesis Engine</title>
<!-- 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="/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">
<!-- 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="/wariosynthlogo.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.">
<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;
}
/* Design System: Game Boy DMG - Authentic light LCD look */
: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 */
/* Console shell colors */
--gb-shell: #C4CFA1;
--gb-shell-dark: #8B956D;
/* Semantic mapping - LIGHT background, DARK text */
--color-bg: #C8D8B0;
--color-surface: #A8B89A;
--color-surface-elevated: #B8C8A8;
--color-border: var(--gb-dark);
--color-text: var(--gb-darkest);
--color-text-dim: var(--gb-medium);
--color-accent-primary: var(--gb-dark);
--color-accent-secondary: var(--gb-medium);
--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 - 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: 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-dark);
background: var(--color-surface);
}
.hero h1 {
color: var(--gb-darkest);
margin: 0;
font-size: 20px;
font-weight: normal;
letter-spacing: 0.05em;
text-transform: uppercase;
}
.hero-top {
display: flex;
align-items: center;
justify-content: center;
gap: calc(var(--spacing-unit) * 2);
flex-wrap: wrap;
}
.hero-top h1 {
margin: 0;
}
.version-tag {
font-size: 10px;
color: var(--gb-medium);
font-weight: normal;
}
.hero .tagline {
margin: calc(var(--spacing-unit) * 2) 0 0 0;
color: var(--gb-dark);
font-size: 8px;
}
.version-history {
margin: calc(var(--spacing-unit) * 2) 0 calc(var(--spacing-unit) * 3) 0;
text-align: center;
}
.version-history details {
display: inline-block;
max-width: 600px;
}
.version-history summary {
cursor: pointer;
font-size: 8px;
color: var(--gb-medium);
list-style: none;
padding: 8px 16px;
border: 2px solid var(--gb-medium);
background: var(--color-surface);
transition: all 0.15s ease;
}
.version-history summary::-webkit-details-marker { display: none; }
.version-history summary:hover {
color: var(--gb-darkest);
border-color: var(--gb-dark);
background: var(--gb-lightest);
}
.version-history details[open] summary {
border-bottom: none;
background: var(--gb-dark);
color: var(--gb-lightest);
border-color: var(--gb-dark);
}
.version-content {
padding: calc(var(--spacing-unit) * 2);
background: var(--gb-dark);
border: 2px solid var(--gb-dark);
border-top: none;
text-align: left;
}
.version-item {
font-size: 8px;
color: var(--gb-light);
line-height: 2;
margin-bottom: 8px;
}
.version-item:last-child {
margin-bottom: 0;
}
.version-item strong {
color: var(--gb-lightest);
}
.version-divider {
height: 2px;
background: var(--gb-medium);
margin: calc(var(--spacing-unit) * 2) 0;
opacity: 0.5;
}
.faq-link {
background: var(--gb-lightest);
border: var(--pixel-border) solid var(--gb-dark);
color: var(--gb-darkest);
padding: 8px 12px;
border-radius: 0;
box-shadow:
inset -3px -3px 0 var(--gb-medium),
inset 3px 3px 0 #fff;
font-size: 8px;
}
.faq-link:hover:not(:disabled) {
background: #fff;
color: var(--gb-darkest);
}
/* FAQ modal - Game Boy style */
.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.5);
display: none;
align-items: center;
justify-content: center;
padding: 20px;
z-index: 1000;
}
.modal-backdrop.open { display: flex; }
.modal {
width: min(720px, 100%);
max-height: calc(100vh - 40px);
max-height: calc(100dvh - 40px);
background: var(--color-surface);
border: var(--pixel-border) solid var(--gb-dark);
overflow: hidden;
display: flex;
flex-direction: column;
}
.modal header {
display: flex;
align-items: center;
gap: 12px;
padding: 14px 16px;
border-bottom: 2px solid var(--gb-dark);
background: var(--gb-dark);
flex-shrink: 0;
flex-wrap: wrap;
}
.modal header h3 {
margin: 0;
font-size: 10px;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--gb-lightest);
}
.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: 2px solid var(--gb-light);
background: var(--gb-darkest);
color: var(--gb-lightest);
text-decoration: none;
font-size: 8px;
line-height: 1;
}
.modal header .faq-header-links a:hover {
background: var(--gb-light);
color: var(--gb-darkest);
}
.modal header .faq-header-links .dot {
width: 6px;
height: 6px;
background: var(--gb-lightest);
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: var(--gb-lightest);
}
@media (max-width: 480px) {
.modal header {
gap: 10px;
padding: 12px 12px;
}
.modal header .faq-header-links a {
padding: 6px 9px;
font-size: 8px;
}
}
.modal header .spacer { margin-left: auto; }
.modal header button {
padding: 8px 12px;
background: var(--gb-light);
border: 2px solid var(--gb-lightest);
color: var(--gb-darkest);
font-size: 8px;
}
.modal header button:hover {
background: var(--gb-lightest);
}
.modal main {
padding: 16px;
background: var(--gb-dark);
overflow-y: auto;
flex: 1;
-webkit-overflow-scrolling: touch;
}
.faq-grid {
display: grid;
grid-template-columns: 1fr;
gap: 10px;
}
.faq-item {
border: 2px solid var(--gb-medium);
padding: 10px;
background: var(--gb-darkest);
}
.faq-item h4 {
margin: 0 0 6px 0;
font-size: 8px;
color: var(--gb-lightest);
}
.faq-item p {
margin: 0;
color: var(--gb-light);
font-size: 8px;
line-height: 1.8;
}
.faq-item a {
color: var(--gb-lightest);
}
.faq-item code {
font-size: 8px;
color: var(--gb-lightest);
}
.controls {
margin: calc(var(--spacing-unit) * 3) 0 calc(var(--spacing-unit) * 2) 0;
display: flex;
gap: calc(var(--spacing-unit) * 1.5);
align-items: stretch;
width: 100%;
box-sizing: border-box;
}
.controls.locked {
opacity: 0.35;
}
/* Chunky 8-bit 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);
}
/* 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-lightest);
border: var(--pixel-border) solid var(--gb-dark);
color: var(--gb-darkest);
font-size: 8px;
min-height: 24px;
}
/* Text input - Game Boy style */
input[type="text"] {
flex: 1;
min-width: 0;
background: var(--gb-lightest);
color: var(--gb-darkest);
border: var(--pixel-border) solid var(--gb-dark);
padding: 12px 14px;
border-radius: 0;
font-family: 'Press Start 2P', monospace;
font-size: 10px;
box-shadow: inset 3px 3px 0 var(--gb-medium);
}
input[type="text"]:focus {
outline: none;
border-color: var(--gb-darkest);
background: #fff;
}
input[type="text"]::placeholder {
color: var(--gb-medium);
}
.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(--color-surface);
border: var(--pixel-border) solid var(--gb-dark);
}
.chooser-helper h4 {
margin: 0 0 8px 0;
font-size: 8px;
text-transform: uppercase;
color: var(--gb-darkest);
}
.chooser-helper p {
margin: 0;
font-size: 8px;
color: var(--gb-dark);
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(--color-surface);
border: var(--pixel-border) solid var(--gb-dark);
}
.results-table th,
.results-table td {
padding: 12px 16px;
text-align: left;
border-bottom: 2px solid var(--gb-medium);
font-size: 8px;
color: var(--gb-darkest);
}
.results-table th {
background: var(--gb-dark);
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-lightest);
}
.results-table tbody tr:last-child td {
border-bottom: none;
}
.results-table tr.selected {
background: var(--gb-dark);
color: var(--gb-lightest);
}
.results-table tr.selected td {
color: var(--gb-lightest);
}
.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: var(--gb-light);
font-size: 8px;
}
details.details-toggle {
margin-top: 12px;
}
details.details-toggle summary {
cursor: pointer;
color: var(--gb-light);
font-size: 8px;
list-style: none;
}
details.details-toggle summary::-webkit-details-marker { display: none; }
.selected-details {
margin-top: 8px;
font-size: 8px;
color: var(--gb-light);
}
.footer {
margin-top: calc(var(--spacing-unit) * 6);
display: flex;
justify-content: center;
gap: calc(var(--spacing-unit) * 1.5);
flex-wrap: wrap;
}
.footer-mascot {
margin-top: calc(var(--spacing-unit) * 4);
text-align: center;
}
.wario-sprite {
width: 192px;
height: auto;
mix-blend-mode: multiply;
opacity: 0.7;
}
.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: var(--pixel-border) solid var(--gb-dark);
border-radius: 0;
}
.player-box:hover {
background: var(--gb-lightest);
}
.player-box h4 {
margin: 0 0 calc(var(--spacing-unit)) 0;
color: var(--gb-darkest);
font-size: 15px;
font-weight: 600;
}
.player-box p {
font-size: 13px;
color: var(--gb-dark);
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: var(--pixel-border) solid var(--gb-dark);
}
.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 {
background: var(--gb-darkest);
}
.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: var(--pixel-border) solid var(--gb-dark);
background: var(--gb-lightest);
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: 8px;
color: var(--gb-dark);
line-height: 2;
flex: 1;
min-width: 220px;
}
.ios-audio-banner .copy strong {
color: var(--gb-darkest);
}
.ios-audio-banner .state {
margin-top: calc(var(--spacing-unit) * 1);
font-size: 8px;
color: var(--gb-dark);
display: none;
}
.motif-kicker {
font-size: 8px;
color: var(--gb-dark);
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: 8px;
color: var(--gb-dark);
}
.volume-control input[type="range"] {
flex: 1;
margin: 0;
}
.motif-progress-container {
margin-top: 8px;
padding-top: 16px;
border-top: 2px solid var(--gb-light);
}
.progress-time {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
font-size: 8px;
color: var(--gb-light);
}
.progress-bar-wrapper {
position: relative;
height: 44px;
display: flex;
align-items: center;
padding: calc(var(--spacing-unit) * 2) 0;
}
.progress-bar {
width: 100%;
height: 8px;
-webkit-appearance: none;
appearance: none;
background: transparent;
border-radius: 0;
outline: none;
cursor: pointer;
position: relative;
z-index: 2;
}
.progress-bar::-webkit-slider-runnable-track {
height: 8px;
background: var(--gb-darkest);
border-radius: 0;
}
.progress-bar::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 16px;
height: 16px;
border-radius: 0;
background: var(--gb-lightest);
border: 2px solid var(--gb-light);
cursor: pointer;
margin-top: -4px;
}
.progress-bar:active::-webkit-slider-thumb {
background: #fff;
}
.progress-bar::-moz-range-track {
height: 8px;
background: var(--gb-darkest);
border-radius: 0;
}
.progress-bar::-moz-range-thumb {
width: 16px;
height: 16px;
border-radius: 0;
background: var(--gb-lightest);
border: 2px solid var(--gb-light);
cursor: pointer;
}
.progress-fill {
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
height: 8px;
background: var(--gb-light);
border-radius: 0;
pointer-events: none;
z-index: 1;
width: 0%;
transition: width 0.1s linear;
}
/* Use on your website */
.embed-card {
background: var(--color-surface);
border: var(--pixel-border) solid var(--gb-dark);
padding: calc(var(--spacing-unit) * 3);
}
.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);
background: var(--gb-lightest);
border: 2px solid var(--gb-medium);
overflow: auto;
}
.codeblock code {
font-size: 8px;
color: var(--gb-darkest);
white-space: pre;
}
.embed-hint {
margin-top: calc(var(--spacing-unit) * 1.5);
color: var(--gb-dark);
font-size: 8px;
}
.embed-hint strong {
color: var(--gb-darkest);
}
.copy-toast {
margin-left: auto;
font-size: 8px;
color: var(--gb-darkest);
display: none;
}
.engine-selector {
margin-top: 10px;
font-size: 8px;
}
.engine-selector label {
color: var(--gb-dark);
display: block;
margin-bottom: 5px;
}
.engine-selector select {
background: var(--gb-lightest);
color: var(--gb-darkest);
border: 2px solid var(--gb-dark);
padding: 8px 12px;
font-family: 'Press Start 2P', monospace;
font-size: 8px;
width: 100%;
}
/* Mobile: increase font sizes for readability */
@media (max-width: 640px) {
body {
font-size: 11px;
line-height: 2.2;
}
.hero h1 {
font-size: 18px;
}
.hero .tagline {
font-size: 9px;
}
button {
font-size: 10px;
padding: 14px 18px;
}
#searchBtn {
font-size: 11px;
}
input[type="text"] {
font-size: 11px;
}
#status {
font-size: 9px;
}
.chooser-helper h4,
.chooser-helper p {
font-size: 9px;
}
.results-table th,
.results-table td {
font-size: 9px;
padding: 14px 12px;
}
.faq-item h4,
.faq-item p {
font-size: 9px;
}
.selected-title {
font-size: 14px;
}
.selected-meta {
font-size: 9px;
}
}
</style>
</head>
<body>
<div class="container">
<div class="hero">
<div class="hero-top">
<h1>WARIO SYNTH <span class="version-tag">v1.3</span></h1>
<button id="faqBtnTop" class="faq-link" type="button">FAQ</button>
</div>
</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. Search any song to make a Game Boy version.</div>
<div id="resultsSection" class="results-section">
<div id="chooseHelper" class="chooser-helper" style="display:none;">
<p>Pick a midi source. Try another if it sounds bad, some work better than others.</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="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>
<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>
</div>
<div id="iosAudioBanner" class="ios-audio-banner" aria-live="polite">
<div class="row">
<div class="copy">
<strong>iPhone:</strong> check not on silent, volume up, Focus mode off. Then tap:
</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 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 style="margin-top: 14px; display: flex; gap: 12px; flex-wrap: wrap;">
<button id="copyLinkBtn" type="button" disabled>Copy link</button>
<button id="shareToXBtn" type="button" disabled>Share to X</button>
</div>
<div id="shareFallback" style="display: none; margin-top: 12px;">
<p style="font-size: 8px; margin: 0 0 8px 0; color: var(--gb-light);">Sorry, copy doesn't work on your device. Here's the link:</p>
<input id="shareFallbackInput" type="text" readonly style="width: 100%; padding: 8px; font-size: 8px; font-family: 'Press Start 2P', monospace; background: var(--gb-darkest); color: var(--gb-lightest); border: 2px solid var(--gb-light);" />
</div>
</div>
</div>
</div>
</div>
<div class="footer">
<button id="newSearchBtn" class="faq-link" type="button" style="display:none;">New search</button>
</div>
<div class="version-history">
<details>
<summary>Version History</summary>
<div class="version-content">
<div class="version-item">
<strong>How it works:</strong> The Wario Synthesis Engine analyses MIDI files to identify melody, bass, and chord tracks. It then resynthesises each part using Web Audio oscillators tuned to mimic the Game Boy's 4-channel sound chip: two pulse wave channels, one wave channel, and one noise channel. All processing runs client-side in your browser - no server-side audio generation. Built with TypeScript, Vite, and Claude Code.
</div>
<div class="version-divider"></div>
<div class="version-item">
<strong>v1.3</strong> - Share to X, light Game Boy palette, iOS audio fixes, local font hosting
</div>
<div class="version-item">
<strong>v1.2</strong> - Short share links with dynamic previews, copy link button, improved MIDI selection
</div>
<div class="version-item">
<strong>v1.1</strong> - Search MIDI files, generate Game Boy style music, basic playback with progress bar
</div>
</div>
</details>
</div>
<div class="footer-mascot">
<img src="/wario-sprite.png" alt="Wario" class="wario-sprite" />
</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>
<div class="spacer"></div>
<button id="faqCloseBtn" type="button">Close</button>
</header>
<main>
<div class="faq-grid">
<div class="faq-item">
<h4>How it works</h4>
<p>Search a song, pick a MIDI source, hit Generate. The Wario Synthesis Engine analyses the MIDI and resynthesises it using Web Audio oscillators tuned to mimic the Game Boy's 4-channel sound chip. All processing runs in your browser.</p>
</div>
<div class="faq-item">
<h4>Why "Enable Audio" on iPhone?</h4>
<p>Apple blocks sound until you tap something. Hit the button once and you're good. Still silent? Check your ringer switch.</p>
</div>
<div class="faq-item">
<h4>About</h4>
<p>A non-commercial project by <a href="https://x.com/b1rdmania" target="_blank" rel="noopener noreferrer">@b1rdmania</a> for lols. Please don't sue me. Built with Claude Code.</p>
<p style="margin-top: 8px;"><a href="https://github.com/b1rdmania/motif" target="_blank" rel="noopener noreferrer">GitHub repo</a></p>
</div>
<div class="faq-item">
<h4>Ps. I love Claude Code.</h4>
<img src="/wario.png" alt="Wario moment" style="margin-top: 8px; max-width: 100%; opacity: 0.85;" />
</div>
</div>
</main>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>