# Smoth Mega Menu

> A full-width mega menu with smooth panel motion and layered reveals — polished site navigation for complex link sets.

**Definition:** Smoth Mega Menu is a navigation UI animation from collections.html. It is built with HTML, CSS, JavaScript, and GSAP, ships with a live preview, and is free to copy into personal and commercial projects.

## Facts
- Category: Navigation
- Stack: HTML, CSS, JavaScript, and GSAP
- Added: 2026-08-02
- Canonical page: https://html.bosconvertpro.com/collection/smoth-mega-menu
- Full-page preview: https://html.bosconvertpro.com/collection/smoth-mega-menu/full
- Live demo: https://html.bosconvertpro.com/demos/smoth-mega-menu/index.html
- Markdown mirror: https://html.bosconvertpro.com/collection/smoth-mega-menu/index.md
- License: https://html.bosconvertpro.com/terms

## How to use
1. Open https://html.bosconvertpro.com/collection/smoth-mega-menu/full to preview the animation in full screen.
2. Copy index.html, styles.css, and script.js from the code tabs on https://html.bosconvertpro.com/collection/smoth-mega-menu.
3. Paste the files into your project and adjust timing, easing, and content as needed.

## FAQ
### What is Smoth Mega Menu?

Smoth Mega Menu is a navigation UI animation from collections.html. A full-width mega menu with smooth panel motion and layered reveals — polished site navigation for complex link sets.

### What is Smoth Mega Menu built with?

Smoth Mega Menu is built with HTML, CSS, JavaScript, and GSAP. The source for every file is shown on the animation page and can be copied straight into your project.

### How do I use Smoth Mega Menu in my project?

