Design system refactor: shared CSS tokens, cleaner customer/admin pages, kiosk name privacy, v0.9.1

This commit is contained in:
Troll (Hermes Agent) 2026-08-31 03:17:14 +00:00
parent 2f5050b29f
commit cc27c5db48
10 changed files with 1490 additions and 1224 deletions

View file

@ -4,144 +4,57 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Your Theme Song</title>
<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=Outfit:wght@500;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="{{ url_for('static', filename='css/booth.css') }}">
<style>
/*
Private customer player page.
Shows two audio players for Version A and Version B, plus approval
buttons or a revision note form depending on request status.
After the customer makes a choice, the controls are hidden and a
confirmation/waiting message is shown. The number of remaining
customer revisions is displayed when revisions are enabled.
*/
body{
font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
background:#111827;
color:#f3f4f6;
margin:0;
padding:1rem;
line-height:1.5;
}
.container{
max-width:640px;
margin:0 auto;
background:#1f2937;
padding:1.5rem;
border-radius:1rem;
}
h1{color:#60a5fa;}
.player{
background:#111827;
padding:1rem;
border-radius:.5rem;
margin:1rem 0;
}
audio{width:100%;margin-top:.5rem;}
.actions{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:1rem;}
button{
flex:1;
min-width:120px;
padding:.8rem;
border:none;
border-radius:.5rem;
background:#3b82f6;
color:#fff;
font-weight:700;
cursor:pointer;
}
button:disabled{background:#374151;color:#9ca3af;cursor:not-allowed;}
button.selected{background:#10b981;}
button.both{background:#8b5cf6;}
button.revision{background:#f59e0b;color:#000;}
form{margin-top:1rem;}
textarea{
width:100%;
padding:.6rem;
border-radius:.5rem;
border:1px solid #374151;
background:#111827;
color:#f3f4f6;
box-sizing:border-box;
min-height:80px;
}
.status{
padding:.8rem;
background:#064e3b;
border-radius:.5rem;
margin-top:1rem;
}
.status.waiting{background:#3f3f46;}
.locked{
margin-top:1rem;
padding:1rem;
background:#111827;
border-radius:.5rem;
border:1px solid #374151;
}
.locked h2{margin-top:0;color:#fbbf24;}
.locked p{margin:.3rem 0;}
.lyrics{
background:#111827;
border:1px solid #374151;
border-radius:.5rem;
padding:1rem 1.25rem;
margin:1rem 0;
line-height:1.3;
font-size:1rem;
}
.lyrics h2{
margin-top:0;
margin-bottom:.5rem;
color:#fbbf24;
font-size:1.2rem;
}
.lyrics .section-label{
color:#60a5fa;
font-weight:700;
display:block;
margin-top:.5rem;
margin-bottom:.1rem;
}
.lyrics .lyric-line{
display:block;
line-height:1.3;
margin:0;
padding:0;
}
.verse + .verse { margin-top: var(--space-5); }
</style>
</head>
<body>
<body class="booth-page">
<div class="container">
<h1>🎧 Your Custom Theme Song</h1>
<h1>Your Custom Theme Song</h1>
<p>Hi {{ req.name }}! Listen to both versions and pick the one you want.</p>
{% if req.suno_lyrics %}
<div class="lyrics">
<h2>🎵 Song Lyrics</h2>
<h2>Song Lyrics</h2>
{% set current_verse = namespace(lines=[]) %}
{% for line in req.suno_lyrics.splitlines() %}
{% set line = line.strip() %}
{% if line and not (line.startswith('[') and line.endswith(']')) %}
<span class="lyric-line">{{ line }}</span>
{% elif not line %}
<br>
{% set _ = current_verse.lines.append(line) %}
{% elif not line and current_verse.lines %}
<div class="verse">
{% for l in current_verse.lines %}
<span class="lyric-line">{{ l }}</span>
{% endfor %}
</div>
{% set current_verse.lines = [] %}
{% endif %}
{% endfor %}
{% if current_verse.lines %}
<div class="verse">
{% for l in current_verse.lines %}
<span class="lyric-line">{{ l }}</span>
{% endfor %}
</div>
{% endif %}
</div>
{% endif %}
<!-- Album cover -->
{% if req.album_cover_url and deliver_album_cover %}
<div style="text-align:center;margin:1rem 0">
<img src="{{ req.album_cover_url }}" alt="Album cover" style="max-width:160px;border-radius:.5rem">
<div class="text-center mt-4 mb-4">
<img src="{{ req.album_cover_url }}" alt="Album cover" style="max-width:160px;border-radius:var(--radius-md)">
</div>
{% endif %}
<!-- Version A player -->
<div class="player">
<h3>Version A</h3>
<audio controls controlsList="nodownload" id="player-a"></audio>
</div>
<!-- Version B player -->
<div class="player">
<h3>Version B</h3>
<audio controls controlsList="nodownload" id="player-b"></audio>
@ -149,63 +62,58 @@
<script>
(function(){
// Audio sources are assigned via JS so they do not appear in static HTML source.
document.getElementById('player-a').src = "{{ url_for('stream_audio', token=req.player_token, version='a') }}";
document.getElementById('player-b').src = "{{ url_for('stream_audio', token=req.player_token, version='b') }}";
})();
</script>
{% if req.status == 'revisions_requested' %}
<!-- Customer asked for changes; lock the page and tell them to wait -->
<div class="locked waiting">
<h2>📝 Revision Requested</h2>
<h2>Revision Requested</h2>
<p>You asked for changes. We will generate a new version and update this page.</p>
<p><strong>Your note:</strong> {{ req.revision_note }}</p>
</div>
{% elif req.status in ['awaiting_payment','paid','delivered'] %}
<!-- Customer already picked a version; show their choice and payment instruction -->
<div class="locked">
<h2>Choice Received</h2>
<h2>Choice Received</h2>
<p>You selected: <strong>{% if req.customer_approved == 'both' %}Both Versions{% else %}Version {{ (req.customer_approved or 'none').upper() }}{% endif %}</strong></p>
{% if req.status == 'awaiting_payment' %}
<p>Please return to the booth to finalize payment and collect your files.</p>
{% elif req.status == 'paid' %}
<p>Payment recorded. Your files are being prepared.</p>
{% elif req.status == 'delivered' %}
<p>Delivered! Check your email for the MP3 attachment(s).</p>
<p>Delivered! Check your email for the MP3 attachment(s).</p>
{% if req.stems_link %}
<p style="margin-top:.8rem">
<a href="{{ req.stems_link }}" target="_blank" rel="noopener noreferrer" style="display:inline-block;padding:.7rem 1rem;background:#10b981;color:#000;border-radius:.5rem;text-decoration:none;font-weight:700;">Download stems / extras</a>
<p class="mt-4">
<a href="{{ req.stems_link }}" target="_blank" rel="noopener noreferrer" class="button">Download stems / extras</a>
</p>
<p style="font-size:.9rem;color:#9ca3af;">This link expires 3 months after delivery. Download soon.</p>
<p class="text-muted" style="font-size:0.9rem">This link expires 3 months after delivery. Download soon.</p>
{% endif %}
{% endif %}
</div>
{% else %}
<!-- Approval form: customer picks Version A, B, or both -->
<form method="POST" action="{{ url_for('approve', token=req.player_token) }}">
<input type="hidden" name="choice" id="choice">
<div class="actions">
<button type="submit" onclick="document.getElementById('choice').value='a'">I want Version A</button>
<button type="submit" onclick="document.getElementById('choice').value='b'">I want Version B</button>
<button type="submit" class="both" onclick="document.getElementById('choice').value='both'">I want both</button>
<button type="submit" class="button-secondary" onclick="document.getElementById('choice').value='a'">I want Version A</button>
<button type="submit" class="button-secondary" onclick="document.getElementById('choice').value='b'">I want Version B</button>
<button type="submit" onclick="document.getElementById('choice').value='both'">I want both</button>
</div>
</form>
{% if revisions_left > 0 %}
<!-- Revision form: customer asks for changes -->
<form method="POST" action="{{ url_for('revise', token=req.player_token) }}">
<p style="color:#93c5fd;font-weight:600">Revisions remaining: {{ revisions_left }}</p>
<p class="text-accent" style="font-weight:600">Revisions remaining: {{ revisions_left }}</p>
<label for="revision_note">Or ask for changes:</label>
<textarea id="revision_note" name="revision_note" placeholder="e.g. make the chorus louder, swap a lyric..."></textarea>
<div class="actions">
<button type="submit" class="revision">Request Changes</button>
<button type="submit" class="button-secondary">Request Changes</button>
</div>
</form>
{% else %}
<p style="margin-top:1rem;color:#f87171;font-weight:600">No revisions remaining. Please speak to the booth operator if you need further changes.</p>
<p class="text-danger" style="margin-top:var(--space-4);font-weight:600">No revisions remaining. Please speak to the booth operator if you need further changes.</p>
{% endif %}
{% endif %}