Open demo

CSS code

HTML
<div><span class="lbl">Native sliders with accent-color</span>
<div class="mx mx-native" data-mx role="group" aria-label="Night Bus to Nowhere by Orla Finch">
  <audio src="../audio/track-3.mp3" preload="metadata"></audio>
  <div class="mx-head">
    <button type="button" class="mx-play" data-play="Night Bus to Nowhere" aria-label="Play Night Bus to Nowhere"><svg class="i-play" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><path d="M8 5.5v13a1 1 0 0 0 1.5.86l10.5-6.5a1 1 0 0 0 0-1.72L9.5 4.64A1 1 0 0 0 8 5.5z"/></svg><svg class="i-pause" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><rect x="6.5" y="5" width="4" height="14" rx="1.2"/><rect x="13.5" y="5" width="4" height="14" rx="1.2"/></svg></button>
    <div><p class="mx-title">Night Bus to Nowhere</p><p class="mx-artist">Orla Finch</p></div>
  </div>
  <div class="mx-row">
    <span class="mx-time" data-cur>0:00</span>
    <input type="range" data-seek min="0" max="30" step="any" value="0" aria-label="Seek Night Bus to Nowhere" aria-valuetext="0:00 of 0:30">
    <span class="mx-time" data-dur>0:30</span>
    <button type="button" class="mx-icon mx-mute" data-mute aria-label="Mute" aria-pressed="false"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 5 6 9H3v6h3l5 4z"/><path class="i-wave" d="M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13"/><path class="i-x" d="m16 9 6 6m0-6-6 6"/></svg></button>
    <input type="range" class="mx-vol" data-vol min="0" max="1" step="0.05" value="0.8" aria-label="Volume" aria-valuetext="80%">
  </div>
</div></div>

<div><span class="lbl">Container query · 260px wide</span>
<div class="mx-cq" style="max-width:260px">
<div class="mx mx-fit" data-mx role="group" aria-label="Copper Sky by Milo & the Tidelines">
  <audio src="../audio/track-4.mp3" preload="metadata"></audio>
  <div class="mx-art" style="--art:radial-gradient(circle at 50% 100%,#fff7ed 0 24%,#fdba74 24% 27%,transparent 27.5%),linear-gradient(180deg,#7c2d12 0 22%,#9a3412 22% 40%,#c2410c 40% 56%,#ea580c 56% 70%,#f59e0b 70% 84%,#fcd34d 84%)" aria-hidden="true"></div>
  <div class="mx-meta"><p class="mx-title">Copper Sky</p><p class="mx-artist">Milo & the Tidelines</p></div>
  <div class="mx-ctrls">
    <button type="button" class="mx-icon mx-skip" data-skip="-15" aria-label="Back 15 seconds"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 12a8.5 8.5 0 1 0 2.6-6.1"/><path d="M3.5 4v4.5H8"/><text x="12.6" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">15</text></svg></button>
    <button type="button" class="mx-play" data-play="Copper Sky" aria-label="Play Copper Sky"><svg class="i-play" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><path d="M8 5.5v13a1 1 0 0 0 1.5.86l10.5-6.5a1 1 0 0 0 0-1.72L9.5 4.64A1 1 0 0 0 8 5.5z"/></svg><svg class="i-pause" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><rect x="6.5" y="5" width="4" height="14" rx="1.2"/><rect x="13.5" y="5" width="4" height="14" rx="1.2"/></svg></button>
    <button type="button" class="mx-icon mx-skip" data-skip="30" aria-label="Forward 30 seconds"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.5 12a8.5 8.5 0 1 1-2.6-6.1"/><path d="M20.5 4v4.5H16"/><text x="11.4" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">30</text></svg></button>
  </div>
  <div class="mx-seek"><span class="mx-time" data-cur>0:00</span><input type="range" data-seek min="0" max="29" step="any" value="0" aria-label="Seek Copper Sky" aria-valuetext="0:00 of 0:29"><span class="mx-time" data-dur>0:29</span></div>
  <div class="mx-volume"><button type="button" class="mx-icon mx-mute" data-mute aria-label="Mute" aria-pressed="false"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 5 6 9H3v6h3l5 4z"/><path class="i-wave" d="M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13"/><path class="i-x" d="m16 9 6 6m0-6-6 6"/></svg></button><input type="range" class="mx-vol" data-vol min="0" max="1" step="0.05" value="0.8" aria-label="Volume" aria-valuetext="80%"></div>
</div></div></div>

<div><span class="lbl">Container query · 420px wide</span>
<div class="mx-cq" style="max-width:420px">
<div class="mx mx-fit" data-mx role="group" aria-label="Paper Kites by The Lumen Choir">
  <audio src="../audio/track-2.mp3" preload="metadata"></audio>
  <div class="mx-art" style="--art:linear-gradient(to bottom right,transparent 50%,#fde047 50%) 37.5% 26.67%/20% 25% no-repeat,linear-gradient(to bottom left,transparent 50%,#f97316 50%) 62.5% 26.67%/20% 25% no-repeat,linear-gradient(to top right,transparent 50%,#fb923c 50%) 37.5% 69.23%/20% 35% no-repeat,linear-gradient(to top left,transparent 50%,#facc15 50%) 62.5% 69.23%/20% 35% no-repeat,linear-gradient(to bottom right,transparent calc(50% - 1px),rgba(255,255,255,.85) 0 calc(50% + 1px),transparent 0) 41.86% 100%/14% 20% no-repeat,linear-gradient(160deg,#0ea5e9,#14b8a6 55%,#84cc16)" aria-hidden="true"></div>
  <div class="mx-meta"><p class="mx-title">Paper Kites</p><p class="mx-artist">The Lumen Choir</p></div>
  <div class="mx-ctrls">
    <button type="button" class="mx-icon mx-skip" data-skip="-15" aria-label="Back 15 seconds"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 12a8.5 8.5 0 1 0 2.6-6.1"/><path d="M3.5 4v4.5H8"/><text x="12.6" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">15</text></svg></button>
    <button type="button" class="mx-play" data-play="Paper Kites" aria-label="Play Paper Kites"><svg class="i-play" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><path d="M8 5.5v13a1 1 0 0 0 1.5.86l10.5-6.5a1 1 0 0 0 0-1.72L9.5 4.64A1 1 0 0 0 8 5.5z"/></svg><svg class="i-pause" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><rect x="6.5" y="5" width="4" height="14" rx="1.2"/><rect x="13.5" y="5" width="4" height="14" rx="1.2"/></svg></button>
    <button type="button" class="mx-icon mx-skip" data-skip="30" aria-label="Forward 30 seconds"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.5 12a8.5 8.5 0 1 1-2.6-6.1"/><path d="M20.5 4v4.5H16"/><text x="11.4" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">30</text></svg></button>
  </div>
  <div class="mx-seek"><span class="mx-time" data-cur>0:00</span><input type="range" data-seek min="0" max="24" step="any" value="0" aria-label="Seek Paper Kites" aria-valuetext="0:00 of 0:24"><span class="mx-time" data-dur>0:24</span></div>
  <div class="mx-volume"><button type="button" class="mx-icon mx-mute" data-mute aria-label="Mute" aria-pressed="false"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 5 6 9H3v6h3l5 4z"/><path class="i-wave" d="M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13"/><path class="i-x" d="m16 9 6 6m0-6-6 6"/></svg></button><input type="range" class="mx-vol" data-vol min="0" max="1" step="0.05" value="0.8" aria-label="Volume" aria-valuetext="80%"></div>
</div></div></div>

<div><span class="lbl">Container query · full width</span>
<div class="mx-cq">
<div class="mx mx-fit" data-mx role="group" aria-label="Harbour Lights by Juniper Vale">
  <audio src="../audio/track-1.mp3" preload="metadata"></audio>
  <div class="mx-art" style="--art:radial-gradient(circle at 68% 40%,#fde68a 0 11%,transparent 11.5%),repeating-linear-gradient(180deg,transparent 0 6%,rgba(253,230,138,.3) 6% 7.5%) bottom/100% 42% no-repeat,linear-gradient(180deg,#fb923c,#e11d48 58%,#312e81 58%,#1e1b4b)" aria-hidden="true"></div>
  <div class="mx-meta"><p class="mx-title">Harbour Lights</p><p class="mx-artist">Juniper Vale · Low Tide Radio</p></div>
  <div class="mx-ctrls">
    <button type="button" class="mx-icon mx-skip" data-skip="-15" aria-label="Back 15 seconds"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 12a8.5 8.5 0 1 0 2.6-6.1"/><path d="M3.5 4v4.5H8"/><text x="12.6" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">15</text></svg></button>
    <button type="button" class="mx-play" data-play="Harbour Lights" aria-label="Play Harbour Lights"><svg class="i-play" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><path d="M8 5.5v13a1 1 0 0 0 1.5.86l10.5-6.5a1 1 0 0 0 0-1.72L9.5 4.64A1 1 0 0 0 8 5.5z"/></svg><svg class="i-pause" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><rect x="6.5" y="5" width="4" height="14" rx="1.2"/><rect x="13.5" y="5" width="4" height="14" rx="1.2"/></svg></button>
    <button type="button" class="mx-icon mx-skip" data-skip="30" aria-label="Forward 30 seconds"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.5 12a8.5 8.5 0 1 1-2.6-6.1"/><path d="M20.5 4v4.5H16"/><text x="11.4" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">30</text></svg></button>
  </div>
  <div class="mx-seek"><span class="mx-time" data-cur>0:00</span><input type="range" data-seek min="0" max="24" step="any" value="0" aria-label="Seek Harbour Lights" aria-valuetext="0:00 of 0:24"><span class="mx-time" data-dur>0:24</span></div>
  <div class="mx-volume"><button type="button" class="mx-icon mx-mute" data-mute aria-label="Mute" aria-pressed="false"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 5 6 9H3v6h3l5 4z"/><path class="i-wave" d="M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13"/><path class="i-x" d="m16 9 6 6m0-6-6 6"/></svg></button><input type="range" class="mx-vol" data-vol min="0" max="1" step="0.05" value="0.8" aria-label="Volume" aria-valuetext="80%"></div>
