website_designs

3D Immersive Design Reference

Overview

3D Immersive web design is a spatial, depth-driven aesthetic that leverages WebGL, Three.js, and GPU-accelerated rendering to transform flat browser windows into navigable three-dimensional environments. Rather than presenting content on a traditional 2D plane, this approach treats the viewport as a window into a scene with real depth, perspective, and physicality. Users scroll through layered parallax landscapes, interact with rotating 3D models, and trigger cinematic camera movements that unfold content like a directed visual narrative.

The aesthetic emerged from the convergence of powerful browser APIs (WebGL, WebGPU), mature JavaScript frameworks (Three.js, Babylon.js, R3F), and animation orchestration libraries like GSAP with its ScrollTrigger plugin. Together, these tools enable designers to build environments where scroll position drives camera paths, lighting transitions, and shader-based visual effects – turning passive browsing into active exploration. Background layers move slower than foreground elements, creating the parallax depth illusion that has become a hallmark of the style.

Visually, 3D Immersive design favors dark, atmospheric backgrounds that allow luminous 3D objects and volumetric lighting to take center stage. Color palettes lean toward deep space blacks, rich indigos, and slate blues, punctuated by electric accent colors – neon cyan, violet, warm amber – that serve as focal points within the dimensional space. Typography is clean and geometric, chosen for legibility against complex 3D backdrops, and often integrated spatially so that text planes recede or advance in the z-axis.

Performance is a first-class concern. The difference between janky 30fps parallax and buttery smooth 60fps GPU-accelerated rendering is immediately felt by users. Optimized model formats (glTF, GLB, Draco-compressed meshes), lazy-loaded assets, and progressive enhancement ensure the experience remains fast. By 2026, 3D immersive design has matured from experimental gimmick to purposeful, interactive spatial storytelling – responsive across desktop, tablet, and mobile without breaking layout or usability.


Visual Characteristics

Core Design Traits

Design Principles


Color Palette

3D Immersive design relies on dark, atmospheric base colors that recede visually, allowing luminous accents, light sources, and 3D geometry to command attention. The palette draws from deep space, underwater environments, and cinematic sci-fi lighting – rich blacks and indigos as canvas, with electric blues, violets, and warm ambers as focal-point accents.

Swatch Hex Role/Usage
Void Black #0B0B0F Primary page background; deepest depth layer
Deep Space #101018 Secondary background; scene container
Midnight Indigo #161630 Card and panel backgrounds
Slate Abyss #1E1E2E Elevated surface; modal backgrounds
Neon Cyan #00E5FF Primary accent; interactive highlights, links
Electric Violet #7C3AED Secondary accent; gradients, glow effects
Plasma Magenta #E040FB Tertiary accent; hover states, particle trails
Amber Glow #F59E0B Warm accent; call-to-action highlights
Holo Green #10B981 Success states; positive indicators
Fog Grey #94A3B8 Secondary text; muted UI elements
Cloud White #F1F5F9 Primary text; headings on dark backgrounds
Ice Blue #E0F2FE Subtle text; descriptions, captions
Depth Blue #1E3A5F Mid-ground elements; subtle layering
Laser Red #EF4444 Error states; danger indicators
Chrome Silver #CBD5E1 Borders; subtle dividers; metadata

CSS Custom Properties

:root {
  --imm-void: #0B0B0F;
  --imm-deep-space: #101018;
  --imm-indigo: #161630;
  --imm-slate: #1E1E2E;
  --imm-cyan: #00E5FF;
  --imm-violet: #7C3AED;
  --imm-magenta: #E040FB;
  --imm-amber: #F59E0B;
  --imm-green: #10B981;
  --imm-fog: #94A3B8;
  --imm-white: #F1F5F9;
  --imm-ice: #E0F2FE;
  --imm-depth-blue: #1E3A5F;
  --imm-red: #EF4444;
  --imm-chrome: #CBD5E1;
}

Typography

3D Immersive sites demand typography that is geometric, clean, and highly legible against complex, animated backgrounds. Sans-serif faces with consistent stroke widths and generous x-heights perform best. Display headings may use wide tracking and uppercase styling to evoke a spatial, HUD-like quality, while body text stays neutral and readable. Spatial typography – text that subtly responds to depth or perspective transforms – adds dimensionality when used with restraint.

Font Weight(s) Usage Link
Inter 300, 400, 500, 600, 700 Body text; UI labels; excellent screen readability Inter
Space Grotesk 300, 400, 500, 600, 700 Subheadings; technical text; modern geometric feel Space Grotesk
Exo 2 300, 400, 500, 600, 700, 800 Display headings; futuristic geometric sans-serif Exo 2
Outfit 300, 400, 500, 600, 700, 800 Versatile geometric sans; clean and contemporary Outfit
JetBrains Mono 400, 500, 700 Code blocks; technical data; monospaced accent JetBrains Mono