Open the animation page (https://html.bosconvertpro.com/collection/smoth-mega-menu), preview it live, then copy index.html, styles.css, and script.js from the code tabs. Paste the files into your project and adjust timing, easing, and content as needed. A standalone demo runs at https://html.bosconvertpro.com/demos/smoth-mega-menu/index.html.

### Is Smoth Mega Menu free to use?

Yes. The Smoth Mega Menu demo code may be used in personal and commercial projects. You may not resell or redistribute the collection itself as a competing template pack. Full terms: https://html.bosconvertpro.com/terms.

## Source — index.html
````html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Smooth Mega Menu — Lumière Studio</title>
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
      rel="stylesheet"
    />
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <!--
      Smooth Mega Menu
      ----------------
      Full-width header only — no page products section.
      Hover (desktop) / click (mobile) mega panels with live Unsplash previews.
    -->
    <nav
      class="mega-nav"
      data-mega-nav
      data-duration="0.5"
      data-ease="expo.out"
      data-stagger="0.04"
      data-trigger-event="hover"
      data-open-delay="0.15"
      data-close-delay="0.2"
      data-direction-aware="true"
      data-mobile-breakpoint="768"
    >
      <a class="mega-nav__logo" href="#">Lumière</a>

      <button
        class="mega-nav__burger"
        data-mega-burger
        type="button"
        aria-expanded="false"
        aria-controls="mega-nav-list"
        aria-label="Open menu"
      >
        <span class="mega-nav__burger-line mega-nav__burger-line--top" aria-hidden="true"></span>
        <span class="mega-nav__burger-line mega-nav__burger-line--bottom" aria-hidden="true"></span>
      </button>

      <div class="mega-nav__list-wrap">
        <ul class="mega-nav__list" id="mega-nav-list" role="list">
          <li class="mega-nav__item" data-mega-item>
            <button
              class="mega-nav__trigger"
              data-mega-trigger
              type="button"
              aria-expanded="false"
              aria-controls="mega-panel-work"
              aria-haspopup="true"
            >
              <span class="mega-nav__trigger-text">Work</span>
              <span class="mega-nav__trigger-arrow" aria-hidden="true"></span>
            </button>
          </li>

          <li class="mega-nav__item" data-mega-item>
            <button
              class="mega-nav__trigger"
              data-mega-trigger
              type="button"
              aria-expanded="false"
              aria-controls="mega-panel-studio"
              aria-haspopup="true"
            >
              <span class="mega-nav__trigger-text">Studio</span>
              <span class="mega-nav__trigger-arrow" aria-hidden="true"></span>
            </button>
          </li>

          <li class="mega-nav__item" data-mega-item>
            <button
              class="mega-nav__trigger"
              data-mega-trigger
              type="button"
              aria-expanded="false"
              aria-controls="mega-panel-journal"
              aria-haspopup="true"
            >
              <span class="mega-nav__trigger-text">Journal</span>
              <span class="mega-nav__trigger-arrow" aria-hidden="true"></span>
            </button>
          </li>
        </ul>

        <span class="mega-nav__indicator" data-mega-indicator aria-hidden="true"></span>
      </div>

      <div class="mega-nav__actions">
        <a class="mega-nav__text-link" data-mega-text-link href="#">Careers</a>
        <a class="mega-nav__cta" href="#">Contact</a>
      </div>

      <div class="mega-nav__dropdown" data-mega-dropdown aria-hidden="true">
        <div class="mega-nav__dropdown-inner">
          <!-- Work -->
          <div
            class="mega-nav__panel"
            id="mega-panel-work"
            data-mega-panel
            aria-hidden="true"
          >
            <div class="mega-nav__panel-body">
              <div class="mega-nav__columns">
                <div class="mega-nav__column" data-mega-column>
                  <span class="mega-nav__column-label">Disciplines</span>
                  <a
                    class="mega-nav__link"
                    data-mega-link
                    href="#"
                    data-preview-src="https://images.unsplash.com/photo-1600607687939-ce8a6c25118c?auto=format&fit=crop&w=800&q=80"
                    data-preview-eyebrow="Interiors"
                    data-preview-heading="Quiet rooms shaped by light and material."
                  >
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Interiors</span>
                  </a>
                  <a
                    class="mega-nav__link"
                    data-mega-link
                    href="#"
                    data-preview-src="https://images.unsplash.com/photo-1487958449943-2429e8be8625?auto=format&fit=crop&w=800&q=80"
                    data-preview-eyebrow="Architecture"
                    data-preview-heading="Structures that hold space with restraint."
                  >
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Architecture</span>
                  </a>
                  <a
                    class="mega-nav__link"
                    data-mega-link
                    href="#"
                    data-preview-src="https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?auto=format&fit=crop&w=800&q=80"
                    data-preview-eyebrow="Branding"
                    data-preview-heading="Identity systems for considered brands."
                  >
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Branding</span>
                  </a>
                  <a
                    class="mega-nav__link"
                    data-mega-link
                    href="#"
                    data-preview-src="https://images.unsplash.com/photo-1618221195710-dd6b41faaea6?auto=format&fit=crop&w=800&q=80"
                    data-preview-eyebrow="Furniture"
                    data-preview-heading="Objects designed for daily ritual."
                  >
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Furniture</span>
                  </a>
                </div>

                <div class="mega-nav__column" data-mega-column>
                  <span class="mega-nav__column-label">Selected</span>
                  <a class="mega-nav__link" data-mega-link href="#">
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Casa Lumen</span>
                  </a>
                  <a class="mega-nav__link" data-mega-link href="#">
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Nord Gallery</span>
                  </a>
                  <a class="mega-nav__link" data-mega-link href="#">
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Vault Office</span>
                  </a>
                  <a class="mega-nav__link" data-mega-link href="#">
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">All projects</span>
                  </a>
                </div>
              </div>

              <div class="mega-nav__preview" data-mega-preview>
                <div class="mega-nav__preview-media">
                  <img
                    class="mega-nav__preview-image"
                    data-mega-preview-image
                    src="https://images.unsplash.com/photo-1600585154340-be6161a56a0c?auto=format&fit=crop&w=800&q=80"
                    alt=""
                    loading="lazy"
                  />
                </div>
                <div class="mega-nav__preview-body">
                  <p class="mega-nav__preview-eyebrow" data-mega-preview-eyebrow>
                    Featured
                  </p>
                  <p class="mega-nav__preview-heading" data-mega-preview-heading>
                    A hillside residence in soft concrete and oak.
                  </p>
                  <a class="mega-nav__preview-cta" href="#">View project</a>
                </div>
              </div>
            </div>
          </div>

          <!-- Studio -->
          <div
            class="mega-nav__panel"
            id="mega-panel-studio"
            data-mega-panel
            aria-hidden="true"
          >
            <div class="mega-nav__panel-body">
              <div class="mega-nav__columns">
                <div class="mega-nav__column" data-mega-column>
                  <span class="mega-nav__column-label">About</span>
                  <a class="mega-nav__link" data-mega-link href="#">
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Our practice</span>
                  </a>
                  <a class="mega-nav__link" data-mega-link href="#">
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Process</span>
                  </a>
                  <a class="mega-nav__link" data-mega-link href="#">
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Team</span>
                  </a>
                </div>

                <div class="mega-nav__column" data-mega-column>
                  <span class="mega-nav__column-label">Locations</span>
                  <a class="mega-nav__link" data-mega-link href="#">
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Copenhagen</span>
                  </a>
                  <a class="mega-nav__link" data-mega-link href="#">
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Lisbon</span>
                  </a>
                  <a class="mega-nav__link" data-mega-link href="#">
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Tokyo</span>
                  </a>
                </div>

                <div class="mega-nav__column" data-mega-column>
                  <span class="mega-nav__column-label">Connect</span>
                  <a class="mega-nav__link" data-mega-link href="#">
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Press kit</span>
                  </a>
                  <a class="mega-nav__link" data-mega-link href="#">
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Newsletter</span>
                  </a>
                  <a class="mega-nav__link" data-mega-link href="#">
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Instagram</span>
                  </a>
                </div>
              </div>
            </div>
          </div>

          <!-- Journal -->
          <div
            class="mega-nav__panel"
            id="mega-panel-journal"
            data-mega-panel
            aria-hidden="true"
          >
            <div class="mega-nav__panel-body">
              <div class="mega-nav__columns">
                <div class="mega-nav__column" data-mega-column>
                  <span class="mega-nav__column-label">Essays</span>
                  <a
                    class="mega-nav__link"
                    data-mega-link
                    href="#"
                    data-preview-src="https://images.unsplash.com/photo-1497366216548-37526070297c?auto=format&fit=crop&w=800&q=80"
                    data-preview-eyebrow="Light"
                    data-preview-heading="How morning light rewrites a floor plan."
                  >
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">On natural light</span>
                  </a>
                  <a
                    class="mega-nav__link"
                    data-mega-link
                    href="#"
                    data-preview-src="https://images.unsplash.com/photo-1615874959474-d609969a20ed?auto=format&fit=crop&w=800&q=80"
                    data-preview-eyebrow="Material"
                    data-preview-heading="Why we still choose solid timber."
                  >
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Material notes</span>
                  </a>
                  <a
                    class="mega-nav__link"
                    data-mega-link
                    href="#"
                    data-preview-src="https://images.unsplash.com/photo-1600566753190-17f0baa2a6c3?auto=format&fit=crop&w=800&q=80"
                    data-preview-eyebrow="Cities"
                    data-preview-heading="Density without noise — a field study."
                  >
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Urban density</span>
                  </a>
                </div>

                <div class="mega-nav__column" data-mega-column>
                  <span class="mega-nav__column-label">Series</span>
                  <a
                    class="mega-nav__link"
                    data-mega-link
                    href="#"
                    data-preview-src="https://images.unsplash.com/photo-1503387762-592deb58ef4e?auto=format&fit=crop&w=800&q=80"
                    data-preview-eyebrow="Voices"
                    data-preview-heading="Conversations with makers we admire."
                  >
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Voices</span>
                  </a>
                  <a
                    class="mega-nav__link"
                    data-mega-link
                    href="#"
                    data-preview-src="https://images.unsplash.com/photo-1512917774080-9991f1c4c750?auto=format&fit=crop&w=800&q=80"
                    data-preview-eyebrow="Sites"
                    data-preview-heading="Before and after on remote sites."
                  >
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Field notes</span>
                  </a>
                  <a
                    class="mega-nav__link"
                    data-mega-link
                    href="#"
                    data-preview-src="https://images.unsplash.com/photo-1600210492486-724fe5c67fb0?auto=format&fit=crop&w=800&q=80"
                    data-preview-eyebrow="Archive"
                    data-preview-heading="Drawings from the last decade."
                  >
                    <span class="mega-nav__link-dot" aria-hidden="true"></span>
                    <span class="mega-nav__link-label">Archive</span>
                  </a>
                </div>
              </div>

              <div class="mega-nav__preview" data-mega-preview>
                <div class="mega-nav__preview-media">
                  <img
                    class="mega-nav__preview-image"
                    data-mega-preview-image
                    src="https://images.unsplash.com/photo-1616486338812-3dadae4b4ace?auto=format&fit=crop&w=800&q=80"
                    alt=""
                    loading="lazy"
                  />
                </div>
                <div class="mega-nav__preview-body">
                  <p class="mega-nav__preview-eyebrow" data-mega-preview-eyebrow>
                    Latest essay
                  </p>
                  <p class="mega-nav__preview-heading" data-mega-preview-heading>
                    Silence as a design material.
                  </p>
                  <a class="mega-nav__preview-cta" href="#">Read essay</a>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </nav>

    <div class="mega-nav__scrim" data-mega-scrim aria-hidden="true"></div>

    <!-- Minimal stage so the menu is the only focus -->
    <div class="stage" aria-hidden="true"></div>

    <script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
    <script src="script.js"></script>
  </body>
</html>
````

## Source — styles.css
````css
/* =============================================================================
   Smooth Mega Menu — Premium Light
   -----------------------------------------------------------------------------
   Header-only mega menu. Soft light palette, sharp CTAs (no pill rounding).
   ============================================================================= */

/* ---------- Tokens ---------- */

:root {
  --mega-nav-height: 68px;
  --mega-nav-height-mobile: 56px;
  --mega-nav-max-width: 1120px;
  --mega-nav-pad-x: 2rem;
  --mega-nav-pad-x-mobile: 1.25rem;

  /* Premium light palette */
  --color-bg: #faf9f7;
  --color-surface: #ffffff;
  --color-stage: #f3f1ed;
  --color-border: #e8e4de;
  --color-border-soft: #efece7;
  --color-ink: #1a1917;
  --color-ink-muted: #5c5954;
  --color-ink-soft: #8a8680;
  --color-ink-faint: #a8a49c;
  --color-surface-media: #ebe7e1;
  --color-cta: #1a1917;
  --color-cta-hover: #2e2c29;
  --color-scrim: rgba(26, 25, 23, 0.18);

  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica,
    Arial, sans-serif;
  --ease-color: 0.2s ease;
  --radius-media: 2px;
  --radius-btn: 2px;
}

/* ---------- Reset ---------- */

*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html,
body {
  width: 100%;
  height: 100%;
  font-family: var(--font-sans);
  color: var(--color-ink);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  background-color: var(--color-stage);
  overflow: hidden;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  font: inherit;
  color: inherit;
  border: 0;
  background: none;
  cursor: pointer;
}

ul {
  list-style: none;
}

img {
  display: block;
  max-width: 100%;
}

/* ---------- Empty stage (menu focus only) ---------- */

.stage {
  width: 100%;
  height: 100%;
  min-height: 100dvh;
  background:
    radial-gradient(
      ellipse 80% 50% at 50% 0%,
      rgba(255, 255, 255, 0.7) 0%,
      transparent 55%
    ),
    var(--color-stage);
}

/* ---------- Mega nav shell ---------- */

.mega-nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--mega-nav-height);
  padding-left: max(
    var(--mega-nav-pad-x),
    calc((100% - var(--mega-nav-max-width)) / 2 + var(--mega-nav-pad-x))
  );
  padding-right: max(
    var(--mega-nav-pad-x),
    calc((100% - var(--mega-nav-max-width)) / 2 + var(--mega-nav-pad-x))
  );
  background-color: var(--color-bg);
  border-bottom: 1px solid var(--color-border);
  font-family: var(--font-sans);
  color: var(--color-ink);
}

