<section id="custom-audio-testimonial">
<style>
#custom-audio-testimonial {
padding-top: 4px;
padding-bottom: 8px;
padding-inline: var(--et-spacing-horizontal, 16px);
background-color: transparent;
}
@media (min-width: 1024px) {
#custom-audio-testimonial {
padding-top: 6px;
padding-bottom: 12px;
padding-inline: var(--et-spacing-horizontal-lg, 24px);
}
}
#custom-audio-testimonial .container {
margin-inline: auto;
max-width: 480px;
display: flex;
flex-direction: column;
align-items: center;
}
#custom-audio-testimonial .player-pill {
background: #141226;
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 9999px;
padding: 6px 14px 6px 6px;
display: flex;
align-items: center;
gap: 12px;
width: 100%;
box-shadow: 0 8px 24px -4px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.08);
transition: all 0.25s ease;
}
#custom-audio-testimonial .avatar-wrap {
width: 46px;
height: 46px;
border-radius: 50%;
border: 2px solid rgba(255, 255, 255, 0.2);
overflow: hidden;
flex-shrink: 0;
background-color: #262340;
}
#custom-audio-testimonial .avatar {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center top;
display: block;
}
#custom-audio-testimonial .play-btn {
width: 42px;
height: 42px;
border-radius: 50%;
background: #2e7d53;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
transition: transform 0.15s ease, background-color 0.2s ease, box-shadow 0.2s ease;
color: #ffffff;
box-shadow: 0 4px 14px rgba(46, 125, 83, 0.45);
}
#custom-audio-testimonial .play-btn:hover {
background-color: #389e69;
transform: scale(1.05);
}
#custom-audio-testimonial .play-btn:active {
transform: scale(0.95);
}
#custom-audio-testimonial .play-btn svg {
width: 18px;
height: 18px;
fill: currentColor;
}
#custom-audio-testimonial .play-btn .icon-play {
margin-left: 2px;
}
#custom-audio-testimonial .waveform-container {
display: flex;
align-items: center;
gap: 2.5px;
flex-grow: 1;
height: 38px;
cursor: pointer;
padding: 0 2px;
position: relative;
user-select: none;
}
#custom-audio-testimonial .waveform-bar {
flex: 1;
background-color: rgba(255, 255, 255, 0.22);
border-radius: 999px;
transition: background-color 0.12s ease;
min-height: 4px;
}
#custom-audio-testimonial .waveform-bar.played {
background-color: #3ecf8e;
box-shadow: 0 0 5px rgba(62, 207, 142, 0.5);
}
#custom-audio-testimonial .time-display {
color: #ffffff;
font-size: 14px;
font-weight: 500;
font-variant-numeric: tabular-nums;
opacity: 0.95;
flex-shrink: 0;
min-width: 36px;
text-align: center;
font-family: inherit;
}
#custom-audio-testimonial .speed-btn {
width: 38px;
height: 38px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.08);
border: 1px solid rgba(255, 255, 255, 0.12);
color: #ffffff;
font-size: 12.5px;
font-weight: 600;
cursor: pointer;
flex-shrink: 0;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
font-family: inherit;
}
#custom-audio-testimonial .speed-btn:hover {
background-color: rgba(255, 255, 255, 0.16);
color: #a3f7c9;
}
#custom-audio-testimonial .hidden-audio {
display: none;
}
@media (max-width: 480px) {
#custom-audio-testimonial .player-pill {
gap: 8px;
padding: 5px 10px 5px 5px;
}
#custom-audio-testimonial .avatar-wrap {
width: 40px;
height: 40px;
}
#custom-audio-testimonial .play-btn {
width: 36px;
height: 36px;
}
#custom-audio-testimonial .play-btn svg {
width: 15px;
height: 15px;
}
#custom-audio-testimonial .waveform-container {
gap: 2px;
height: 32px;
}
#custom-audio-testimonial .time-display {
font-size: 12px;
min-width: 30px;
}
#custom-audio-testimonial .speed-btn {
width: 34px;
height: 34px;
font-size: 11px;
}
}
</style>
<div class="container">
<div class="player-pill">
<div class="avatar-wrap">
<img class="avatar" src="/files/pages/assets/2026-09-08/zrzut-ekranu-2026-05-28-o-163620_mtt2xp8y.png" alt="Kursant" loading="lazy" width="46" height="46">
</div>
<button class="play-btn" aria-label="Odtwórz / Wstrzymaj nagranie" type="button">
<svg class="icon-play" viewBox="0 0 24 24">
<polygon points="6 3 20 12 6 21 6 3"></polygon>
</svg>
<svg class="icon-pause" viewBox="0 0 24 24" style="display: none;">
<rect x="5" y="4" width="4" height="16" rx="1"></rect>
<rect x="15" y="4" width="4" height="16" rx="1"></rect>
</svg>
</button>
<div class="waveform-container" role="slider" aria-label="Postęp nagrania" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div class="waveform-bar" style="height: 25%"></div>
<div class="waveform-bar" style="height: 35%"></div>
<div class="waveform-bar" style="height: 55%"></div>
<div class="waveform-bar" style="height: 75%"></div>
<div class="waveform-bar" style="height: 95%"></div>
<div class="waveform-bar" style="height: 65%"></div>
<div class="waveform-bar" style="height: 45%"></div>
<div class="waveform-bar" style="height: 35%"></div>
<div class="waveform-bar" style="height: 25%"></div>
<div class="waveform-bar" style="height: 45%"></div>
<div class="waveform-bar" style="height: 65%"></div>
<div class="waveform-bar" style="height: 85%"></div>
<div class="waveform-bar" style="height: 100%"></div>
<div class="waveform-bar" style="height: 85%"></div>
<div class="waveform-bar" style="height: 55%"></div>
<div class="waveform-bar" style="height: 35%"></div>
<div class="waveform-bar" style="height: 45%"></div>
<div class="waveform-bar" style="height: 75%"></div>
<div class="waveform-bar" style="height: 95%"></div>
<div class="waveform-bar" style="height: 85%"></div>
<div class="waveform-bar" style="height: 65%"></div>
<div class="waveform-bar" style="height: 45%"></div>
<div class="waveform-bar" style="height: 25%"></div>
<div class="waveform-bar" style="height: 35%"></div>
<div class="waveform-bar" style="height: 55%"></div>
<div class="waveform-bar" style="height: 85%"></div>
<div class="waveform-bar" style="height: 95%"></div>
<div class="waveform-bar" style="height: 75%"></div>
<div class="waveform-bar" style="height: 55%"></div>
<div class="waveform-bar" style="height: 35%"></div>
<div class="waveform-bar" style="height: 25%"></div>
<div class="waveform-bar" style="height: 45%"></div>
<div class="waveform-bar" style="height: 65%"></div>
<div class="waveform-bar" style="height: 55%"></div>
<div class="waveform-bar" style="height: 35%"></div>
<div class="waveform-bar" style="height: 25%"></div>
</div>
<div class="time-display" aria-live="polite">0:00</div>
<button class="speed-btn" aria-label="Zmień tempo odtwarzania" type="button">1x</button>
</div>
<audio class="hidden-audio" src="https://files.catbox.moe/dne6qp.mp3" preload="metadata"></audio>
</div>
<script>
(function initCustomAudioPlayer() {
const section = document.getElementById('custom-audio-testimonial');
if (!section) return;
const audio = section.querySelector('.hidden-audio');
const playBtn = section.querySelector('.play-btn');
const iconPlay = section.querySelector('.icon-play');
const iconPause = section.querySelector('.icon-pause');
const waveform = section.querySelector('.waveform-container');
const bars = section.querySelectorAll('.waveform-bar');
const timeDisplay = section.querySelector('.time-display');
const speedBtn = section.querySelector('.speed-btn');
if (!audio || !playBtn || !waveform || !timeDisplay || !speedBtn) return;
const formatTime = (seconds) => {
if (isNaN(seconds) || seconds < 0) return "0:00";
const m = Math.floor(seconds / 60);
const s = Math.floor(seconds % 60);
return m + ":" + (s < 10 ? '0' : '') + s;
};
let isPlaying = false;
let animInterval = null;
let simulatedSec = 0;
const fallbackDuration = 17;
const setPlayState = (playing) => {
isPlaying = playing;
if (playing) {
iconPlay.style.display = 'none';
iconPause.style.display = 'block';
} else {
iconPlay.style.display = 'block';
iconPause.style.display = 'none';
}
};
const updateBars = (progress) => {
const activeBarsCount = Math.floor(progress * bars.length);
bars.forEach((bar, index) => {
if (index < activeBarsCount) {
bar.classList.add('played');
} else {
bar.classList.remove('played');
}
});
waveform.setAttribute('aria-valuenow', Math.round(progress * 100));
};
playBtn.addEventListener('click', (e) => {
e.preventDefault();
const hasSrc = audio.getAttribute('src') && audio.getAttribute('src').trim() !== '';
if (!hasSrc) {
setPlayState(!isPlaying);
if (isPlaying) {
clearInterval(animInterval);
animInterval = setInterval(() => {
simulatedSec += 0.25;
if (simulatedSec > fallbackDuration) {
simulatedSec = 0;
setPlayState(false);
clearInterval(animInterval);
}
timeDisplay.textContent = formatTime(simulatedSec);
updateBars(simulatedSec / fallbackDuration);
}, 250);
} else {
clearInterval(animInterval);
}
return;
}
if (audio.paused) {
audio.play().then(() => setPlayState(true)).catch(() => setPlayState(true));
} else {
audio.pause();
setPlayState(false);
}
});
audio.addEventListener('timeupdate', () => {
const current = audio.currentTime;
const duration = audio.duration || fallbackDuration;
timeDisplay.textContent = formatTime(current);
if (duration > 0) {
updateBars(current / duration);
}
});
audio.addEventListener('loadedmetadata', () => {
if (audio.duration && !isNaN(audio.duration)) {
timeDisplay.textContent = formatTime(audio.duration);
}
});
waveform.addEventListener('click', (e) => {
const rect = waveform.getBoundingClientRect();
const clickX = e.clientX - rect.left;
const percentage = Math.max(0, Math.min(1, clickX / rect.width));
const hasSrc = audio.getAttribute('src') && audio.getAttribute('src').trim() !== '';
if (hasSrc && audio.duration) {
audio.currentTime = percentage * audio.duration;
} else {
simulatedSec = percentage * fallbackDuration;
timeDisplay.textContent = formatTime(simulatedSec);
updateBars(percentage);
}
});
const speeds = [1, 1.5, 2];
let speedIndex = 0;
speedBtn.addEventListener('click', (e) => {
e.preventDefault();
speedIndex = (speedIndex + 1) % speeds.length;
const speed = speeds[speedIndex];
audio.playbackRate = speed;
speedBtn.textContent = speed + 'x';
});
audio.addEventListener('ended', () => {
setPlayState(false);
audio.currentTime = 0;
bars.forEach(bar => bar.classList.remove('played'));
});
})();
</script>
</section>