const HOME_CONFIG = { RELEASE_DATE: "2027-05-14T00:00:00+02:00", AUDIO_URL: "https://www.dropbox.com/scl/fi/qmzdb4ar3rq7ocrbgm8br/Ive-been-running_test.mp3?rlkey=h2trmv9y6wg59cy8mpueipaz2&dl=0", DEFAULT_VOLUME: 0.5, FADE_OUT_MS: 4000 };

COME SEE WHAT YOU CAME FOR ?

NEXT RELEASE
00DAYS
:
00HOURS
:
00MIN
:
00SEC
(() => { const root = document.getElementById("hh-home-test"); if (!root) return; /* CARRD TRANSPARENCY */ let parent = root.parentElement; let level = 0; while ( parent && level < 8 ) { parent.style.background = "transparent"; parent.style.backgroundColor = "transparent"; parent.style.boxShadow = "none"; parent.style.border = "0"; parent.style.backdropFilter = "none"; parent.style.webkitBackdropFilter = "none"; parent = parent.parentElement; level++; } const get = id => document.getElementById(id); /* COUNTDOWN */ const days = get("hh-days"); const hours = get("hh-hours"); const minutes = get("hh-minutes"); const seconds = get("hh-seconds"); const countdownLabel = root.querySelector(".hh-countdown-label"); const releaseDate = new Date(HOME_CONFIG.RELEASE_DATE); const pad = value => String(value).padStart(2, "0"); function updateCountdown() { const difference = releaseDate.getTime() - Date.now(); if (!Number.isFinite(difference)) { return; } if (difference <= 0) { countdownLabel.textContent = "OUT NOW"; days.textContent = hours.textContent = minutes.textContent = seconds.textContent = "00"; return; } const total = Math.floor( difference / 1000 ); days.textContent = pad( Math.floor( total / 86400 ) ); hours.textContent = pad( Math.floor( (total % 86400) / 3600 ) ); minutes.textContent = pad( Math.floor( (total % 3600) / 60 ) ); seconds.textContent = pad( total % 60 ); } updateCountdown(); setInterval( updateCountdown, 1000 ); /* AUDIO */ const audio = get("hh-atmosphere-audio"); const toggle = get("hh-audio-toggle"); const slider = get("hh-volume"); const hearMeOut = get("hh-hear-me-out-link"); let preferredVolume = Math.max( 0, Math.min( 1, Number( HOME_CONFIG.DEFAULT_VOLUME ) || 0 ) ); let fadeFrame = null; let hardStopTimer = null; let fadeInProgress = false; let pendingFadeCallback = null; let autoplayBlocked = false; let interactionStartDone = false; function createStreamURL( original ) { try { const url = new URL(original); url.searchParams.delete("dl"); url.searchParams.delete("raw"); url.searchParams.set( "raw", "1" ); return url.toString(); } catch { return original; } } audio.src = createStreamURL( HOME_CONFIG.AUDIO_URL ); audio.volume = preferredVolume; slider.value = preferredVolume; /* IMPORTANT: Keep audio alive when Carrd switches sections. */ document.body.appendChild( audio ); function showPlay() { toggle.textContent = "β–Ά"; toggle.setAttribute( "aria-label", "Play" ); } function showPause() { toggle.textContent = "β…‘"; toggle.setAttribute( "aria-label", "Pause" ); } async function playAudio() { audio.volume = preferredVolume; try { await audio.play(); showPause(); autoplayBlocked = false; return true; } catch { showPlay(); return false; } } function pauseAudio() { audio.pause(); audio.volume = preferredVolume; showPlay(); } /* FIRST BACKGROUND INTERACTION */ async function startFromInteraction( event ) { if ( interactionStartDone || !autoplayBlocked || !audio.paused ) { return; } const interactiveElement = event.target.closest( "a, button, input, .hh-audio-player" ); if (interactiveElement) { return; } interactionStartDone = true; const success = await playAudio(); if (!success) { interactionStartDone = false; } } root.addEventListener( "pointerdown", startFromInteraction ); /* PLAY / PAUSE */ toggle.addEventListener( "click", () => { interactionStartDone = true; if (audio.paused) { playAudio(); } else { pauseAudio(); } } ); /* VOLUME */ slider.addEventListener( "input", () => { preferredVolume = Number( slider.value ); audio.volume = preferredVolume; } ); audio.addEventListener( "playing", showPause ); audio.addEventListener( "pause", showPlay ); audio.addEventListener( "error", showPlay ); /* ============================================================ SOFT "SKI SLOPE" dB FADE 4000 ms / 0 dB -> approximately -60 dB Includes a hard-stop fallback so the audio always pauses even if Carrd changes section while the fade is running. ============================================================ */ function fadeOut( callback ) { if ( typeof callback === "function" ) { pendingFadeCallback = callback; } if ( fadeInProgress ) { return; } if ( audio.paused ) { const callbackToRun = pendingFadeCallback; pendingFadeCallback = null; if ( typeof callbackToRun === "function" ) { callbackToRun(); } return; } fadeInProgress = true; const startVolume = audio.volume; const startTime = performance.now(); const duration = Math.max( 1, Number( HOME_CONFIG.FADE_OUT_MS ) || 1 ); function finishFade() { if ( !fadeInProgress ) { return; } fadeInProgress = false; if ( fadeFrame ) { cancelAnimationFrame( fadeFrame ); fadeFrame = null; } if ( hardStopTimer ) { clearTimeout( hardStopTimer ); hardStopTimer = null; } audio.pause(); audio.volume = preferredVolume; showPlay(); const callbackToRun = pendingFadeCallback; pendingFadeCallback = null; if ( typeof callbackToRun === "function" ) { callbackToRun(); } } function step(now) { if ( !fadeInProgress ) { return; } const progress = Math.min( 1, ( now - startTime ) / duration ); const shapedProgress = Math.pow( progress, 2.2 ); const db = -60 * shapedProgress; const gain = Math.pow( 10, db / 20 ); audio.volume = startVolume * gain; if ( progress < 1 ) { fadeFrame = requestAnimationFrame( step ); return; } finishFade(); } fadeFrame = requestAnimationFrame( step ); hardStopTimer = setTimeout( finishFade, duration + 150 ); } /* ============================================================ HEAR ME OUT Start the fade before Carrd handles the section link. Carrd keeps its normal navigation behaviour. ============================================================ */ hearMeOut.addEventListener( "pointerdown", () => { fadeOut(); } ); hearMeOut.addEventListener( "click", () => { fadeOut(); } ); /* Extra fallback: if Carrd changes the URL hash by another event path, make sure the fade has started. */ window.addEventListener( "hashchange", () => { if ( window.location.hash === "#hear-me-out" ) { fadeOut(); } } ); /* DSP BUTTONS */ document.addEventListener( "click", event => { const link = event.target.closest( ".hh-service" ); if (!link) { return; } const destination = link.href; if ( !destination || destination.endsWith("#") ) { return; } if ( event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey ) { fadeOut(); return; } event.preventDefault(); fadeOut( () => { window.location.href = destination; } ); } ); /* AUTOPLAY ATTEMPT */ audio.volume = preferredVolume; audio .play() .then( () => { autoplayBlocked = false; interactionStartDone = true; showPause(); } ) .catch( () => { autoplayBlocked = true; showPlay(); } ); })();
const HEAR_CONFIG = { /* ========================================================== πŸ”΄ SPOTIFY PLAYLIST Paste the NORMAL Spotify playlist URL here. Used ONLY to fetch the playlist artwork. ========================================================== */ SPOTIFY_PLAYLIST_URL: "https://open.spotify.com/playlist/0h1Ols9LSkTUlTyTGR1RLS", /* ========================================================== πŸ”΄ FEATURE.FM SMART LINK Paste the BASE Feature.fm Smart Link here. Example: https://ffm.to/raw-dark-music-2026 DO NOT add: /spotify /tidal /apple etc. The script adds those automatically. ========================================================== */ FEATUREFM_SMART_LINK_URL: "https://ffm.to/raw-dark-music-2026" };
← CHANGE YOUR MIND
HEAR ME OUT
(() => { /* ============================================================ ROOT ============================================================ */ const root = document.getElementById( "hh-hear-section" ); /* ============================================================ MAKE CARRD WRAPPERS TRANSPARENT ============================================================ */ let currentParent = root.parentElement; let levels = 0; while ( currentParent && levels < 8 ) { currentParent.style.background = "transparent"; currentParent.style.backgroundColor = "transparent"; currentParent.style.boxShadow = "none"; currentParent.style.border = "0"; currentParent.style.backdropFilter = "none"; currentParent.style.webkitBackdropFilter = "none"; currentParent = currentParent.parentElement; levels += 1; } /* ============================================================ ELEMENTS ============================================================ */ const artwork = document.getElementById( "hh-artwork" ); const spotifyLink = document.getElementById( "hh-spotify-link" ); const tidalLink = document.getElementById( "hh-tidal-link" ); const appleLink = document.getElementById( "hh-apple-link" ); const youtubeMusicLink = document.getElementById( "hh-youtube-music-link" ); const amazonLink = document.getElementById( "hh-amazon-link" ); /* ============================================================ FEATURE.FM DIRECT-TO-STORE LINKS ============================================================ */ const featureFmBase = HEAR_CONFIG.FEATUREFM_SMART_LINK_URL .replace(/\/+$/, ""); spotifyLink.href = featureFmBase + "/spotify"; tidalLink.href = featureFmBase + "/tidal"; appleLink.href = featureFmBase + "/apple"; youtubeMusicLink.href = featureFmBase + "/youtubemusic"; amazonLink.href = featureFmBase + "/amazon"; /* ============================================================ LOAD PLAYLIST ARTWORK FROM SPOTIFY ============================================================ */ const oEmbedURL = "https://open.spotify.com/oembed?url=" + encodeURIComponent( HEAR_CONFIG.SPOTIFY_PLAYLIST_URL ); fetch( oEmbedURL ) .then( response => { if ( !response.ok ) { throw new Error( "Spotify metadata could not be loaded." ); } return response.json(); } ) .then( data => { if ( data.thumbnail_url ) { artwork.src = data.thumbnail_url; artwork.alt = data.title ? data.title.trim() : "Playlist artwork"; } } ) .catch( () => { root .querySelector( ".hh-artwork-wrap" ) .style.display = "none"; } ); })();
const CLOSER_CONFIG = { INTRO_TEXT: "If you’re still here, come a little closer.", PRIVACY_URL: "#", TERMS_URL: "#", DEMO_MODE: true };
← CHANGE YOUR MIND

