Logo
  • About
  • Blog
  • Podcast
  • Mindset Reflections
  • Creative Explorations

Code Archive

Body

Logo

Listen On

Spotify

Apple Music

YouTube

Pandora

Amazon

Terms

Terms of Use

Privacy Policy

Links

About

Blog

Podcast

© 2025 Isak Vidinghoff. Minds of Means is a voluntary creative study created as part of personal recovery. Non-commercial, no sponsorships.

InstagramFacebookXTiktokYouTube
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-W3MVGFD2"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>

<!-- Site core script: modes, embeds, related limiter, readbar, conditional loaders -->
<script>
(function(){
  /* ---------------- Feature flags ---------------- */
  const FEATURES = {
    shareThis:  false, // using native sharebar
    scrollReveal: false,
    readBar:    true
  };

  /* -------------- One-time loader with guards -------------- */
  function inject(src, attrs){
    if (document.querySelector('script[src="'+src+'"]')) return;
    const s=document.createElement('script');
    s.src=src; s.defer=true;
    if (attrs) Object.entries(attrs).forEach(([k,v])=>s.setAttribute(k,v));
    document.head.appendChild(s);
  }

  /* ---------------- Page tags / modes ---------------- */
  const html = document.documentElement;
  const BLOG_PREFIX="/blog/";
  const EPISODE_PREFIX="/podcast/episodes/";
  const PAGE_CLASSES={ "/":"page-home", "/blog":"blog-index", "/podcast":"podcast-index",
                       "/terms-of-use":"legal", "/privacy-policy":"legal", "/cookies-policy":"legal" };
  const forceReading=["/success-mindset-the-ultimate-guide","/the-creator-journey-from-idea-to-impact","/creators-roadmap"];
  const isIdx=(p,pre)=>p===pre||p===pre.slice(0,-1);
  const isBlogPost=p=>p.startsWith(BLOG_PREFIX)&&!isIdx(p,BLOG_PREFIX);
  const isEpisode =p=>p.startsWith(EPISODE_PREFIX)&&!isIdx(p,EPISODE_PREFIX);
  const isForce   =p=>forceReading.some(x=>p===x||p.startsWith(x+"/"));

  function markCover(){
    // Blog index: always no-cover (keeps the mini-hero/CTA visible)
    if (location.pathname.replace(/\/+$/,'/') === '/blog/') {
      html.classList.remove('has-cover');
      html.classList.add('no-cover');
      return;
    }
    const img = document.querySelector('.notion-header__cover img, .notion-header .notion-cover img');
    const has = !!img && img.complete && img.naturalWidth > 1;
    html.classList.toggle('has-cover', has);
    html.classList.toggle('no-cover', !has);
  }

  function applyPageTags(){
    const p=location.pathname.replace(/\/+$/,'');
    // clear previous
    Object.values(PAGE_CLASSES).forEach(c=>html.classList.remove(c));
    if (PAGE_CLASSES[p] || PAGE_CLASSES[p+'/']) html.classList.add(PAGE_CLASSES[p] || PAGE_CLASSES[p+'/']);
    html.classList.toggle("reading-mode", isBlogPost(p+'/') || isForce(p));
    html.classList.toggle("episode-mode", isEpisode(p+'/'));
    markCover();
  }

  /* --- Ensure Blog/Podcast "hero" callouts exist after SPA nav --- */
  function ensureIndexHeroes(){
    const firstCallout = () =>
      document.querySelector('.notion-page-content .notion-callout, .super-content__page .notion-callout');

    if (html.classList.contains('blog-index')) {
      const co = firstCallout();
      if (co && !co.classList.contains('blog-index-hero')) co.classList.add('blog-index-hero');
    }
    if (html.classList.contains('podcast-index')) {
      const co = firstCallout();
      if (co && !co.classList.contains('podcast-hero')) co.classList.add('podcast-hero');
    }
  }

  /* ---------------- Conditional third-parties ---------------- */
  function loadThirdParties(){
    if (FEATURES.shareThis && isBlogPost(location.pathname) &&
        document.querySelector('.sharethis-inline-share-buttons,[data-sharethis]')) {
      inject('https://platform-api.sharethis.com/js/sharethis.js#property=67d4b6febc169300120859c4&product=sop', { async:'async' });
    }
    if (FEATURES.scrollReveal &&
        document.querySelector('[data-sr],.notion-quote,.notion-callout,.notion-image')) {
      inject('https://unpkg.com/[email protected]/dist/scrollreveal.min.js');
    }
    // Lottie only if used
    if (document.querySelector('lottie-player,[data-lottie]')) {
      inject('https://unpkg.com/@lottiefiles/lottie-player@latest/dist/lottie-player.js');
    }
  }

  /* ---------------- Latest podcast (RSS + trailer fallback) ---------------- */
  function initLatestEpisode(){
    if (window.__moomLatestV2) return; window.__moomLatestV2 = true;
    const mount=document.querySelector('[data-latest-episode]'); if (!mount) return;

    const RSS="https://mindsofmeans.com/podcast/episodes.rss";
    let showed=false;
    const render=o=>{
      showed=true;
      const date=o.pubDate?new Date(o.pubDate).toLocaleDateString():"";
      mount.innerHTML=`
        <div class="latest-wrap">
          <span class="badge">Latest Episode</span>
          <h3 class="latest-title"><a href="${o.link||'#'}" target="_blank" rel="noopener">${o.title||'Latest episode'}</a></h3>
          <div class="latest-meta">${date}</div>
          ${o.audioUrl?`<audio class="latest-audio" controls preload="none" src="${o.audioUrl}" aria-label="Play latest"></audio>`:''}
        </div>`;
    };
    const loadTrailer=()=>{
      if (showed) return;
      showed=true;
      const id="PodOps44855player";
      mount.innerHTML=`<div class="latest-wrap"><span class="badge">Trailer</span><div id="${id}"></div></div>`;
      const s=document.createElement("script");
      s.src=`https://podopshost.com/js/embedd.js?container_id=${id}&player=44855`;
      s.async=true; document.body.appendChild(s);
    };
    const parse=xml=>{
      const doc=new DOMParser().parseFromString(xml,"text/xml");
      const item=doc.querySelector("channel > item"); if(!item) return null;
      const enc=item.querySelector("enclosure[url]");
      return { title:item.querySelector("title")?.textContent?.trim()||"",
               link:item.querySelector("link")?.textContent?.trim()||"#",
               pubDate:item.querySelector("pubDate")?.textContent||"",
               audioUrl:enc?.getAttribute("url")||"" };
    };

    const start = window.requestIdleCallback ? (cb)=>requestIdleCallback(cb,{timeout:2500}) : (cb)=>setTimeout(cb,0);
    start(()=>{
      const ctrl=new AbortController(); setTimeout(()=>ctrl.abort(), 5000);
      fetch(RSS,{headers:{Accept:"application/rss+xml, application/xml, text/xml"}, signal:ctrl.signal})
        .then(r=>r.ok?r.text():Promise.reject())
        .then(xml=>{ const latest=parse(xml); if(latest) render(latest); else loadTrailer(); })
        .catch(loadTrailer);
    });
  }

  /* ---------------- Limit related DB cards (after marker) ---------------- */
  function limitNextCollection(marker,n){
    const root=document.querySelector('.notion-root')||document;
    const collections=[...root.querySelectorAll('.notion-collection, .notion-collection-gallery, .notion-collection-list')];
    const target=collections.find(el=>marker.compareDocumentPosition(el)&Node.DOCUMENT_POSITION_FOLLOWING);
    if(!target) return;
    const cards=target.querySelectorAll('.notion-collection-card, .notion-collection-item, .notion-collection__item, .notion-collection-gallery > div, .notion-collection-list > div');
    cards.forEach((el,i)=>{ if(i>=n) el.style.display='none'; });
    if(target.classList.contains('notion-collection-gallery')) target.style.gridTemplateColumns='1fr';
  }
  function applyRelLimits(){
    document.querySelectorAll('.limit-related[data-limit]:not([data-limited])').forEach(el=>{
      const n=parseInt(el.dataset.limit,10)||1;
      limitNextCollection(el,n);
      el.setAttribute('data-limited','true');
    });
  }

  /* ---------------- Read progress (reading pages only) ---------------- */
  function ensureReadbar(){
    if (!html.classList.contains('reading-mode') || document.getElementById('readbar')) return;
    const bar=document.createElement('div');
    bar.id='readbar';
    bar.style.cssText='position:fixed;top:0;left:0;height:3px;width:0;background:#f5c518;z-index:9999;box-shadow:0 0 0 1px rgba(0,0,0,.05)';
    document.body.appendChild(bar);
    let ticking=false;
    function update(){
      const d=Math.max(0,document.documentElement.scrollHeight - innerHeight);
      bar.style.width=((d? scrollY/d : 0)*100)+'%';
      ticking=false;
    }
    addEventListener('scroll', ()=>{ if(!ticking){ ticking=true; requestAnimationFrame(update);} }, {passive:true});
    addEventListener('resize', ()=>requestAnimationFrame(update), {passive:true});
    update();
  }

  /* ---------------- Optional ScrollReveal ---------------- */
  function initScrollReveal(){
    if (!FEATURES.scrollReveal || typeof ScrollReveal === 'undefined' || window.__moomSR) return;
    window.__moomSR = true;
    const sr=ScrollReveal({ distance:'-50px' });
    ['.notion-quote','.notion-callout','.notion-image','.notion-collection'].forEach(sel=>{
      if (document.querySelector(sel)) sr.reveal(sel,{ duration:500 });
    });
  }

  /* ---------------- Orchestration ---------------- */
  function applyAll(){
    applyPageTags();
    ensureIndexHeroes();   // <- make sure heroes exist before anything that reads layout
    loadThirdParties();
    initLatestEpisode();
    applyRelLimits();
    if (FEATURES.readBar) ensureReadbar();
    initScrollReveal();
  }

  // expose tiny bits so soft-nav can call them immediately
  window.__moom = Object.assign(window.__moom||{}, { applyPageTags, markCover, ensureIndexHeroes });

  // Initial
  if (document.readyState!=='loading') applyAll();
  else document.addEventListener('DOMContentLoaded', applyAll);

  // SPA pageviews + early retagging so blog/podcast CTA appears without refresh
  window.dataLayer = window.dataLayer || [];

  addEventListener('super:load', () => {
    window.__moom.applyPageTags?.();
    window.__moom.ensureIndexHeroes?.();
    dataLayer.push({ event:'virtual_pageview', page_location:location.href, page_path:location.pathname+location.search, page_title:document.title });
    setTimeout(applyAll, 0);
    setTimeout(markCover, 150);
  });

  addEventListener('super:navigation', () => {
    window.__moom.applyPageTags?.();
    window.__moom.ensureIndexHeroes?.();
    dataLayer.push({ event:'virtual_pageview', page_location:location.href, page_path:location.pathname+location.search, page_title:document.title });
    setTimeout(applyAll, 0);
    setTimeout(markCover, 150);
    setTimeout(markCover, 600);
  });

  addEventListener('pageshow', (e)=>{ if (e.persisted){ setTimeout(applyAll,0); }});
  addEventListener('popstate', () => { window.__moom.applyPageTags?.(); setTimeout(applyAll, 0); });

  // Scoped MutationObserver: re-run once after Notion reflow
  const target=document.querySelector('.notion-root')||document.documentElement;
  let settleTimer; const mo=new MutationObserver(()=>{ clearTimeout(settleTimer);
    settleTimer=setTimeout(()=>{ applyAll(); mo.disconnect(); }, 300);
  });
  mo.observe(target, { childList:true, subtree:true });
  setTimeout(()=>mo.disconnect(), 8000);
})();
</script>

