
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-WBK1X6GQEJ"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-WBK1X6GQEJ');
</script>
<meta name="title" content="James Trosh - Video Content Producer & Director from London, UK">
<meta name="description" content="London based producer of documentaries, social campaigns, live streams, sports content, music content, podcasts, and experimental video.">
<meta name="keywords" content="Documentary, Experimental, Social campaign, Live streaming, Sports content, Music content, Podcasting, London, UK, James Trosh, Troshy, Madebytrosh">
<meta name="robots" content="index, follow">
<meta property="og:title" content="James Trosh - Video Content Producer & Director from London, UK" />
<meta property="og:description" content="London based producer of documentaries, social campaigns, live streams, sports content, music content, podcasts, and experimental video." />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://www.jamestrosh.com/" />
<meta property="og:image" content="https://www.jamestrosh.com/staticimages/opengraph.jpg" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="627" />
<meta property="og:site_name" content="madebytrosh" />
<meta property="og:locale" content="en_GB" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="James Trosh - Video Content Producer & Director from London, UK" />
<meta name="twitter:description" content="London based producer of documentaries, social campaigns, live streams, sports content, music content, podcasts, and experimental video." />
<meta name="twitter:image" content="https://www.jamestrosh.com/staticimages/opengraph.jpg" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="language" content="English">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">

    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>James Trosh - Video Content Producer & Director</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
    <style>
        /* Lighter Greyscale scheme */
        body {
            font-family: 'Roboto', sans-serif;
            background-color: #f5f5f5; /* neutral-100 */
            color: #404040; /* neutral-700 */
        }
        .nav-active {
            color: #171717; /* neutral-900 */
            font-weight: bold;
        }
        .gradient-bg-sections {
            background: linear-gradient(135deg, #e5e5e5 0%, #f5f5f5 50%, #e5e5e5 100%);
        }
        .subtle-hover:hover {
            transform: translateY(-2px);
            transition: transform 0.2s ease-out;
        }
        .section-title {
            font-size: 2.5rem; 
            font-weight: 700; 
            margin-bottom: 2rem; 
            text-align: center;
            background: linear-gradient(to right, #525252, #262626);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }
        html {
            scroll-behavior: smooth;
        }
        ::-webkit-scrollbar {
            width: 8px;
        }
        ::-webkit-scrollbar-track {
            background: #e5e5e5; 
        }
        ::-webkit-scrollbar-thumb {
            background: #a3a3a3; 
            border-radius: 4px;
        }
        ::-webkit-scrollbar-thumb:hover {
            background: #737373;
        }
        [x-cloak] { display: none !important; }

        /* Aspect ratio utilities for videos/iframes if not using Tailwind's aspect-ratio plugin */
        .aspect-w-16 { position: relative; padding-bottom: 56.25%; /* 16:9 */ }
        .aspect-h-9 { /* Helper class, actual height is controlled by padding-bottom on parent */ }
        .aspect-w-16 > * {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }
    </style>
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">

<!-- BEGIN: ChatGPT mobile lightbox fix -->
<style>
  :root { --header-h: 64px; } /* adjust if your fixed header changes height */

  /* Mobile-first: prevent clipped lightbox under header/notch */
  @media (max-width: 639px) {
    .modal {
      align-items: flex-start !important;
      padding-top: calc(var(--header-h) + env(safe-area-inset-top, 0px)) !important;
    }
    .modal .modal-scroll-content {
      max-height: calc(100vh - 24px - env(safe-area-inset-top, 0px));
    }
    /* If your lightbox content has internal padding, make sure it's not too tight */
    .modal .content,
    .modal .panel,
    .modal .dialog {
      padding-top: max(1rem, env(safe-area-inset-top, 0px));
    }
  }

  /* Tablet/desktop: keep centring */
  @media (min-width: 640px) {
    .modal {
      align-items: center !important;
      padding-top: 0 !important;
    }
  }

  /* Respect notches/safe areas for any "top-3" UI inside the modal (close buttons, counters, etc.) */
  @supports (top: max(0px)) {
    .modal .top-3 { top: max(0.75rem, env(safe-area-inset-top, 0px)); }
    .safe-top { top: max(0.75rem, env(safe-area-inset-top, 0px)); }
  }
</style>
<!-- END: ChatGPT mobile lightbox fix -->

</head>
<body x-data="{ currentSection: 'home' }" @set-active-section.window="currentSection = $event.detail" class="text-neutral-700">

    <header class="bg-neutral-100/80 backdrop-blur-md fixed top-0 left-0 right-0 z-50 shadow-md">
        <nav class="container mx-auto px-6 py-4 flex items-center justify-center md:justify-between">
            <a href="#home" @click="currentSection = 'home'" class="text-2xl font-bold text-neutral-700 hover:text-neutral-900 transition-colors hidden md:inline-block">madebytrosh</a>
            <div class="flex flex-wrap justify-center space-x-3 sm:space-x-4 md:space-x-6 text-sm md:text-base">
                <a href="#home" @click="currentSection = 'home'" :class="{ 'nav-active': currentSection === 'home' }" class="text-neutral-600 hover:text-neutral-900 transition-colors">Home</a>
                <a href="#recent-work" @click="currentSection = 'recent-work'" :class="{ 'nav-active': currentSection === 'recent-work' }" class="text-neutral-600 hover:text-neutral-900 transition-colors">Recent Work</a>
                <a href="#showreel" @click="currentSection = 'showreel'" :class="{ 'nav-active': currentSection === 'showreel' }" class="text-neutral-600 hover:text-neutral-900 transition-colors">Showreel</a>
                <a href="#contact" @click="currentSection = 'contact'" :class="{ 'nav-active': currentSection === 'contact' }" class="text-neutral-600 hover:text-neutral-900 transition-colors">Contact</a>
            </div>
        </nav>
    </header>

    <main class="pt-16">

        <section id="home" class="min-h-screen relative overflow-hidden flex items-center justify-center bg-black">
            <video
                src="https://player.vimeo.com/progressive_redirect/playback/1082519489/rendition/720p/file.mp4?loc=external&log_user=0&signature=fbded381af91e39effaa5de4f9b5446e6eea1628acdd8dd81e70bd6badeb8b1e"
                autoplay loop muted playsinline
                class="absolute inset-0 w-full h-full object-cover z-0">
                Your browser does not support the video tag.
            </video>
            <div class="absolute inset-0 bg-black/60 z-1"></div>
            <div class="relative z-10 text-center p-8">
                <div class="mb-8">
                    <div class="max-w-2xl md:max-w-3xl mx-auto">
                        <img src="jamestrosh.png" 
                             alt="JAMES TROSH" 
                             class="w-full h-auto object-contain"
                             onerror="this.onerror=null;this.src='https://placehold.co/900x150/transparent/FFFFFF?text=JAMES+TROSH&font=roboto';"
                        >
                    </div>
                </div>
                <p class="text-xl md:text-2xl text-white max-w-2xl mx-auto mb-12 drop-shadow-md">
                    Content producer and director
                </p>
                <a href="#recent-work" @click="currentSection = 'recent-work'"
                   class="bg-white/80 hover:bg-white text-neutral-800 font-semibold py-3 px-8 rounded-lg text-lg transition-all duration-300 ease-in-out transform hover:scale-105 subtle-hover shadow-xl backdrop-blur-sm">
                    View My Work
                </a>
            </div>
        </section>

        <section id="recent-work" class="py-16 md:py-24 bg-white" x-data="recentWork()">
            <div class="container mx-auto px-6">
                <h2 class="section-title">Recent Work</h2>

                <div class="flex flex-wrap justify-center gap-2 md:gap-3 mb-10 md:mb-12">
                    <template x-for="category in categories" :key="category">
                        <button @click="filterProjects(category)"
                                :class="{ 'bg-neutral-700 text-white': activeCategory === category, 'bg-neutral-200 hover:bg-neutral-300 text-neutral-700 hover:text-neutral-800': activeCategory !== category }"
                                class="py-2 px-4 rounded-md text-sm font-medium transition-colors subtle-hover">
                            <span x-text="category"></span>
                        </button>
                    </template>
                </div>

                <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8 md:gap-10">
                    <template x-for="project in visibleProjects" :key="project.id">
                        <div @click="openProjectModal(project)"
                             class="bg-white rounded-lg shadow-lg overflow-hidden cursor-pointer transition-all duration-300 hover:shadow-neutral-400/50 hover:ring-2 hover:ring-neutral-400 subtle-hover group border border-neutral-200">
                            <div class="aspect-w-16 aspect-h-9 bg-neutral-200">
                                <img :src="project.keyImage" :alt="project.title" class="w-full h-full object-cover transition-transform duration-300 group-hover:scale-105" onerror="this.onerror=null;this.src='https://placehold.co/600x400/eeeeee/aaaaaa?text=Image+Not+Found';">
                            </div>
                            <div class="p-5 md:p-6">
                                <div class="flex flex-wrap gap-2 mb-2">
                                    <template x-for="cat in project.categories" :key="cat">
                                        <span class="inline-block bg-neutral-200 text-neutral-600 text-xs font-semibold px-2 py-1 rounded-full" x-text="cat"></span>
                                    </template>
                                </div>
                                <h3 class="text-xl md:text-2xl font-semibold text-neutral-800 mb-1" x-text="project.title"></h3>
                                <p class="text-sm text-neutral-500" x-text="project.subtitle"></p>
                            </div>
                        </div>
                    </template>
                    <div x-show="visibleProjects.length === 0 && _allFilteredProjectsCache.length > 0" class="col-span-full text-center text-neutral-500 py-10">
                        No projects found for this category.
                    </div>
                     <div x-show="allProjects.length === 0" class="col-span-full text-center text-neutral-500 py-10">
                        Projects coming soon!
                    </div>
                </div>

                <div x-show="showMoreButtonVisible" class="text-center mt-12">
                    <button @click="showMoreProjects()"
                            class="bg-neutral-600 hover:bg-neutral-700 text-white font-semibold py-2 px-6 rounded-lg transition-colors subtle-hover">
                        Show More
                    </button>
                </div>

            </div>
        </section>

        <section id="showreel" class="py-16 md:py-24 bg-neutral-200" x-data="showreelPlayer()">
            <div class="container mx-auto px-6">
                <h2 class="section-title">Showreels</h2>
                <div class="max-w-4xl mx-auto">
                    <div class="aspect-w-16 aspect-h-9 mb-6 bg-black rounded-lg shadow-xl overflow-hidden max-h-[70vh]">
                        <video x-ref="showreelVideoPlayer" controls :src="currentShowreel.videoUrl" :poster="currentShowreel.posterUrl || 'loading.jpg'" class="w-full h-full object-contain" x-show="currentShowreel.videoUrl">
                            Your browser does not support the video tag.
                        </video>
                         <div x-show="!currentShowreel.videoUrl" class="w-full h-full flex items-center justify-center text-neutral-500 bg-neutral-800">Select a showreel to play.</div>
                    </div>
                    <div class="flex flex-wrap justify-center gap-3 md:gap-4">
                        <template x-for="(reel, index) in availableShowreels" :key="index">
                            <button @click="playShowreel(index)"
                                    :class="{ 'bg-neutral-700 text-white': currentShowreelIndex === index, 'bg-neutral-300 hover:bg-neutral-400 text-neutral-800 hover:text-neutral-900': currentShowreelIndex !== index }"
                                    class="py-2 px-4 rounded-md text-sm md:text-base font-medium transition-colors subtle-hover">
                                <span x-text="reel.title"></span>
                            </button>
                        </template>
                    </div>
                </div>
            </div>
        </section>

        <section id="contact" class="py-16 md:py-24 gradient-bg-sections">
            <div class="container mx-auto px-6">
                <h2 class="section-title">Get In Touch</h2>
                <div class="max-w-2xl mx-auto bg-white/80 backdrop-blur-sm p-8 md:p-10 rounded-xl shadow-xl border border-neutral-300">
                    <p class="text-center text-neutral-600 mb-8 text-lg">
                        Have a project in mind or just want to say hello? Contact me below.
                    </p>
                    <form id="contactForm" action="https://formsubmit.co/5f60e46d3ec138abce35fe1386873ffd" method="POST" class="space-y-6">
                        <input type="hidden" name="_subject" value="New submission from James Trosh Portfolio!">
                        <input type="hidden" name="_next" :value="window.location.origin + window.location.pathname + '#contact'">
                        <input type="hidden" name="_captcha" value="true">
                        <div>
                            <label for="name" class="block text-sm font-medium text-neutral-700">Full Name</label>
                            <input type="text" name="name" id="name" autocomplete="name" required
                                   class="mt-1 block w-full bg-neutral-50 border border-neutral-300 rounded-md shadow-sm py-2 px-3 text-neutral-800 focus:outline-none focus:ring-neutral-500 focus:border-neutral-500 sm:text-sm">
                        </div>
                        <div>
                            <label for="email" class="block text-sm font-medium text-neutral-700">Email Address</label>
                            <input type="email" name="email" id="email" autocomplete="email" required
                                   class="mt-1 block w-full bg-neutral-50 border border-neutral-300 rounded-md shadow-sm py-2 px-3 text-neutral-800 focus:outline-none focus:ring-neutral-500 focus:border-neutral-500 sm:text-sm">
                        </div>
                        <div>
                            <label for="message" class="block text-sm font-medium text-neutral-700">Message</label>
                            <textarea id="message" name="message" rows="4" required
                                      class="mt-1 block w-full bg-neutral-50 border border-neutral-300 rounded-md shadow-sm py-2 px-3 text-neutral-800 focus:outline-none focus:ring-neutral-500 focus:border-neutral-500 sm:text-sm"></textarea>
                        </div>
                        <div>
                            <button type="submit"
                                    class="w-full flex justify-center py-3 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-neutral-700 hover:bg-neutral-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-neutral-100 focus:ring-neutral-500 transition-colors subtle-hover">
                                Send Message
                            </button>
                        </div>
                        <div id="formStatus" class="mt-4 text-center text-sm"></div>
                    </form>

                    <div class="mt-10 text-center">
                        <p class="text-neutral-700 mb-3">Or follow me on social media:</p>
                        <div class="flex justify-center space-x-6">
                            <a href="https://www.instagram.com/madebytrosh/" target="_blank" rel="noopener noreferrer" class="text-neutral-500 hover:text-neutral-800 transition-colors" aria-label="Instagram">
                                <svg class="w-7 h-7" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948s.014 3.667.072 4.947c.2 4.359 2.618 6.78 6.98 6.98 1.281.059 1.689.073 4.948.073s3.667-.014 4.947-.072c4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.947s-.014-3.667-.072-4.947c-.196-4.354-2.617-6.78-6.979-6.98-1.28-.059-1.69-.073-4.948-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4s1.791-4 4-4 4 1.79 4 4-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/></svg>
                            </a>
                            <a href="https://www.linkedin.com/in/troshy/" target="_blank" rel="noopener noreferrer" class="text-neutral-500 hover:text-neutral-800 transition-colors" aria-label="LinkedIn">
                                <svg class="w-7 h-7" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z"/></svg>
                            </a>
                            <a href="https://www.youtube.com/@troshy" target="_blank" rel="noopener noreferrer" class="text-neutral-500 hover:text-neutral-800 transition-colors" aria-label="YouTube"> <svg class="w-7 h-7" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg>
                            </a>
                            <a href="https://www.tiktok.com/@troshy" target="_blank" rel="noopener noreferrer" class="text-neutral-500 hover:text-neutral-800 transition-colors" aria-label="TikTok">
                                <svg class="w-7 h-7" fill="currentColor" viewBox="0 0 448 512" aria-hidden="true"><path d="M448 209.9a210.1 210.1 0 0 1 -122.8-39.3V349.4A162.6 162.6 0 1 1 185 188.3V278.2a74.6 74.6 0 1 0 52.2 71.2V0l88 0a121.2 121.2 0 0 0 1.9 22.2h0A122.2 122.2 0 0 0 381 102.4a121.4 121.4 0 0 0 67 20.1z"/></svg>
                            </a>
                        </div>
                    </div>
                </div>
            </div>
        </section>
    </main>

    <div x-show="$store.app.openModal"
         x-cloak
         @keydown.escape.window="$store.app.openModal = false"
         x-data="projectModal()" 
         class="fixed inset-0 bg-neutral-900/70 backdrop-blur-sm flex items-center justify-center p-4 z-[100] modal">

        <div @click.away="$store.app.openModal = false" 
             class="relative bg-white rounded-lg shadow-2xl max-w-3xl w-full border border-neutral-300 flex flex-col group"
             style="max-height: 90vh;"
             x-transition:enter="ease-out duration-300" x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
             x-transition:leave="ease-in duration-200" x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100" x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">

            <button @click="$store.app.openModal = false" 
                    class="absolute top-3 right-3 text-neutral-500 hover:text-neutral-800 transition-colors z-30 
                           bg-white/70 hover:bg-white/90 backdrop-blur-sm rounded-full p-1" 
                    aria-label="Close modal">
                <svg class="w-6 h-6 sm:w-7 sm:h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>
            </button>

            <div class="overflow-y-auto flex-grow modal-scroll-content">
                <template x-if="$store.app.currentProject">
                    <div class="text-neutral-700">
                        <div class="bg-neutral-100 relative">
                            <template x-if="$store.app.currentProject.media && $store.app.currentProject.media.length > 0">
                                <div>
                                    <template x-for="(mediaItem, index) in $store.app.currentProject.media" :key="mediaItem.src + '-' + index">
                                        <div x-show="$store.app.currentMediaIndex === index">
                                            <div class="max-h-[60vh] flex items-center justify-center bg-black">
                                                <template x-if="mediaItem.type === 'video' || mediaItem.type === 'loopingvideo'">
                                                    <video
                                                        :data-media-index="index" :controls="mediaItem.type === 'video'"
                                                        :autoplay="mediaItem.type === 'loopingvideo'"
                                                        :loop="mediaItem.type === 'loopingvideo'"
                                                        :muted="mediaItem.type === 'loopingvideo'"
                                                        :src="mediaItem.src"
                                                        :poster="mediaItem.posterUrl || 'loading.jpg'"
                                                        class="w-auto h-auto max-w-full max-h-[60vh] object-contain"
                                                        playsinline> Your browser does not support videos.
                                                    </video>
                                                </template>
                                                <template x-if="mediaItem.type === 'image'">
                                                    <img :src="mediaItem.src" :alt="mediaItem.description || $store.app.currentProject.title" class="w-auto h-auto max-w-full max-h-[60vh] object-contain" onerror="this.onerror=null;this.src='https://placehold.co/1200x800/eeeeee/aaaaaa?text=Image+Not+Found';">
                                                </template>
                                                <template x-if="mediaItem.type === 'youtube'">
                                                    <div class="aspect-w-16 aspect-h-9 w-full bg-black">
                                                        <div x-show="!$store.device.isMobileOrTabletView || (mediaItem.src && !mediaItem.src.includes('PzLIDonbfow'))" class="w-full h-full"> <iframe
                                                                :data-media-index="index"
                                                                class="w-full h-full"
                                                                :src="`https://www.youtube.com/embed/${mediaItem.src}?enablejsapi=1&origin=${window.location.origin}&autoplay=0&widgetid=${index+1}`"
                                                                frameborder="0"
                                                                allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
                                                                allowfullscreen
                                                                title="YouTube video player">
                                                            </iframe>
                                                        </div>
                                                         <div x-show="$store.device.isMobileOrTabletView && mediaItem.src && mediaItem.src.includes('PzLIDonbfow')" 
                                                             class="w-full h-full flex flex-col items-center justify-center p-4 sm:p-6 text-center bg-neutral-200">
                                                            <p class="mb-4 text-neutral-700 text-sm sm:text-base">
                                                                On mobile? 360º video content works best when viewed in the YouTube app.
                                                            </p>
                                                            <a :href="`https://www.youtube.com/watch?v=${mediaItem.src}`"
                                                               target="_blank" rel="noopener noreferrer"
                                                               class="inline-block bg-red-500 hover:bg-red-600 text-white font-semibold py-2.5 px-5 rounded-md text-sm sm:text-base transition-colors subtle-hover shadow-md">
                                                                Tap here to open the YouTube app
                                                            </a>
                                                        </div>
                                                    </div>
                                                </template>
                                            </div>
<div x-show="mediaItem.description" class="p-3 bg-neutral-100 text-center text-sm text-neutral-700 font-medium border-t border-neutral-200">
    <p x-text="mediaItem.description"></p>
</div>
                                        </div>
                                    </template>
                                    
                                    <!-- SLIDE COUNTER -->
                                    <div x-show="$store.app.currentProject.media.length > 1" 
                                         class="absolute top-3 left-3 z-10 bg-black/50 text-white text-xs font-medium px-2 py-1 rounded-md"
                                         aria-hidden="true">
                                        <span x-text="$store.app.currentMediaIndex + 1"></span> / <span x-text="$store.app.currentProject.media.length"></span>
                                    </div>

                                    <div x-show="$store.app.currentProject.media.length > 1" class="absolute inset-0 flex items-center justify-between p-2 pointer-events-none z-10">
                                        <button @click="$store.app.currentMediaIndex = ($store.app.currentMediaIndex - 1 + $store.app.currentProject.media.length) % $store.app.currentProject.media.length"
                                                class="bg-black/50 md:bg-black md:opacity-30 md:group-hover:opacity-50 hover:bg-neutral-700 md:hover:opacity-100 text-white p-3 rounded-full transition-all duration-200 ease-in-out pointer-events-auto scale-100 group-hover:scale-125" aria-label="Previous media">
                                            <svg class="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path></svg>
                                        </button>
                                        <button @click="$store.app.currentMediaIndex = ($store.app.currentMediaIndex + 1) % $store.app.currentProject.media.length"
                                                class="bg-black/50 md:bg-black md:opacity-30 md:group-hover:opacity-50 hover:bg-neutral-700 md:hover:opacity-100 text-white p-3 rounded-full transition-all duration-200 ease-in-out pointer-events-auto scale-100 group-hover:scale-125" aria-label="Next media">
                                            <svg class="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg>
                                        </button>
                                    </div>
                                </div>
                            </template>
                            <div x-show="!$store.app.currentProject.media || $store.app.currentProject.media.length === 0" class="aspect-w-16 aspect-h-9 flex items-center justify-center text-neutral-500 p-8">
                                No media available for this project.
                            </div>
                        </div>
                        <div class="p-6 md:p-8">
                            <h3 class="text-2xl md:text-3xl font-bold text-neutral-800 mb-2" x-text="$store.app.currentProject.title"></h3>
                            <div class="flex flex-wrap gap-2 mb-4">
                                 <template x-for="cat in $store.app.currentProject.categories" :key="cat">
                                    <span class="inline-block bg-neutral-200 text-neutral-600 text-xs font-semibold px-2 py-1 rounded-full" x-text="cat"></span>
                                </template>
                            </div>
                            <p class="text-neutral-600 mb-4 leading-relaxed prose prose-sm max-w-none" x-html="$store.app.currentProject.description"></p>
                        </div>
                    </div>
                </template>
                <template x-if="!$store.app.currentProject && $store.app.openModal">
                    <div class="p-8 text-center text-neutral-500">Loading project details...</div>
                </template>
            </div>

        </div>
    </div>

    <footer class="py-8 bg-neutral-200 text-center border-t border-neutral-300">
        <p class="text-neutral-500 text-sm">© <span x-text="new Date().getFullYear()"></span> James Trosh. All rights reserved.</p>
        <p class="text-xs text-neutral-400 mt-1">James Trosh - London based Content Producer and Director.</p>
    </footer>

<script>

    // --- EASILY EDITABLE CONTENT BELOW ---
    const siteShowreels = [
        { title: "Branded Content Agency Showreel", videoUrl: "https://player.vimeo.com/progressive_redirect/playback/872569195/rendition/1080p/file.mp4?loc=external&log_user=0&signature=ee0666c4d86f49f83ce56de752f6d60a0c8cd5ccf3aa6f5b856a692d94f7d21e", posterUrl: "videoposters/showreel.jpg" },
    ];
    const siteProjects = [ {
            id: "proj1", categories: ["Documentary"], title: "Finding Home", subtitle: "Selected as a 'Top 8' film in the Straight 8 2025 film competition",
            keyImage: "thumbs/findinghome2.jpg",
            description: "<strong>Finding Home</strong> was a film made for the 2025 <em>'Straight 8'</em> film competition, where filmmakers create a short film on a single roll of Super 8mm film with no retakes or post-production. The documentary captures the unbelievable true story of <strong>Monica Macias</strong>, a West African woman who was raised in North Korea and has travelled the world in search of her true identity.<br><br>The film was selected as one of the <strong>Top 8 films</strong> from 150 entries submitted to <em>Straight 8</em> from across the globe. It premiered in May 2025 at the Straight 8 showcase during the <strong>Cannes Film Festival</strong>, and had it's UK premiere at the <strong>BFI London IMAX</strong>, the UK’s largest cinema screen.<br><br>The documentary was shot on a <strong>single roll of Kodak 200T Super 8mm film</strong>, using a <strong>Canon 310XL</strong> camera from the 1970s.<br><br><strong>Directed and Produced by:</strong> James Trosh<br><strong>Director of Photography:</strong> Liam Southall<br><strong>Original Music Composition:</strong> Joe Garvey<br><strong>Production Assistant:</strong> Victor Bennett",
            media: [
                { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1100606781/rendition/1080p/file.mp4?loc=external&log_user=0&signature=15b4c894327ab18b142680427b9a125a7b8753a30c0eac94a76963c973b8494d", posterUrl: "videoposters/monica.jpg", description: "‘Finding Home’ - Directors Cut.  Adapted from a Straight 8 film." },
                { type: "image", src: "staticimages/findinghome2.jpg", description: "Selected as a 'Top 8' finalist in the Straight 8 2025 film competition, and premiered during the Cannes Film Festival." },
                { type: "image", src: "staticimages/findinghome3.jpg", description: "Behind the scenes during the shoot of 'Finding Home'." }
            ]
        },
        {
            id: "proj2", categories: ["Experimental"], title: "Toy Robot in Space!", subtitle: "A viral video filmed at the edge of space",
            keyImage: "thumbs/robot.jpg",
            description: "My university project that created an online video trend, kicking off the phenomenon of launching objects to the edge of space with a GoPro and a weather balloon.<br><br>I came up with the idea and captured this footage for my final year graduation project, and it quickly gained global attention.  The project was featured on CBS '60 Minutes', a global advertising campaign for GoPro, Cartoon Network's Adult Swim, CNN, Discovery Channel, screens across the London Underground, The Daily Mail, The Guardian, The Washington Post and more.  It has since been viewed over <strong>1.8 million times</strong> on YouTube.<br><br>The robot and rig flew a height of over 95,000 feet (around 30,000 metres) to reach the limits of the earth's atmosphere and film the blackness of space, before the pressure popped the weather balloon and a parachute carried it back down to earth.<br><br>We eventually found the robot and camera in a field 11 miles away using a mini GPS tracker.",
            media: [
                { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082543661/rendition/720p/file.mp4?loc=external&log_user=0&signature=f8ce4e47d84d77c83144d710221bc17261fedda16111423c1fc9678c15ae5bb9", posterUrl: "videoposters/robot.jpg", description: "The full edit of Toy Robot in Space!" },
                { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082564692/rendition/1080p/file.mp4?loc=external&log_user=0&signature=8e18c69362d0ef7901a400f79a2a4d99dbae43e937171884a62d7468d73ef85e", posterUrl: "videoposters/60minutes.jpg", description: "GoPro CEO Nick Woodman speaks to Anderson Cooper about 'Toy Robot in Space!'" },
                { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082567283/rendition/720p/file.mp4?loc=external&log_user=0&signature=accee3fca3b2fb4b43c22e26f153ef178409bedfdf708102a5f3083bf993d4d3", posterUrl: "videoposters/discovery.jpg", description: "A clip from Discovery Channel's 'You Have Been Warned' (UK)/'Outrageous Acts Of Science' (USA) broadcast in over 150 countries, explaining the science behind filming in near-space using a helium filled weather balloon." },
                { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082568885/rendition/1080p/file.mp4?loc=external&log_user=0&signature=325c992a1a6747d062c1814a176e0dd948ee3609d0dca344d82b078789acc32f", posterUrl: "videoposters/gopro.jpg", description: "'Toy Robot in Space!' was featured in an advertising campaign for the launch of the GoPro HD Hero 2.  The commercial was released internationally across TV, print, cinema, billboard, in-store and more." }
            ]
        },
                
                {
            id: "proj28", categories: ["Live streaming"], title: "Format Webinar", subtitle: "How can sports brands maximise the potential of social media?",
            keyImage: "thumbs/format.jpg",
            description: "I was asked to produce the live stream and edit highlights of Format's webinar for social media professionals within the sports industry, featuring ex-England International rugby star James Haskell and the team from The Good, The Bad & The Rugby podcast.  <br><br>The webinar broadcast a live discussion on how the sports industry can maximise the potential of social media, and a demonstration of how the Format asset creation tool can help sports brands boost engagement online.", media: [
                { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1083017012/rendition/720p/file.mp4?loc=external&log_user=0&signature=03e3d206cb80037e6c1b6bc835f567136dc62e07bc114c335bb43521b9a1511d", posterUrl: "videoposters/format2.jpg", description: "James Haskell demonstrates how to use Format" },
                { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1083016962/rendition/720p/file.mp4?loc=external&log_user=0&signature=1ebbbc3d4d3fc8f894425a16d89fa4d21f61d3bc4aa0c3203d2510b9fcd75275", posterUrl: "videoposters/format1.jpg", description: "How Format can make your social teams more efficient" },

            ]
        },
        
        {
            id: "proj4", categories: ["Social campaign"], title: "Currensea Pro", subtitle: "Helping to launch a brand new travel debit card",
            keyImage: "thumbs/currensea.jpg",
            description: "How do pro travellers save money when spending abroad? ✈️<br><br>I edited this explainer film for Currensea Pro, showcasing how the FX debit card fits into the everyday life of a frequent flyer.<br><br>Producer: Liam Southall<br>Editor: James Trosh<br>Agency: PickledEgg<br>Director of Photography: Konstantin Kovalev<br>Motion Graphics: Toby Dale", media: [
                { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1075392383/rendition/1080p/file.mp4?loc=external&log_user=0&signature=489706d9072bc0f4c641fe0c498c2ab82b8ecd5fab7157504d120b5cfbdd7d1d", posterUrl: "videoposters/currensea.jpg", description: "Explainer video for the Currensea Pro travel card" },
            ]
        },
         {
            id: "proj5", categories: ["Live streaming"], title: "Red Bull Racing", subtitle: "Virtual events streamed live from RBR's iconic Formula One factory",
            keyImage: "thumbs/rbr.jpg",
            description: "I work with the Red Bull Racing Formula 1 team to produce interactive live streams from their factory in Milton Keynes, broadcasting to employees, partners and fans all over the world.", media: [
                { type: "image", src: "staticimages/rbr2.jpg", description: "Innovation Days powered by Zoom - An annual event featuring keynotes, Q+As and panel sessions from Red Bull Racing's management team and technical partners.  Broadcast live via Zoom Events, featuring virtual and in-person speakers presenting to an audience watching at home and inside the factory." },
                { type: "image", src: "staticimages/rbr1.jpg", description: "An Evening With Red Bull Racing - I produced a live-streamed season review and charity auction with the Red Bull Racing drivers, including a virtual Q+A with fans.  Presented by Sky Sports F1 presenter, Simon Lazenby." },
                { type: "image", src: "staticimages/rbr3.jpg", description: "'Pen to Pit Lane' student lectures - Live lectures on motorsports engineering from Red Bull Racing employees to students at universities in the UK, Czech Republic and Slovakia." }
            ]
        },
        {
            id: "proj3", categories: ["Social campaign"], title: "Randies Underwear", subtitle: "A social campaign for the world's most comfortable men's underwear",
            keyImage: "thumbs/randies.jpg",
            description: "I edited this Spring 2025 social media campaign for Randies underwear, delivering over 40 different assets to help bring this premium men's underwear brand to a wider audience.<br><br>Producer: Liam Southall<br>Editor: James Trosh<br>Agency: PickledEgg",
            media: [
                { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082571875/rendition/1080p/file.mp4?loc=external&log_user=0&signature=05301d36acfe7d9f9056dd735d43de17b6c22e90ce0ad39f26b75d99c1208c30", posterUrl: "videoposters/randiesmashup.jpg",  description: "Randies brand lookbook" },
                { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082571521/rendition/1080p/file.mp4?loc=external&log_user=0&signature=d17d2057f52cf1f8f4573b8befca752baadf822227f272eed278d8b2c12ae601", posterUrl: "videoposters/randiesbts.jpg", description: "Randies photoshoot BTS" },
                { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082571698/rendition/720p/file.mp4?loc=external&log_user=0&signature=71cc14d7748264a82cf276ecf7cf6ceaba6a981269b8b3510b861c9c56b8aae6", posterUrl: "videoposters/randiesmoody.jpg", description: "Randies moody photoshoot" }
            ]
        },

                        {
            id: "proj29", categories: ["Podcasting"], title: "High Net Purpose Podcast", subtitle: "A podcast that invites industry leaders to share their purpose",
            keyImage: "thumbs/hnp.jpg",
            description: "I provided filming and production support for Islandbridge Capital's ‘High Net Purpose’ podcast, a show that explores how global leaders and entrepreneurs bring purpose to what they do.<br><br>I worked on shows with fascinating thought leaders who are helping to impact the world in a positive way, including political and humanitarian heavyweight David Miliband, and vegan chefs and authors The Happy Pear.", media: [
                { type: "image", src: "staticimages/hnp1.jpg", description: "Chief executive officer of the International Rescue Committee and former British Foreign Secretary, David Miliband." },
                { type: "image", src: "staticimages/hnp2.jpg", description: "Irish chefs and plant-based diet advocates, The Happy Pear." }
                ]
        },
                        {
            id: "proj7", categories: ["Sports content"], title: "Maddie Hinch", subtitle: "Thumb-stopping hockey challenges with an Olympic gold medallist",
            keyImage: "thumbs/maddie.jpg",
            description: "I was asked to develop a series of hockey challenge videos for Team GB Olympic Gold medallist Maddie Hinch, that tested her goalkeeping skills. <br><br>The challenges included Maddie saving shots while wearing vision-warping rave glasses, a drill where she had to focus solely on saving hockey balls while ignoring any other distraction fired at her, and a race where Maddie had to put on her goalkeeping gear as fast as possible while blindfolded.", media: [
            { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082597459/rendition/1080p/file.mp4?loc=external&log_user=0&signature=8bce498a91581485db6e2c1fbaa5a12938534c2b08b34746dcf7ed948e745ad7", posterUrl: "videoposters/kitracechallenge.jpg",  description: "Kit Race Challenge" },
                { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082597612/rendition/1080p/file.mp4?loc=external&log_user=0&signature=d44c172581576ac642323f9157fdd2c3fdd4dbd4e4a8cfb5f49dd02a3e4b81e8", posterUrl: "videoposters/ravechallenge.jpg", description: "Rave Glasses Challenge" }
                ]
        },
        
                {
            id: "proj8", categories: ["Sports content"], title: "Monster x Spurs - No Rules FIFA", subtitle: "Playing FIFA on the largest stadium screens in Western Europe",
            keyImage: "thumbs/fanvpro.jpg",
            description: "What happens when you take four Premier League football players, pair them against four lucky competition winners, and play a FIFA tournament on the largest stadium screens in Western Europe?<br><br>I was asked to create the ‘Fan V Pro’ YouTube series for Tottenham Hotspur and Monster Energy, filming top players Lucas Moura, Emerson Royal, Ryan Sessegnon, and Joe Rodon play ‘No Rules’ FIFA22 against diehard Spurs fans on the giant screens inside the Tottenham Hotspur Stadium.<br><br>I produced and directed the edits for the Spurs YouTube channel of each match, complete with epic stadium drone footage and live commentary, capturing the lucky fans competing against their heroes on some of the biggest TV screens in football video game history.<br><br>Produced & Directed: James Trosh<br>Director of Photography: Liam Southall<br>Additional Camera: Tim Fernandez<br>Drone: Luke de la Nougerede<br>Sound Recordist: Alex Hanton-Rhys", media: [
                { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082601676/rendition/1080p/file.mp4?loc=external&log_user=0&signature=348f7cd6ec8f53f8de86ffd0ba3350ec75cfddf64babb1ee2ca3bb754f737455", posterUrl: "videoposters/monster1.jpg", description: "Ep 1 - Lucas Moura and Emerson Royal" },
                { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082602025/rendition/1080p/file.mp4?loc=external&log_user=0&signature=4635241267f2c4380b81fd28421d7f716dba505ed3bd6c1c2367938d75058ee0", posterUrl: "videoposters/monster2.jpg", description: "Ep 2 - Ryan Sessegnon and Joe Rodon" }
            ]
        },
        {
            id: "proj6", categories: ["Sports content"], title: "Red Bull Athlete Content", subtitle: "Producing creative video content with top athletes",
            keyImage: "thumbs/rbathlete.jpg",
            description: "I help Red Bull activate their diverse roster of athletes, with creative video content produced for multiple social media platforms.", media: [
               { type: "loopingvideo", src: "https://player.vimeo.com/progressive_redirect/playback/1082584850/rendition/720p/file.mp4?loc=external&log_user=0&signature=075f4f88b4c487a2dd84ed283910888a9a0998450fc1afd824c03d4a2863399a",  description: "I created animated GIFs and stickers with Red Bull's UK athlete roster, featuring Liverpool footballer Trent Alexander-Arnold, England rugby player Jack Nowell and more." },
                { type: "loopingvideo", src: "https://player.vimeo.com/progressive_redirect/playback/1082588267/rendition/720p/file.mp4?loc=external&log_user=0&signature=590613130104b943e81653d6bd1e4594ef1e91aa2e7f3965840d43294f15ff7a", description: "To help promote Red Bull's 'Project Pro' campaign, I created a series of authentic 'day in the life' vlog-style films from the point of view of six professional athletes.  The edits included England cricket captain Ben Stokes, top UK climber Shauna Coxsey, Winter Olympic medallist Billy Morgan, Ironman World Champion Lucy Charles-Barclay, and more." },
                { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082589066/rendition/720p/file.mp4?loc=external&log_user=0&signature=1e751e4b4d4e0b05bdad2c2f3f0d801e0c927507e2f9da7120eb6a8a84d37bbc", posterUrl: "videoposters/maxverstappen.jpg", description: "I create fun sport-specific challenges for social media featuring Red Bull's sponsored athletes, including this edit with Formula One World Chamption Max Verstappen." },
                { type: "loopingvideo", src: "https://player.vimeo.com/progressive_redirect/playback/1082591044/rendition/540p/file.mp4?loc=external&log_user=0&signature=49b0ef5112734cbac55fdcc422fe6eb302686e161e91a4aacd2d686d357682b8", description: "I create content that engages sports fans, with platform native social media edits." }
            ]
        },


        {
            id: "proj9", categories: ["Sports content"], title: "eSkootr Championship", subtitle: "Launching a new motorsport on social media",
            keyImage: "thumbs/esc.jpg",
            description: "How do you launch a brand new motorsport to the world on social media before any racing has taken place?<br><br>I was asked to help launch the eSkootr Championship on Instagram and TikTok, attending the test event at Circuit Paul Ricard in France to film and build a library of social first content of the high-performance electric scooters in action.", media: [
            
             { type: "image", src: "staticimages/esc-lets-go.gif", description: "I filmed and edited a suite of multilingual animated GIFs of the eSC athletes, to be used by fans and on official channels." },
                { type: "loopingvideo", src: "https://player.vimeo.com/progressive_redirect/playback/1082614424/rendition/1080p/file.mp4?loc=external&log_user=0&signature=268b8e52203867c2c40ea1469c17206a462f063b4c7dd9d446aabda01d9d45d9", description: "I created an interactive game for the eSC Instagram Stories to demonstrate the skills involved in racing in the eSkootr Championships, to promote awareness of the new rider programme." },
                { type: "loopingvideo", src: "https://player.vimeo.com/progressive_redirect/playback/1082620954/rendition/1080p/file.mp4?loc=external&log_user=0&signature=7bd6931b08a9bbe2fcca9509cb290c095f162801b7481cba0942389af79d9541", description: "I created a library of behind the scenes content of the S1-X eSkootr in action to help build the eSC social audience before racing began." }
            ]
        },
        {
            id: "proj10", categories: ["Sports content"], title: "Monster x Premier League", subtitle: "Activating Monster's sponsorship of major EPL clubs",
            keyImage: "thumbs/monsterepl.jpg",
            description: "I work with Monster Energy to create fan centric video content featuring their growing sponsorship portfolio of Premier League football clubs.", media: [
                      { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082878097/rendition/720p/file.mp4?loc=external&log_user=0&signature=b5b3a07ffc49ccc504b8170b113a2a1706a68603c17a2ee0d28d843e17b83805", posterUrl: "videoposters/monsterspurs.jpg", description: "Tottenham POV Fan Cam - The ultimate pre-match experience, from the point of view of three lucky competition winners.  The content received 443k views on Tottenham's official Instagram." },
                            { type: "loopingvideo", src: "https://player.vimeo.com/progressive_redirect/playback/1082879714/rendition/720p/file.mp4?loc=external&log_user=0&signature=1b35baa84bb927919237a8930dd8aaab5bb14c8cd1c332c542aaf3f06ec4e3e2", description: "#ToeTapChallenge - A social media challenge set by football influencers F2Freestylers, and completed by players from eight Premier League clubs, as well as fans from around the world.  I created the video content to be released on the official club channels, generating over 3 million combined organic views." },
                             { type: "loopingvideo", src: "https://player.vimeo.com/progressive_redirect/playback/1082879931/rendition/720p/file.mp4?loc=external&log_user=0&signature=d7f568b5d97c693840b9188e7dca40daf3afc366aea7b3d9aa2a365d499332d7", description: "HydroSport Hot Seat - Quick-fire Q+A interviews with current and former players of six clubs including Brighton, Everton, Tottenham and West Ham.  The content was filmed remotely during COVID and released on the official club channels, receiving over 1.5 million organic views across YouTube, Twitter, Facebook and Instagram." }
            
            
            ]
        },
        {
            id: "proj11", categories: ["Live streaming", "Sports content"], title: "Ross Edgley's Great British Swim", subtitle: "Broadcasting Ross's epic swim to the world",
            keyImage: "thumbs/ross.jpg",
            description: "In November 2018, Ross Edgley became the first person to swim around the entire coast of mainland Great Britain, in a brutal 157-day endurance challenge.<br><br>I provided production support for the weekly vlogs on YouTube, filmed at sea and viewed by an audience of millions, and produced the live stream of Ross's final swim as he completed the challenge alongside hundreds of fans who came to swim with him for his return back into Margate Harbour.<br><br>The live stream was an early pioneer of remote live production, with four remote cameras transmitting simultaneously over bonded 4G sim cards, including live coverage from a drone and a camera located onboard the support boat 3km out at sea. <br><br>The camera feeds were received by me and my crew live at Red Bull's HQ in Salzburg, Austria to be broadcast online to over 400k viewers watching live on YouTube and Red Bull TV. <br><br>In addition to the live coverage, I produced a variety of VTs with highlights from Ross's five month challenge to be inserted into the stream, alongside graphical overlays featuring real-time comments from viewers watching live, live stats and location data, and telemetry from Ross during his final swim.", media: [
{ type: "loopingvideo", src: "https://player.vimeo.com/progressive_redirect/playback/1082882608/rendition/1080p/file.mp4?loc=external&log_user=0&signature=5e71387ee1cd0a697c8251de896ccdf058b49d356fca2732541b23238945a573", description: "Highlights from the interactive live stream of Ross's final swim back to Margate, with multiple remote cameras broadcasting from land and sea, live telemetry and real-time comments pulled from social media." }
]
        },
                {
            id: "proj19", categories: ["Live streaming", "Music content"], title: "Red Bull Music Studios live", subtitle: "Can Toddla T remix a track in less than 90 minutes?",
            keyImage: "thumbs/toddla.jpg",
            description: "I produced the monthly multi-camera live broadcasts of Red Bull Music Studios Live, a real-time music production show hosted by BBC Radio 1 DJ and producer Toddla T.<br><br>Each month, Toddla T teamed up with different artists such as Swindle, Conducta, Alicai Harley, Kamakaze, TQD, and Shy One, to remix a track live from the Red Bull Studio in London within 90 minutes. <br><br>The full creative process was streamed across YouTube, Facebook, and Periscope, with viewers encouraged to vote, comment, and submit ideas in real time to help shape the final track.", media: [
             { type: "loopingvideo", src: "https://player.vimeo.com/progressive_redirect/playback/1082888037/rendition/1080p/file.mp4?loc=external&log_user=0&signature=de3af049a2ae479833ca9c802e7e6a60e1bd35ced5336a4ece174f2b2e2b0469", description: "Toddla T teams up with a different artist each month to remix a track live from the Red Bull Studio in London, in less than 90 minutes." }]
        },

        {
            id: "proj13", categories: ["Sports content"], title: "Exeter Chiefs - Animated GIFs", subtitle: "High quality animated GIFs of the rugby union team",
            keyImage: "thumbs/exeter.jpg",
            description: "I worked with rugby union club Exeter Chiefs to produce a suite of high-quality GIFs and stickers featuring their entire team. The GIFs were widely shared by fans across multiple social platforms, with the player stickers collectively receiving over 25 million views.", media: [{ type: "loopingvideo", src: "https://player.vimeo.com/progressive_redirect/playback/1082913061/rendition/720p/file.mp4?loc=external&log_user=0&signature=e8cd2ae187c1c6820c2bf8bcee13ccecc40c06c1b9dab829cc660da86a32d078", description: "A selection of the popular rugby themed GIFs" }]
        },
        {
            id: "proj14", categories: ["Sports content"], title: "Red Bull Event Content", subtitle: "Impactful highlight edits of Red Bull's unique sporting events",
            keyImage: "thumbs/rbevents.jpg",
            description: "I create impactful highlight edits of Red Bull’s unique sporting event concepts for social media, and capture footage for distribution to international broadcasters and news journalists.", media: [
            { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082916899/rendition/1080p/file.mp4?loc=external&log_user=0&signature=fd75a2289c06a0de81c06bdf783af3522769fe897230a72e0807388366234d26", posterUrl: "videoposters/driftshifters.jpg", description: "Red Bull Drift Shifters was a drifting event like no other - featuring the world’s best drifters on a custom track rigged with high-tech speed and proximity sensors in the streets of Liverpool. I produced quick-turnaround event highlights for YouTube and social media, as well as a newsreel for distribution to international and local media outlets." },
            { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082916975/rendition/720p/file.mp4?loc=external&log_user=0&signature=f70c37ca017b8536b4be8f81fc6cfe2690dbd5e9ac10183063ea4c2ec2c6e7a6", posterUrl: "videoposters/reign.jpg", description: "Red Bull Reign was the ultimate 3-on-3 basketball tournament, testing teams on endurance, skill, teamwork, and their ability to dominate the court while racking up points to outlast opponents. I collaborated with basketball content creators PureKicks and Insta360 to produce an event highlight package filmed using the Insta360 One X." },
            { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082917096/rendition/720p/file.mp4?loc=external&log_user=0&signature=a918140dcdbf807507d8c0f65f9b2fa31b86502e1f980b8529999a9a11abc664", posterUrl: "videoposters/rubik.jpg", description: "The Red Bull Rubik’s Cube World Cup was a global competition designed to test the world’s top Cube solvers. I created social media edits from the London qualifiers, along with a quick-turnaround news package that was broadcast on news programmes around the world." },
            ]
        },
               {
            id: "proj16", categories: ["Documentary", "Sports content"], title: "Wings for Life - Claire Danson", subtitle: "A short profile film for the Wings for Life spinal cord foundation",
            keyImage: "thumbs/wfl.jpg",
            description: "Wings for Life is a non-profit research foundation that works towards the goal of curing spinal cord injuries. <br><br>I produced and directed this short documentary about WfL ambassador Claire Danson, to promote the annual Wings for Life World Run global running event.", media: [
            
             { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082922130/rendition/1080p/file.mp4?loc=external&log_user=0&signature=ef18f3180cbf856d9adc61736769f6ade829731f99f66b6a8130d30c830b13a3", posterUrl: "videoposters/clairewfl.jpg", description: "A short profile film I produced and directed for spinal cord research charity Wings for Life." }
            ]
        },
                {
            id: "proj18", categories: ["Music content"], title: "Alix Perez x Foreign Beggars freestyle", subtitle: "The best of UK Hip Hop teams up with a top drum and bass DJ",
            keyImage: "thumbs/alixperez.jpg",
            description: "I directed, filmed, and edited this live performance of UK hip hop group Foreign Beggars with drum and bass DJ and producer Alix Perez, as part of a series of live music videos produced with Red Bull Music.<br><br>I shot the performance using a 360-degree camera, which allowed me to add perfectly choreographed virtual camera moves in post-production that responded dynamically to the artist performance.", media: [
            { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082925043/rendition/1080p/file.mp4?loc=external&log_user=0&signature=4e01baa2f1f261b2923ba35995c7428df984c52ddd8de9dcb912c91dbea6c1bb", posterUrl: "videoposters/alixperez.jpg", description: "Alix Perez and Foreign Beggars team up for a mind-bending freestyle, filmed with a 360-degree camera." }
            ]
        },
        {
            id: "proj17", categories: ["Music content"], title: "Laucan - Live Session", subtitle: "A unique performance of 'Up Tomorrow | In Between’",
            keyImage: "thumbs/laucan.jpg",
            description: "I worked with Sunday Best Recordings artist Laucan to film a live session of 'Up Tomorrow | In Between’ at Goldsmiths Music Studio.<br><br>I filmed the performance with a 360-degree camera to allow me to create impossible camera moves and explore unique distorted visuals that mirrored the music.", media: [
                        { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082927775/rendition/1080p/file.mp4?loc=external&log_user=0&signature=fed860a9e314928ae4193d89a50051a48aab61fdfd6a7057bd9d0bbf9df1e609", posterUrl: "videoposters/laucan.jpg", description: "Laucan live session at Goldsmiths Music Studio." }
            ]
        },
        {
            id: "proj12", categories: ["Live streaming"], title: "Red Bull Live Streams", subtitle: "Giving Red Bull's live broadcasts wiiings",
            keyImage: "thumbs/rblive.jpg",
            description: "I have produced high quality live broadcasts for the Red Bull TV app, as well as interactive live streams for Red Bull's global social platforms.", media: [
                             { type: "loopingvideo", src: "https://player.vimeo.com/progressive_redirect/playback/1082890536/rendition/720p/file.mp4?loc=external&log_user=0&signature=0e028f3971d50cd63a7b27b8ddc2aa060285042b24a0628e1307cb536e496f0a", description: "10 Years of Danny MacAskill - An interactive live Q+A celebrating viral YouTube trials rider Danny MacAskill's 10 years anniversary since his first film collaboration with Red Bull." },
                             { type: "loopingvideo", src: "https://player.vimeo.com/progressive_redirect/playback/1082890511/rendition/1080p/file.mp4?loc=external&log_user=0&signature=786a04088f2bc1e40d367ee13d9645417f472fc39ac6607e7346e66a75c7a727", description: "Red Bull Basement - Live talks and Q+As around innovation for students looking to enter the Red Bull Basement entrepreneurship competition." },
                             { type: "loopingvideo", src: "https://player.vimeo.com/progressive_redirect/playback/1082890599/rendition/1080p/file.mp4?loc=external&log_user=0&signature=dda2c7551f3c96403bdeb8d594c777e178b2ee74349018c570cfe6d5cfb835fa", description: "Women in Sport - Live talks and Q+As streamed from events organised by women's motorbike collective VC London, and panel sessions from the Women's Climbing Symposium. " }
            
            ]
        },
        {
            id: "proj20", categories: ["Sports content"], title: "Zwift @ Six Day London", subtitle: "Fast turnaround virtual cycling event highlights",
            keyImage: "thumbs/zwift.jpg",
            description: "I worked with virtual cycling platform Zwift to produce fast-turnaround highlights of their virtual esports series at the London Six Day competition. My daily edits were distributed online, shown on the big screens within the venue, and supplied to broadcast partner Eurosport.", media: [
            { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082930005/rendition/720p/file.mp4?loc=external&log_user=0&signature=86967dfd54ed4eda8d64c26f2803ebee915155679dcabac82d8faa6d2aba59f2", posterUrl: "videoposters/zwift.jpg", description: "Fast turnaround virtual cycling event highlights from Six Day in London" }

            ]
        },
         {
            id: "proj15", categories: ["Music content"], title: "Birmingham Grime Cypher", subtitle: "Birmingham's top Grime MCs in a revolutionary cypher",
            keyImage: "thumbs/grime.jpg",
            description: "Watch Birmingham's best grime MCs, Jaykae, Safone, Mayhem, Trilla, Bomma B, Deadly, YG and Tornado tear up the mic in a revolutionary cypher shot in Red Bull Studios.<br><br>I created this video using six GoPro cameras inside a 360 rig, and added the camera moves in post-production.", media: [
            { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082919099/rendition/1080p/file.mp4?loc=external&log_user=0&signature=0eb58b89eac9fbcf46b8cd2d54b8d809ce1679343136364fc01d0e8e37e0341c", posterUrl: "videoposters/jaykae.jpg", description: "Birmingham's best grime MCs perform at Red Bull Studios in London." }
            ]
        },

        {
            id: "proj21", categories: ["Sports content"], title: "Gymkhana Grid", subtitle: "Fast turnaround content from Ken Block's drifting event in Poland",
            keyImage: "thumbs/grid.jpg",
            description: "I created high quality quick turnaround social media content from Ken Block's drifting event in Poland.  The content generated over 2.5 million organic views.", media: [
                        { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082931823/rendition/1080p/file.mp4?loc=external&log_user=0&signature=4936a2ced3e0da693d7a871f2605c33ebccee8aaf07185e7dededa91c4e13c31", posterUrl: "videoposters/grid.jpg", description: "Fast turnaround content of drifting through the streets of Poland" }
            ]
        },
        {
            id: "proj22", categories: ["Music content"], title: "Joe Garvey - 'What Your Time Is Worth'", subtitle: "An early example of synchronised smartphone choreography",
            keyImage: "thumbs/garvey.jpg",
            description: "I shot and directed the music video for 'What Your Time Is Worth' by Joe Garvey, one of the first examples of synchronised smartphone choreography.<br><br>We used five different smartphones displaying footage shot in four countries.  No visual effects were used, and the whole video was shot in a single take.<br><br>The music video was featured in the Evening Standard, and myself and Joe were invited into the London Live studio to discuss the project.", media: [
             { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082934406/rendition/1080p/file.mp4?loc=external&log_user=0&signature=34ac3af8fec8cd2131c601108abda1d9dc193519f417d50f1089dc1fefcbbd58", posterUrl: "videoposters/garvey.jpg", description: "The music video for 'What Your Time Is Worth' by Joe Garvey" },
              { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082934604/rendition/1080p/file.mp4?loc=external&log_user=0&signature=69d56675faa8ba5dad1a9e6ebdc6625978d371d70235e4487c289776b307506b", posterUrl: "videoposters/jamestrosh.jpg", description: "Discussing the music video on London Live" }


            ]
        },
        {
            id: "proj23", categories: ["Experimental"], title: "YouTube VR Creator Lab", subtitle: "A pioneering 360º video filmed at the edge of space",
            keyImage: "thumbs/ytcreatorlab.jpg",
            description: "YouTube’s ‘Creator Lab' asked me to produce a 360-degree video project to demonstrate the possibilities of YouTube VR, with a spherical video filmed at the edge of space.  <br><br>My team designed and built a bespoke six camera GoPro rig, and we attached it to a helium filled weather balloon to capture immersive 360-degree video footage 32km above earth.  <br><br>Once the project was complete, I presented the project to Google employees and invited delegates from the VR industry at a conference held at the YouTube Space in London.", media: [
            
             { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1082961909/rendition/720p/file.mp4?loc=external&log_user=0&signature=ddcfadac98a5cd570e1871a448c7ed4f1161571fa5fe4d3cbfd8267c0ea21b00", posterUrl: "videoposters/ytcreatorlab.jpg", description: "Take a virtual reality ride on a weather balloon from the bet365 Stadium in Stoke, England up 32,704 metres (107,297ft) to the edge of space." }
            ]
        },
                {
            id: "proj25", categories: ["Documentary", "Sports content"], title: "Kriss Kyle’s Kaleidoscope BTS (360º)", subtitle: "A VR behind the scenes experience of the award winning BMX edit",
            keyImage: "thumbs/kyle.jpg",
            description: "A 360° behind the scenes look at the filming of Kriss Kyle’s groundbreaking BMX film, Kaleidoscope.  <br><br>I shot the 360° video on the set of Kaleidoscope, stitched and edited the footage together, and recorded the narration for the video with Kriss.", media: [
             { type: "youtube", src: "PzLIDonbfow", description: "Experience how Kriss Kyle's Kaleidoscope was made in 360-degrees." },
               
            ]
        },
        {
            id: "proj26", categories: ["Music content"], title: "Lucky Elephant - 'Edgar'", subtitle: "The first music video filmed at the edge of space!",
            keyImage: "thumbs/edgar.jpg",
            description: "A music video that follows a small toy robot’s journey to a rocket that takes it into space.  Filmed on location in Bournemouth, Cambridge and over 95,000 ft into the stratosphere.<br><br>The video was nominated for <em>'Best Music Video'</em> at the <em>National Student Film Awards</em>, and was screened at film festivals including the <em>2011 BBC Music Video Festival</em>.", media: [
                        { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1083012130/rendition/720p/file.mp4?loc=external&log_user=0&signature=b9bc53690dccc633b97b670e0e0d97c425f8d238d5c18436a42e671d15646023", posterUrl: "videoposters/edgar.jpg", description: "The first music video filmed at the edge of space!" }

            ]
        },
        {
            id: "proj27", categories: ["Music content", "Documentary"], title: "Kuricorder Quartet in London", subtitle: "A Japanese folk band visits the UK",
            keyImage: "thumbs/kuri.jpg",
            description: "A short film I produced and directed on Japanese folk band the Kuricorder Quartet, and their first ever performance in the UK.", media: [
                                    { type: "video", src: "https://player.vimeo.com/progressive_redirect/playback/1083013775/rendition/720p/file.mp4?loc=external&log_user=0&signature=f408d8e6a94607324548d5fdd450a074723e71859e0211c985555a4797cb2c52", posterUrl: "videoposters/kuri.jpg", description: "Kuricorder Quartet - Japanese folk band in London" }
            ]
        }   ];
    const siteProjectCategories = ["All", "Documentary", "Experimental", "Sports content", "Music content", "Live streaming", "Social campaign", "Podcasting"];
    // --- END OF EASILY EDITABLE CONTENT ---

    // Helper function to pause YouTube videos via postMessage API
    function pauseYouTubeVideo(iframeElement) {
        if (iframeElement && iframeElement.contentWindow) {
            if (iframeElement.src && iframeElement.src.startsWith('https://www.youtube.com/embed/') && iframeElement.src.includes('enablejsapi=1')) {
                iframeElement.contentWindow.postMessage(JSON.stringify({
                    event: 'command',
                    func: 'pauseVideo',
                    args: ''
                }), 'https://www.youtube.com');
            }
        }
    }

    document.addEventListener('alpine:init', () => {
        Alpine.store('app', { openModal: false, currentProject: null, currentMediaIndex: 0 });
        Alpine.store('device', { isMobileOrTabletView: window.innerWidth < 1024, updateView() { this.isMobileOrTabletView = window.innerWidth < 1024; } });
        Alpine.store('device').updateView();
        window.addEventListener('resize', () => Alpine.store('device').updateView());

        document.addEventListener('open-project-modal', (event) => {
            const project = event.detail;
            if (project) {
                Alpine.store('app').currentProject = project;
                Alpine.store('app').currentMediaIndex = 0;
                Alpine.store('app').openModal = true;
            }
        });

        Alpine.data('showreelPlayer', () => ({
            availableShowreels: siteShowreels, currentShowreelIndex: 0, currentShowreel: siteShowreels[0] || { title: 'No Showreel', videoUrl: null, posterUrl: null },
            init() { if(this.availableShowreels.length > 0) { this.loadVideo(0); } else { this.currentShowreel = { title: 'No showreels available', videoUrl: null, posterUrl: null }; } },
            playShowreel(index) { this.loadVideo(index); },
            loadVideo(index) { if (index < 0 || index >= this.availableShowreels.length) return; this.currentShowreelIndex = index; this.currentShowreel = this.availableShowreels[index]; const videoElement = this.$refs.showreelVideoPlayer; if (!videoElement || !this.currentShowreel.videoUrl) return; if (!videoElement.paused) { videoElement.pause(); } videoElement.src = this.currentShowreel.videoUrl; videoElement.load(); }
        }));
        Alpine.data('recentWork', () => ({
            allProjects: siteProjects, categories: siteProjectCategories, activeCategory: 'All', initialProjectCount: 9, projectsToShowIncrement: 9, currentVisibleProjectCount: 0, _allFilteredProjectsCache: [], visibleProjects: [], showMoreButtonVisible: false,
            init() { this.currentVisibleProjectCount = this.initialProjectCount; this.filterProjects('All'); },
            updateDisplayedProjects() { this.visibleProjects = this._allFilteredProjectsCache.slice(0, this.currentVisibleProjectCount); this.showMoreButtonVisible = this.currentVisibleProjectCount < this._allFilteredProjectsCache.length; },
            filterProjects(category) { this.activeCategory = category; this.currentVisibleProjectCount = this.initialProjectCount; if (category === 'All') { this._allFilteredProjectsCache = [...this.allProjects]; } else { this._allFilteredProjectsCache = this.allProjects.filter(p => p.categories.includes(category)); } this.updateDisplayedProjects(); },
            showMoreProjects() { this.currentVisibleProjectCount = Math.min(this.currentVisibleProjectCount + this.projectsToShowIncrement, this._allFilteredProjectsCache.length); this.updateDisplayedProjects(); },
            openProjectModal(project) { if (project) { this.$dispatch('open-project-modal', project); } }
        }));

        Alpine.data('projectModal', () => ({
            init() {
                this.$watch('$store.app.openModal', isOpen => {
                    const modalScrollContent = this.$el.querySelector('.modal-scroll-content');
                    if (!isOpen) {
                        this.$el.querySelectorAll('video[data-media-index]').forEach(vid => {
                            vid.pause();
                            vid.currentTime = 0;
                        });
                        this.$el.querySelectorAll('iframe[data-media-index]').forEach(iframe => {
                            pauseYouTubeVideo(iframe);
                        });
                        if (modalScrollContent) modalScrollContent.scrollTop = 0;
                    } else {
                        if (modalScrollContent) modalScrollContent.scrollTop = 0;
                        this.$nextTick(() => {
                            if (this.$store.app.currentProject && this.$store.app.currentProject.media && this.$store.app.currentProject.media.length > 0) {
                                 const firstMedia = this.$store.app.currentProject.media[this.$store.app.currentMediaIndex || 0];
                                 if (firstMedia.type === 'loopingvideo') {
                                    const videoElement = this.$el.querySelector(`video[data-media-index="${this.$store.app.currentMediaIndex || 0}"]`);
                                    if (videoElement) {
                                        if (videoElement.getAttribute('src') !== firstMedia.src) { videoElement.setAttribute('src', firstMedia.src); }
                                        videoElement.play().catch(e => console.warn('Autoplay for looping video blocked:', e));
                                    }
                                 }
                            }
                        });
                    }
                });

                this.$watch('$store.app.currentMediaIndex', (newIndex, oldIndex) => {
                    this.$nextTick(() => { 
                        if (this.$store.app.currentProject && this.$store.app.currentProject.media) {
                            if (oldIndex !== undefined && oldIndex !== newIndex && this.$store.app.currentProject.media[oldIndex]) {
                                const oldMediaItem = this.$store.app.currentProject.media[oldIndex];
                                if (oldMediaItem.type === 'video' || oldMediaItem.type === 'loopingvideo') {
                                    const previousVideoElement = this.$el.querySelector(`video[data-media-index="${oldIndex}"]`);
                                    if (previousVideoElement && !previousVideoElement.paused) {
                                        previousVideoElement.pause();
                                    }
                                } else if (oldMediaItem.type === 'youtube') {
                                    const previousIframeElement = this.$el.querySelector(`iframe[data-media-index="${oldIndex}"]`);
                                    if (previousIframeElement) {
                                        pauseYouTubeVideo(previousIframeElement);
                                    }
                                }
                            }
    
                            const currentMedia = this.$store.app.currentProject.media[newIndex];
                            if (currentMedia) {
                                if (currentMedia.type === 'loopingvideo') { 
                                    const videoElement = this.$el.querySelector(`video[data-media-index="${newIndex}"]`);
                                    if (videoElement) {
                                        if (videoElement.getAttribute('src') !== currentMedia.src) { videoElement.setAttribute('src', currentMedia.src); }
                                        videoElement.load(); 
                                        videoElement.play().catch(e => console.warn('Autoplay for looping video blocked:', e));
                                    }
                                } else if (currentMedia.type === 'video') { 
                                     const videoElement = this.$el.querySelector(`video[data-media-index="${newIndex}"]`);
                                     if (videoElement) {
                                        if (videoElement.getAttribute('src') !== currentMedia.src) { videoElement.setAttribute('src', currentMedia.src); }
                                        videoElement.load();
                                     }
                                }
                            }
                        }
                    });
                });
            }
        }));
        
        setTimeout(() => { 
            const sections = document.querySelectorAll('main section[id]'); const headerElement = document.querySelector('header'); let headerOffset = headerElement ? headerElement.offsetHeight + 20 : 100;
            const calculateHeaderOffset = () => { if (headerElement) headerOffset = headerElement.offsetHeight + 20; };
            const handleScroll = () => { if (!sections || sections.length === 0) return; calculateHeaderOffset(); const scrollPosition = window.scrollY; let newActiveSectionId = sections[0].getAttribute('id'); for (let i = 0; i < sections.length; i++) { const section = sections[i]; if (scrollPosition >= section.offsetTop - headerOffset) { newActiveSectionId = section.getAttribute('id'); } } if ((window.innerHeight + Math.ceil(scrollPosition)) >= document.body.offsetHeight - 5 && sections.length > 0) { newActiveSectionId = sections[sections.length - 1].getAttribute('id'); } if (newActiveSectionId !== Alpine.store('app').currentSection) { window.dispatchEvent(new CustomEvent('set-active-section', { detail: newActiveSectionId })); } };
            if (sections.length > 0) { calculateHeaderOffset(); window.addEventListener('scroll', handleScroll, { passive: true }); window.addEventListener('resize', () => { calculateHeaderOffset(); handleScroll(); }); handleScroll(); } else { console.warn('Scroll Spy: No sections with IDs found.'); }
        }, 0);
    });
</script>

</body>
</html>