.mega-nav__logo {
  flex-shrink: 0;
  z-index: 10;
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--color-ink);
  white-space: nowrap;
}

/* ---------- Primary list ---------- */

.mega-nav__list-wrap {
  position: relative;
  display: flex;
  align-items: center;
  height: 100%;
}

.mega-nav__list {
  display: flex;
  align-items: center;
  height: 100%;
  gap: 0;
}

.mega-nav__item {
  position: static;
  display: flex;
  align-items: center;
  height: 100%;
}

.mega-nav__trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  height: 100%;
  padding: 0 1.25rem;
  font-size: 0.875rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--color-ink-muted);
  white-space: nowrap;
  transition: color var(--ease-color);
}

.mega-nav__trigger:hover,
.mega-nav__trigger[aria-expanded="true"] {
  color: var(--color-ink);
}

.mega-nav__trigger-arrow {
  display: inline-block;
  width: 0.4rem;
  height: 0.4rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translateY(-1px);
  transform-origin: center;
  transition: transform 0.25s ease;
  will-change: transform;
  opacity: 0.7;
}

.mega-nav__trigger[aria-expanded="true"] .mega-nav__trigger-arrow {
  transform: rotate(-135deg) translateY(-1px);
  opacity: 1;
}

.mega-nav__indicator {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 1px;
  height: 1.5px;
  background-color: var(--color-ink);
  transform-origin: left center;
  opacity: 0;
  pointer-events: none;
  will-change: transform, opacity;
}

/* ---------- Header actions ---------- */

.mega-nav__actions {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-shrink: 0;
  z-index: 10;
}

.mega-nav__text-link {
  position: relative;
  font-size: 0.875rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--color-ink-muted);
  white-space: nowrap;
  padding-bottom: 2px;
}

.mega-nav__text-link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background-color: var(--color-ink);
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}

.mega-nav__text-link:hover {
  color: var(--color-ink);
}

.mega-nav__text-link:hover::after {
  transform: scaleX(1);
  transform-origin: left center;
}

/* Sharp CTA — smooth background only (no scale / lift) */
.mega-nav__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 38px;
  padding: 0 1.35rem;
  background-color: var(--color-cta);
  border-radius: var(--radius-btn);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #faf9f7;
  white-space: nowrap;
  transition: background-color 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}

.mega-nav__cta:hover {
  background-color: var(--color-cta-hover);
}

.mega-nav__cta:focus-visible {
  outline: 2px solid var(--color-ink);
  outline-offset: 3px;
}

/* ---------- Burger (mobile) ---------- */

.mega-nav__burger {
  display: none;
  position: relative;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  padding: 0;
}

.mega-nav__burger-line {
  position: absolute;
  left: 50%;
  width: 18px;
  height: 1.5px;
  background-color: var(--color-ink);
  transform: translateX(-50%);
  transform-origin: center;
  transition: transform 0.3s ease;
  will-change: transform;
}

.mega-nav__burger-line--top {
  top: calc(50% - 4px);
}

.mega-nav__burger-line--bottom {
  top: calc(50% + 4px);
}

.mega-nav__burger[aria-expanded="true"] .mega-nav__burger-line--top {
  transform: translate(-50%, 4px) rotate(45deg);
}

.mega-nav__burger[aria-expanded="true"] .mega-nav__burger-line--bottom {
  transform: translate(-50%, -4px) rotate(-45deg);
}

/* ---------- Dropdown shell ---------- */

.mega-nav__dropdown {
  position: fixed;
  top: var(--mega-nav-height);
  left: 0;
  right: 0;
  z-index: 190;
  background-color: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  overflow: hidden;
  transform-origin: top center;
  visibility: hidden;
  pointer-events: none;
  will-change: transform, height;
  box-shadow: 0 24px 48px rgba(26, 25, 23, 0.06);
}

.mega-nav__dropdown-inner {
  position: relative;
  width: 100%;
  height: 0;
}

.mega-nav__panel {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
  will-change: opacity;
}

.mega-nav__panel-body {
  display: flex;
  gap: 3.5rem;
  max-width: var(--mega-nav-max-width);
  margin: 0 auto;
  padding: 2.5rem 2rem 2.75rem;
}

.mega-nav__columns {
  display: flex;
  flex: 1;
  gap: 3rem;
}

.mega-nav__column {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  min-width: 150px;
  will-change: transform, opacity;
}

.mega-nav__column-label {
  display: block;
  margin-bottom: 0.65rem;
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-ink-faint);
}

/* ---------- Links ---------- */

.mega-nav__link {
  position: relative;
  display: block;
  padding: 0.3rem 0;
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: -0.015em;
  color: var(--color-ink-muted);
  transition: color var(--ease-color);
  will-change: transform, opacity;
}

.mega-nav__link:hover {
  color: var(--color-ink);
}

.mega-nav__link-dot {
  position: absolute;
  left: 0;
  top: 50%;
  display: inline-block;
  width: 0.3rem;
  height: 0.3rem;
  border-radius: 50%;
  background-color: var(--color-ink);
  transform: translateY(-50%) scale(0);
  transform-origin: center;
  pointer-events: none;
  will-change: transform;
}

.mega-nav__link-label {
  display: inline-block;
  will-change: transform;
}

/* ---------- Preview card ---------- */

.mega-nav__preview {
  flex-shrink: 0;
  width: 280px;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  will-change: opacity, transform;
}

.mega-nav__preview-media {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-media);
  overflow: hidden;
  background-color: var(--color-surface-media);
  /* GPU layer for buttery opacity blends */
  transform: translateZ(0);
}

/* Dual absolute layers — opacity crossfade only (no layout shift) */
.mega-nav__preview-image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
  pointer-events: none;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  will-change: opacity;
  /* Prevent image drag flash */
  user-select: none;
  -webkit-user-drag: none;
}

.mega-nav__preview-image--a {
  z-index: 2;
}

.mega-nav__preview-image--b {
  z-index: 1;
  opacity: 0;
}

.mega-nav__preview-body {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  overflow: hidden;
}

.mega-nav__preview-eyebrow {
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-ink-faint);
  will-change: transform, opacity;
}

.mega-nav__preview-heading {
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.4;
  color: var(--color-ink);
  will-change: transform, opacity;
}

/* Outline CTA — smooth fill + text color only (no scale / wipe) */
.mega-nav__preview-cta {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  margin-top: 0.5rem;
  height: 34px;
  padding: 0 1rem;
  background-color: transparent;
  border: 1px solid var(--color-ink);
  border-radius: var(--radius-btn);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-ink);
  transition:
    background-color 0.4s cubic-bezier(0.22, 1, 0.36, 1),
    color 0.4s cubic-bezier(0.22, 1, 0.36, 1),
    border-color 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}