<!-- Blog-index & Sharebar styles -->
<style>
/* Blog index: remove cover and tighten spacing so CTA shows immediately (belt + suspenders) */
:root.blog-index .notion-header__cover,
:root.blog-index .notion-header .notion-cover{ display:none !important; }
:root.blog-index .notion-header{ margin-bottom:10px !important; padding-bottom:0 !important; }
/* Optional: hide default "Blog" title if you use a custom mini-hero */
:root.blog-index .notion-page-title{ display:none !important; }

/* Ensure heroes sit above the cover plane so CTAs are never hidden */
.blog-index-hero, .podcast-hero{ position:relative; z-index:2; }

/* Native sharebar (hover + compact variant) */
.sharebar{display:flex;gap:.5rem;flex-wrap:wrap;align-items:center}
.sharebar a,.sharebar button{
  display:inline-flex;align-items:center;gap:.4rem;
  padding:.45rem .65rem;border-radius:.65rem;
  border:1px solid var(--border,rgba(255,255,255,.14));
  background:transparent;color:inherit;text-decoration:none;
  font:500 .9rem/1.1 system-ui;
  transition:transform .12s ease, background-color .12s ease, border-color .12s ease, opacity .12s ease;
}
.sharebar a:hover,.sharebar button:hover,
.sharebar a:focus-visible,.sharebar button:focus-visible{
  background: rgba(255,255,255,.06);
  border-color: rgba(255,255,255,.22);
  outline: none;
}
.sharebar a:active,.sharebar button:active{ transform: translateY(1px) }
.sharebar .copy-ok{ opacity:.75 }
.sharebar--compact a,.sharebar--compact button{ padding:.35rem .55rem; font-size:.85rem; border-radius:.55rem }
@media (prefers-reduced-motion: reduce){ .sharebar a,.sharebar button{ transition:none } }
</style>