Font Pairing Suggestions

Heading Body Vibe
Exo 2 700 Inter 400 Cinematic spatial interface
Space Grotesk 600 Inter 400 Technical 3D dashboard
Outfit 700 Space Grotesk 400 Clean immersive product showcase

CSS Example

@import url('https://fonts.googleapis.com/css2?family=Exo+2:wght@300;400;500;600;700;800&family=Inter:wght@300;400;500;600;700&family=Space+Grotesk:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap');

body {
  font-family: 'Inter', 'Helvetica Neue', Arial, sans-serif;
  font-size: 1rem;
  line-height: 1.75;
  color: #F1F5F9;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3 {
  font-family: 'Exo 2', sans-serif;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #F1F5F9;
}

h1 { font-size: clamp(2.2rem, 5vw, 4rem); }
h2 { font-size: clamp(1.4rem, 3vw, 2rem); }
h3 { font-size: clamp(1.1rem, 2vw, 1.4rem); }

.mono {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.9rem;
  letter-spacing: 0.02em;
}

Layout Principles


CSS / Design Techniques

Immersive Card

.imm-card {
  background: rgba(22, 22, 48, 0.65);
  border: 1px solid rgba(0, 229, 255, 0.15);
  border-radius: 12px;
  padding: 36px;
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  box-shadow:
    0 0 30px rgba(0, 229, 255, 0.06),
    0 8px 32px rgba(0, 0, 0, 0.5);
  transform: translateZ(0);
  transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94),
              box-shadow 0.4s ease;
}

.imm-card:hover {
  transform: translateY(-4px) translateZ(0);
  box-shadow:
    0 0 40px rgba(0, 229, 255, 0.12),
    0 16px 48px rgba(0, 0, 0, 0.6);
  border-color: rgba(0, 229, 255, 0.3);
}

.imm-card h3 {
  font-family: 'Exo 2', sans-serif;
  font-size: 1.1rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #00E5FF;
  margin-bottom: 12px;
}

.imm-card p {
  color: #CBD5E1;
  line-height: 1.7;
}

Depth Button

.imm-button {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: linear-gradient(135deg, rgba(0, 229, 255, 0.15), rgba(124, 58, 237, 0.15));
  color: #00E5FF;
  border: 1px solid rgba(0, 229, 255, 0.3);
  border-radius: 8px;
  padding: 14px 32px;
  font-family: 'Exo 2', sans-serif;
  font-size: 0.85rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  cursor: pointer;
  transition: all 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  position: relative;
  overflow: hidden;
}

.imm-button::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(0, 229, 255, 0.1), transparent);
  transition: left 0.5s ease;
}

.imm-button:hover {
  background: linear-gradient(135deg, rgba(0, 229, 255, 0.25), rgba(124, 58, 237, 0.25));
  box-shadow:
    0 0 24px rgba(0, 229, 255, 0.2),
    0 0 48px rgba(124, 58, 237, 0.1);
  border-color: rgba(0, 229, 255, 0.5);
  transform: translateY(-2px);
}

.imm-button:hover::before {
  left: 100%;
}

Spatial Navigation

.imm-nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 40px;
  background: rgba(11, 11, 15, 0.7);
  border-bottom: 1px solid rgba(0, 229, 255, 0.1);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  transition: background 0.3s ease;
}

.imm-nav.scrolled {
  background: rgba(11, 11, 15, 0.92);
  border-bottom-color: rgba(0, 229, 255, 0.2);
}

.imm-nav .logo {
  font-family: 'Exo 2', sans-serif;
  font-size: 1.2rem;
  font-weight: 700;
  color: #F1F5F9;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  text-decoration: none;
}

.imm-nav a {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 0.85rem;
  font-weight: 500;
  color: #94A3B8;
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 8px 16px;
  border-radius: 6px;
  transition: color 0.25s ease, background 0.25s ease;
}

.imm-nav a:hover {
  color: #00E5FF;
  background: rgba(0, 229, 255, 0.06);
}

.imm-nav a.active {
  color: #00E5FF;
}

Hero Scene Overlay

.imm-hero {
  position: relative;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  overflow: hidden;
}

.imm-hero .content {
  position: relative;
  z-index: 10;
  max-width: 720px;
  padding: 0 24px;
}

.imm-hero h1 {
  font-family: 'Exo 2', sans-serif;
  font-size: clamp(2.5rem, 6vw, 5rem);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #F1F5F9;
  text-shadow: 0 0 60px rgba(0, 229, 255, 0.2);
  margin-bottom: 20px;
  line-height: 1.1;
}