0 / 3
I LEFT SOMETHING FOR YOU. Check your inbox.

ALBUM TRAILER

Some footage from the making of my debut album. I’ve been working on these songs for a long time β€” recording, changing things, throwing things away and starting again when something didn’t feel right. I wanted to leave a little of that process here rather than turn it into something too polished.

The album will be released in 2028. Pre-order the Limited Edition Colour Vinyl here .

(()=>{ const root= document.getElementById( "hh-closer" ); if(!root){ return; } /* CARRD TRANSPARENCY */ let parent= root.parentElement; let levels= 0; while( parent && levels<8 ){ parent.style.background= "transparent"; parent.style.backgroundColor= "transparent"; parent.style.boxShadow= "none"; parent.style.border= "0"; parent.style.backdropFilter= "none"; parent.style.webkitBackdropFilter= "none"; parent= parent.parentElement; levels+=1; } /* TEXT / LINKS */ document .getElementById( "cc-intro" ) .textContent= CLOSER_CONFIG.INTRO_TEXT; document .getElementById( "cc-privacy" ) .href= CLOSER_CONFIG.PRIVACY_URL; document .getElementById( "cc-terms" ) .href= CLOSER_CONFIG.TERMS_URL; /* STATE */ const state={ music: new Set(), youtube: false, email: false }; const count= document.getElementById( "cc-count" ); const gift= document.getElementById( "cc-gift" ); function update(){ const value= (state.music.size ? 1 : 0) + (state.youtube ? 1 : 0) + (state.email ? 1 : 0); count.textContent= value; gift.classList.toggle( "is-on", value===3 ); } /* MUSIC DEMO */ document .querySelectorAll( "#hh-closer .music" ) .forEach( row=>{ row.addEventListener( "click", ()=>{ if( !CLOSER_CONFIG.DEMO_MODE ){ return; } const name= row .querySelector( ".cc-box-name" ) .textContent .trim(); if( state.music.has( name ) ){ state.music.delete( name ); }else{ state.music.add( name ); } const active= state.music.has( name ); row.classList.toggle( "is-on", active ); row .querySelector( ".cc-box-action" ) .textContent= active ? "CONNECTED βœ“" : "FOLLOW β†—"; update(); }); }); /* YOUTUBE DEMO */ const youtube= document.getElementById( "cc-youtube" ); youtube.addEventListener( "click", ()=>{ if( !CLOSER_CONFIG.DEMO_MODE ){ return; } state.youtube= !state.youtube; youtube.classList.toggle( "is-on", state.youtube ); youtube .querySelector( ".cc-box-action" ) .textContent= state.youtube ? "CONNECTED βœ“" : "FOLLOW β†—"; update(); }); /* EMAIL DEMO */ const email= document.getElementById( "cc-email" ); const consent= document.getElementById( "cc-consent" ); const submit= document.getElementById( "cc-email-submit" ); const emailRow= document.getElementById( "cc-email-row" ); const error= document.getElementById( "cc-error" ); submit.addEventListener( "click", ()=>{ if( !CLOSER_CONFIG.DEMO_MODE ){ return; } if( state.email )