Storytell

by SvennMats

HTML

<!-- JSFiddle: HTML-panel
     External resources (legg til under Resources i JSFiddle):
     - https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;700;800;900&family=Inter:wght@400;500;600&display=swap
     - https://player.vimeo.com/api/player.js
-->

<!-- NAVBAR ================================================= -->
<div class="svenn-wrapper">
  <div class="navbar-sticky">
    <nav class="navbar">
      <a href="https://svenn.com/" class="nav-logo">
        <img src="https://cdn.sanity.io/images/kczjvvqi/production/d4c9c4e2d4f06a0c4d93b32b2fb64d5eede8a513-300x150.png" alt="Svenn Logo">
      </a>
      <input type="checkbox" id="mobile-menu" class="mobile-menu-toggle">
      <label for="mobile-menu" class="mobile-menu-icon">☰</label>
      <div class="nav-menu">
        <div class="nav-links">
          <div class="nav-dropdown">
            <input type="checkbox" id="verktøy-toggle" class="dropdown-toggle">
            <label for="verktøy-toggle" class="dropdown-label">Verktøy ▾</label>
            <div class="nav-dropdown-menu two-columns">
              <a href="https://svenn.com/kalkulasjon" class="has-icon"><div class="dropdown-icon"><svg viewBox="-2 -2 24 24" fill="currentColor"><path d="M8.88 9.44c.05 0 .1-.02.13-.05.03-.04.05-.09.05-.14V1.44c0-.05-.02-.1-.05-.13A.18.18 0 008.88 1.25H4.04c-.74 0-1.45.29-1.97.82C1.54 2.59 1.25 3.3 1.25 4.04v5.21c0 .05.02.1.05.14.04.03.08.05.14.05h7.44zM7.02 6.46H5.9c-.05 0-.1.02-.13.06-.04.03-.05.08-.05.13v1.12c0 .15-.06.29-.16.39-.1.11-.25.16-.4.16-.15 0-.29-.05-.4-.16a.54.54 0 01-.16-.39V6.65c0-.05-.02-.1-.05-.13a.18.18 0 00-.13-.06H3.3c-.15 0-.29-.06-.4-.16a.54.54 0 01-.16-.4c0-.15.06-.29.16-.4.1-.1.25-.16.4-.16h1.12c.05 0 .1-.02.13-.05.04-.03.05-.08.05-.13V4.04c0-.15.06-.29.16-.4.1-.1.25-.16.4-.16.15 0 .29.06.4.16.1.1.16.25.16.4v1.12c0 .05.02.1.05.13.04.04.08.05.13.05h1.12c.15 0 .29.06.4.16.1.1.16.25.16.4 0 .15-.06.29-.16.4-.1.1-.25.16-.4.16z"></path><path d="M10.19 9.26c0...

CSS

/* =========================================
   SKJUL GAMMEL MENY (Sanity/CMS-spesifikt)
   ========================================= */
.Header_header__qBw1J { display: none; }
.PageTransition_page__XtMgn { padding-top: 0px; }
.TopHeader_topHeader__content__cPDXk { display: none; }

/* =========================================
   GLOBALE STILER
   ========================================= */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html { background: #0d0b10; }
body { min-height: 100vh; background: #0d0b10; overflow-x: hidden; }
:root {
  --orange:   #F96529;
  --yellow:   #F5E871;
  --green:    #BDE37C;
  --dark:     #241D2D;
  --dark-rgb: 36, 29, 45;
  --display:  'Outfit', system-ui, sans-serif;
  --body:     'Inter', system-ui, sans-serif;
}

/* =========================================
   NAVBAR
   ========================================= */
.svenn-wrapper { font-family: 'Outfit', system-ui, sans-serif; color: #241D2D; background: transparent; padding-bottom: 0; overflow: visible; }
.svenn-wrapper .navbar-sticky { position: fixed; top: 0; z-index: 1000; width: 100%; background-color: #F4F6FB; animation: scrollNavbar linear both; animation-timeline: scroll(); animation-range: 0px 120px; }
@keyframes scrollNavbar { to { background-color: #FFFFFF; box-shadow: 0 4px 20px rgba(36,29,45,0.08); } }
.svenn-wrapper .navbar { display: flex; justify-content: space-between; align-items: center; padding: 16px 40px; max-width: 1200px; margin: 0 auto; gap: 40px; }
.svenn-wrapper .nav-logo { display: flex; align-items: center; text-decoration: none; flex-shrink: 0; }
.svenn-wrapper .nav-logo img { height: 30px; width: auto; display: block; }
.svenn-wrapper .nav-menu { display: flex; align-items: center; flex: 1; justify-content: space-between; }
.svenn-wrapper .nav-links { display: flex; gap: 32px; align-items: center; }
.svenn-wrapper .nav-links a { text-decoration: none; color: #241D2D; font-size: 16px;...

JavaScript

const sections   = document.querySelectorAll('.section');
const sectionArr = Array.from(sections);
const bgImgs     = document.querySelectorAll('.bg__img');
const bgVideo    = document.getElementById('bg-video');
const bgDark     = document.getElementById('bg-dark');
const progress   = document.getElementById('progress');

// Slides 0–2 bruker video. Slide 3+ bruker stillbilde.
const VIDEO_SLIDES = 3;

// Eksplisitt mapping: slide → bg img-indeks (9 slides totalt)
const BG_MAP = [0, 0, 0, 3, 3, 5, 5, 6, 6];

let lastIndex = -1;

function bgImgIndex(i) {
  return BG_MAP[i] ?? 0;
}

function activateBg(index, prevIndex) {
  const useVideo       = index < VIDEO_SLIDES;
  const wasVideo       = prevIndex < VIDEO_SLIDES;
  const isLeavingVideo = wasVideo && !useVideo;

  bgVideo.classList.toggle('is-active', useVideo);

  const imgIdx  = bgImgIndex(index);
  const overlay = sectionArr[index]?.dataset.overlay || 'normal';

  if (overlay === 'dark') {
    bgDark.style.transition = 'none';
    bgDark.style.opacity = '1';
    requestAnimationFrame(() => requestAnimationFrame(() => {
      bgImgs.forEach((img, i) => {
        if (isLeavingVideo && i === 0) return;
        img.classList.toggle('is-active', i === imgIdx);
      });
      bgDark.style.transition = 'opacity 0.7s ease';
    }));
  } else {
    bgImgs.forEach((img, i) => {
      if (isLeavingVideo && i === 0) return;
      img.classList.toggle('is-active', i === imgIdx);
    });
    bgDark.style.transition = 'opacity 0.7s ease';
    bgDark.style.opacity = overlay === 'medium' ? '0.6' : '0';
  }

  if (isLeavingVideo) {
    setTimeout(() => bgImgs[0].classList.remove('is-active'), 950);
  }
}

function onScroll() {
  const scrollY = window.scrollY;
  const vh      = window.innerHeight;
  const index   = Math.max(0, Math.min(Math.round(scrollY / vh), sectionArr.length - 1));
  if (index !== lastIndex) {
    const prevIndex = lastIndex;
    lastIndex =...