.mega-nav__preview-cta:hover {
  background-color: var(--color-ink);
  color: var(--color-bg);
  border-color: var(--color-ink);
}

.mega-nav__preview-cta:focus-visible {
  outline: 2px solid var(--color-ink);
  outline-offset: 3px;
}

/* ---------- Scrim ---------- */

.mega-nav__scrim {
  position: fixed;
  top: var(--mega-nav-height);
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 180;
  background-color: var(--color-scrim);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  opacity: 0;
  pointer-events: none;
  will-change: opacity;
}

/* ---------- Mobile ---------- */

@media (max-width: 768px) {
  .mega-nav {
    flex-wrap: wrap;
    height: auto;
    padding-left: var(--mega-nav-pad-x-mobile);
    padding-right: var(--mega-nav-pad-x-mobile);
  }

  .mega-nav__logo {
    order: 1;
    display: flex;
    align-items: center;
    height: var(--mega-nav-height-mobile);
  }

  .mega-nav__burger {
    display: inline-flex;
    order: 2;
    margin-left: auto;
  }

  .mega-nav__actions {
    display: none;
  }

  .mega-nav__list-wrap {
    order: 3;
    display: block;
    width: 100%;
    height: auto;
  }

  .mega-nav__list {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    height: 0;
    border-top: 1px solid var(--color-border);
    overflow: hidden;
    opacity: 0;
    visibility: hidden;
  }

  .mega-nav__dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    width: auto;
    border-top: 1px solid var(--color-border);
    border-bottom: none;
    overflow: hidden;
    transform-origin: top center;
    display: none;
    box-shadow: none;
  }

  .mega-nav[data-mobile-open="true"] .mega-nav__dropdown {
    display: block;
  }

  .mega-nav__indicator {
    display: none;
  }

  .mega-nav__item {
    flex-direction: column;
    align-items: stretch;
    height: auto;
  }

  .mega-nav__trigger {
    justify-content: space-between;
    height: 48px;
    padding: 0 1.25rem 0 0;
    border-bottom: 1px solid var(--color-border-soft);
  }

  .mega-nav__panel-body {
    flex-direction: column;
    gap: 1.5rem;
    padding: 1.25rem 1.25rem 1.5rem;
  }

  .mega-nav__columns {
    flex-direction: column;
    gap: 1.5rem;
  }

  .mega-nav__preview {
    display: none;
  }

  .mega-nav__scrim {
    display: none;
  }
}

/* ---------- Reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  .mega-nav__trigger-arrow,
  .mega-nav__trigger,
  .mega-nav__link,
  .mega-nav__burger-line,
  .mega-nav__cta,
  .mega-nav__preview-cta,
  .mega-nav__text-link::after {
    transition: none;
  }
}
````

## Source — script.js
````javascript
/**
 * Smooth Mega Menu
 * ----------------
 * Desktop: hover (with open/close delay) opens full-width mega panels.
 * Mobile / touch / reduced-motion: click opens panels; burger expands the list.
 *
 * Features
 * 1. Direction-aware panel enter (from left/right when switching items)
 * 2. scaleY dropdown open + scrim fade
 * 3. Underline indicator under the active trigger
 * 4. Link hover: dot scale + label shift
 * 5. Live preview image / eyebrow / heading swap on link hover
 * 6. Keyboard: arrows, Escape, Home/End
 *
 * Config (data-* on [data-mega-nav]):
 *   data-duration, data-ease, data-stagger,
 *   data-trigger-event, data-open-delay, data-close-delay,
 *   data-direction-aware, data-mobile-breakpoint
 */

