    /* ── Lenis smooth scroll ── */
    (function () {
      const s = document.createElement('script');
      s.src = 'https://unpkg.com/lenis@1.1.14/dist/lenis.min.js';
      s.onload = function () {
        window.lenis = new Lenis({ lerp: 0.12, smoothWheel: true });
        function raf(time) { window.lenis.raf(time); requestAnimationFrame(raf); }
        requestAnimationFrame(raf);
      };
      document.head.appendChild(s);
    })();

    function fitText(el) {
      if (!el) return 0;
      const parent = el.parentElement;
      const available = parent.clientWidth;
      let lo = 1, hi = 2000;
      el.style.fontSize = hi + 'px';
      while (hi - lo > 0.5) {
        const mid = (lo + hi) / 2;
        el.style.fontSize = mid + 'px';
        if (el.scrollWidth <= available) lo = mid;
        else hi = mid;
      }
      el.style.fontSize = lo + 'px';
      return lo;
    }

    function fitAll() {
      fitText(document.getElementById('text-marina'));
      const studioSize = fitText(document.getElementById('text-studio'));
      if (studioSize) {
        document.querySelectorAll('.studio-layer').forEach(el => {
          el.style.fontSize = studioSize + 'px';
        });
      }
      fitText(document.getElementById('nav-marina'));
      fitText(document.getElementById('nav-studio'));
      const ctaSize = fitText(document.getElementById('text-cta'));
      if (ctaSize) {
        document.querySelectorAll('.cta-layer').forEach(el => {
          el.style.fontSize = ctaSize + 'px';
        });
      }
    }

    document.fonts.ready.then(fitAll);
    window.addEventListener('resize', fitAll);

    // Cycle a set of image layers
    function cycleLayers(selector, interval) {
      const layers = document.querySelectorAll(selector);
      if (layers.length < 2) return;
      let current = 0;
      setInterval(() => {
        layers[current].classList.remove('active');
        current = (current + 1) % layers.length;
        layers[current].classList.add('active');
      }, interval);
    }

    cycleLayers('.studio-layer', 1500);
    cycleLayers('.cta-layer', 2000);

    // Collapsed nav reveal on scroll (homepage only)
    const navExpanded = document.getElementById('nav-expanded');
    const navCollapsed = document.getElementById('nav-collapsed');
    if (navExpanded && navCollapsed) {
      const observer = new IntersectionObserver(
        ([entry]) => {
          navCollapsed.classList.toggle('visible', !entry.isIntersecting);
        },
        { threshold: 0 }
      );
      observer.observe(navExpanded);
    }

    // Menu dropdown toggles — delegated so they work with async-loaded nav
    document.addEventListener('click', (e) => {
      const btn = e.target.closest('.nav-menu-btn');
      if (btn) {
        e.stopPropagation();
        const menu = btn.closest('.nav-menu');
        const isOpen = menu.classList.toggle('open');
        btn.setAttribute('aria-expanded', isOpen);
        return;
      }
      document.querySelectorAll('.nav-menu.open').forEach(menu => {
        menu.classList.remove('open');
        menu.querySelector('.nav-menu-btn').setAttribute('aria-expanded', 'false');
      });
    });

    // Contact form: show error banner if redirected back with ?error=1
    const formError = document.getElementById('form-error');
    if (formError && new URLSearchParams(location.search).has('error')) {
      formError.hidden = false;
      formError.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }

    /* ── Work preview modal ── */
    const previewData = {
      maison: {
        title: 'Maison Wellesley',
        images: ['assets/imgs/mstudio_case_study_maison_wellesley_1.webp', 'assets/imgs/mstudio_case_study_maison_wellesley_2.webp', 'assets/imgs/mstudio_case_study_maison_wellesley_3.webp', 'assets/imgs/mstudio_case_study_maison_wellesley_4.webp'],
        meta: ['Creative Direction', 'Web Design', 'Web Development', 'WordPress'],
        blurb: 'A WordPress site for Maison Wellesley, a boutique 14-storey condominium at 506 Church Street in Downtown Toronto, capturing its elevated urban lifestyle.',
        href: 'https://maisonwellesleytoronto.com/'
      },
      comefromaway: {
        title: 'Come From Away: E-commerce',
        images: ['assets/imgs/mstudio_case_study_comefromaway_1.webp', 'assets/imgs/mstudio_case_study_comefromaway_2.webp', 'assets/imgs/mstudio_case_study_comefromaway_3.webp', 'assets/imgs/mstudio_case_study_comefromaway_4.webp'],
        meta: ['Creative Direction', 'Web Design', 'Web Development', 'E-commerce'],
        blurb: 'A Shopify store for Come From Away, whose commemorative rings, labels, and medallions celebrate the 75th anniversary of Newfoundland\'s Confederation.',
        href: 'https://comefromaway.ai/'
      },
      benchbrine: {
        title: 'Bench & Brine Winery Website',
        images: ['assets/imgs/mstudio_case_study_benchbrine_1.webp', 'assets/imgs/mstudio_case_study_benchbrine_2.webp', 'assets/imgs/mstudio_case_study_benchbrine_3.webp', 'assets/imgs/mstudio_case_study_benchbrine_4.webp', 'assets/imgs/mstudio_case_study_benchbrine_5.webp'],
        meta: ['Creative Direction', 'Web Design', 'Web Development', 'Website Template'],
        blurb: 'A website template for Bench & Brine, a boutique winery, pairing warm, editorial design with an immersive, scrollable experience. Available as a fully customizable template.',
        href: 'https://winery.marina.studio'
      },
      benchbakehouse: {
        title: 'Bench Bakehouse',
        images: ['assets/imgs/mstudio_case_study_benchbakehouse_1.webp', 'assets/imgs/mstudio_case_study_benchbakehouse_2.webp', 'assets/imgs/mstudio_case_study_benchbakehouse_3.webp'],
        meta: ['Creative Direction', 'Web Design', 'Web Development', 'Website Template'],
        blurb: 'A website template for Bench Bakehouse, an artisan bakery and café in Beamsville, Ontario. Warm, editorial design built around slow craft, handmade goods, and same-day baking.',
        href: 'https://bakery.marina.studio/'
      }
    };

    const modal = document.getElementById('work-modal');
    if (modal) {
      const modalTrack = document.getElementById('modal-track');
      const modalDots  = document.getElementById('modal-dots');
      const modalTitle = document.getElementById('modal-title');
      const modalMeta  = document.getElementById('modal-meta');
      const modalBlurb = document.getElementById('modal-blurb');
      const modalCta   = document.getElementById('modal-cta');
      let currentSlide = 0;
      let slideCount   = 0;
      let lastFocused  = null;

      const goToSlide = (i) => {
        slideCount = modalTrack.children.length;
        currentSlide = (i + slideCount) % slideCount;
        modalTrack.style.transform = `translateX(-${currentSlide * 100}%)`;
        modalDots.querySelectorAll('.modal-dot').forEach((d, idx) =>
          d.classList.toggle('active', idx === currentSlide));
      };

      const openModal = (key) => {
        const data = previewData[key];
        if (!data) return;

        modalTitle.textContent = data.title;
        modalBlurb.textContent = data.blurb;
        modalCta.href = data.href;

        modalMeta.innerHTML = data.meta
          .map(t => `<span class="scope-tag">${t}</span>`).join('');

        modalTrack.innerHTML = data.images
          .map(src => `<div class="modal-slide"><img src="${src}" alt=""></div>`).join('');

        modalDots.innerHTML = data.images
          .map((_, i) => `<button class="modal-dot" aria-label="Go to image ${i + 1}"></button>`).join('');
        modalDots.querySelectorAll('.modal-dot').forEach((dot, i) =>
          dot.addEventListener('click', () => goToSlide(i)));

        goToSlide(0);

        lastFocused = document.activeElement;
        modal.classList.add('open');
        document.body.style.overflow = 'hidden';
        if (window.lenis) window.lenis.stop();
        document.getElementById('modal-close').focus();
      };

      const closeModal = () => {
        modal.classList.remove('open');
        document.body.style.overflow = '';
        if (window.lenis) window.lenis.start();
        if (lastFocused) lastFocused.focus();
      };

      document.querySelectorAll('.work-preview-btn').forEach(btn => {
        btn.addEventListener('click', (e) => {
          e.preventDefault();
          openModal(btn.dataset.preview);
        });
      });

      document.getElementById('modal-close').addEventListener('click', closeModal);
      document.getElementById('modal-prev').addEventListener('click', () => goToSlide(currentSlide - 1));
      document.getElementById('modal-next').addEventListener('click', () => goToSlide(currentSlide + 1));

      modal.addEventListener('click', (e) => {
        if (e.target === modal) closeModal();
      });

      document.addEventListener('keydown', (e) => {
        if (!modal.classList.contains('open')) return;
        if (e.key === 'Escape') closeModal();
        if (e.key === 'ArrowLeft') goToSlide(currentSlide - 1);
        if (e.key === 'ArrowRight') goToSlide(currentSlide + 1);
      });
    }

    /* ── Blur-in reveal on scroll ── */
    (function () {
      const addReveal = (el, delay) => {
        el.classList.add('reveal');
        if (delay) el.style.transitionDelay = delay + 'ms';
      };

      // Standalone elements
      ['.header', '.section-label', '.about-photo', '.about-content',
       '.cta-heading-wrap', '.cta-bottom', '.site-footer', '.page-intro', '.work-feature',
       '.block-heading', '.contact-details', '.contact-form',
       '.post-header', '.post-feature-full', '.related-heading', '.niche-split-media']
        .forEach(sel => document.querySelectorAll(sel).forEach(el => addReveal(el)));

      // Staggered groups: [container, child]
      [['.nav-expanded', ':scope > *'],
       ['.services-grid', '.service-row'],
       ['.services-list', '.svc-row'],
       ['.work-grid', '.work-card'],
       ['.resource-list', '.resource-row'],
       ['.client-grid', '.client-item'],
       ['.process-grid', '.process-step'],
       ['.reviews-grid', '.review-card'],
       ['.posts', '.post-item'],
       ['.related-grid', '.related-card'],
       ['.faq-list', '.faq-item'],
       ['.niche-features', '.niche-feature'],
       ['.industry-grid', '.industry-card']]
        .forEach(([containerSel, childSel]) => {
          document.querySelectorAll(containerSel).forEach(container => {
            container.querySelectorAll(childSel).forEach((child, i) => addReveal(child, i * 80));
          });
        });

      const revealObserver = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            entry.target.classList.add('is-visible');
            revealObserver.unobserve(entry.target);
          }
        });
      }, { threshold: 0.12, rootMargin: '0px 0px -8% 0px' });

      document.querySelectorAll('.reveal').forEach(el => revealObserver.observe(el));
    })();
