<!-- SOLID BIG ISLAND — the game shell · part 2 -->
ay:flex;align-items:center;gap:10px;margin:6px 0 2px}
.seek span{font-size:17px;color:var(--mute);font-variant-numeric:tabular-nums;min-width:52px;text-align:center}
input[type=range]{flex:1;min-width:0;height:var(--tap);background:transparent;-webkit-appearance:none;appearance:none;margin:0}
input[type=range]::-webkit-slider-runnable-track{height:6px;border-radius:3px;background:linear-gradient(90deg,var(--gold) var(--p,0%),#3b311f var(--p,0%))}
input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:24px;height:24px;border-radius:50%;background:var(--gold2);margin-top:-9px;border:2px solid #000}
input[type=range]::-moz-range-track{height:6px;border-radius:3px;background:#3b311f}
input[type=range]::-moz-range-progress{height:6px;border-radius:3px;background:var(--gold)}
input[type=range]::-moz-range-thumb{width:22px;height:22px;border-radius:50%;background:var(--gold2);border:2px solid #000}
.controls{display:flex;align-items:center;justify-content:space-between;gap:8px;max-width:420px;margin:0 auto}
.controls .btn.big{min-width:64px;min-height:64px;background:var(--gold);color:#120e08;border-color:var(--gold2)}
.controls .btn.big svg{width:30px;height:30px}
.btn[aria-pressed=true]{background:var(--gold);color:#120e08}
.status{font-size:17px;color:var(--mute);min-height:0}
footer{text-align:center;color:var(--goldDim);font-size:17px;padding:22px 16px}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
@media (min-width:760px){ul,.searchwrap,footer{max-width:760px;margin-left:auto;margin-right:auto}}
</style>
</head>
<body>
<header>
  <div class="crest">Solid The Epistolary</div>
  <h1 class="serif">SolidBigIsland</h1>
  <p class="sub">The Record Studio · <b id="total">333</b> songs · Big Island, Hawaiʻi</p>
</header>

<div class="searchwrap">
  <div class="search">
    <label class="sr" for="q">Search songs</label>
    <input id="q" type="search" placeholder="Search a title or lyric word" autocomplete="off" autocorrect="off" spellcheck="false" enterkeyhint="search">
  </div>
  <div class="count" id="count" aria-live="polite">Loading the vault…</div>
</div>

<ul id="list" aria-label="Songs, newest first"></ul>
<footer>All songs by SolidBigIsland · lyrics are auto-transcribed, so expect mishearings<br><a class="pill" style="margin-top:10px" href="https://www.tiktok.com/@solidbigisland" target="_blank" rel="noopener">@solidbigisland</a></footer>

<div id="player" role="region" aria-label="Player">
  <div class="np">
    <div class="thumb ph" id="npThumb">♛</div>
    <div class="meta"><div class="t" id="npTitle">Tap a song to start the set</div><div class="d" id="npSub">Plays straight through, newest first</div></div>
  </div>
  <div class="seek">
    <span id="cur">0:00</span>
    <input id="seek" type="range" min="0" max="1000" value="0" step="1" aria-label="Seek">
    <span id="dur">0:00</span>
  </div>
  <div class="controls">
    <button class="btn" id="shuf" aria-pressed="false" aria-label="Shuffle" title="Shuffle"><svg viewBox="0 0 24 24"><path d="M17 3l4 4-4 4V8h-2.6l-2.2 2.6-1.3-1.5L13.5 6H17V3zM3 6h4.5l9 10H17v-3l4 4-4 4v-3h-1.4l-9-10H3V6zm0 12v-2h3.6l2.2-2.6 1.3 1.5L7.5 18H3z"/></svg></button>
    <button class="btn" id="prev" aria-label="Previous"><svg viewBox="0 0 24 24"><path d="M6 5h2v14H6zM20 5v14L9 12z"/></svg></button>
    <button class="btn big" id="play" aria-label="Play"><svg viewBox="0 0 24 24" id="playIcon"><path d="M8 5v14l11-7z"/></svg></button>
    <button class="btn" id="next" aria-label="Next"><svg viewBox="0 0 24 24"><path d="M16 5h2v14h-2zM4 5v14l11-7z"/></svg></button>
    <button class="btn" id="top" aria-label="Scroll to current song" title="Find current song"><svg viewBox="0 0 24 24"><path d="M12 8a4 4 0 100 8 4 4 0 000-8zm9 3h-2.1A7 7 0 0013 5.1V3h-2v2.1A7 7 0 005.1 11H3v2h2.1a7 7 0 005.9 5.9V21h2v-2.1a7 7 0 005.9-5.9H21v-2z"/></svg></button>
  </div>
  <div class="status" id="status" aria-live="polite"></div>
</div>

<audio id="audio" preload="none" playsinline></audio>

<script>
(function(){
  const $=s=>document.querySelector(s);
  const audio=$('#audio'), list=$('#list'), q=$('#q');
  const PLAY='<path d="M8 5v14l11-7z"/>', PAUSE='<path d="M6 5h4v14H6zM14 5h4v14h-4z"/>';
  let songs=[], visible=[], cur=-1, shuffle=false, history=[], seeking=false;
  const esc=s=>String(s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
  const fmt=t=>{t=Math.max(0,Math.floor(t||0));const h=Math.floor(t/3600),m=Math.floor(t%3600/60),s=String(t%60).padStart(2,'0');return h?`${h}:${String(m).padStart(2,'0')}:${s}`:`${m}:${s}`};
  const fdate=d=>{const [y,m,dd]=d.split('-');return `${['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'][+m-1]} ${+dd}, ${y}`};
  const norm=s=>s.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f\u02bb\u2018\u2019']/g,'');

  fetch('songs.json').then(r=>{if(!r.ok)throw new Error(r.status);return r.jso