.imm-hero .subtitle {
  font-family: 'Inter', sans-serif;
  font-size: 1.15rem;
  color: #CBD5E1;
  line-height: 1.8;
  max-width: 560px;
  margin: 0 auto 32px;
}

.imm-hero .scroll-cue {
  position: absolute;
  bottom: 40px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: #94A3B8;
  font-family: 'Space Grotesk', sans-serif;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  animation: scrollBounce 2s ease-in-out infinite;
}

@keyframes scrollBounce {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50% { transform: translateX(-50%) translateY(8px); }
}

Parallax Layer System

.imm-parallax-container {
  perspective: 1px;
  height: 100vh;
  overflow-x: hidden;
  overflow-y: auto;
  transform-style: preserve-3d;
}

.imm-parallax-layer--back {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  transform: translateZ(-2px) scale(3);
  z-index: -1;
}

.imm-parallax-layer--mid {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  transform: translateZ(-1px) scale(2);
  z-index: 0;
}

.imm-parallax-layer--front {
  position: relative;
  transform: translateZ(0);
  z-index: 1;
}

Glow Text Effect

.imm-glow-text {
  color: #F1F5F9;
  text-shadow:
    0 0 10px rgba(0, 229, 255, 0.4),
    0 0 30px rgba(0, 229, 255, 0.2),
    0 0 60px rgba(0, 229, 255, 0.1);
}