(function () {
  "use strict";

  /* ---------- boot when GSAP is ready ---------- */

  function whenReady(callback, attempt) {
    attempt = attempt || 0;
    if (typeof gsap === "undefined") {
      if (attempt < 100) {
        setTimeout(function () {
          whenReady(callback, attempt + 1);
        }, 50);
      } else {
        console.error("[Smooth Mega Menu] GSAP failed to load");
      }
      return;
    }
    callback();
  }

  whenReady(function () {
    const instances = [];

    document.querySelectorAll("[data-mega-nav]").forEach(function (root) {
      const api = initMegaNav(root);
      if (api) instances.push(api);
    });

    window.SmoothMegaMenu = {
      refresh: function () {
        instances.forEach(function (api) {
          if (api.kill) api.kill();
        });
        instances.length = 0;
        document.querySelectorAll("[data-mega-nav]").forEach(function (root) {
          const api = initMegaNav(root);
          if (api) instances.push(api);
        });
      },
      open: function (index) {
        instances.forEach(function (api) {
          api.open(index);
        });
      },
      close: function () {
        instances.forEach(function (api) {
          api.close();
        });
      },
    };
  });

  /* ---------- one mega-nav instance ---------- */

  function initMegaNav(root) {
    const items = Array.from(root.querySelectorAll("[data-mega-item]"));
    const triggers = Array.from(root.querySelectorAll("[data-mega-trigger]"));
    const burger = root.querySelector("[data-mega-burger]");
    const dropdown = root.querySelector("[data-mega-dropdown]");
    const dropdownInner = dropdown
      ? dropdown.querySelector(".mega-nav__dropdown-inner")
      : null;
    const panels = dropdown
      ? Array.from(dropdown.querySelectorAll("[data-mega-panel]"))
      : [];
    const indicator = root.querySelector("[data-mega-indicator]");
    const scrim = document.querySelector("[data-mega-scrim]");
    const navList = root.querySelector(".mega-nav__list");

    if (!items.length || !dropdown || !dropdownInner || !panels.length) {
      return null;
    }

    /* Config */
    const duration = parseFloat(root.dataset.duration || "0.5");
    const ease = root.dataset.ease || "expo.out";
    const stagger = parseFloat(root.dataset.stagger || "0.04");
    let triggerEvent = root.dataset.triggerEvent || "hover";
    const openDelay = parseFloat(root.dataset.openDelay || "0.15");
    const closeDelay = parseFloat(root.dataset.closeDelay || "0.2");
    const directionAware =
      (root.dataset.directionAware || "true").toLowerCase() !== "false";
    const mobileBreakpoint = parseInt(
      root.dataset.mobileBreakpoint || "768",
      10
    );

    const openDelayMs = Math.round(openDelay * 1000);
    const closeDelayMs = Math.round(closeDelay * 1000);

    /* Animation constants */
    const CROSSFADE = 0.18;
    const OPEN_SCALE = 0.3;
    const LINK_HOVER_DURATION = 0.45;
    const LINK_HOVER_EASE = "power3.out";
    const PREVIEW_CROSSFADE = 0.55;
    const PREVIEW_TEXT_OUT = 0.2;
    const PREVIEW_TEXT_IN = 0.4;

    let activeIndex = -1;
    const openTimers = {};
    let closeTimer = null;
    const panelHeights = [];
    const panelParts = [];
    const previewState = [];
    let openTimeline = null;
    let contentTimeline = null;
    let mobileTimeline = null;
    let resizeTimer = null;
    let wasMobile = isMobile();

    /* ---------- helpers ---------- */

    function isMobile() {
      return window.innerWidth <= mobileBreakpoint;
    }

    function clearOpenTimer(index) {
      if (openTimers[index]) {
        clearTimeout(openTimers[index]);
        openTimers[index] = null;
      }
    }

    function clearCloseTimer() {
      if (closeTimer) {
        clearTimeout(closeTimer);
        closeTimer = null;
      }
    }

    function setTriggerExpanded(index, expanded) {
      const trigger = triggers[index];
      if (trigger) {
        trigger.setAttribute("aria-expanded", expanded ? "true" : "false");
      }
    }

    function setPanelHidden(index, hidden) {
      const panel = panels[index];
      if (!panel) return;
      panel.setAttribute("aria-hidden", hidden ? "true" : "false");
      if (hidden) panel.setAttribute("inert", "");
      else panel.removeAttribute("inert");
    }

    function focusFirstLink(index) {
      const panel = panels[index];
      if (!panel) return;
      const first = panel.querySelector("[data-mega-link]");
      if (first) first.focus();
    }

    /**
     * Direction from previous → next active item.
     *  1 = forward (enter from left), -1 = backward (enter from right)
     */
    function getDirection(nextIndex, prevIndex) {
      if (prevIndex === -1 || prevIndex === nextIndex) return 1;
      return nextIndex > prevIndex ? 1 : -1;
    }

    function offsetXForCols(dir) {
      if (!directionAware) return -64;
      return dir === 1 ? -64 : 64;
    }

    function offsetXForLinks(dir) {
      if (!directionAware) return -18;
      return dir === 1 ? -18 : 18;
    }

    function staggerConfig(dir) {
      if (directionAware && dir === -1) {
        return { each: stagger, from: "end" };
      }
      return { each: stagger, from: "start" };
    }

    /* ---------- measure ---------- */

    function measurePanelHeights() {
      const prevDisplay = dropdown.style.display;
      const prevVisibility = dropdown.style.visibility;
      const prevHeight = dropdownInner.style.height;

      dropdown.style.display = "block";
      dropdown.style.visibility = "hidden";
      dropdownInner.style.height = "auto";

      panels.forEach(function (panel, index) {
        const prevPos = panel.style.position;
        const prevVis = panel.style.visibility;
        const prevOp = panel.style.opacity;

        panel.style.position = "relative";
        panel.style.visibility = "hidden";
        panel.style.opacity = "0";
        panelHeights[index] = panel.offsetHeight;

        panel.style.position = prevPos;
        panel.style.visibility = prevVis;
        panel.style.opacity = prevOp;
      });

      dropdown.style.display = prevDisplay;
      dropdown.style.visibility = prevVisibility;
      dropdownInner.style.height = prevHeight;
    }

    function cachePanelParts() {
      panels.forEach(function (panel, index) {
        const preview = panel.querySelector("[data-mega-preview]");
        panelParts[index] = {
          columns: Array.from(panel.querySelectorAll("[data-mega-column]")),
          links: Array.from(panel.querySelectorAll("[data-mega-link]")),
          preview: preview,
          previewImg: preview
            ? preview.querySelector("[data-mega-preview-image]")
            : null,
        };
      });
    }

    function cachePreviewDefaults() {
      panels.forEach(function (panel, index) {
        const img = panel.querySelector("[data-mega-preview-image]");
        const eyebrow = panel.querySelector("[data-mega-preview-eyebrow]");
        const heading = panel.querySelector("[data-mega-preview-heading]");

        if (!img && !eyebrow && !heading) {
          previewState[index] = null;
          return;
        }

        const defaultSrc = img ? img.getAttribute("src") || "" : "";

        const state = {
          imgEl: img,
          layerA: img,
          layerB: null,
          front: img,
          back: null,
          eyebrowEl: eyebrow,
          headingEl: heading,
          src: defaultSrc,
          eyebrow: eyebrow ? eyebrow.textContent : "",
          heading: heading ? heading.textContent : "",
          currentSrc: defaultSrc,
          pendingSrc: null,
          swapToken: 0,
          swapTl: null,
          textTl: null,
        };

        /* Dual layers: always crossfade opacity (never swap src on the visible image) */
        if (img && img.parentElement) {
          const media = img.parentElement;
          media.classList.add("mega-nav__preview-media--ready");

          const layerB = document.createElement("img");
          layerB.className = "mega-nav__preview-image mega-nav__preview-image--b";
          layerB.alt = "";
          layerB.setAttribute("aria-hidden", "true");
          layerB.decoding = "async";
          layerB.draggable = false;
          media.appendChild(layerB);

          img.classList.add("mega-nav__preview-image--a");
          img.decoding = "async";
          img.draggable = false;

          gsap.set(img, { opacity: 1, zIndex: 2, force3D: true });
          gsap.set(layerB, { opacity: 0, zIndex: 1, force3D: true });

          state.layerB = layerB;
          state.back = layerB;
        }

        previewState[index] = state;
      });

      preloadAllPreviewImages();
    }

    /** Warm the browser cache so hover swaps never wait on the network. */
    function preloadAllPreviewImages() {
      const urls = new Set();

      panels.forEach(function (panel) {
        const main = panel.querySelector("[data-mega-preview-image]");
        if (main && main.getAttribute("src")) {
          urls.add(main.getAttribute("src"));
        }
        panel.querySelectorAll("[data-preview-src]").forEach(function (link) {
          const src = link.getAttribute("data-preview-src");
          if (src) urls.add(src);
        });
      });

      urls.forEach(function (url) {
        const probe = new Image();
        probe.decoding = "async";
        probe.src = url;
      });
    }

    /**
     * Resolve when `img` has pixels for `src` (decode when supported).
     * Never leaves a half-loaded frame in the crossfade.
     */
    function whenImageReady(img, src) {
      return new Promise(function (resolve) {
        var settled = false;

        function done() {
          if (settled) return;
          settled = true;
          resolve(img);
        }

        function assignAndWait() {
          function onLoad() {
            img.removeEventListener("load", onLoad);
            img.removeEventListener("error", onError);
            if (img.decode) {
              img.decode().then(done).catch(done);
            } else {
              done();
            }
          }

          function onError() {
            img.removeEventListener("load", onLoad);
            img.removeEventListener("error", onError);
            done();
          }

          /* Already showing this decoded source */
          if (
            img.getAttribute("src") === src &&
            img.complete &&
            img.naturalWidth > 0
          ) {
            done();
            return;
          }

          img.addEventListener("load", onLoad);
          img.addEventListener("error", onError);
          img.src = src;

          /* Cached: complete may flip true immediately after .src set */
          if (img.complete && img.naturalWidth > 0) {
            img.removeEventListener("load", onLoad);
            img.removeEventListener("error", onError);
            if (img.decode) {
              img.decode().then(done).catch(done);
            } else {
              done();
            }
          }
        }

        assignAndWait();
      });
    }

    /* ---------- preview swap (opacity-only dual-layer crossfade) ---------- */

    function animatePreviewText(state, eyebrow, heading) {
      const textEls = [state.eyebrowEl, state.headingEl].filter(Boolean);
      if (!textEls.length) return;

      if (state.textTl) state.textTl.kill();

      state.textTl = gsap
        .timeline()
        .to(textEls, {
          y: -6,
          opacity: 0,
          duration: PREVIEW_TEXT_OUT,
          ease: "power2.in",
          stagger: 0.025,
          overwrite: "auto",
        })
        .add(function () {
          if (state.eyebrowEl && eyebrow !== undefined) {
            state.eyebrowEl.textContent = eyebrow;
          }
          if (state.headingEl && heading !== undefined) {
            state.headingEl.textContent = heading;
          }
        })
        .set(textEls, { y: 8 })
        .to(textEls, {
          y: 0,
          opacity: 1,
          duration: PREVIEW_TEXT_IN,
          ease: "power3.out",
          stagger: 0.04,
          overwrite: "auto",
        });
    }

    function crossfadeLayers(state, fromLayer, toLayer) {
      if (state.swapTl) {
        state.swapTl.kill();
        state.swapTl = null;
      }

      /* Kill any stray tweens on either layer */
      gsap.killTweensOf([fromLayer, toLayer]);

      /* Stack: new image on top, fully transparent — old stays solid underneath */
      gsap.set(toLayer, {
        opacity: 0,
        zIndex: 3,
        force3D: true,
      });
      gsap.set(fromLayer, {
        opacity: 1,
        zIndex: 2,
        force3D: true,
      });

      state.swapTl = gsap.timeline({
        defaults: { ease: "power2.inOut", force3D: true },
        onComplete: function () {
          gsap.set(fromLayer, { opacity: 0, zIndex: 1 });
          gsap.set(toLayer, { opacity: 1, zIndex: 2 });
          state.front = toLayer;
          state.back = fromLayer;
          state.swapTl = null;
        },
      });

      /* Simultaneous equal-length opacity blend — true dissolve, no pop */
      state.swapTl.to(
        toLayer,
        {
          opacity: 1,
          duration: PREVIEW_CROSSFADE,
        },
        0
      );
      state.swapTl.to(
        fromLayer,
        {
          opacity: 0,
          duration: PREVIEW_CROSSFADE,
        },
        0
      );
    }

    function swapPreview(panelIndex, src, eyebrow, heading) {
      const state = previewState[panelIndex];
      if (!state || !src) return;

      /* Same image: only update copy if needed */
      if (state.currentSrc === src && state.pendingSrc === null) {
        if (state.eyebrowEl && eyebrow !== undefined) {
          state.eyebrowEl.textContent = eyebrow;
        }
        if (state.headingEl && heading !== undefined) {
          state.headingEl.textContent = heading;
        }
        return;
      }

      const prevSrc = state.currentSrc;
      state.currentSrc = src;
      state.pendingSrc = src;

      if (eyebrow !== undefined || heading !== undefined) {
        animatePreviewText(state, eyebrow, heading);
      }

      if (!state.layerA || !state.layerB) {
        /* Single-layer fallback */
        if (!state.imgEl) return;
        const token = ++state.swapToken;
        whenImageReady(state.imgEl, src).then(function () {
          if (token !== state.swapToken) return;
          state.pendingSrc = null;
        });
        return;
      }

      const fromLayer = state.front || state.layerA;
      const toLayer =
        fromLayer === state.layerA ? state.layerB : state.layerA;

      const token = ++state.swapToken;

      whenImageReady(toLayer, src).then(function () {
        /* A newer hover won — discard this frame */
        if (token !== state.swapToken) return;
        if (state.currentSrc !== src) return;

        state.pendingSrc = null;
        crossfadeLayers(state, fromLayer, toLayer);
      });

      /* If user left before load finished, currentSrc still tracks intent */
      if (prevSrc === src) {
        state.pendingSrc = null;
      }
    }

    function resetPreview(panelIndex) {
      const state = previewState[panelIndex];
      if (!state) return;
      swapPreview(panelIndex, state.src, state.eyebrow, state.heading);
    }

    /* ---------- content enter timeline ---------- */

    function buildContentTimeline(panelIndex, dir) {
      const tl = gsap.timeline({
        paused: true,
        defaults: { ease: "power3.out", force3D: true },
      });
      const parts = panelParts[panelIndex];
      if (!parts) return tl;

      const colX = offsetXForCols(dir);
      const linkX = offsetXForLinks(dir);
      const colStagger = staggerConfig(dir);
      const linkStagger = { each: stagger * 0.5, from: "start" };

      if (parts.columns.length) {
        tl.fromTo(
          parts.columns,
          { x: colX, autoAlpha: 0 },
          {
            x: 0,
            autoAlpha: 1,
            duration: duration * 0.7,
            stagger: colStagger,
          },
          0
        );
      }

      if (parts.links.length) {
        tl.fromTo(
          parts.links,
          { x: linkX, autoAlpha: 0 },
          {
            x: 0,
            autoAlpha: 1,
            duration: duration * 0.5,
            stagger: linkStagger,
          },
          duration * 0.15
        );
      }

      if (parts.preview) {
        tl.fromTo(
          parts.preview,
          { x: colX * 0.6, autoAlpha: 0 },
          {
            x: 0,
            autoAlpha: 1,
            duration: duration * 0.7,
          },
          0
        );
      }

      /* Soft settle on the visible front image only (no scale fight with swaps) */
      if (parts.previewImg) {
        const previewStateItem = previewState[panelIndex];
        const frontImg =
          (previewStateItem && previewStateItem.front) || parts.previewImg;
        tl.fromTo(
          frontImg,
          { scale: 1.04 },
          {
            scale: 1,
            duration: duration * 1.1,
            ease: "power2.out",
          },
          0
        );
      }

      return tl;
    }

    function clearContentProps(panelIndex) {
      const parts = panelParts[panelIndex];
      if (!parts) return;

      if (parts.columns.length) {
        gsap.set(parts.columns, {
          clearProps: "transform,opacity,visibility",
        });
      }
      if (parts.links.length) {
        gsap.set(parts.links, {
          clearProps: "transform,opacity,visibility",
        });
      }
      if (parts.preview) {
        gsap.set(parts.preview, {
          clearProps: "transform,opacity,visibility",
        });
      }
      if (parts.previewImg) {
        gsap.set(parts.previewImg, { clearProps: "transform" });
      }
    }

    /* ---------- open / close / switch ---------- */

    function buildOpenShellTimeline() {
      const tl = gsap.timeline({
        paused: true,
        defaults: { ease: "power3.out", force3D: true },
      });

      tl.fromTo(
        dropdown,
        { scaleY: 0, transformOrigin: "top center" },
        { scaleY: 1, duration: OPEN_SCALE },
        0
      );

      if (scrim) {
        tl.fromTo(
          scrim,
          { autoAlpha: 0, pointerEvents: "none" },
          {
            autoAlpha: 1,
            pointerEvents: "auto",
            duration: OPEN_SCALE,
          },
          0
        );
      }

      return tl;
    }

    function moveIndicator(index, animate) {
      if (!indicator) return;
      const trigger = triggers[index];
      if (!trigger) return;

      const x = trigger.offsetLeft;
      const width = trigger.offsetWidth;

      if (animate) {
        gsap.to(indicator, {
          x: x,
          scaleX: width,
          autoAlpha: 1,
          duration: 0.4,
          ease: ease,
          force3D: true,
          overwrite: "auto",
        });
      } else {
        gsap.fromTo(
          indicator,
          { x: x, scaleX: width, autoAlpha: 0 },
          {
            autoAlpha: 1,
            duration: duration * 0.6,
            ease: ease,
            force3D: true,
            overwrite: "auto",
          }
        );
      }
    }

    function hideIndicator() {
      if (!indicator) return;
      gsap.to(indicator, {
        autoAlpha: 0,
        duration: duration * 0.4,
        ease: "expo.in",
        overwrite: "auto",
      });
    }

    function openPanel(index) {
      const dir = getDirection(index, activeIndex);
      activeIndex = index;

      setTriggerExpanded(index, true);
      setPanelHidden(index, false);
      resetPreview(index);
      clearContentProps(index);

      gsap.set(dropdownInner, { height: panelHeights[index] });
      gsap.set(panels[index], { autoAlpha: 1, pointerEvents: "auto" });
      gsap.set(dropdown, {
        visibility: "visible",
        pointerEvents: "auto",
      });

      if (scrim) scrim.setAttribute("aria-hidden", "false");

      if (openTimeline) openTimeline.kill();
      if (contentTimeline) contentTimeline.kill();

      openTimeline = buildOpenShellTimeline();
      contentTimeline = buildContentTimeline(index, dir);

      openTimeline.play(0);
      gsap.delayedCall(0.18, function () {
        if (contentTimeline) contentTimeline.play(0);
      });

      moveIndicator(index, false);
    }

    function closePanel() {
      if (activeIndex === -1) return;

      const index = activeIndex;
      activeIndex = -1;

      setTriggerExpanded(index, false);
      setPanelHidden(index, true);
      if (scrim) scrim.setAttribute("aria-hidden", "true");

      function hideShell() {
        gsap.set(dropdownInner, { height: 0 });
        gsap.set(panels[index], {
          autoAlpha: 0,
          pointerEvents: "none",
        });
        gsap.set(dropdown, {
          visibility: "hidden",
          pointerEvents: "none",
        });
      }

      function reverseShell() {
        if (openTimeline && openTimeline.progress() > 0) {
          openTimeline.eventCallback("onReverseComplete", hideShell);
          openTimeline.reverse();
        } else {
          hideShell();
        }
      }

      if (contentTimeline && contentTimeline.progress() > 0) {
        contentTimeline.eventCallback("onReverseComplete", reverseShell);
        contentTimeline.reverse();
      } else {
        reverseShell();
      }

      hideIndicator();
    }

    function switchPanel(index) {
      const prev = activeIndex;
      if (prev === index) return;

      const dir = getDirection(index, prev);
      activeIndex = index;

      setTriggerExpanded(prev, false);
      setPanelHidden(prev, true);
      setTriggerExpanded(index, true);
      setPanelHidden(index, false);
      resetPreview(index);

      gsap.to(panels[prev], {
        autoAlpha: 0,
        pointerEvents: "none",
        duration: CROSSFADE,
        ease: "expo.in",
        overwrite: "auto",
      });

      gsap.to(dropdownInner, {
        height: panelHeights[index],
        duration: 0.4,
        ease: "power3.out",
        overwrite: "auto",
      });

      gsap.set(panels[index], { autoAlpha: 0 });
      gsap.to(panels[index], {
        autoAlpha: 1,
        pointerEvents: "auto",
        duration: 0.27,
        ease: "power3.out",
        delay: 0.126,
        overwrite: "auto",
      });

      if (contentTimeline) contentTimeline.kill();
      clearContentProps(index);
      contentTimeline = buildContentTimeline(index, dir);

      gsap.delayedCall(0.126, function () {
        if (contentTimeline) contentTimeline.play(0);
      });

      moveIndicator(index, true);
    }

    function setActive(index) {
      if (index === activeIndex) return;
      if (activeIndex === -1) openPanel(index);
      else switchPanel(index);
    }

    function scheduleClose() {
      clearCloseTimer();
      closeTimer = setTimeout(function () {
        closeTimer = null;
        closePanel();
      }, closeDelayMs);
    }

    /* ---------- mobile drawer ---------- */

    function setMobileOpen(open) {
      if (burger) {
        burger.setAttribute("aria-expanded", open ? "true" : "false");
        burger.setAttribute(
          "aria-label",
          open ? "Close menu" : "Open menu"
        );
      }

      if (open) {
        root.setAttribute("data-mobile-open", "true");
        if (mobileTimeline) mobileTimeline.kill();

        mobileTimeline = gsap.timeline({
          paused: true,
          defaults: { ease: "power3.out", force3D: true },
        });

        if (navList) {
          mobileTimeline.fromTo(
            navList,
            { height: 0, autoAlpha: 0 },
            {
              height: "auto",
              autoAlpha: 1,
              duration: OPEN_SCALE,
            },
            0
          );
        }

        if (triggers.length) {
          mobileTimeline.fromTo(
            triggers,
            { y: -8, autoAlpha: 0 },
            {
              y: 0,
              autoAlpha: 1,
              duration: duration * 0.5,
              stagger: stagger * 1.5,
            },
            0.12
          );
        }

        mobileTimeline.play(0);
        return;
      }

      const hadPanel = activeIndex !== -1;
      const prevIndex = activeIndex;

      function finishClose() {
        root.removeAttribute("data-mobile-open");
        if (navList) gsap.set(navList, { clearProps: "all" });
        if (triggers.length) {
          gsap.set(triggers, {
            clearProps: "transform,opacity,visibility",
          });
        }
        if (hadPanel) {
          gsap.set(dropdownInner, { height: 0 });
          gsap.set(panels[prevIndex], {
            autoAlpha: 0,
            pointerEvents: "none",
          });
          gsap.set(dropdown, {
            visibility: "hidden",
            pointerEvents: "none",
            clearProps: "transform,scaleY",
          });
          if (scrim) {
            gsap.set(scrim, { autoAlpha: 0, pointerEvents: "none" });
          }
        }
      }

      if (hadPanel) {
        activeIndex = -1;
        setTriggerExpanded(prevIndex, false);
        setPanelHidden(prevIndex, true);
        if (scrim) scrim.setAttribute("aria-hidden", "true");
        if (contentTimeline) contentTimeline.kill();
        if (openTimeline) openTimeline.kill();
      }

      if (mobileTimeline && mobileTimeline.progress() > 0) {
        if (hadPanel) {
          const d = mobileTimeline.duration();
          gsap.to(panels[prevIndex], {
            autoAlpha: 0,
            duration: d * 0.35,
            ease: "power2.out",
            overwrite: "auto",
          });
          gsap.to(dropdown, {
            scaleY: 0,
            duration: d,
            ease: "power3.out",
            force3D: true,
            overwrite: "auto",
          });
          if (scrim) {
            gsap.to(scrim, {
              autoAlpha: 0,
              duration: d,
              ease: "power3.out",
              overwrite: "auto",
            });
          }
        }
        mobileTimeline.eventCallback("onReverseComplete", finishClose);
        mobileTimeline.reverse();
      } else {
        finishClose();
      }
    }

    /* ---------- link hover (dot + label) ---------- */

    function bindLinkHover(link) {
      const dot = link.querySelector(".mega-nav__link-dot");
      const label = link.querySelector(".mega-nav__link-label");
      if (!dot || !label) return;

      link.addEventListener("mouseenter", function () {
        const shift = dot.offsetWidth + 10;
        gsap.to(dot, {
          scale: 1,
          duration: LINK_HOVER_DURATION,
          ease: "back.out(1.6)",
          overwrite: "auto",
          force3D: true,
        });
        gsap.to(label, {
          x: shift,
          duration: LINK_HOVER_DURATION,
          ease: LINK_HOVER_EASE,
          overwrite: "auto",
          force3D: true,
        });
      });

      link.addEventListener("mouseleave", function () {
        gsap.to(dot, {
          scale: 0,
          duration: 0.32,
          ease: "power2.inOut",
          overwrite: "auto",
          force3D: true,
        });
        gsap.to(label, {
          x: 0,
          duration: 0.35,
          ease: "power3.out",
          overwrite: "auto",
          force3D: true,
        });
      });
    }

    /* ---------- events ---------- */

    /* Measure + cache before binding (links need panelParts) */
    cachePanelParts();
    cachePreviewDefaults();
    measurePanelHeights();

    function onTriggerEnter(index) {
      if (isMobile()) return;
      clearCloseTimer();
      clearOpenTimer(index);
      openTimers[index] = setTimeout(function () {
        openTimers[index] = null;
        setActive(index);
      }, openDelayMs);
    }

    function onTriggerLeave(index, event) {
      if (isMobile()) return;
      clearOpenTimer(index);
      if (dropdown && dropdown.contains(event.relatedTarget)) return;
      scheduleClose();
    }

    function onTriggerClick(index, event) {
      const isKeyboard = event && event.detail === 0;
      if (activeIndex !== index) {
        clearOpenTimer(index);
        clearCloseTimer();
        setActive(index);
        if (isKeyboard) focusFirstLink(index);
      } else {
        closePanel();
      }
    }

    /* Bind triggers */
    items.forEach(function (_item, index) {
      const trigger = triggers[index];
      if (!trigger) return;

      if (triggerEvent !== "click") {
        trigger.addEventListener("mouseenter", function () {
          onTriggerEnter(index);
        });
        trigger.addEventListener("mouseleave", function (event) {
          onTriggerLeave(index, event);
        });
      }

      trigger.addEventListener("click", function (event) {
        onTriggerClick(index, event);
      });

      trigger.addEventListener("keydown", function (event) {
        if (event.key === "ArrowDown") {
          event.preventDefault();
          if (activeIndex !== index) setActive(index);
          focusFirstLink(index);
        } else if (event.key === "ArrowRight") {
          event.preventDefault();
          const next = (index + 1) % triggers.length;
          triggers[next].focus();
          if (activeIndex !== -1) setActive(next);
        } else if (event.key === "ArrowLeft") {
          event.preventDefault();
          const prev = (index - 1 + triggers.length) % triggers.length;
          triggers[prev].focus();
          if (activeIndex !== -1) setActive(prev);
        }
      });
    });

    /* Bind panel links */
    panels.forEach(function (_panel, panelIndex) {
      const links = panelParts[panelIndex]
        ? panelParts[panelIndex].links
        : [];

      links.forEach(function (link, linkIndex) {
        bindLinkHover(link);

        function applyPreviewFromLink() {
          const src = link.getAttribute("data-preview-src");
          if (!src) {
            resetPreview(panelIndex);
            return;
          }
          const state = previewState[panelIndex];
          swapPreview(
            panelIndex,
            src,
            link.getAttribute("data-preview-eyebrow") ||
              (state ? state.eyebrow : ""),
            link.getAttribute("data-preview-heading") ||
              (state ? state.heading : "")
          );
        }

        link.addEventListener("mouseenter", applyPreviewFromLink);
        link.addEventListener("focus", applyPreviewFromLink);
        link.addEventListener("mouseleave", function () {
          resetPreview(panelIndex);
        });

        link.addEventListener("keydown", function (event) {
          if (event.key === "ArrowDown") {
            event.preventDefault();
            const next = links[linkIndex + 1];
            if (next) next.focus();
          } else if (event.key === "ArrowUp") {
            event.preventDefault();
            if (linkIndex === 0) triggers[panelIndex].focus();
            else links[linkIndex - 1].focus();
          } else if (event.key === "ArrowRight") {
            event.preventDefault();
            const next = (panelIndex + 1) % triggers.length;
            triggers[next].focus();
            setActive(next);
          } else if (event.key === "ArrowLeft") {
            event.preventDefault();
            const prev =
              (panelIndex - 1 + triggers.length) % triggers.length;
            triggers[prev].focus();
            setActive(prev);
          } else if (event.key === "Home") {
            event.preventDefault();
            if (links[0]) links[0].focus();
          } else if (event.key === "End") {
            event.preventDefault();
            if (links[links.length - 1]) links[links.length - 1].focus();
          }
        });
      });
    });

    /* Dropdown keep-open / leave */
    if (dropdown) {
      dropdown.addEventListener("mouseenter", function () {
        if (!isMobile()) clearCloseTimer();
      });
      dropdown.addEventListener("mouseleave", function (event) {
        if (isMobile()) return;
        if (root.contains(event.relatedTarget)) return;
        scheduleClose();
      });
    }

    if (scrim) {
      scrim.addEventListener("click", function () {
        clearCloseTimer();
        closePanel();
      });
    }

    if (burger) {
      burger.addEventListener("click", function () {
        const open = burger.getAttribute("aria-expanded") === "true";
        setMobileOpen(!open);
      });
    }

    function onDocumentKeydown(event) {
      if (event.key === "Escape" && activeIndex !== -1) {
        clearCloseTimer();
        const index = activeIndex;
        closePanel();
        if (triggers[index]) triggers[index].focus();
      }
    }

    function onDocumentClick(event) {
      if (activeIndex === -1) return;
      if (root.contains(event.target)) return;
      if (scrim && scrim.contains(event.target)) return;
      closePanel();
    }

    document.addEventListener("keydown", onDocumentKeydown);
    document.addEventListener("click", onDocumentClick);

    /* Focus out: close when focus leaves the nav + dropdown */
    items.forEach(function (item, index) {
      item.addEventListener("focusout", function (event) {
        if (!event.relatedTarget) return;
        if (dropdown && dropdown.contains(event.relatedTarget)) return;
        if (!root.contains(event.relatedTarget) && activeIndex === index) {
          closePanel();
        }
      });
    });

    if (dropdown) {
      dropdown.addEventListener("focusout", function (event) {
        if (!event.relatedTarget) return;
        if (!root.contains(event.relatedTarget)) closePanel();
      });
    }

    function onResize() {
      clearTimeout(resizeTimer);
      resizeTimer = setTimeout(function () {
        const mobile = isMobile();
        if (mobile !== wasMobile) {
          wasMobile = mobile;
          setMobileOpen(false);
        }
        measurePanelHeights();
        if (activeIndex !== -1) {
          gsap.set(dropdownInner, { height: panelHeights[activeIndex] });
          moveIndicator(activeIndex, false);
        }
      }, 150);
    }

    function onVisibility() {
      if (document.hidden) gsap.globalTimeline.pause();
      else gsap.globalTimeline.resume();
    }

    window.addEventListener("resize", onResize);
    document.addEventListener("visibilitychange", onVisibility);

    /* Reduced motion + coarse pointer → click only */
    gsap.matchMedia().add("(prefers-reduced-motion: reduce)", function () {
      gsap.globalTimeline.timeScale(20);
      triggerEvent = "click";
      return function () {
        gsap.globalTimeline.timeScale(1);
      };
    });

    gsap.matchMedia().add("(pointer: coarse)", function () {
      triggerEvent = "click";
    });

    /* ---------- initial presentation ---------- */

    gsap.set(dropdown, {
      scaleY: 0,
      visibility: "hidden",
      pointerEvents: "none",
      force3D: true,
    });
    gsap.set(dropdownInner, { height: 0 });
    gsap.set(panels, { autoAlpha: 0 });
    if (scrim) gsap.set(scrim, { autoAlpha: 0 });
    if (indicator) gsap.set(indicator, { autoAlpha: 0, x: 0, scaleX: 0 });

    panels.forEach(function (panel) {
      panel.setAttribute("aria-hidden", "true");
      panel.setAttribute("inert", "");
    });
    triggers.forEach(function (trigger) {
      trigger.setAttribute("aria-expanded", "false");
    });

    return {
      open: function (index) {
        if (typeof index !== "undefined") setActive(index);
      },
      close: function () {
        closePanel();
      },
      setActive: setActive,
      refresh: function () {
        closePanel();
        cachePanelParts();
        cachePreviewDefaults();
        measurePanelHeights();
      },
      kill: function () {
        window.removeEventListener("resize", onResize);
        document.removeEventListener("visibilitychange", onVisibility);
        document.removeEventListener("keydown", onDocumentKeydown);
        document.removeEventListener("click", onDocumentClick);
        clearCloseTimer();
        Object.keys(openTimers).forEach(clearOpenTimer);
        if (openTimeline) openTimeline.kill();
        if (contentTimeline) contentTimeline.kill();
        if (mobileTimeline) mobileTimeline.kill();
      },
    };
  }
})();
````