<!-- Native sharebar (multi-instance, SPA-safe) -->
<script>
(function(){
  const SELECTOR='[data-sharebar]';

  function openPopup(href){
    const w=680,h=540,l=(screen.width-w)/2,t=(screen.height-h)/2;
    window.open(href,'share','width='+w+',height='+h+',left='+l+',top='+t+',noopener');
  }
  function buildSharebar(mount){
    if (!mount || mount.dataset.sharebarRendered === '1') return;
    mount.dataset.sharebarRendered='1';

    const canonical=document.querySelector('link[rel="canonical"]')?.href;
    const pageUrl=canonical||location.href;
    const encUrl=encodeURIComponent(pageUrl);
    const encText=encodeURIComponent(document.title);
    const via='mindsofmeans';

    const endpoints={
      x:        () => `https://twitter.com/intent/tweet?url=${encUrl}&text=${encText}&via=${via}`,
      linkedin: () => `https://www.linkedin.com/sharing/share-offsite/?url=${encUrl}`,
      facebook: () => `https://www.facebook.com/sharer/sharer.php?u=${encUrl}`,
      reddit:   () => `https://www.reddit.com/submit?url=${encUrl}&title=${encText}`,
      whatsapp: () => `https://api.whatsapp.com/send?text=${encText}%20${encUrl}`,
      email:    () => `mailto:?subject=${encText}&body=${encText}%0A${encUrl}`,
      copy:     'copy'
    };
    const list=(mount.dataset.platforms||'x,linkedin,facebook,reddit,whatsapp,email,copy')
      .split(',').map(s=>s.trim().toLowerCase()).filter(Boolean);

    const frag=document.createDocumentFragment();

    if (navigator.share && !list.includes('copy')){
      const btn=document.createElement('button');
      btn.type='button'; btn.textContent='Share';
      btn.setAttribute('aria-label','Share');
      btn.addEventListener('click', ()=>navigator.share({ title:document.title, url:pageUrl }).catch(()=>{}));
      frag.appendChild(btn);
    }

    list.forEach(p=>{
      if (p==='copy'){
        const copy=document.createElement('button');
        copy.type='button'; copy.textContent='Copy link'; copy.setAttribute('aria-label','Copy link');
        copy.addEventListener('click', async ()=>{
          try{
            await navigator.clipboard.writeText(pageUrl);
            copy.textContent='Copied!'; copy.classList.add('copy-ok');
            setTimeout(()=>{ copy.textContent='Copy link'; copy.classList.remove('copy-ok'); },1400);
          }catch(_){}
        });
        frag.appendChild(copy); return;
      }
      const make=endpoints[p]; if (!make) return;
      const href=typeof make==='function'? make() : make;
      const a=document.createElement('a');
      a.href=href; a.target='_blank'; a.rel='noopener nofollow';
      a.textContent=p.charAt(0).toUpperCase()+p.slice(1);
      a.setAttribute('aria-label','Share on '+p);
      a.addEventListener('click', e=>{ if (!navigator.share){ e.preventDefault(); openPopup(href); } });
      frag.appendChild(a);
    });

    mount.appendChild(frag);
  }

  function renderAll(){ document.querySelectorAll(SELECTOR).forEach(buildSharebar); }

  if (document.readyState !== 'loading') renderAll();
  else document.addEventListener('DOMContentLoaded', renderAll);

  addEventListener('super:load',       ()=> setTimeout(renderAll, 0));
  addEventListener('super:navigation', ()=> setTimeout(renderAll, 0));
  addEventListener('pageshow', (e)=>{ if (e.persisted) setTimeout(renderAll, 0); });
  addEventListener('popstate', ()=> setTimeout(renderAll, 0));

  const debounced = (()=>{ let t; return ()=>{ clearTimeout(t); t=setTimeout(renderAll, 80); }; })();
  new MutationObserver(debounced).observe(document.documentElement, { childList:true, subtree:true });

  let tries=0; (function tick(){
    const pending=[...document.querySelectorAll(SELECTOR)].some(el=>!el.dataset.sharebarRendered);
    if (pending && tries++ < 40){ renderAll(); setTimeout(tick, 250); }
  })();

  (window.MOOM = window.MOOM || {}).renderSharebars = renderAll;
})();
</script>