</div></div></div>
CSS
/* Modern CSS players. 1: native range inputs coloured with accent-color only.
   2: one player markup that changes layout with container queries; thumbs are styled per engine,
   Firefox paints the fill with ::-moz-range-progress and WebKit reads --p / --v written by the script. */
.mx{--mx-accent:#be185d;--mx-ink:#1f1235;--mx-muted:#6b5a73;--mx-track:#8e7a90;--p:0;--v:1;color:var(--mx-ink);
  background:#fff;border-radius:20px;box-shadow:0 1px 2px rgba(31,18,53,.06),0 12px 30px rgba(190,24,93,.1)}
.mx button{flex:none;display:grid;place-items:center;border:0;background:none;color:inherit;cursor:pointer;font:inherit}
.mx button:focus-visible{outline:2px solid var(--mx-accent);outline-offset:2px}
.mx svg{display:block;width:20px;height:20px}
.mx .mx-play{width:44px;height:44px;border-radius:50%;background:var(--mx-accent);color:#fff}
.mx .mx-play:hover{background:color-mix(in oklab,var(--mx-accent),#000 15%)}
.mx .i-pause,.mx[data-playing] .i-play{display:none}
.mx[data-playing] .i-pause{display:block}
.mx .mx-icon{width:38px;height:38px;border-radius:50%;color:var(--mx-muted)}
.mx .mx-icon:hover{background:color-mix(in oklab,var(--mx-accent) 10%,#fff)}
.mx .mx-icon svg{width:24px;height:24px}
.mx-mute .i-x,.mx-mute[aria-pressed="true"] .i-wave{display:none}
.mx-mute[aria-pressed="true"] .i-x{display:block}
.mx-title{font-weight:700;font-size:.98rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mx-artist{font-size:.84rem;color:var(--mx-muted);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mx-time{font-size:.78rem;color:var(--mx-muted);font-variant-numeric:tabular-nums;min-width:2.3em}
.mx-art{border-radius:12px;background:var(--art)}
/* 1. native range inputs: accent-color is the whole styling */
.mx-native{display:grid;gap:14px;padding:18px 20px}
.mx-native .mx-head{display:flex;align-items:center;gap:16px}
.mx-native .mx-head > div{flex:1;min-width:0}
.mx-row{display:flex;align-items:center;gap:8px}
.mx-native input[type="range"]{flex:1;min-width:0;margin:0;accent-color:var(--mx-accent);cursor:pointer}
.mx-native input[type="range"].mx-vol{flex:none;width:110px}
.mx-native input[type="range"]:focus-visible{outline:2px solid var(--mx-accent);outline-offset:3px;border-radius:4px}
@media (max-width:480px){.mx-native input[type="range"].mx-vol{display:none}}
/* 2. container-query player: the wrapper is the container, the player reads its width */
.mx-cq{container-type:inline-size}
.mx-fit{display:grid;grid-template-columns:44px minmax(0,1fr) auto;grid-template-areas:"art meta ctrls" "seek seek seek";
  align-items:center;gap:10px 12px;padding:12px 14px}
.mx-fit .mx-art{grid-area:art;width:100%;aspect-ratio:1;border-radius:10px}
.mx-fit .mx-meta{grid-area:meta;min-width:0}
.mx-fit .mx-ctrls{grid-area:ctrls;display:flex;align-items:center;gap:6px}
.mx-fit .mx-seek{grid-area:seek;display:flex;align-items:center;gap:10px}
.mx-fit .mx-volume{grid-area:vol;display:none;align-items:center;gap:6px}
.mx-fit .mx-skip,.mx-fit .mx-time{display:none}
.mx-fit input[type="range"]{-webkit-appearance:none;appearance:none;display:block;flex:1;min-width:0;height:16px;margin:0;background:none;cursor:pointer;--f:var(--p)}
.mx-fit input[type="range"].mx-vol{--f:var(--v);flex:none;width:96px}
.mx-fit input[type="range"]:focus-visible{outline:none}
.mx-fit input[type="range"]::-webkit-slider-runnable-track{height:6px;border-radius:999px;
  background:linear-gradient(to right,var(--mx-accent) 0 calc(8px + (100% - 16px) * var(--f)),var(--mx-track) 0)}
.mx-fit input[type="range"]::-moz-range-track{height:6px;border-radius:999px;background:var(--mx-track)}
.mx-fit input[type="range"]::-moz-range-progress{height:6px;border-radius:999px;background:var(--mx-accent)}
.mx-fit input[type="range"]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;margin-top:-5px;
  border:3px solid #fff;border-radius:50%;background:var(--mx-accent);box-shadow:0 1px 4px rgba(31,18,53,.35);box-sizing:border-box}
.mx-fit input[type="range"]::-moz-range-thumb{width:16px;height:16px;border:3px solid #fff;border-radius:50%;background:var(--mx-accent);
  box-shadow:0 1px 4px rgba(31,18,53,.35);box-sizing:border-box}
.mx-fit input[type="range"]:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 2px #fff,0 0 0 4px var(--mx-accent)}
.mx-fit input[type="range"]:focus-visible::-moz-range-thumb{box-shadow:0 0 0 2px #fff,0 0 0 4px var(--mx-accent)}
@container (min-width:360px){
  .mx-fit{grid-template-columns:64px minmax(0,1fr) auto;padding:14px 18px}
  .mx-fit .mx-art{border-radius:12px}
  .mx-fit .mx-time{display:block}
  .mx-fit .mx-seek .mx-time:last-child{text-align:right}
}
@container (min-width:560px){
  .mx-fit{grid-template-columns:148px minmax(0,1fr) auto;grid-template-areas:"art meta meta" "art seek seek" "art ctrls vol";gap:12px 20px;padding:18px}
  .mx-fit .mx-art{border-radius:16px}
  .mx-fit .mx-title{font-size:1.2rem;font-weight:800}
  .mx-fit .mx-ctrls{gap:10px}
  .mx-fit .mx-skip{display:grid}
  .mx-fit .mx-play{width:52px;height:52px}
  .mx-fit .mx-volume{display:flex}
}
JavaScript
// Each [data-mx] wraps one <audio>. The script wires play, seek, skip, mute and volume, and writes --p and --v
// (0 to 1) for the WebKit track fill. Layout changes come from CSS container queries, not from the script.
(() => {
  const fmt = s => { s = Math.floor(s || 0); return Math.floor(s / 60) + ':' + String(s % 60).padStart(2, '0'); };
  document.querySelectorAll('[data-mx]').forEach(root => {
    const $ = s => root.querySelector(s);
    const audio = $('audio'), play = $('[data-play]'), seek = $('[data-seek]'), cur = $('[data-cur]'), dur = $('[data-dur]');
    const vol = $('[data-vol]'), mute = $('[data-mute]'), name = play.dataset.play;
    let raf = 0;
    const length = () => audio.duration || +seek.max;
    const sync = () => {
      const t = audio.currentTime, d = length(), text = fmt(t) + ' of ' + fmt(d);
      seek.value = t;
      root.style.setProperty('--p', d ? t / d : 0);
      if (cur) cur.textContent = fmt(t);
      if (seek.getAttribute('aria-valuetext') !== text) seek.setAttribute('aria-valuetext', text);
    };
    const tick = () => { sync(); raf = requestAnimationFrame(tick); };
    const meta = () => { seek.max = audio.duration; if (dur) dur.textContent = fmt(audio.duration); sync(); };
    const sound = () => {
      const v = audio.muted ? 0 : audio.volume;
      root.style.setProperty('--v', v);
      if (vol) { vol.value = v; vol.setAttribute('aria-valuetext', Math.round(v * 100) + '%'); }
      if (mute) mute.setAttribute('aria-pressed', String(v === 0));
    };
    play.addEventListener('click', () => {
      if (!audio.paused) return audio.pause();
      document.querySelectorAll('audio').forEach(a => { if (a !== audio) a.pause(); });
      audio.play().catch(() => {});
    });
    audio.addEventListener('play', () => { root.setAttribute('data-playing', ''); play.setAttribute('aria-label', 'Pause ' + name); tick(); });
    audio.addEventListener('pause', () => { root.removeAttribute('data-playing'); play.setAttribute('aria-label', 'Play ' + name); cancelAnimationFrame(raf); sync(); });
    audio.addEventListener('loadedmetadata', meta);
    audio.addEventListener('volumechange', sound);
    if (audio.readyState > 0) meta();
    seek.addEventListener('input', () => { audio.currentTime = seek.value; sync(); });
    // Arrow keys jump 5 seconds; Home and End work natively.
    seek.addEventListener('keydown', e => {
      const step = { ArrowLeft: -5, ArrowDown: -5, ArrowRight: 5, ArrowUp: 5 }[e.key];
      if (!step) return;
      e.preventDefault();
      audio.currentTime = Math.min(Math.max(audio.currentTime + step, 0), length());
      sync();
    });
    root.querySelectorAll('[data-skip]').forEach(b => b.addEventListener('click', () => {
      audio.currentTime = Math.min(Math.max(audio.currentTime + +b.dataset.skip, 0), length());
      sync();
    }));
    if (vol) {
      audio.volume = vol.value;
      vol.addEventListener('input', () => { audio.volume = vol.value; audio.muted = false; });
    }
    if (mute) mute.addEventListener('click', () => {
      if (audio.muted || audio.volume === 0) { audio.muted = false; if (audio.volume === 0) audio.volume = 0.6; }
      else audio.muted = true;
    });
    sound();
  });
})();

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl">Native sliders with accent-color</span>
<div class="card mx mx-native" data-mx role="group" aria-label="Night Bus to Nowhere by Orla Finch">
  <div class="card-body">
  <audio src="../audio/track-3.mp3" preload="metadata"></audio>
  <div class="d-flex align-items-center gap-3">
    <button type="button" class="btn mx-play rounded-circle" data-play="Night Bus to Nowhere" aria-label="Play Night Bus to Nowhere"><svg class="i-play" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><path d="M8 5.5v13a1 1 0 0 0 1.5.86l10.5-6.5a1 1 0 0 0 0-1.72L9.5 4.64A1 1 0 0 0 8 5.5z"/></svg><svg class="i-pause" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><rect x="6.5" y="5" width="4" height="14" rx="1.2"/><rect x="13.5" y="5" width="4" height="14" rx="1.2"/></svg></button>
    <div class="flex-grow-1 text-truncate"><p class="mx-title mb-0 text-truncate">Night Bus to Nowhere</p><p class="mx-artist mb-0 text-truncate">Orla Finch</p></div>
  </div>
  <div class="d-flex align-items-center gap-2">
    <span class="mx-time" data-cur>0:00</span>
    <input type="range" data-seek min="0" max="30" step="any" value="0" aria-label="Seek Night Bus to Nowhere" aria-valuetext="0:00 of 0:30">
    <span class="mx-time" data-dur>0:30</span>
    <button type="button" class="btn mx-icon mx-mute rounded-circle" data-mute aria-label="Mute" aria-pressed="false"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 5 6 9H3v6h3l5 4z"/><path class="i-wave" d="M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13"/><path class="i-x" d="m16 9 6 6m0-6-6 6"/></svg></button>
    <input type="range" class="mx-vol" data-vol min="0" max="1" step="0.05" value="0.8" aria-label="Volume" aria-valuetext="80%">
  </div>
  </div>
</div></div>
<div><span class="lbl">Container query · 260px wide</span>
<div class="mx-cq" style="max-width:260px">
<div class="card mx mx-fit" data-mx role="group" aria-label="Copper Sky by Milo & the Tidelines">
  <audio src="../audio/track-4.mp3" preload="metadata"></audio>
  <div class="mx-art" style="--art:radial-gradient(circle at 50% 100%,#fff7ed 0 24%,#fdba74 24% 27%,transparent 27.5%),linear-gradient(180deg,#7c2d12 0 22%,#9a3412 22% 40%,#c2410c 40% 56%,#ea580c 56% 70%,#f59e0b 70% 84%,#fcd34d 84%)" aria-hidden="true"></div>
  <div class="mx-meta text-truncate"><p class="mx-title mb-0 text-truncate">Copper Sky</p><p class="mx-artist mb-0 text-truncate">Milo & the Tidelines</p></div>
  <div class="mx-ctrls">
    <button type="button" class="btn mx-icon mx-skip rounded-circle" data-skip="-15" aria-label="Back 15 seconds"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 12a8.5 8.5 0 1 0 2.6-6.1"/><path d="M3.5 4v4.5H8"/><text x="12.6" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">15</text></svg></button>
    <button type="button" class="btn mx-play rounded-circle" data-play="Copper Sky" aria-label="Play Copper Sky"><svg class="i-play" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><path d="M8 5.5v13a1 1 0 0 0 1.5.86l10.5-6.5a1 1 0 0 0 0-1.72L9.5 4.64A1 1 0 0 0 8 5.5z"/></svg><svg class="i-pause" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><rect x="6.5" y="5" width="4" height="14" rx="1.2"/><rect x="13.5" y="5" width="4" height="14" rx="1.2"/></svg></button>
    <button type="button" class="btn mx-icon mx-skip rounded-circle" data-skip="30" aria-label="Forward 30 seconds"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.5 12a8.5 8.5 0 1 1-2.6-6.1"/><path d="M20.5 4v4.5H16"/><text x="11.4" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">30</text></svg></button>
  </div>
  <div class="mx-seek"><span class="mx-time" data-cur>0:00</span><input type="range" class="form-range" data-seek min="0" max="29" step="any" value="0" aria-label="Seek Copper Sky" aria-valuetext="0:00 of 0:29"><span class="mx-time" data-dur>0:29</span></div>
  <div class="mx-volume"><button type="button" class="btn mx-icon mx-mute rounded-circle" data-mute aria-label="Mute" aria-pressed="false"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 5 6 9H3v6h3l5 4z"/><path class="i-wave" d="M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13"/><path class="i-x" d="m16 9 6 6m0-6-6 6"/></svg></button><input type="range" class="form-range mx-vol" data-vol min="0" max="1" step="0.05" value="0.8" aria-label="Volume" aria-valuetext="80%"></div>
</div></div></div>
<div><span class="lbl">Container query · 420px wide</span>
<div class="mx-cq" style="max-width:420px">
<div class="card mx mx-fit" data-mx role="group" aria-label="Paper Kites by The Lumen Choir">
  <audio src="../audio/track-2.mp3" preload="metadata"></audio>
  <div class="mx-art" style="--art:linear-gradient(to bottom right,transparent 50%,#fde047 50%) 37.5% 26.67%/20% 25% no-repeat,linear-gradient(to bottom left,transparent 50%,#f97316 50%) 62.5% 26.67%/20% 25% no-repeat,linear-gradient(to top right,transparent 50%,#fb923c 50%) 37.5% 69.23%/20% 35% no-repeat,linear-gradient(to top left,transparent 50%,#facc15 50%) 62.5% 69.23%/20% 35% no-repeat,linear-gradient(to bottom right,transparent calc(50% - 1px),rgba(255,255,255,.85) 0 calc(50% + 1px),transparent 0) 41.86% 100%/14% 20% no-repeat,linear-gradient(160deg,#0ea5e9,#14b8a6 55%,#84cc16)" aria-hidden="true"></div>
  <div class="mx-meta text-truncate"><p class="mx-title mb-0 text-truncate">Paper Kites</p><p class="mx-artist mb-0 text-truncate">The Lumen Choir</p></div>
  <div class="mx-ctrls">
    <button type="button" class="btn mx-icon mx-skip rounded-circle" data-skip="-15" aria-label="Back 15 seconds"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 12a8.5 8.5 0 1 0 2.6-6.1"/><path d="M3.5 4v4.5H8"/><text x="12.6" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">15</text></svg></button>
    <button type="button" class="btn mx-play rounded-circle" data-play="Paper Kites" aria-label="Play Paper Kites"><svg class="i-play" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><path d="M8 5.5v13a1 1 0 0 0 1.5.86l10.5-6.5a1 1 0 0 0 0-1.72L9.5 4.64A1 1 0 0 0 8 5.5z"/></svg><svg class="i-pause" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><rect x="6.5" y="5" width="4" height="14" rx="1.2"/><rect x="13.5" y="5" width="4" height="14" rx="1.2"/></svg></button>
    <button type="button" class="btn mx-icon mx-skip rounded-circle" data-skip="30" aria-label="Forward 30 seconds"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.5 12a8.5 8.5 0 1 1-2.6-6.1"/><path d="M20.5 4v4.5H16"/><text x="11.4" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">30</text></svg></button>
  </div>
  <div class="mx-seek"><span class="mx-time" data-cur>0:00</span><input type="range" class="form-range" data-seek min="0" max="24" step="any" value="0" aria-label="Seek Paper Kites" aria-valuetext="0:00 of 0:24"><span class="mx-time" data-dur>0:24</span></div>
  <div class="mx-volume"><button type="button" class="btn mx-icon mx-mute rounded-circle" data-mute aria-label="Mute" aria-pressed="false"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 5 6 9H3v6h3l5 4z"/><path class="i-wave" d="M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13"/><path class="i-x" d="m16 9 6 6m0-6-6 6"/></svg></button><input type="range" class="form-range mx-vol" data-vol min="0" max="1" step="0.05" value="0.8" aria-label="Volume" aria-valuetext="80%"></div>
</div></div></div>
<div><span class="lbl">Container query · full width</span>
<div class="mx-cq">
<div class="card mx mx-fit" data-mx role="group" aria-label="Harbour Lights by Juniper Vale">
  <audio src="../audio/track-1.mp3" preload="metadata"></audio>
  <div class="mx-art" style="--art:radial-gradient(circle at 68% 40%,#fde68a 0 11%,transparent 11.5%),repeating-linear-gradient(180deg,transparent 0 6%,rgba(253,230,138,.3) 6% 7.5%) bottom/100% 42% no-repeat,linear-gradient(180deg,#fb923c,#e11d48 58%,#312e81 58%,#1e1b4b)" aria-hidden="true"></div>
  <div class="mx-meta text-truncate"><p class="mx-title mb-0 text-truncate">Harbour Lights</p><p class="mx-artist mb-0 text-truncate">Juniper Vale · Low Tide Radio</p></div>
  <div class="mx-ctrls">
    <button type="button" class="btn mx-icon mx-skip rounded-circle" data-skip="-15" aria-label="Back 15 seconds"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 12a8.5 8.5 0 1 0 2.6-6.1"/><path d="M3.5 4v4.5H8"/><text x="12.6" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">15</text></svg></button>
    <button type="button" class="btn mx-play rounded-circle" data-play="Harbour Lights" aria-label="Play Harbour Lights"><svg class="i-play" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><path d="M8 5.5v13a1 1 0 0 0 1.5.86l10.5-6.5a1 1 0 0 0 0-1.72L9.5 4.64A1 1 0 0 0 8 5.5z"/></svg><svg class="i-pause" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><rect x="6.5" y="5" width="4" height="14" rx="1.2"/><rect x="13.5" y="5" width="4" height="14" rx="1.2"/></svg></button>
    <button type="button" class="btn mx-icon mx-skip rounded-circle" data-skip="30" aria-label="Forward 30 seconds"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.5 12a8.5 8.5 0 1 1-2.6-6.1"/><path d="M20.5 4v4.5H16"/><text x="11.4" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">30</text></svg></button>
  </div>
  <div class="mx-seek"><span class="mx-time" data-cur>0:00</span><input type="range" class="form-range" data-seek min="0" max="24" step="any" value="0" aria-label="Seek Harbour Lights" aria-valuetext="0:00 of 0:24"><span class="mx-time" data-dur>0:24</span></div>
  <div class="mx-volume"><button type="button" class="btn mx-icon mx-mute rounded-circle" data-mute aria-label="Mute" aria-pressed="false"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 5 6 9H3v6h3l5 4z"/><path class="i-wave" d="M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13"/><path class="i-x" d="m16 9 6 6m0-6-6 6"/></svg></button><input type="range" class="form-range mx-vol" data-vol min="0" max="1" step="0.05" value="0.8" aria-label="Volume" aria-valuetext="80%"></div>
</div></div></div>
CSS
/* Modern CSS players on Bootstrap. 1: native range inputs coloured with accent-color only (no .form-range,
   which would replace the native look). 2: one .card player that changes layout with container queries;
   .form-range thumbs are restyled, Firefox paints the fill with ::-moz-range-progress and WebKit reads --p / --v. */
.mx{--mx-accent:#be185d;--mx-ink:#1f1235;--mx-muted:#6b5a73;--mx-track:#8e7a90;--p:0;--v:1;
  --bs-card-border-width:0;--bs-card-border-radius:20px;--bs-card-color:var(--mx-ink);color:var(--mx-ink);
  box-shadow:0 1px 2px rgba(31,18,53,.06),0 12px 30px rgba(190,24,93,.1)}
.mx .btn{--bs-btn-padding-x:0;--bs-btn-padding-y:0;--bs-btn-border-width:0;flex:none;display:grid;place-items:center}
.mx .btn:focus-visible{outline:2px solid var(--mx-accent);outline-offset:2px;box-shadow:none}
.mx svg{display:block;width:20px;height:20px}
.mx .mx-play{--bs-btn-bg:var(--mx-accent);--bs-btn-color:#fff;--bs-btn-hover-bg:color-mix(in oklab,var(--mx-accent),#000 15%);--bs-btn-hover-color:#fff;
  --bs-btn-active-bg:color-mix(in oklab,var(--mx-accent),#000 25%);--bs-btn-active-color:#fff;width:44px;height:44px}
.mx .i-pause,.mx[data-playing] .i-play{display:none}
.mx[data-playing] .i-pause{display:block}
.mx .mx-icon{--bs-btn-color:var(--mx-muted);--bs-btn-hover-color:var(--mx-muted);--bs-btn-hover-bg:color-mix(in oklab,var(--mx-accent) 10%,#fff);
  --bs-btn-active-color:var(--mx-accent);--bs-btn-active-bg:color-mix(in oklab,var(--mx-accent) 16%,#fff);width:38px;height:38px}
.mx .mx-icon svg{width:24px;height:24px}
.mx-mute .i-x,.mx-mute[aria-pressed="true"] .i-wave{display:none}
.mx-mute[aria-pressed="true"] .i-x{display:block}
.mx-title{font-weight:700;font-size:.98rem}
.mx-artist{font-size:.84rem;color:var(--mx-muted);margin-top:2px}
.mx-time{font-size:.78rem;color:var(--mx-muted);font-variant-numeric:tabular-nums;min-width:2.3em}
.mx-art{border-radius:12px;background:var(--art)}
/* 1. native range inputs: accent-color is the whole styling */
.mx-native .card-body{display:grid;gap:14px;padding:18px 20px}
.mx-native input[type="range"]{flex:1;min-width:0;margin:0;accent-color:var(--mx-accent);cursor:pointer}
.mx-native input[type="range"].mx-vol{flex:none;width:110px}
.mx-native input[type="range"]:focus-visible{outline:2px solid var(--mx-accent);outline-offset:3px;border-radius:4px}
@media (max-width:480px){.mx-native input[type="range"].mx-vol{display:none}}
/* 2. container-query player: the wrapper is the container, the player reads its width */
.mx-cq{container-type:inline-size}
.mx-fit{display:grid;grid-template-columns:44px minmax(0,1fr) auto;grid-template-areas:"art meta ctrls" "seek seek seek";
  align-items:center;gap:10px 12px;padding:12px 14px}
.mx-fit .mx-art{grid-area:art;width:100%;aspect-ratio:1;border-radius:10px}
.mx-fit .mx-meta{grid-area:meta;min-width:0}
.mx-fit .mx-ctrls{grid-area:ctrls;display:flex;align-items:center;gap:6px}
.mx-fit .mx-seek{grid-area:seek;display:flex;align-items:center;gap:10px}
.mx-fit .mx-volume{grid-area:vol;display:none;align-items:center;gap:6px}
.mx-fit .mx-skip,.mx-fit .mx-time{display:none}
.mx-fit .form-range{flex:1;min-width:0;width:auto;height:16px;--f:var(--p)}
.mx-fit .form-range.mx-vol{--f:var(--v);flex:none;width:96px}
.mx-fit .form-range::-webkit-slider-runnable-track{height:6px;border-radius:999px;
  background:linear-gradient(to right,var(--mx-accent) 0 calc(8px + (100% - 16px) * var(--f)),var(--mx-track) 0)}
.mx-fit .form-range::-moz-range-track{height:6px;border-radius:999px;background:var(--mx-track)}
.mx-fit .form-range::-moz-range-progress{height:6px;border-radius:999px;background:var(--mx-accent)}
.mx-fit .form-range::-webkit-slider-thumb{width:16px;height:16px;margin-top:-5px;border:3px solid #fff;background:var(--mx-accent);
  box-shadow:0 1px 4px rgba(31,18,53,.35);box-sizing:border-box}
.mx-fit .form-range::-moz-range-thumb{width:16px;height:16px;border:3px solid #fff;background:var(--mx-accent);box-shadow:0 1px 4px rgba(31,18,53,.35);box-sizing:border-box}
.mx-fit .form-range:focus::-webkit-slider-thumb{box-shadow:0 1px 4px rgba(31,18,53,.35)}
.mx-fit .form-range:focus::-moz-range-thumb{box-shadow:0 1px 4px rgba(31,18,53,.35)}
.mx-fit .form-range:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 2px #fff,0 0 0 4px var(--mx-accent)}
.mx-fit .form-range:focus-visible::-moz-range-thumb{box-shadow:0 0 0 2px #fff,0 0 0 4px var(--mx-accent)}
@container (min-width:360px){
  .mx-fit{grid-template-columns:64px minmax(0,1fr) auto;padding:14px 18px}
  .mx-fit .mx-art{border-radius:12px}
  .mx-fit .mx-time{display:block}
  .mx-fit .mx-seek .mx-time:last-child{text-align:right}
}
@container (min-width:560px){
  .mx-fit{grid-template-columns:148px minmax(0,1fr) auto;grid-template-areas:"art meta meta" "art seek seek" "art ctrls vol";gap:12px 20px;padding:18px}
  .mx-fit .mx-art{border-radius:16px}
  .mx-fit .mx-title{font-size:1.2rem;font-weight:800}
  .mx-fit .mx-ctrls{gap:10px}
  .mx-fit .mx-skip{display:grid}
  .mx-fit .mx-play{width:52px;height:52px}
  .mx-fit .mx-volume{display:flex}
}
JavaScript
// Each [data-mx] wraps one <audio>. The script wires play, seek, skip, mute and volume, and writes --p and --v
// (0 to 1) for the WebKit track fill. Layout changes come from CSS container queries, not from the script.
(() => {
  const fmt = s => { s = Math.floor(s || 0); return Math.floor(s / 60) + ':' + String(s % 60).padStart(2, '0'); };
  document.querySelectorAll('[data-mx]').forEach(root => {
    const $ = s => root.querySelector(s);
    const audio = $('audio'), play = $('[data-play]'), seek = $('[data-seek]'), cur = $('[data-cur]'), dur = $('[data-dur]');
    const vol = $('[data-vol]'), mute = $('[data-mute]'), name = play.dataset.play;
    let raf = 0;
    const length = () => audio.duration || +seek.max;
    const sync = () => {
      const t = audio.currentTime, d = length(), text = fmt(t) + ' of ' + fmt(d);
      seek.value = t;
      root.style.setProperty('--p', d ? t / d : 0);
      if (cur) cur.textContent = fmt(t);
      if (seek.getAttribute('aria-valuetext') !== text) seek.setAttribute('aria-valuetext', text);
    };
    const tick = () => { sync(); raf = requestAnimationFrame(tick); };
    const meta = () => { seek.max = audio.duration; if (dur) dur.textContent = fmt(audio.duration); sync(); };
    const sound = () => {
      const v = audio.muted ? 0 : audio.volume;
      root.style.setProperty('--v', v);
      if (vol) { vol.value = v; vol.setAttribute('aria-valuetext', Math.round(v * 100) + '%'); }
      if (mute) mute.setAttribute('aria-pressed', String(v === 0));
    };
    play.addEventListener('click', () => {
      if (!audio.paused) return audio.pause();
      document.querySelectorAll('audio').forEach(a => { if (a !== audio) a.pause(); });
      audio.play().catch(() => {});
    });
    audio.addEventListener('play', () => { root.setAttribute('data-playing', ''); play.setAttribute('aria-label', 'Pause ' + name); tick(); });
    audio.addEventListener('pause', () => { root.removeAttribute('data-playing'); play.setAttribute('aria-label', 'Play ' + name); cancelAnimationFrame(raf); sync(); });
    audio.addEventListener('loadedmetadata', meta);
    audio.addEventListener('volumechange', sound);
    if (audio.readyState > 0) meta();
    seek.addEventListener('input', () => { audio.currentTime = seek.value; sync(); });
    // Arrow keys jump 5 seconds; Home and End work natively.
    seek.addEventListener('keydown', e => {
      const step = { ArrowLeft: -5, ArrowDown: -5, ArrowRight: 5, ArrowUp: 5 }[e.key];
      if (!step) return;
      e.preventDefault();
      audio.currentTime = Math.min(Math.max(audio.currentTime + step, 0), length());
      sync();
    });
    root.querySelectorAll('[data-skip]').forEach(b => b.addEventListener('click', () => {
      audio.currentTime = Math.min(Math.max(audio.currentTime + +b.dataset.skip, 0), length());
      sync();
    }));
    if (vol) {
      audio.volume = vol.value;
      vol.addEventListener('input', () => { audio.volume = vol.value; audio.muted = false; });
    }
    if (mute) mute.addEventListener('click', () => {
      if (audio.muted || audio.volume === 0) { audio.muted = false; if (audio.volume === 0) audio.volume = 0.6; }
      else audio.muted = true;
    });
    sound();
  });
})();

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#5f4f66] uppercase">Native sliders with accent-color</span>
<div class="group grid gap-3.5 rounded-[20px] bg-white px-5 py-[18px] text-[#1f1235] shadow-[0_1px_2px_rgba(31,18,53,.06),0_12px_30px_rgba(190,24,93,.1)]" data-mx role="group" aria-label="Night Bus to Nowhere by Orla Finch">
  <audio src="../audio/track-3.mp3" preload="metadata"></audio>
  <div class="flex items-center gap-4">
    <button type="button" class="grid size-11 flex-none cursor-pointer place-items-center rounded-full bg-mx-accent text-white hover:bg-[color-mix(in_oklab,var(--color-mx-accent),#000_15%)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent" data-play="Night Bus to Nowhere" aria-label="Play Night Bus to Nowhere"><svg class="block size-5 group-data-playing:hidden" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><path d="M8 5.5v13a1 1 0 0 0 1.5.86l10.5-6.5a1 1 0 0 0 0-1.72L9.5 4.64A1 1 0 0 0 8 5.5z"/></svg><svg class="hidden size-5 group-data-playing:block" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><rect x="6.5" y="5" width="4" height="14" rx="1.2"/><rect x="13.5" y="5" width="4" height="14" rx="1.2"/></svg></button>
    <div class="min-w-0 flex-1"><p class="truncate text-[.98rem] font-bold">Night Bus to Nowhere</p><p class="mt-0.5 truncate text-[.84rem] text-mx-muted">Orla Finch</p></div>
  </div>
  <div class="flex items-center gap-2">
    <span class="min-w-[2.3em] text-[.78rem] text-mx-muted tabular-nums" data-cur>0:00</span>
    <input type="range" class="min-w-0 flex-1 cursor-pointer accent-mx-accent focus-visible:rounded focus-visible:outline-2 focus-visible:outline-offset-3 focus-visible:outline-mx-accent" data-seek min="0" max="30" step="any" value="0" aria-label="Seek Night Bus to Nowhere" aria-valuetext="0:00 of 0:30">
    <span class="min-w-[2.3em] text-[.78rem] text-mx-muted tabular-nums" data-dur>0:30</span>
    <button type="button" class="group/m grid size-[38px] flex-none cursor-pointer place-items-center rounded-full text-mx-muted hover:bg-[color-mix(in_oklab,var(--color-mx-accent)_10%,#fff)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent" data-mute aria-label="Mute" aria-pressed="false"><svg class="block size-6" viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 5 6 9H3v6h3l5 4z"/><path class="group-aria-pressed/m:hidden" d="M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13"/><path class="hidden group-aria-pressed/m:inline" d="m16 9 6 6m0-6-6 6"/></svg></button>
    <input type="range" class="w-[110px] flex-none cursor-pointer accent-mx-accent focus-visible:rounded focus-visible:outline-2 focus-visible:outline-offset-3 focus-visible:outline-mx-accent max-[480px]:hidden" data-vol min="0" max="1" step="0.05" value="0.8" aria-label="Volume" aria-valuetext="80%">
  </div>
</div></div>
<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#5f4f66] uppercase">Container query · 260px wide</span>
<div class="@container max-w-[260px]">
<div class="group grid grid-cols-[44px_minmax(0,1fr)_auto] items-center gap-x-3 gap-y-2.5 rounded-[20px] bg-white px-3.5 py-3 text-[#1f1235] shadow-[0_1px_2px_rgba(31,18,53,.06),0_12px_30px_rgba(190,24,93,.1)] [grid-template-areas:'art_meta_ctrls'_'seek_seek_seek'] [--p:0] [--v:1] @min-[360px]:grid-cols-[64px_minmax(0,1fr)_auto] @min-[360px]:px-[18px] @min-[360px]:py-3.5 @min-[560px]:grid-cols-[148px_minmax(0,1fr)_auto] @min-[560px]:gap-x-5 @min-[560px]:gap-y-3 @min-[560px]:p-[18px] @min-[560px]:[grid-template-areas:'art_meta_meta'_'art_seek_seek'_'art_ctrls_vol']" data-mx role="group" aria-label="Copper Sky by Milo & the Tidelines">
  <audio src="../audio/track-4.mp3" preload="metadata"></audio>
  <div class="aspect-square w-full rounded-[10px] [grid-area:art] [background:radial-gradient(circle_at_50%_100%,#fff7ed_0_24%,#fdba74_24%_27%,transparent_27.5%),linear-gradient(180deg,#7c2d12_0_22%,#9a3412_22%_40%,#c2410c_40%_56%,#ea580c_56%_70%,#f59e0b_70%_84%,#fcd34d_84%)] @min-[360px]:rounded-xl @min-[560px]:rounded-2xl" aria-hidden="true"></div>
  <div class="min-w-0 [grid-area:meta]"><p class="truncate text-[.98rem] font-bold @min-[560px]:text-[1.2rem] @min-[560px]:font-extrabold">Copper Sky</p><p class="mt-0.5 truncate text-[.84rem] text-mx-muted">Milo & the Tidelines</p></div>
  <div class="flex items-center gap-1.5 [grid-area:ctrls] @min-[560px]:gap-2.5">
    <button type="button" class="grid size-[38px] flex-none cursor-pointer place-items-center rounded-full text-mx-muted hover:bg-[color-mix(in_oklab,var(--color-mx-accent)_10%,#fff)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent hidden @min-[560px]:grid" data-skip="-15" aria-label="Back 15 seconds"><svg class="block size-6" viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 12a8.5 8.5 0 1 0 2.6-6.1"/><path d="M3.5 4v4.5H8"/><text x="12.6" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">15</text></svg></button>
    <button type="button" class="grid size-11 flex-none cursor-pointer place-items-center rounded-full bg-mx-accent text-white hover:bg-[color-mix(in_oklab,var(--color-mx-accent),#000_15%)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent @min-[560px]:size-[52px]" data-play="Copper Sky" aria-label="Play Copper Sky"><svg class="block size-5 group-data-playing:hidden" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><path d="M8 5.5v13a1 1 0 0 0 1.5.86l10.5-6.5a1 1 0 0 0 0-1.72L9.5 4.64A1 1 0 0 0 8 5.5z"/></svg><svg class="hidden size-5 group-data-playing:block" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><rect x="6.5" y="5" width="4" height="14" rx="1.2"/><rect x="13.5" y="5" width="4" height="14" rx="1.2"/></svg></button>
    <button type="button" class="grid size-[38px] flex-none cursor-pointer place-items-center rounded-full text-mx-muted hover:bg-[color-mix(in_oklab,var(--color-mx-accent)_10%,#fff)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent hidden @min-[560px]:grid" data-skip="30" aria-label="Forward 30 seconds"><svg class="block size-6" viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.5 12a8.5 8.5 0 1 1-2.6-6.1"/><path d="M20.5 4v4.5H16"/><text x="11.4" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">30</text></svg></button>
  </div>
  <div class="flex items-center gap-2.5 [grid-area:seek]"><span class="hidden min-w-[2.3em] text-[.78rem] text-mx-muted tabular-nums @min-[360px]:block" data-cur>0:00</span><input type="range" class="flex-1 block h-4 min-w-0 cursor-pointer appearance-none bg-transparent [--f:var(--p)] focus-visible:outline-none [&::-webkit-slider-runnable-track]:h-1.5 [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_right,var(--color-mx-accent)_0_calc(8px_+_(100%_-_16px)_*_var(--f)),var(--color-mx-track)_0)] [&::-moz-range-track]:h-1.5 [&::-moz-range-track]:rounded-full [&::-moz-range-track]:bg-mx-track [&::-moz-range-progress]:h-1.5 [&::-moz-range-progress]:rounded-full [&::-moz-range-progress]:bg-mx-accent [&::-webkit-slider-thumb]:-mt-[5px] [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:box-border [&::-webkit-slider-thumb]:size-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-[3px] [&::-webkit-slider-thumb]:border-solid [&::-webkit-slider-thumb]:border-white [&::-webkit-slider-thumb]:bg-mx-accent [&::-webkit-slider-thumb]:shadow-[0_1px_4px_rgba(31,18,53,.35)] focus-visible:[&::-webkit-slider-thumb]:shadow-[0_0_0_2px_#fff,0_0_0_4px_var(--color-mx-accent)] [&::-moz-range-thumb]:box-border [&::-moz-range-thumb]:size-4 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-[3px] [&::-moz-range-thumb]:border-solid [&::-moz-range-thumb]:border-white [&::-moz-range-thumb]:bg-mx-accent [&::-moz-range-thumb]:shadow-[0_1px_4px_rgba(31,18,53,.35)] focus-visible:[&::-moz-range-thumb]:shadow-[0_0_0_2px_#fff,0_0_0_4px_var(--color-mx-accent)]" data-seek min="0" max="29" step="any" value="0" aria-label="Seek Copper Sky" aria-valuetext="0:00 of 0:29"><span class="hidden min-w-[2.3em] text-right text-[.78rem] text-mx-muted tabular-nums @min-[360px]:block" data-dur>0:29</span></div>
  <div class="hidden items-center gap-1.5 [grid-area:vol] @min-[560px]:flex"><button type="button" class="group/m grid size-[38px] flex-none cursor-pointer place-items-center rounded-full text-mx-muted hover:bg-[color-mix(in_oklab,var(--color-mx-accent)_10%,#fff)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent" data-mute aria-label="Mute" aria-pressed="false"><svg class="block size-6" viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 5 6 9H3v6h3l5 4z"/><path class="group-aria-pressed/m:hidden" d="M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13"/><path class="hidden group-aria-pressed/m:inline" d="m16 9 6 6m0-6-6 6"/></svg></button><input type="range" class="w-24 flex-none block h-4 min-w-0 cursor-pointer appearance-none bg-transparent [--f:var(--v)] focus-visible:outline-none [&::-webkit-slider-runnable-track]:h-1.5 [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_right,var(--color-mx-accent)_0_calc(8px_+_(100%_-_16px)_*_var(--f)),var(--color-mx-track)_0)] [&::-moz-range-track]:h-1.5 [&::-moz-range-track]:rounded-full [&::-moz-range-track]:bg-mx-track [&::-moz-range-progress]:h-1.5 [&::-moz-range-progress]:rounded-full [&::-moz-range-progress]:bg-mx-accent [&::-webkit-slider-thumb]:-mt-[5px] [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:box-border [&::-webkit-slider-thumb]:size-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-[3px] [&::-webkit-slider-thumb]:border-solid [&::-webkit-slider-thumb]:border-white [&::-webkit-slider-thumb]:bg-mx-accent [&::-webkit-slider-thumb]:shadow-[0_1px_4px_rgba(31,18,53,.35)] focus-visible:[&::-webkit-slider-thumb]:shadow-[0_0_0_2px_#fff,0_0_0_4px_var(--color-mx-accent)] [&::-moz-range-thumb]:box-border [&::-moz-range-thumb]:size-4 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-[3px] [&::-moz-range-thumb]:border-solid [&::-moz-range-thumb]:border-white [&::-moz-range-thumb]:bg-mx-accent [&::-moz-range-thumb]:shadow-[0_1px_4px_rgba(31,18,53,.35)] focus-visible:[&::-moz-range-thumb]:shadow-[0_0_0_2px_#fff,0_0_0_4px_var(--color-mx-accent)]" data-vol min="0" max="1" step="0.05" value="0.8" aria-label="Volume" aria-valuetext="80%"></div>
</div></div></div>
<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#5f4f66] uppercase">Container query · 420px wide</span>
<div class="@container max-w-[420px]">
<div class="group grid grid-cols-[44px_minmax(0,1fr)_auto] items-center gap-x-3 gap-y-2.5 rounded-[20px] bg-white px-3.5 py-3 text-[#1f1235] shadow-[0_1px_2px_rgba(31,18,53,.06),0_12px_30px_rgba(190,24,93,.1)] [grid-template-areas:'art_meta_ctrls'_'seek_seek_seek'] [--p:0] [--v:1] @min-[360px]:grid-cols-[64px_minmax(0,1fr)_auto] @min-[360px]:px-[18px] @min-[360px]:py-3.5 @min-[560px]:grid-cols-[148px_minmax(0,1fr)_auto] @min-[560px]:gap-x-5 @min-[560px]:gap-y-3 @min-[560px]:p-[18px] @min-[560px]:[grid-template-areas:'art_meta_meta'_'art_seek_seek'_'art_ctrls_vol']" data-mx role="group" aria-label="Paper Kites by The Lumen Choir">
  <audio src="../audio/track-2.mp3" preload="metadata"></audio>
  <div class="aspect-square w-full rounded-[10px] [grid-area:art] [background:linear-gradient(to_bottom_right,transparent_50%,#fde047_50%)_37.5%_26.67%/20%_25%_no-repeat,linear-gradient(to_bottom_left,transparent_50%,#f97316_50%)_62.5%_26.67%/20%_25%_no-repeat,linear-gradient(to_top_right,transparent_50%,#fb923c_50%)_37.5%_69.23%/20%_35%_no-repeat,linear-gradient(to_top_left,transparent_50%,#facc15_50%)_62.5%_69.23%/20%_35%_no-repeat,linear-gradient(to_bottom_right,transparent_calc(50%_-_1px),rgba(255,255,255,.85)_0_calc(50%_+_1px),transparent_0)_41.86%_100%/14%_20%_no-repeat,linear-gradient(160deg,#0ea5e9,#14b8a6_55%,#84cc16)] @min-[360px]:rounded-xl @min-[560px]:rounded-2xl" aria-hidden="true"></div>
  <div class="min-w-0 [grid-area:meta]"><p class="truncate text-[.98rem] font-bold @min-[560px]:text-[1.2rem] @min-[560px]:font-extrabold">Paper Kites</p><p class="mt-0.5 truncate text-[.84rem] text-mx-muted">The Lumen Choir</p></div>
  <div class="flex items-center gap-1.5 [grid-area:ctrls] @min-[560px]:gap-2.5">
    <button type="button" class="grid size-[38px] flex-none cursor-pointer place-items-center rounded-full text-mx-muted hover:bg-[color-mix(in_oklab,var(--color-mx-accent)_10%,#fff)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent hidden @min-[560px]:grid" data-skip="-15" aria-label="Back 15 seconds"><svg class="block size-6" viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 12a8.5 8.5 0 1 0 2.6-6.1"/><path d="M3.5 4v4.5H8"/><text x="12.6" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">15</text></svg></button>
    <button type="button" class="grid size-11 flex-none cursor-pointer place-items-center rounded-full bg-mx-accent text-white hover:bg-[color-mix(in_oklab,var(--color-mx-accent),#000_15%)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent @min-[560px]:size-[52px]" data-play="Paper Kites" aria-label="Play Paper Kites"><svg class="block size-5 group-data-playing:hidden" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><path d="M8 5.5v13a1 1 0 0 0 1.5.86l10.5-6.5a1 1 0 0 0 0-1.72L9.5 4.64A1 1 0 0 0 8 5.5z"/></svg><svg class="hidden size-5 group-data-playing:block" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><rect x="6.5" y="5" width="4" height="14" rx="1.2"/><rect x="13.5" y="5" width="4" height="14" rx="1.2"/></svg></button>
    <button type="button" class="grid size-[38px] flex-none cursor-pointer place-items-center rounded-full text-mx-muted hover:bg-[color-mix(in_oklab,var(--color-mx-accent)_10%,#fff)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent hidden @min-[560px]:grid" data-skip="30" aria-label="Forward 30 seconds"><svg class="block size-6" viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.5 12a8.5 8.5 0 1 1-2.6-6.1"/><path d="M20.5 4v4.5H16"/><text x="11.4" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">30</text></svg></button>
  </div>
  <div class="flex items-center gap-2.5 [grid-area:seek]"><span class="hidden min-w-[2.3em] text-[.78rem] text-mx-muted tabular-nums @min-[360px]:block" data-cur>0:00</span><input type="range" class="flex-1 block h-4 min-w-0 cursor-pointer appearance-none bg-transparent [--f:var(--p)] focus-visible:outline-none [&::-webkit-slider-runnable-track]:h-1.5 [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_right,var(--color-mx-accent)_0_calc(8px_+_(100%_-_16px)_*_var(--f)),var(--color-mx-track)_0)] [&::-moz-range-track]:h-1.5 [&::-moz-range-track]:rounded-full [&::-moz-range-track]:bg-mx-track [&::-moz-range-progress]:h-1.5 [&::-moz-range-progress]:rounded-full [&::-moz-range-progress]:bg-mx-accent [&::-webkit-slider-thumb]:-mt-[5px] [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:box-border [&::-webkit-slider-thumb]:size-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-[3px] [&::-webkit-slider-thumb]:border-solid [&::-webkit-slider-thumb]:border-white [&::-webkit-slider-thumb]:bg-mx-accent [&::-webkit-slider-thumb]:shadow-[0_1px_4px_rgba(31,18,53,.35)] focus-visible:[&::-webkit-slider-thumb]:shadow-[0_0_0_2px_#fff,0_0_0_4px_var(--color-mx-accent)] [&::-moz-range-thumb]:box-border [&::-moz-range-thumb]:size-4 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-[3px] [&::-moz-range-thumb]:border-solid [&::-moz-range-thumb]:border-white [&::-moz-range-thumb]:bg-mx-accent [&::-moz-range-thumb]:shadow-[0_1px_4px_rgba(31,18,53,.35)] focus-visible:[&::-moz-range-thumb]:shadow-[0_0_0_2px_#fff,0_0_0_4px_var(--color-mx-accent)]" data-seek min="0" max="24" step="any" value="0" aria-label="Seek Paper Kites" aria-valuetext="0:00 of 0:24"><span class="hidden min-w-[2.3em] text-right text-[.78rem] text-mx-muted tabular-nums @min-[360px]:block" data-dur>0:24</span></div>
  <div class="hidden items-center gap-1.5 [grid-area:vol] @min-[560px]:flex"><button type="button" class="group/m grid size-[38px] flex-none cursor-pointer place-items-center rounded-full text-mx-muted hover:bg-[color-mix(in_oklab,var(--color-mx-accent)_10%,#fff)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent" data-mute aria-label="Mute" aria-pressed="false"><svg class="block size-6" viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 5 6 9H3v6h3l5 4z"/><path class="group-aria-pressed/m:hidden" d="M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13"/><path class="hidden group-aria-pressed/m:inline" d="m16 9 6 6m0-6-6 6"/></svg></button><input type="range" class="w-24 flex-none block h-4 min-w-0 cursor-pointer appearance-none bg-transparent [--f:var(--v)] focus-visible:outline-none [&::-webkit-slider-runnable-track]:h-1.5 [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_right,var(--color-mx-accent)_0_calc(8px_+_(100%_-_16px)_*_var(--f)),var(--color-mx-track)_0)] [&::-moz-range-track]:h-1.5 [&::-moz-range-track]:rounded-full [&::-moz-range-track]:bg-mx-track [&::-moz-range-progress]:h-1.5 [&::-moz-range-progress]:rounded-full [&::-moz-range-progress]:bg-mx-accent [&::-webkit-slider-thumb]:-mt-[5px] [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:box-border [&::-webkit-slider-thumb]:size-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-[3px] [&::-webkit-slider-thumb]:border-solid [&::-webkit-slider-thumb]:border-white [&::-webkit-slider-thumb]:bg-mx-accent [&::-webkit-slider-thumb]:shadow-[0_1px_4px_rgba(31,18,53,.35)] focus-visible:[&::-webkit-slider-thumb]:shadow-[0_0_0_2px_#fff,0_0_0_4px_var(--color-mx-accent)] [&::-moz-range-thumb]:box-border [&::-moz-range-thumb]:size-4 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-[3px] [&::-moz-range-thumb]:border-solid [&::-moz-range-thumb]:border-white [&::-moz-range-thumb]:bg-mx-accent [&::-moz-range-thumb]:shadow-[0_1px_4px_rgba(31,18,53,.35)] focus-visible:[&::-moz-range-thumb]:shadow-[0_0_0_2px_#fff,0_0_0_4px_var(--color-mx-accent)]" data-vol min="0" max="1" step="0.05" value="0.8" aria-label="Volume" aria-valuetext="80%"></div>
</div></div></div>
<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#5f4f66] uppercase">Container query · full width</span>
<div class="@container">
<div class="group grid grid-cols-[44px_minmax(0,1fr)_auto] items-center gap-x-3 gap-y-2.5 rounded-[20px] bg-white px-3.5 py-3 text-[#1f1235] shadow-[0_1px_2px_rgba(31,18,53,.06),0_12px_30px_rgba(190,24,93,.1)] [grid-template-areas:'art_meta_ctrls'_'seek_seek_seek'] [--p:0] [--v:1] @min-[360px]:grid-cols-[64px_minmax(0,1fr)_auto] @min-[360px]:px-[18px] @min-[360px]:py-3.5 @min-[560px]:grid-cols-[148px_minmax(0,1fr)_auto] @min-[560px]:gap-x-5 @min-[560px]:gap-y-3 @min-[560px]:p-[18px] @min-[560px]:[grid-template-areas:'art_meta_meta'_'art_seek_seek'_'art_ctrls_vol']" data-mx role="group" aria-label="Harbour Lights by Juniper Vale">
  <audio src="../audio/track-1.mp3" preload="metadata"></audio>
  <div class="aspect-square w-full rounded-[10px] [grid-area:art] [background:radial-gradient(circle_at_68%_40%,#fde68a_0_11%,transparent_11.5%),repeating-linear-gradient(180deg,transparent_0_6%,rgba(253,230,138,.3)_6%_7.5%)_bottom/100%_42%_no-repeat,linear-gradient(180deg,#fb923c,#e11d48_58%,#312e81_58%,#1e1b4b)] @min-[360px]:rounded-xl @min-[560px]:rounded-2xl" aria-hidden="true"></div>
  <div class="min-w-0 [grid-area:meta]"><p class="truncate text-[.98rem] font-bold @min-[560px]:text-[1.2rem] @min-[560px]:font-extrabold">Harbour Lights</p><p class="mt-0.5 truncate text-[.84rem] text-mx-muted">Juniper Vale · Low Tide Radio</p></div>
  <div class="flex items-center gap-1.5 [grid-area:ctrls] @min-[560px]:gap-2.5">
    <button type="button" class="grid size-[38px] flex-none cursor-pointer place-items-center rounded-full text-mx-muted hover:bg-[color-mix(in_oklab,var(--color-mx-accent)_10%,#fff)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent hidden @min-[560px]:grid" data-skip="-15" aria-label="Back 15 seconds"><svg class="block size-6" viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 12a8.5 8.5 0 1 0 2.6-6.1"/><path d="M3.5 4v4.5H8"/><text x="12.6" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">15</text></svg></button>
    <button type="button" class="grid size-11 flex-none cursor-pointer place-items-center rounded-full bg-mx-accent text-white hover:bg-[color-mix(in_oklab,var(--color-mx-accent),#000_15%)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent @min-[560px]:size-[52px]" data-play="Harbour Lights" aria-label="Play Harbour Lights"><svg class="block size-5 group-data-playing:hidden" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><path d="M8 5.5v13a1 1 0 0 0 1.5.86l10.5-6.5a1 1 0 0 0 0-1.72L9.5 4.64A1 1 0 0 0 8 5.5z"/></svg><svg class="hidden size-5 group-data-playing:block" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><rect x="6.5" y="5" width="4" height="14" rx="1.2"/><rect x="13.5" y="5" width="4" height="14" rx="1.2"/></svg></button>
    <button type="button" class="grid size-[38px] flex-none cursor-pointer place-items-center rounded-full text-mx-muted hover:bg-[color-mix(in_oklab,var(--color-mx-accent)_10%,#fff)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent hidden @min-[560px]:grid" data-skip="30" aria-label="Forward 30 seconds"><svg class="block size-6" viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.5 12a8.5 8.5 0 1 1-2.6-6.1"/><path d="M20.5 4v4.5H16"/><text x="11.4" y="15.4" fill="currentColor" stroke="none" font-size="7" font-weight="700" text-anchor="middle" font-family="system-ui,sans-serif">30</text></svg></button>
  </div>
  <div class="flex items-center gap-2.5 [grid-area:seek]"><span class="hidden min-w-[2.3em] text-[.78rem] text-mx-muted tabular-nums @min-[360px]:block" data-cur>0:00</span><input type="range" class="flex-1 block h-4 min-w-0 cursor-pointer appearance-none bg-transparent [--f:var(--p)] focus-visible:outline-none [&::-webkit-slider-runnable-track]:h-1.5 [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_right,var(--color-mx-accent)_0_calc(8px_+_(100%_-_16px)_*_var(--f)),var(--color-mx-track)_0)] [&::-moz-range-track]:h-1.5 [&::-moz-range-track]:rounded-full [&::-moz-range-track]:bg-mx-track [&::-moz-range-progress]:h-1.5 [&::-moz-range-progress]:rounded-full [&::-moz-range-progress]:bg-mx-accent [&::-webkit-slider-thumb]:-mt-[5px] [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:box-border [&::-webkit-slider-thumb]:size-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-[3px] [&::-webkit-slider-thumb]:border-solid [&::-webkit-slider-thumb]:border-white [&::-webkit-slider-thumb]:bg-mx-accent [&::-webkit-slider-thumb]:shadow-[0_1px_4px_rgba(31,18,53,.35)] focus-visible:[&::-webkit-slider-thumb]:shadow-[0_0_0_2px_#fff,0_0_0_4px_var(--color-mx-accent)] [&::-moz-range-thumb]:box-border [&::-moz-range-thumb]:size-4 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-[3px] [&::-moz-range-thumb]:border-solid [&::-moz-range-thumb]:border-white [&::-moz-range-thumb]:bg-mx-accent [&::-moz-range-thumb]:shadow-[0_1px_4px_rgba(31,18,53,.35)] focus-visible:[&::-moz-range-thumb]:shadow-[0_0_0_2px_#fff,0_0_0_4px_var(--color-mx-accent)]" data-seek min="0" max="24" step="any" value="0" aria-label="Seek Harbour Lights" aria-valuetext="0:00 of 0:24"><span class="hidden min-w-[2.3em] text-right text-[.78rem] text-mx-muted tabular-nums @min-[360px]:block" data-dur>0:24</span></div>
  <div class="hidden items-center gap-1.5 [grid-area:vol] @min-[560px]:flex"><button type="button" class="group/m grid size-[38px] flex-none cursor-pointer place-items-center rounded-full text-mx-muted hover:bg-[color-mix(in_oklab,var(--color-mx-accent)_10%,#fff)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-mx-accent" data-mute aria-label="Mute" aria-pressed="false"><svg class="block size-6" viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 5 6 9H3v6h3l5 4z"/><path class="group-aria-pressed/m:hidden" d="M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13"/><path class="hidden group-aria-pressed/m:inline" d="m16 9 6 6m0-6-6 6"/></svg></button><input type="range" class="w-24 flex-none block h-4 min-w-0 cursor-pointer appearance-none bg-transparent [--f:var(--v)] focus-visible:outline-none [&::-webkit-slider-runnable-track]:h-1.5 [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_right,var(--color-mx-accent)_0_calc(8px_+_(100%_-_16px)_*_var(--f)),var(--color-mx-track)_0)] [&::-moz-range-track]:h-1.5 [&::-moz-range-track]:rounded-full [&::-moz-range-track]:bg-mx-track [&::-moz-range-progress]:h-1.5 [&::-moz-range-progress]:rounded-full [&::-moz-range-progress]:bg-mx-accent [&::-webkit-slider-thumb]:-mt-[5px] [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:box-border [&::-webkit-slider-thumb]:size-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-[3px] [&::-webkit-slider-thumb]:border-solid [&::-webkit-slider-thumb]:border-white [&::-webkit-slider-thumb]:bg-mx-accent [&::-webkit-slider-thumb]:shadow-[0_1px_4px_rgba(31,18,53,.35)] focus-visible:[&::-webkit-slider-thumb]:shadow-[0_0_0_2px_#fff,0_0_0_4px_var(--color-mx-accent)] [&::-moz-range-thumb]:box-border [&::-moz-range-thumb]:size-4 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-[3px] [&::-moz-range-thumb]:border-solid [&::-moz-range-thumb]:border-white [&::-moz-range-thumb]:bg-mx-accent [&::-moz-range-thumb]:shadow-[0_1px_4px_rgba(31,18,53,.35)] focus-visible:[&::-moz-range-thumb]:shadow-[0_0_0_2px_#fff,0_0_0_4px_var(--color-mx-accent)]" data-vol min="0" max="1" step="0.05" value="0.8" aria-label="Volume" aria-valuetext="80%"></div>
</div></div></div>
CSS
@theme {
  --color-mx-accent: #be185d;
  --color-mx-muted: #6b5a73;
  --color-mx-track: #8e7a90;
}
JavaScript
// Each [data-mx] wraps one <audio>. The script wires play, seek, skip, mute and volume, and writes --p and --v
// (0 to 1) for the WebKit track fill. Layout changes come from CSS container queries, not from the script.
(() => {
  const fmt = s => { s = Math.floor(s || 0); return Math.floor(s / 60) + ':' + String(s % 60).padStart(2, '0'); };
  document.querySelectorAll('[data-mx]').forEach(root => {
    const $ = s => root.querySelector(s);
    const audio = $('audio'), play = $('[data-play]'), seek = $('[data-seek]'), cur = $('[data-cur]'), dur = $('[data-dur]');
    const vol = $('[data-vol]'), mute = $('[data-mute]'), name = play.dataset.play;
    let raf = 0;
    const length = () => audio.duration || +seek.max;
    const sync = () => {
      const t = audio.currentTime, d = length(), text = fmt(t) + ' of ' + fmt(d);
      seek.value = t;
      root.style.setProperty('--p', d ? t / d : 0);
      if (cur) cur.textContent = fmt(t);
      if (seek.getAttribute('aria-valuetext') !== text) seek.setAttribute('aria-valuetext', text);
    };
    const tick = () => { sync(); raf = requestAnimationFrame(tick); };
    const meta = () => { seek.max = audio.duration; if (dur) dur.textContent = fmt(audio.duration); sync(); };
    const sound = () => {
      const v = audio.muted ? 0 : audio.volume;
      root.style.setProperty('--v', v);
      if (vol) { vol.value = v; vol.setAttribute('aria-valuetext', Math.round(v * 100) + '%'); }
      if (mute) mute.setAttribute('aria-pressed', String(v === 0));
    };
    play.addEventListener('click', () => {
      if (!audio.paused) return audio.pause();
      document.querySelectorAll('audio').forEach(a => { if (a !== audio) a.pause(); });
      audio.play().catch(() => {});
    });
    audio.addEventListener('play', () => { root.setAttribute('data-playing', ''); play.setAttribute('aria-label', 'Pause ' + name); tick(); });
    audio.addEventListener('pause', () => { root.removeAttribute('data-playing'); play.setAttribute('aria-label', 'Play ' + name); cancelAnimationFrame(raf); sync(); });
    audio.addEventListener('loadedmetadata', meta);
    audio.addEventListener('volumechange', sound);
    if (audio.readyState > 0) meta();
    seek.addEventListener('input', () => { audio.currentTime = seek.value; sync(); });
    // Arrow keys jump 5 seconds; Home and End work natively.
    seek.addEventListener('keydown', e => {
      const step = { ArrowLeft: -5, ArrowDown: -5, ArrowRight: 5, ArrowUp: 5 }[e.key];
      if (!step) return;
      e.preventDefault();
      audio.currentTime = Math.min(Math.max(audio.currentTime + step, 0), length());
      sync();
    });
    root.querySelectorAll('[data-skip]').forEach(b => b.addEventListener('click', () => {
      audio.currentTime = Math.min(Math.max(audio.currentTime + +b.dataset.skip, 0), length());
      sync();
    }));
    if (vol) {
      audio.volume = vol.value;
      vol.addEventListener('input', () => { audio.volume = vol.value; audio.muted = false; });
    }
    if (mute) mute.addEventListener('click', () => {
      if (audio.muted || audio.volume === 0) { audio.muted = false; if (audio.volume === 0) audio.volume = 0.6; }
      else audio.muted = true;
    });
    sound();
  });
})();

About this set

Two modern CSS techniques for audio players. The first player keeps the browser’s own range inputs and colours them with accent-color alone: no pseudo-elements, no fill script, and the slider still looks native on every platform. The second is one player markup shown three times, in a 260 pixel box, a 420 pixel box and at full width, and it lays itself out from the width of its box rather than the viewport. The wrapper sets container-type: inline-size; below 360 pixels the player shows a small cover, the title and artist, a play button and a bare seek line, from 360 pixels it adds a larger cover and the times, and from 560 pixels it switches grid-template-areas to a 148 pixel cover beside the title, seek slider, skip back 15 and forward 30 buttons, play and volume. Its sliders are styled per engine: Firefox paints the filled part natively with ::-moz-range-progress, while WebKit reads –p and –v, which the script writes as the track plays. Hover tints come from color-mix(). Drop the same player into a sidebar, a card grid or a full-width section and it picks the right layout.

What’s included

  • Native sliders styled with accent-color only
  • One player markup that adapts to its container, not the viewport
  • Three layouts at under 360px, 360px and 560px container widths
  • Firefox fill with ::-moz-range-progress, WebKit fill from --p
  • Hover tints with color-mix()
  • Tailwind version uses @container and @min-[560px]: variants

Accessibility

Each player is a group named after its track; the play button is labelled Play or Pause with the track name, seek sliders read as 0:10 of 0:24 and volume as a percentage. Controls hidden at small container widths use display: none, so they leave the tab order too. Native sliders get a 2px outline on keyboard focus and custom thumbs a two-colour ring. The players use no motion.

Customise it

Change --mx-accent, --mx-muted and --mx-track on .mx, and the 360px and 560px breakpoints in the two @container rules. In Tailwind edit the --color-mx-* theme colours and the @min-[360px]: and @min-[560px]: variants.