.imm-gradient-text {
  background: linear-gradient(135deg, #00E5FF, #7C3AED, #E040FB);
  background-size: 200% 200%;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  animation: gradientShift 4s ease infinite;
}

@keyframes gradientShift {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

Atmospheric Background

.imm-atmosphere {
  min-height: 100vh;
  background: #0B0B0F;
  background-image:
    radial-gradient(ellipse at 20% 30%, rgba(124, 58, 237, 0.08) 0%, transparent 50%),
    radial-gradient(ellipse at 80% 70%, rgba(0, 229, 255, 0.06) 0%, transparent 50%),
    radial-gradient(ellipse at 50% 50%, rgba(245, 158, 11, 0.03) 0%, transparent 40%);
  position: relative;
}

.imm-atmosphere::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(1px 1px at 10% 20%, rgba(241, 245, 249, 0.4) 50%, transparent 50%),
    radial-gradient(1px 1px at 30% 60%, rgba(241, 245, 249, 0.3) 50%, transparent 50%),
    radial-gradient(1px 1px at 55% 15%, rgba(241, 245, 249, 0.5) 50%, transparent 50%),
    radial-gradient(1px 1px at 72% 45%, rgba(241, 245, 249, 0.25) 50%, transparent 50%),
    radial-gradient(1px 1px at 88% 78%, rgba(241, 245, 249, 0.35) 50%, transparent 50%),
    radial-gradient(1px 1px at 45% 90%, rgba(241, 245, 249, 0.2) 50%, transparent 50%);
  pointer-events: none;
  animation: starTwinkle 6s ease-in-out infinite alternate;
}

@keyframes starTwinkle {
  0% { opacity: 0.6; }
  100% { opacity: 1; }
}

Scroll-Reveal Animation

.imm-reveal {
  opacity: 0;
  transform: translateY(40px) translateZ(0);
  transition: opacity 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94),
              transform 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.imm-reveal.visible {
  opacity: 1;
  transform: translateY(0) translateZ(0);
}

.imm-reveal.from-left {
  transform: translateX(-60px) translateZ(0);
}

.imm-reveal.from-left.visible {
  transform: translateX(0) translateZ(0);
}

.imm-reveal.from-right {
  transform: translateX(60px) translateZ(0);
}

.imm-reveal.from-right.visible {
  transform: translateX(0) translateZ(0);
}

.imm-reveal.scale-in {
  transform: scale(0.9) translateZ(0);
}

.imm-reveal.scale-in.visible {
  transform: scale(1) translateZ(0);
}

Design Do’s and Don’ts

Do’s

Don’ts


Aesthetic Relationship
Glassmorphism Shares the frosted, translucent panel approach used to float UI elements over dynamic backgrounds; 3D Immersive uses glass panels as its primary content container strategy
Dark Mode / Dark UI Both rely on dark backgrounds and luminous accents; 3D Immersive extends dark UI into literal spatial depth with WebGL scenes
Cyberpunk Overlaps in neon accent colors, dark environments, and futuristic atmosphere, but Cyberpunk leans grittier with more saturated chaos
Neomorphism Both explore depth and dimensionality, but Neomorphism uses soft shadows on flat surfaces while 3D Immersive uses actual rendered geometry
Parallax Minimal A stripped-down relative; uses CSS-only parallax layers without full WebGL scenes, suitable as a lightweight alternative
Spatial UI (Apple Vision) Shares the philosophy of UI elements existing in 3D space with depth-based hierarchy; visionOS design language is a native-app cousin
Holographic Both use iridescent, light-refracting visual language; Holographic focuses on surface treatment while 3D Immersive focuses on spatial environment
Sci-Fi Interface Shares the HUD-style typography and technical aesthetic, but Sci-Fi Interface is typically 2D with faux-depth styling rather than true 3D rendering

Quick-Start HTML Template

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>3D Immersive Layout</title>
  <link href="https://fonts.googleapis.com/css2?family=Exo+2:wght@300;400;500;600;700;800&family=Inter:wght@300;400;500;600;700&family=Space+Grotesk:wght@300;400;500;600;700&display=swap" rel="stylesheet">
  <style>
    *, *::before, *::after {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    :root {
      --imm-void: #0B0B0F;
      --imm-deep-space: #101018;
      --imm-indigo: #161630;
      --imm-slate: #1E1E2E;
      --imm-cyan: #00E5FF;
      --imm-violet: #7C3AED;
      --imm-magenta: #E040FB;
      --imm-amber: #F59E0B;
      --imm-green: #10B981;
      --imm-fog: #94A3B8;
      --imm-white: #F1F5F9;
      --imm-ice: #E0F2FE;
      --imm-depth-blue: #1E3A5F;
      --imm-red: #EF4444;
      --imm-chrome: #CBD5E1;
    }

    html {
      scroll-behavior: smooth;
    }

    body {
      font-family: 'Inter', 'Helvetica Neue', Arial, sans-serif;
      font-size: 1rem;
      line-height: 1.75;
      color: var(--imm-white);
      background: var(--imm-void);
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      overflow-x: hidden;
    }

    /* ===== CANVAS BACKGROUND ===== */
    #scene-canvas {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      z-index: 0;
      pointer-events: none;
    }

    /* ===== ATMOSPHERIC BACKGROUND FALLBACK ===== */
    .atmosphere {
      position: fixed;
      inset: 0;
      z-index: 0;
      background: var(--imm-void);
      background-image:
        radial-gradient(ellipse at 20% 30%, rgba(124, 58, 237, 0.08) 0%, transparent 50%),
        radial-gradient(ellipse at 80% 70%, rgba(0, 229, 255, 0.06) 0%, transparent 50%),
        radial-gradient(ellipse at 50% 50%, rgba(245, 158, 11, 0.03) 0%, transparent 40%);
    }

    .atmosphere::before {
      content: '';
      position: absolute;
      inset: 0;
      background-image:
        radial-gradient(1px 1px at 8% 15%, rgba(241, 245, 249, 0.5) 50%, transparent 50%),
        radial-gradient(1px 1px at 22% 65%, rgba(241, 245, 249, 0.3) 50%, transparent 50%),
        radial-gradient(1px 1px at 38% 28%, rgba(241, 245, 249, 0.4) 50%, transparent 50%),
        radial-gradient(1px 1px at 52% 82%, rgba(241, 245, 249, 0.25) 50%, transparent 50%),
        radial-gradient(1px 1px at 68% 10%, rgba(241, 245, 249, 0.45) 50%, transparent 50%),
        radial-gradient(1px 1px at 75% 50%, rgba(241, 245, 249, 0.2) 50%, transparent 50%),
        radial-gradient(1px 1px at 90% 35%, rgba(241, 245, 249, 0.35) 50%, transparent 50%),
        radial-gradient(1px 1px at 15% 92%, rgba(241, 245, 249, 0.3) 50%, transparent 50%);
      animation: twinkle 8s ease-in-out infinite alternate;
    }

    @keyframes twinkle {
      0% { opacity: 0.5; }
      100% { opacity: 1; }
    }

    /* ===== NAVIGATION ===== */
    .nav {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      z-index: 30;
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 18px 40px;
      background: rgba(11, 11, 15, 0.6);
      border-bottom: 1px solid rgba(0, 229, 255, 0.08);
      backdrop-filter: blur(16px);
      -webkit-backdrop-filter: blur(16px);
      transition: background 0.4s ease, border-color 0.4s ease;
    }

    .nav.scrolled {
      background: rgba(11, 11, 15, 0.92);
      border-bottom-color: rgba(0, 229, 255, 0.2);
    }

    .nav .logo {
      font-family: 'Exo 2', sans-serif;
      font-size: 1.15rem;
      font-weight: 700;
      color: var(--imm-white);
      text-decoration: none;
      text-transform: uppercase;
      letter-spacing: 0.12em;
    }

    .nav .logo span {
      color: var(--imm-cyan);
    }

    .nav-links {
      display: flex;
      gap: 4px;
      list-style: none;
    }

    .nav-links a {
      font-family: 'Space Grotesk', sans-serif;
      font-size: 0.82rem;
      font-weight: 500;
      color: var(--imm-fog);
      text-decoration: none;
      text-transform: uppercase;
      letter-spacing: 0.06em;
      padding: 8px 16px;
      border-radius: 6px;
      transition: color 0.25s ease, background 0.25s ease;
    }

    .nav-links a:hover,
    .nav-links a.active {
      color: var(--imm-cyan);
      background: rgba(0, 229, 255, 0.06);
    }

    /* ===== CONTENT WRAPPER ===== */
    .content-wrapper {
      position: relative;
      z-index: 10;
    }

    /* ===== HERO SECTION ===== */
    .hero {
      position: relative;
      height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
      text-align: center;
      overflow: hidden;
    }

    .hero .inner {
      position: relative;
      z-index: 5;
      max-width: 760px;
      padding: 0 24px;
    }

    .hero .tag {
      font-family: 'Space Grotesk', sans-serif;
      font-size: 0.75rem;
      font-weight: 500;
      color: var(--imm-cyan);
      text-transform: uppercase;
      letter-spacing: 0.2em;
      margin-bottom: 20px;
      display: inline-block;
      padding: 6px 18px;
      border: 1px solid rgba(0, 229, 255, 0.2);
      border-radius: 20px;
      background: rgba(0, 229, 255, 0.05);
    }

    .hero h1 {
      font-family: 'Exo 2', sans-serif;
      font-size: clamp(2.5rem, 6vw, 4.5rem);
      font-weight: 800;
      text-transform: uppercase;
      letter-spacing: 0.05em;
      line-height: 1.1;
      color: var(--imm-white);
      margin-bottom: 24px;
    }

    .hero h1 .accent {
      background: linear-gradient(135deg, var(--imm-cyan), var(--imm-violet));
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
      background-clip: text;
    }

    .hero .subtitle {
      font-size: 1.1rem;
      color: var(--imm-chrome);
      line-height: 1.8;
      max-width: 540px;
      margin: 0 auto 36px;
    }

    .hero .cta-group {
      display: flex;
      gap: 16px;
      justify-content: center;
      flex-wrap: wrap;
    }

    .scroll-indicator {
      position: absolute;
      bottom: 36px;
      left: 50%;
      transform: translateX(-50%);
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 10px;
      color: var(--imm-fog);
      font-family: 'Space Grotesk', sans-serif;
      font-size: 0.7rem;
      text-transform: uppercase;
      letter-spacing: 0.15em;
      animation: bounce 2.5s ease-in-out infinite;
    }

    .scroll-indicator .line {
      width: 1px;
      height: 40px;
      background: linear-gradient(to bottom, var(--imm-cyan), transparent);
    }

    @keyframes bounce {
      0%, 100% { transform: translateX(-50%) translateY(0); opacity: 1; }
      50% { transform: translateX(-50%) translateY(10px); opacity: 0.5; }
    }

    /* ===== BUTTONS ===== */
    .btn {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 14px 32px;
      font-family: 'Exo 2', sans-serif;
      font-size: 0.82rem;
      font-weight: 600;
      text-transform: uppercase;
      letter-spacing: 0.1em;
      text-decoration: none;
      border-radius: 8px;
      cursor: pointer;
      transition: all 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94);
      position: relative;
      overflow: hidden;
    }

    .btn-primary {
      background: linear-gradient(135deg, rgba(0, 229, 255, 0.2), rgba(124, 58, 237, 0.2));
      color: var(--imm-cyan);
      border: 1px solid rgba(0, 229, 255, 0.3);
    }

    .btn-primary:hover {
      background: linear-gradient(135deg, rgba(0, 229, 255, 0.3), rgba(124, 58, 237, 0.3));
      box-shadow: 0 0 24px rgba(0, 229, 255, 0.2), 0 0 48px rgba(124, 58, 237, 0.1);
      border-color: rgba(0, 229, 255, 0.5);
      transform: translateY(-2px);
    }

    .btn-ghost {
      background: transparent;
      color: var(--imm-fog);
      border: 1px solid rgba(148, 163, 184, 0.2);
    }

    .btn-ghost:hover {
      color: var(--imm-white);
      border-color: rgba(148, 163, 184, 0.4);
      background: rgba(148, 163, 184, 0.05);
    }

    /* ===== SECTION LAYOUT ===== */
    .section {
      padding: 120px 24px;
      max-width: 1100px;
      margin: 0 auto;
    }

    .section-label {
      font-family: 'Space Grotesk', sans-serif;
      font-size: 0.72rem;
      font-weight: 500;
      color: var(--imm-cyan);
      text-transform: uppercase;
      letter-spacing: 0.2em;
      margin-bottom: 12px;
    }

    .section-title {
      font-family: 'Exo 2', sans-serif;
      font-size: clamp(1.6rem, 3.5vw, 2.4rem);
      font-weight: 700;
      text-transform: uppercase;
      letter-spacing: 0.04em;
      color: var(--imm-white);
      margin-bottom: 16px;
    }

    .section-desc {
      font-size: 1.05rem;
      color: var(--imm-chrome);
      max-width: 600px;
      line-height: 1.8;
      margin-bottom: 48px;
    }

    .divider {
      height: 1px;
      background: linear-gradient(90deg, transparent, rgba(0, 229, 255, 0.15), rgba(124, 58, 237, 0.15), transparent);
      margin: 0 24px;
    }

    /* ===== CARDS GRID ===== */
    .card-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
      gap: 24px;
    }

    .card {
      background: rgba(22, 22, 48, 0.55);
      border: 1px solid rgba(0, 229, 255, 0.1);
      border-radius: 12px;
      padding: 36px;
      backdrop-filter: blur(12px);
      -webkit-backdrop-filter: blur(12px);
      box-shadow: 0 4px 24px rgba(0, 0, 0, 0.3);
      transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94),
                  box-shadow 0.4s ease,
                  border-color 0.4s ease;
    }

    .card:hover {
      transform: translateY(-6px);
      box-shadow: 0 0 30px rgba(0, 229, 255, 0.08), 0 12px 40px rgba(0, 0, 0, 0.5);
      border-color: rgba(0, 229, 255, 0.25);
    }

    .card .icon {
      width: 48px;
      height: 48px;
      border-radius: 10px;
      background: linear-gradient(135deg, rgba(0, 229, 255, 0.15), rgba(124, 58, 237, 0.15));
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 1.4rem;
      margin-bottom: 20px;
      border: 1px solid rgba(0, 229, 255, 0.1);
    }

    .card h3 {
      font-family: 'Exo 2', sans-serif;
      font-size: 1rem;
      font-weight: 600;
      text-transform: uppercase;
      letter-spacing: 0.05em;
      color: var(--imm-white);
      margin-bottom: 12px;
    }

    .card p {
      color: var(--imm-fog);
      font-size: 0.95rem;
      line-height: 1.7;
    }

    /* ===== STATS ROW ===== */
    .stats {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
      gap: 24px;
      margin-top: 48px;
    }

    .stat {
      text-align: center;
      padding: 32px 16px;
      background: rgba(22, 22, 48, 0.4);
      border-radius: 12px;
      border: 1px solid rgba(0, 229, 255, 0.06);
    }

    .stat .number {
      font-family: 'Exo 2', sans-serif;
      font-size: 2.4rem;
      font-weight: 700;
      color: var(--imm-cyan);
      display: block;
      margin-bottom: 6px;
    }

    .stat .label {
      font-family: 'Space Grotesk', sans-serif;
      font-size: 0.78rem;
      color: var(--imm-fog);
      text-transform: uppercase;
      letter-spacing: 0.08em;
    }

    /* ===== FEATURE SPLIT ===== */
    .feature-split {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 60px;
      align-items: center;
      margin-top: 80px;
    }

    .feature-visual {
      aspect-ratio: 4/3;
      border-radius: 16px;
      background: linear-gradient(135deg, var(--imm-indigo), var(--imm-slate));
      border: 1px solid rgba(0, 229, 255, 0.1);
      display: flex;
      align-items: center;
      justify-content: center;
      position: relative;
      overflow: hidden;
    }

    .feature-visual::before {
      content: '';
      position: absolute;
      width: 200px;
      height: 200px;
      border-radius: 50%;
      background: radial-gradient(circle, rgba(0, 229, 255, 0.12) 0%, transparent 70%);
      animation: pulse 4s ease-in-out infinite;
    }

    @keyframes pulse {
      0%, 100% { transform: scale(1); opacity: 0.6; }
      50% { transform: scale(1.2); opacity: 1; }
    }

    .feature-visual .placeholder-text {
      font-family: 'Space Grotesk', sans-serif;
      font-size: 0.8rem;
      color: var(--imm-fog);
      text-transform: uppercase;
      letter-spacing: 0.1em;
      z-index: 1;
    }

    .feature-content h3 {
      font-family: 'Exo 2', sans-serif;
      font-size: 1.4rem;
      font-weight: 700;
      text-transform: uppercase;
      letter-spacing: 0.04em;
      color: var(--imm-white);
      margin-bottom: 16px;
    }

    .feature-content p {
      color: var(--imm-chrome);
      line-height: 1.8;
      margin-bottom: 24px;
    }

    .feature-list {
      list-style: none;
      display: flex;
      flex-direction: column;
      gap: 10px;
    }

    .feature-list li {
      font-size: 0.92rem;
      color: var(--imm-fog);
      padding-left: 20px;
      position: relative;
    }

    .feature-list li::before {
      content: '';
      position: absolute;
      left: 0;
      top: 10px;
      width: 6px;
      height: 6px;
      border-radius: 50%;
      background: var(--imm-cyan);
      box-shadow: 0 0 8px rgba(0, 229, 255, 0.4);
    }

    /* ===== FOOTER ===== */
    .footer {
      padding: 60px 40px;
      text-align: center;
      border-top: 1px solid rgba(0, 229, 255, 0.06);
      margin-top: 80px;
    }

    .footer p {
      font-family: 'Space Grotesk', sans-serif;
      font-size: 0.82rem;
      color: var(--imm-fog);
    }

    .footer a {
      color: var(--imm-cyan);
      text-decoration: none;
      transition: opacity 0.2s;
    }

    .footer a:hover {
      opacity: 0.7;
    }

    /* ===== SCROLL REVEAL ===== */
    .reveal {
      opacity: 0;
      transform: translateY(30px);
      transition: opacity 0.7s cubic-bezier(0.25, 0.46, 0.45, 0.94),
                  transform 0.7s cubic-bezier(0.25, 0.46, 0.45, 0.94);
    }

    .reveal.visible {
      opacity: 1;
      transform: translateY(0);
    }

    /* ===== REDUCED MOTION ===== */
    @media (prefers-reduced-motion: reduce) {
      *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
      }
      .reveal {
        opacity: 1;
        transform: none;
      }
    }

    /* ===== RESPONSIVE ===== */
    @media (max-width: 768px) {
      .nav {
        padding: 14px 20px;
      }

      .nav-links {
        display: none;
      }

      .hero h1 {
        font-size: clamp(1.8rem, 8vw, 3rem);
      }

      .section {
        padding: 80px 20px;
      }

      .feature-split {
        grid-template-columns: 1fr;
        gap: 32px;
      }

      .card-grid {
        grid-template-columns: 1fr;
      }

      .stats {
        grid-template-columns: repeat(2, 1fr);
      }

      .cta-group {
        flex-direction: column;
        align-items: center;
      }
    }
  </style>