<script>
/* Minds of Means – Inline email CTA (SPA-safe, idempotent) */
(function () {
  const SELECTOR = '#moom-inline-optin';  // place this div in Notion
  const FORM_BASE = 'https://forms.mindsofmeans.com/T6TKyu';

  function pageInfo() {
    const loc = new URL(location.href);
    const path = loc.pathname || '/';
    const isIdx = (p, pre) => p === pre || p === pre.slice(0, -1);
    const isEpisode = path.startsWith('/podcast/episodes/') && !isIdx(path, '/podcast/episodes/');
    const isPodcastSection = path.startsWith('/podcast') && !isEpisode;
    const isBlog = path.startsWith('/blog');
    const h1 = document.querySelector('h1')?.innerText?.trim();
    const title = (h1 || document.title || 'Minds of Means').trim();
    return { path, isEpisode, isPodcastSection, isBlog, title, origin: loc.origin };
  }

  function buildUrl(source, returnUrl) {
    const qs = new URLSearchParams();
    qs.set('rmee4', source);
    qs.set('zc6ai', returnUrl);
    return `${FORM_BASE}?${qs.toString()}`;
  }

  function renderOne(host) {
    if (!host || host.dataset.ctaRendered === '1') return;
    host.dataset.ctaRendered = '1';

    const { path, isEpisode, isPodcastSection, isBlog, title, origin } = pageInfo();

    // Allow optional overrides from data-attributes
    const sourceOverride = host.dataset.source?.trim();
    const labelOverride  = host.dataset.label?.trim();
    const variantClass   = host.dataset.variant?.trim(); // e.g., "is-gold"

    // Source used by Deftform
    const source = sourceOverride
      ? sourceOverride
      : isEpisode
        ? title                                // e.g., "Episode 4 — Hugh Massie"
        : isPodcastSection
          ? 'Podcast — Minds of Means'
          : isBlog
            ? `Blog: ${title}`
            : 'Minds of Means';

    // Button label
    const label = labelOverride
      ? labelOverride
      : isEpisode
        ? 'Get episode alerts by email'
        : isPodcastSection
          ? 'Get show updates by email'
          : isBlog
            ? 'Get new posts by email'
            : 'Get updates by email';

    // Small note under the button
    const noteText = isEpisode
      ? '1 email per episode. Unsubscribe anytime.'
      : isPodcastSection
        ? '1 email per release. Unsubscribe anytime.'
        : isBlog
          ? '1 email per post. Unsubscribe anytime.'
          : 'Unsubscribe anytime.';

    const returnUrl = `${origin}${path}?sub=thanks`;
    const formUrl = buildUrl(source, returnUrl);

    host.innerHTML = `
      <a href="${formUrl}" class="moom-cta ${variantClass ? variantClass : ''}" aria-label="${label}">
        ${label}
      </a>
      <div class="moom-cta-note">${noteText}</div>
    `;
  }

  function renderAll() {
    document.querySelectorAll(SELECTOR).forEach(renderOne);
  }

  // Init + SPA/rehydration hooks
  if (document.readyState !== 'loading') renderAll();
  else document.addEventListener('DOMContentLoaded', renderAll);

  addEventListener('super:load',       () => setTimeout(renderAll, 0));
  addEventListener('super:navigation', () => setTimeout(renderAll, 0));
  addEventListener('pageshow', (e) => { if (e.persisted) setTimeout(renderAll, 0); });
  addEventListener('popstate',         () => setTimeout(renderAll, 0));

  // Light observer to catch Notion DOM reflows
  const debounced = (() => { let t; return () => { clearTimeout(t); t = setTimeout(renderAll, 80); }; })();
  new MutationObserver(debounced).observe(document.documentElement, { childList: true, subtree: true });

  // Safety retries for slow renders
  let tries = 0; (function tick(){ const pending = document.querySelector(SELECTOR)?.dataset.ctaRendered !== '1';
    if (pending && tries++ < 30) { renderAll(); setTimeout(tick, 250); }
  })();
})();
</script>