// CaseStudyNicoleMoudaber.jsx — case study for Nicole Moudaber tour visuals.
// Wrapped in an IIFE so internal constants (CS, helper components) don't
// collide with other case studies.

;(function () {

const { useState: useStateCS, useEffect: useEffectCS, useRef: useRefCS } = React;

// ============ SOURCE CONTENT ============
const CS = {
  slug: 'nicole-moudaber',
  title: 'Nicole Moudaber',
  subtitle: 'Tour visuals and live performance package for the techno headliner.',
  client: 'Nicole Moudaber',
  studio: 'Volvox Labs',
  year: '2021 - 2024',
  role: 'Art Direction / Motion Design Direction · Live Visual Performance',

  // Lead — opening paragraph after the at-a-glance strip.
  lead: "A multi-year collaboration with Nicole Moudaber, building and refreshing the visual library that travels with her sets across the globe. Every frame was made to be impactful for the crowd of true ravers — visuals woven directly into the narrative arc of her performance.",

  blocks: [
    {
      no: '01',
      key: 'narrative-arc',
      eyebrow: '01 — 2024 New narrative arc',
      title: 'Journey of the Ankh — the throughline of this chapter.',
      body: [
        'An ethereal trip between fantasy and reality, an emotional awakening built from color, dimension, and the texture of memory.',
        'The package was produced with every tool in reach: high-end pre-rendered simulation, real-time generative graphics, game-engine renders, and a then-emerging AI generative pipeline — all blended into a single high-octane visual language.',
      ],
      video: 'site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/Reel_NM24_06_content_only_HD_v1_1080p.mp4',
      cornerTl: '2024, Journey of the Ankh',
      stillsCols: 1,
      stills: [
        'site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/Reel_NM24_02_Avatar_v1_1920p.mp4',
        'site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/Reel_NM24_01_AI_v1_1920p.mp4',
        'site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/Reel_NM24_04_Snake_v1_1920p.mp4',
      ],
    },
    {
      no: '02',
      key: 'special-immersive-show',
      eyebrow: '02 — 2023, Special Immersive Show',
      title: 'Brooklyn Arts District Show — A Special Immersive Night',
      body: [
        "An eight-hour live set with every surface in the room mapped to content. The team extended the existing tour package to fit the space exactly and produced a new set of custom content built specifically for the venue's walls — Nicole's visual identity carried across the entire night.",
      ],
      stillsCols: 1,
      stills: [
        'site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/2023/VDO/Visuals%20for%20Nicole%20Moudaber%20%40%20Arts%20District%20In%20Brooklyn%20July%202023_1080p.mp4',
        'site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/2023/VDO/MOUDABER_Teaser_AD%20Brooklyn_HD_03_03_INFO_1.mp4',
        'site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/2023/AD_3Dmodel_Spin_02-1.gif',
        'site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/2023/NM23_BTS_01.jpg',
      ],
    },
    {
      no: '03',
      key: 'original-tour-visuals',
      eyebrow: '03 — 2021, The Original Tour Visuals',
      title: 'The original twenty-minute loop.',
      body: [
        'The first collaboration between Nicole Moudaber and Volvox Labs. A twenty-minute loop built to replay throughout the night with light VJ intervention — a montage of pre-rendered 3D, 2D type and graphics, and live footage.',
      ],
      stillsGroups: [
        { cols: 1, stills: [
          'site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/2021/1694092408.mp4',
        ]},
        { cols: 2, stills: [
          'site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/2021/3D_02.webp',
          'site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/2021/3D_03.webp',
          'site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/2021/3D_04.webp',
          'site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/2021/3D_05.webp',
          'site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/2021/3D_07.webp',
          'site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/2021/TYPO_04.webp',
        ]},
        { cols: 1, stills: [
          'site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/2021/Moudaber_Animated_2D_gif_06.gif',
        ]},
      ],
    },
  ],

  credits: [
    { role: 'Client',                       who: 'Nicole Moudaber' },
    { divider: true },
    { role: 'Studio',                       who: 'Volvox Labs' },
    { role: 'Art Direction',                who: 'Kamil Nawratil' },
    { role: 'Art Direction',                who: 'Pasakorn Nontananandh' },
    { role: 'Cinema 4D + AI',               who: 'Siriphong Tipayakesorn' },
    { role: 'Houdini FX',                   who: 'Pasakorn Nontananandh' },
    { role: 'Houdini + Notch FX',           who: 'Mark McCallum' },
    { role: 'Houdini FX',                   who: 'Boning Li' },
    { role: 'Houdini + UE',                 who: 'Wenyi Zhang' },
    { role: 'Unreal Engine',                who: 'Chatrin S.' },
    { role: 'Technologist + Touch Design',  who: 'Matt Ross' },
    { role: 'VJs',                          who: 'Pasakorn Nontananandh · Siriphong Tipayakesorn · Kamil Nawratil · Matt Ross' },
  ],
};

// =====================================================================
// Shared atoms — scoped to this IIFE.
// =====================================================================

function MonoLabel({ children, dim, size = 11, style }) {
  return (
    <div style={{
      fontFamily: "'JetBrains Mono', SFMono-Regular, Menlo, monospace",
      fontSize: size, letterSpacing: '0.16em',
      color: dim ? 'var(--ak-fg-2)' : 'var(--ak-fg)',
      textTransform: 'uppercase',
      ...style,
    }}>{children}</div>
  );
}

const proseP = {
  fontFamily: "'PP Neue Montreal', 'Geist', system-ui, sans-serif",
  fontSize: 17, lineHeight: 1.55, letterSpacing: '-0.005em',
  fontWeight: 400, color: 'var(--ak-fg-2)',
  margin: '20px 0 0',
};

function ProseSection({ eyebrow, title, children, dark }) {
  return (
    <section style={{
      padding: '120px 32px',
      background: dark ? 'var(--ak-bg-3)' : 'var(--ak-bg)',
      color: dark ? 'var(--ak-fg-on3)' : 'var(--ak-fg)',
      borderTop: '1px solid var(--ak-line)',
    }}>
      <div style={{ maxWidth: 1280, margin: '0 auto', display: 'grid', gridTemplateColumns: '1fr 1.4fr', gap: 64, alignItems: 'start' }}>
        <Reveal>
          <MonoLabel dim>{eyebrow}</MonoLabel>
          <h2 style={{
            fontFamily: "'PP Neue Montreal', 'Geist', system-ui, sans-serif",
            fontSize: 'clamp(36px, 4vw, 56px)', lineHeight: 1.05,
            letterSpacing: '-0.02em', fontWeight: 400,
            margin: '20px 0 0',
            color: dark ? 'var(--ak-fg-on3)' : 'var(--ak-fg)',
            textWrap: 'balance',
          }}>
            {title}
          </h2>
        </Reveal>
        <Reveal y={28} delay={120} style={{ marginTop: 14 }}>
          <div style={{ color: dark ? 'var(--ak-fg-2-on3)' : 'var(--ak-fg-2)' }}>
            {children}
          </div>
        </Reveal>
      </div>
    </section>
  );
}

function CornerMeta({ tl, br }) {
  return (
    <>
      {tl && (
        <div style={{
          position: 'absolute', top: 16, right: 16,
          fontFamily: "'JetBrains Mono', monospace", fontSize: 10,
          letterSpacing: '0.14em', color: 'rgba(255,255,255,0.7)',
          textTransform: 'uppercase',
        }}>{tl}</div>
      )}
      {br && (
        <div style={{
          position: 'absolute', bottom: 16, right: 16,
          fontFamily: "'JetBrains Mono', monospace", fontSize: 10,
          letterSpacing: '0.14em', color: 'rgba(255,255,255,0.7)',
          textTransform: 'uppercase',
        }}>{br}</div>
      )}
    </>
  );
}

function StillsGrid({ stills, alt, cols = 2 }) {
  if (!stills || stills.length === 0) return null;
  const naturalAspect = cols === 1;
  return (
    <div style={{
      maxWidth: 1280, margin: '16px auto 0',
      display: 'grid',
      gridTemplateColumns: `repeat(${cols}, 1fr)`,
      gap: 16,
    }}>
      {stills.map((src, i) => {
        const isVideo = /\.mp4($|\?)/i.test(src);
        return (
          <Reveal key={src} y={20} delay={i * 80}>
            <div style={{
              position: 'relative', overflow: 'hidden',
              ...(naturalAspect ? {} : { aspectRatio: '16/9' }),
              borderRadius: 12,
              background: '#0a0b0d',
              border: '1px solid var(--ak-line)',
            }}>
              {isVideo ? (
                <video src={src} autoPlay loop muted playsInline
                  style={naturalAspect
                    ? { width: '100%', height: 'auto', display: 'block' }
                    : { width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
              ) : (
                <img src={src} alt={`${alt} still ${i + 1}`}
                  style={naturalAspect
                    ? { width: '100%', height: 'auto', display: 'block' }
                    : { width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
              )}
            </div>
          </Reveal>
        );
      })}
    </div>
  );
}

function BlockMedia({ block }) {
  const hasMedia = block.image || block.video || block.vimeo;
  if (!hasMedia) return null;
  return (
    <Reveal y={20}>
      <div style={{
        maxWidth: 1280, margin: '0 auto',
        borderRadius: 16, overflow: 'hidden',
        background: '#0a0b0d',
        border: '1px solid var(--ak-line)',
        position: 'relative',
      }}>
        {block.vimeo ? (
          <iframe
            src={block.vimeo}
            title={block.title}
            frameBorder="0"
            referrerPolicy="strict-origin-when-cross-origin"
            allow="autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share"
            allowFullScreen
            style={{ aspectRatio: '16/9', width: '100%', height: 'auto', border: 0, display: 'block' }}
          />
        ) : block.video ? (
          <video src={block.video} autoPlay loop muted playsInline
            style={{ width: '100%', height: 'auto', display: 'block' }} />
        ) : (
          <img src={block.image} alt={block.title}
            style={{ width: '100%', height: 'auto', display: 'block' }} />
        )}
        <CornerMeta tl={block.cornerTl} br={block.cornerBr} />
      </div>
    </Reveal>
  );
}

function CreditsBlock() {
  return (
    <section style={{
      padding: '72px 32px',
      background: 'var(--ak-bg)',
      borderTop: '1px solid var(--ak-line)',
    }}>
      <div style={{ maxWidth: 768, margin: '0 auto' }}>
        <Reveal>
          <MonoLabel dim style={{ marginBottom: 28 }}>Credits</MonoLabel>
        </Reveal>
        <Reveal y={20} delay={120}>
          <table style={{
            width: '100%', borderCollapse: 'collapse',
            fontFamily: "'JetBrains Mono', monospace", fontSize: 10, letterSpacing: '0.04em',
          }}>
            <tbody>
              {CS.credits.map((row, i) => {
                if (row.divider) {
                  return (<tr key={i}><td colSpan="2" style={{ height: 14 }} /></tr>);
                }
                return (
                  <tr key={i} style={{ borderTop: '1px solid var(--ak-line)' }}>
                    <td style={{ padding: '10px 10px 10px 0', color: 'var(--ak-fg-2)', textTransform: 'uppercase', whiteSpace: 'nowrap', verticalAlign: 'top', width: 220 }}>{row.role}</td>
                    <td style={{ padding: '10px 0', color: 'var(--ak-fg)' }}>{row.who}</td>
                  </tr>
                );
              })}
              <tr style={{ borderTop: '1px solid var(--ak-line)' }}><td colSpan="2" style={{ height: 0 }} /></tr>
            </tbody>
          </table>
        </Reveal>
      </div>
    </section>
  );
}

// =====================================================================
// CASE STUDY — editorial long-form
// =====================================================================
function CaseStudyA({ onNavigate }) {
  return (
    <div style={{ background: 'var(--ak-bg)', color: 'var(--ak-fg)' }}>

      {/* HERO */}
      <section style={{ padding: '40px 32px 24px', borderBottom: '1px solid var(--ak-line)' }}>
        <div style={{ maxWidth: 1280, margin: '0 auto' }}>
          <Reveal y={20}>
            <button onClick={() => onNavigate && onNavigate('work', { restore: true })}
              style={{
                background: 'transparent', border: 'none', padding: 0, cursor: 'pointer',
                fontFamily: "'JetBrains Mono', monospace", fontSize: 12,
                letterSpacing: '0.14em', textTransform: 'uppercase',
                color: 'var(--ak-fg-2)',
                display: 'inline-flex', alignItems: 'center', gap: 8,
                marginBottom: 24,
                transition: 'color 200ms cubic-bezier(0.2,0.6,0.2,1)',
              }}
              onMouseEnter={(e) => { e.currentTarget.style.color = 'var(--ak-fg)'; }}
              onMouseLeave={(e) => { e.currentTarget.style.color = 'var(--ak-fg-2)'; }}>
              <span style={{ display: 'inline-block', transition: 'transform 240ms cubic-bezier(0.2,0.6,0.2,1)' }}>←</span>
              back to work
            </button>
          </Reveal>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 48, alignItems: 'end', marginTop: 0 }}>
            <Reveal y={32}>
              <h1 style={{
                fontFamily: "'PP Neue Montreal', 'Geist', system-ui, sans-serif",
                fontSize: 'clamp(48px, 6vw, 88px)',
                lineHeight: 0.92,
                letterSpacing: '-0.04em',
                fontWeight: 400,
                margin: 0,
              }}>
                {CS.title}<span style={{ color: 'var(--ak-blue, #0052ff)' }}>.</span>
              </h1>
            </Reveal>
            <Reveal y={32} delay={120}>
              <p style={{
                fontFamily: "'PP Neue Montreal', 'Geist', system-ui, sans-serif",
                fontSize: 16, lineHeight: 1.4, letterSpacing: '-0.005em',
                color: 'var(--ak-fg)', margin: 0, maxWidth: 460,
              }}>
                {CS.subtitle}
              </p>
            </Reveal>
          </div>
        </div>
      </section>

      {/* HERO MEDIA */}
      <section style={{ padding: '0 32px', background: 'var(--ak-bg)' }}>
        <Reveal y={20}>
          <div style={{
            maxWidth: 1280, margin: '20px auto 0',
            borderRadius: 16, overflow: 'hidden',
            background: '#0a0b0d',
            border: '1px solid var(--ak-line)',
            position: 'relative',
          }}>
            <HeroVideo src="site/assets/02_PROJECT/2023/Nicole%20Moudaber/VDO/Reel_NM24_01_AI_v1_1920p.mp4" />
            <CornerMeta tl="NICOLE MOUDABER / TOUR" br={`PERFORMANCE · ${CS.year}`} />
          </div>
        </Reveal>
      </section>

      {/* AT A GLANCE STRIP */}
      <section style={{ padding: '64px 32px 32px' }}>
        <div style={{ maxWidth: 1280, margin: '0 auto',
          display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 24,
          paddingTop: 32, borderTop: '1px solid var(--ak-line)',
        }}>
          {[
            ['client', CS.client],
            ['studio', CS.studio],
            ['year',   CS.year],
            ['role',   CS.role],
          ].map(([k, v], i) => (
            <Reveal key={k} delay={i * 50}>
              <MonoLabel dim style={{ marginBottom: 10 }}>{k}</MonoLabel>
              <div style={{ fontSize: 15, lineHeight: 1.4, letterSpacing: '-0.005em' }}>{v}</div>
            </Reveal>
          ))}
        </div>
      </section>

      {/* LEAD */}
      <section style={{ padding: '48px 32px 96px' }}>
        <div style={{ maxWidth: 920, margin: '0 auto' }}>
          <Reveal>
            <p style={{
              fontFamily: "'PP Neue Montreal', 'Geist', system-ui, sans-serif",
              fontSize: 28, lineHeight: 1.32, letterSpacing: '-0.015em',
              fontWeight: 400, color: 'var(--ak-fg)', margin: 0,
              textWrap: 'balance',
            }}>
              {CS.lead}
            </p>
          </Reveal>
        </div>
      </section>

      {/* INDIVIDUAL BLOCKS */}
      {CS.blocks.map((b) => (
        <React.Fragment key={b.key}>
          <ProseSection eyebrow={b.eyebrow} title={b.title}>
            {b.body.map((p, i) => (
              <p key={i} style={proseP}>{p}</p>
            ))}
          </ProseSection>
          <section style={{ padding: '0 32px 120px', background: 'var(--ak-bg)' }}>
            <BlockMedia block={b} />
            {b.stillsGroups ? (
              b.stillsGroups.map((g, gi) => (
                <StillsGrid key={gi} stills={g.stills} alt={b.title} cols={g.cols} />
              ))
            ) : (
              <StillsGrid stills={b.stills} alt={b.title} cols={b.stillsCols} />
            )}
          </section>
        </React.Fragment>
      ))}

      {/* CREDITS */}
      <CreditsBlock />

    </div>
  );
}

window.CaseStudyNicoleMoudaber = CaseStudyA;

})();