</head>
<body>

  <!-- Atmospheric background (CSS fallback; replace with <canvas> for Three.js) -->
  <div class="atmosphere"></div>

  <!-- Fixed navigation -->
  <nav class="nav" id="mainNav">
    <a href="#" class="logo">Depth<span>Lab</span></a>
    <ul class="nav-links">
      <li><a href="#features" class="active">Features</a></li>
      <li><a href="#showcase">Showcase</a></li>
      <li><a href="#stats">Metrics</a></li>
      <li><a href="#about">About</a></li>
    </ul>
  </nav>

  <!-- Main content (sits above the canvas/atmosphere layer) -->
  <div class="content-wrapper">

    <!-- Hero -->
    <section class="hero">
      <div class="inner">
        <span class="tag">WebGL-Powered Experience</span>
        <h1>Enter the <span class="accent">Third Dimension</span></h1>
        <p class="subtitle">
          Spatial interfaces driven by scroll-triggered 3D,
          parallax depth, and real-time GPU rendering.
          Explore content as an environment, not just a page.
        </p>
        <div class="cta-group">
          <a href="#features" class="btn btn-primary">Explore Depth</a>
          <a href="#about" class="btn btn-ghost">Learn More</a>
        </div>
      </div>
      <div class="scroll-indicator">
        <span>Scroll to explore</span>
        <div class="line"></div>
      </div>
    </section>

    <div class="divider"></div>

    <!-- Features -->
    <section class="section" id="features">
      <div class="reveal">
        <p class="section-label">Core Capabilities</p>
        <h2 class="section-title">Spatial Design Features</h2>
        <p class="section-desc">
          Every element exists in dimensional space. Scroll drives the camera,
          interaction reveals layers, and content unfolds like a cinematic sequence.
        </p>
      </div>

      <div class="card-grid">
        <div class="card reveal">
          <div class="icon">&#x25E6;</div>
          <h3>Parallax Depth</h3>
          <p>Multi-layer scroll at different velocities creates the illusion
             of spatial depth without full 3D rendering overhead.</p>
        </div>
        <div class="card reveal">
          <div class="icon">&#x25CB;</div>
          <h3>Scroll Cinema</h3>
          <p>GSAP ScrollTrigger binds page position to camera paths,
             lighting shifts, and shader transitions for narrative flow.</p>
        </div>
        <div class="card reveal">
          <div class="icon">&#x25C7;</div>
          <h3>Interactive Models</h3>
          <p>Rotate, zoom, and explore glTF models embedded in the page,
             driven by pointer input and GPU-accelerated rendering.</p>
        </div>
        <div class="card reveal">
          <div class="icon">&#x25A1;</div>
          <h3>Shader Effects</h3>
          <p>Custom GLSL shaders produce distortion, noise, chromatic
             aberration, and post-processing effects in real time.</p>
        </div>
        <div class="card reveal">
          <div class="icon">&#x25B3;</div>
          <h3>Particle Systems</h3>
          <p>Ambient particles, dust motes, and data-driven point clouds
             add atmospheric density and visual richness to scenes.</p>
        </div>
        <div class="card reveal">
          <div class="icon">&#x2B21;</div>
          <h3>Glass Panels</h3>
          <p>Frosted glassmorphic containers float above 3D scenes,
             keeping text legible while the environment stays visible.</p>
        </div>
      </div>
    </section>

    <div class="divider"></div>

    <!-- Showcase split -->
    <section class="section" id="showcase">
      <div class="feature-split reveal">
        <div class="feature-visual">
          <span class="placeholder-text">3D Scene Viewport</span>
        </div>
        <div class="feature-content">
          <h3>Cinematic Scroll Sequences</h3>
          <p>
            Connect scroll position to camera movement and scene transitions.
            Each viewport-height section becomes a "shot" in a directed
            visual narrative, unfolding content through spatial motion.
          </p>
          <ul class="feature-list">
            <li>Camera path keyframes bound to scroll progress</li>
            <li>Lighting and material transitions between sections</li>
            <li>Smooth lerp-based scroll interpolation</li>
            <li>Progressive asset loading with skeleton placeholders</li>
          </ul>
        </div>
      </div>
    </section>

    <div class="divider"></div>

    <!-- Stats -->
    <section class="section" id="stats">
      <div class="reveal">
        <p class="section-label">Performance Metrics</p>
        <h2 class="section-title">Built for Speed</h2>
        <p class="section-desc">
          Immersive 3D must never sacrifice performance.
          Every asset is optimized, every animation GPU-composited.
        </p>
      </div>
      <div class="stats reveal">
        <div class="stat">
          <span class="number">60</span>
          <span class="label">Target FPS</span>
        </div>
        <div class="stat">
          <span class="number">&lt;3s</span>
          <span class="label">Scene Load</span>
        </div>
        <div class="stat">
          <span class="number">GLB</span>
          <span class="label">Asset Format</span>
        </div>
        <div class="stat">
          <span class="number">0</span>
          <span class="label">Layout Shifts</span>
        </div>
      </div>
    </section>

    <div class="divider"></div>

    <!-- About -->
    <section class="section" id="about">
      <div class="reveal">
        <p class="section-label">Philosophy</p>
        <h2 class="section-title">Depth with Purpose</h2>
        <p class="section-desc">
          3D Immersive design transforms the browser from a document viewer
          into a spatial environment. Every scroll, hover, and interaction
          reveals another layer of the experience. The page is not read --
          it is explored.
        </p>
      </div>
      <div style="text-align: center; margin-top: 36px;" class="reveal">
        <a href="#" class="btn btn-primary">Start Building</a>
      </div>
    </section>

    <!-- Footer -->
    <footer class="footer">
      <p>3D Immersive Design Reference &middot;
         Built with WebGL, Three.js &amp; GSAP</p>
    </footer>

  </div>

  <script>
    // --- Nav scroll effect ---
    const nav = document.getElementById('mainNav');
    window.addEventListener('scroll', () => {
      nav.classList.toggle('scrolled', window.scrollY > 60);
    }, { passive: true });

    // --- Scroll reveal (IntersectionObserver) ---
    const revealElements = document.querySelectorAll('.reveal');
    const revealObserver = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          entry.target.classList.add('visible');
          revealObserver.unobserve(entry.target);
        }
      });
    }, { threshold: 0.15 });
    revealElements.forEach(el => revealObserver.observe(el));

    // --- Respect reduced motion ---
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
      revealElements.forEach(el => el.classList.add('visible'));
    }

    /*
     * NOTE: For a full 3D Immersive implementation, replace the
     * .atmosphere div with a Three.js <canvas> scene:
     *
     * import * as THREE from 'three';
     * import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
     * import gsap from 'gsap';
     * import { ScrollTrigger } from 'gsap/ScrollTrigger';
     *
     * gsap.registerPlugin(ScrollTrigger);
     *
     * const scene = new THREE.Scene();
     * const camera = new THREE.PerspectiveCamera(75, w/h, 0.1, 1000);
     * const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true });
     *
     * // Bind scroll to camera position:
     * ScrollTrigger.create({
     *   trigger: '.content-wrapper',
     *   start: 'top top',
     *   end: 'bottom bottom',
     *   onUpdate: (self) => {
     *     camera.position.z = 5 - self.progress * 4;
     *     camera.position.y = self.progress * 2;
     *   }
     * });
     */
  </script>

</body>
</html>

Implementation Tips