Text effects, pad crossfade, playback progress + per-track durations

- Scrolling text: font, size, weight, colour and movement effects (up/down, wave,
  zoom, flash, rotate) rendered per-letter (and captured in recordings).
- Larger multiline text input.
- Pad bank: crossfade between pads (per-source gain ramps in the audio engine).
- Duration + remaining-time and progress bars for the playlist and the active pad,
  via metadata probing and live progress reports from the output window.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
lucianoandClaude Opus 4.8 committed 2026-06-19 15:44:28 +02:00
1 parent 0a04df32de
commit 9653306a68
6 files changed
+226 -28

No files matched your search

+60 -6
View File
@@ -225,6 +225,29 @@ body.control select { width: 100%; max-width: 100%; }
opacity: 0.85;
}
.pad-key:hover { background: rgba(120,150,255,0.45); }
.pad-time {
position: absolute;
bottom: 3px;
left: 4px;
font-size: 8.5px;
opacity: 0.7;
font-variant-numeric: tabular-nums;
}
.pad-prog {
position: absolute;
left: 0; bottom: 0;
height: 3px;
background: linear-gradient(90deg, #5ad18a, #aef0c0);
width: 0;
}
/* Larger ticker text area */
textarea.textarea-lg {
min-height: 78px;
resize: vertical;
font-size: 14px;
line-height: 1.4;
}
/* ---- Recording status ---- */
.rec-status {
@@ -269,6 +292,7 @@ body.control select { width: 100%; max-width: 100%; }
.hint-mini { font-size: 10px; opacity: 0.45; margin-top: 6px; }
.track {
position: relative;
display: flex;
align-items: center;
gap: 6px;
@@ -278,6 +302,22 @@ body.control select { width: 100%; max-width: 100%; }
border: 1px solid rgba(255,255,255,0.08);
border-radius: 9px;
font-size: 12px;
overflow: hidden;
}
.track .ttime {
flex: 0 0 auto;
font-size: 10px;
opacity: 0.65;
font-variant-numeric: tabular-nums;
min-width: 34px;
text-align: right;
}
.track .tprog {
position: absolute;
left: 0; bottom: 0;
height: 2px;
background: linear-gradient(90deg, #5ad1ff, #7aa2ff, #ff7ad1);
width: 0;
}
.track.playing {
background: rgba(110,150,255,0.22);
@@ -368,15 +408,17 @@ body.output { cursor: none; background: #000; }
display: inline-flex;
white-space: nowrap;
will-change: transform;
animation: ticker-scroll var(--ticker-dur, 18s) linear infinite;
}
#ticker-track span {
font-size: 6vh;
font-weight: 800;
letter-spacing: 2px;
padding: 0 4vw;
text-transform: uppercase;
color: #fff;
text-transform: uppercase;
animation: ticker-scroll var(--ticker-dur, 18s) linear infinite;
}
.tick-copy { display: inline-flex; padding: 0 2vw; }
.tl {
display: inline-block;
white-space: pre;
letter-spacing: 2px;
text-shadow: 0 0 calc(8px + var(--ticker-glow, 0px)) rgba(140,180,255,0.9),
0 2px 30px rgba(0,0,0,0.8);
}
@@ -385,6 +427,18 @@ body.output { cursor: none; background: #000; }
to { transform: translateX(-50%); }
}
/* Text movement effects (applied per letter) */
.fx-updown .tl { animation: tl-updown 1.1s ease-in-out infinite; }
.fx-wave .tl { animation: tl-wave 1.2s ease-in-out infinite; animation-delay: calc(var(--i) * 0.05s); }
.fx-zoom .tl { animation: tl-zoom 0.9s ease-in-out infinite; animation-delay: calc(var(--i) * 0.04s); }
.fx-flash .tl { animation: tl-flash 0.6s steps(1, end) infinite; }
.fx-rotate .tl { animation: tl-rotate 2s ease-in-out infinite; animation-delay: calc(var(--i) * 0.03s); }
@keyframes tl-updown { 0%, 100% { transform: translateY(-0.18em); } 50% { transform: translateY(0.18em); } }
@keyframes tl-wave { 0%, 100% { transform: translateY(-0.24em); } 50% { transform: translateY(0.24em); } }
@keyframes tl-zoom { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.35); } }
@keyframes tl-flash { 0%, 100% { opacity: 1; } 50% { opacity: 0.12; } }
@keyframes tl-rotate { 0%, 100% { transform: rotate(-12deg); } 50% { transform: rotate(12deg); } }
/* ---- Drop hint ---- */
#drop-hint {
position: fixed;