// CaseStudyMetDubfire.jsx — case study for The Met: DUBFIRE.
// 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: 'met-dubfire',
  title: 'The Met: DUBFIRE',
  subtitle: 'Live XR performance on-site at The Met Cloister.',
  client: 'The Metropolitan Museum of Art',
  studio: 'Volvox Labs',
  year: 2023,
  role: 'Motion Designer',

  // Lead — opening paragraph after the at-a-glance strip.
  lead: "Volvox Labs received an invitation to create a live performance set for Dubfire's techno music set under the Sonic Cloister project — a series of site-specific electronic music performances at The Metropolitan Museum of Art in New York. The team produced a full XR creative-and-technology setup that delivered a fresh presentation of visuals and sound, bridging the metaverse and reality in a one-hour cohesive live stream.",

  blocks: [
    {
      no: '01',
      key: 'content-design',
      eyebrow: '01 — Content Design',
      title: 'Content Design.',
      body: [
        'A custom visual system tuned to the cloister architecture — orange-red light forms that ride the geometry of the medieval space, scaled to read at every camera angle of the live stream.',
        'Each scene was authored as a self-contained set, sequenced to follow the dynamics of the music set so the visuals breathe with the performance instead of running in parallel to it.',
      ],
      stills: [
        'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/01_Content%20design/2D_01.webp',
        'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/01_Content%20design/Dubfire_Cloister_01.webp',
        'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/01_Content%20design/Dubfire_Cloister_03.webp',
        'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/01_Content%20design/Laser_03.webp',
        'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/01_Content%20design/Laser_04.webp',
        'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/01_Content%20design/Reader_01.webp',
      ],
      trailerVideo: 'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/VDO/2761432505.mp4',
    },
    {
      no: '02',
      key: 'chapter-house',
      eyebrow: '02 — The Chapter House',
      title: 'The Chapter House.',
      body: [
        'A 3D-scanned model of the Chapter House drove the content workflow end to end. The scan let the team design against the volumetric LED panel layout and the angles of the sided walls used for the additional dynamic camera movement during the performance.',
      ],
      stills: [
        'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/02_Chapter%20House/chapter_01.jpg',
        'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/02_Chapter%20House/chapter_02.jpg',
        'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/02_Chapter%20House/chapter_03.jpg',
        'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/02_Chapter%20House/Screenshot%202026-05-05%20173856.png',
      ],
    },
    {
      no: '03',
      key: 'behind-the-scene',
      eyebrow: '03 — Behind the Scene',
      title: 'Behind the Scene.',
      body: [
        'Production unfolded across the Cloister floor — operators, camera tracking, LED panels, and live broadcast infrastructure threaded through medieval architecture for a single one-hour run.',
      ],
      video: 'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/VDO/2775870828.mp4',
      cornerTl: 'BLOCK 03 / BTS',
      cornerBr: 'ON-SITE',
      stills: [
        'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/03_BTS/site_01.webp',
        'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/03_BTS/site_02.webp',
        'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/03_BTS/site_04.webp',
        'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/03_BTS/site_05.webp',
        'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/03_BTS/site_06.webp',
        'site/assets/02_PROJECT/2023/The%20Met_DUBFIRE/03_BTS/site_10.webp',
      ],
    },
  ],

  credits: [
    { role: 'Composition & Performance', who: 'Dubfire' },
    { role: 'Venue',                     who: 'The Met Cloisters' },
    { role: 'Video Team',                who: 'Bespoke Studios' },
    { divider: true },
    { role: 'Studio',                    who: 'Volvox Labs' },
    { role: 'Creative Director',         who: 'Kamil Nawratil' },
    { role: 'Director of xR Production', who: 'Javier Cruz · Ben Forest' },
    { role: 'UE4 Developer',             who: 'Pasakorn Nontananadh · Emilio Ramos' },
    { role: 'LED Lighting',              who: 'Lightworks Interactive' },
    { role: 'Photogrammetry',            who: 'MYND Workshop' },
    { role: 'Lighting',                  who: 'See Factor' },
    { role: 'Photography',               who: 'Sasha Bianca · Rory Higginson' },
  ],
};

// =====================================================================
// 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 BlockMedia({ block }) {
  const placeholderGradient = 'radial-gradient(ellipse at 50% 50%, #1a1a1a 0%, #0a0b0d 60%, #050505 100%)';
  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>
  );
}

// Stills grid — renders block.stills as a 2-col image grid below the BlockMedia.
function StillsGrid({ stills, alt }) {
  if (!stills || stills.length === 0) return null;
  return (
    <div style={{
      maxWidth: 1280, margin: '16px auto 0',
      display: 'grid',
      gridTemplateColumns: 'repeat(2, 1fr)',
      gap: 16,
    }}>
      {stills.map((src, i) => (
        <Reveal key={src} y={20} delay={i * 80}>
          <div style={{
            position: 'relative', overflow: 'hidden',
            aspectRatio: '16/9', borderRadius: 12,
            background: '#0a0b0d',
            border: '1px solid var(--ak-line)',
          }}>
            <img src={src} alt={`${alt} still ${i + 1}`}
              style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
          </div>
        </Reveal>
      ))}
    </div>
  );
}

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,
              }}>
                The Met:<br />DUBFIRE<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/The%20Met_DUBFIRE/VDO/2763411949.mp4" />
            <CornerMeta tl="THE MET / DUBFIRE" br={`SONIC CLOISTER · ${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}{' '}You can watch the whole performance{' '}
              <a href="https://youtu.be/vyTDQtEGIt8?si=FESAU8OrsnqQmC1b"
                target="_blank" rel="noopener noreferrer"
                style={{
                  color: 'var(--ak-blue, #0052ff)',
                  textDecoration: 'underline',
                  textUnderlineOffset: '4px',
                }}>
                here
              </a>.
            </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} />
            <StillsGrid stills={b.stills} alt={b.title} />
            {b.trailerVideo && (
              <Reveal y={20}>
                <div style={{
                  maxWidth: 1280, margin: '16px auto 0',
                  borderRadius: 16, overflow: 'hidden',
                  background: '#0a0b0d',
                  border: '1px solid var(--ak-line)',
                }}>
                  <video src={b.trailerVideo} autoPlay loop muted playsInline
                    style={{ width: '100%', height: 'auto', display: 'block' }} />
                </div>
              </Reveal>
            )}
          </section>
        </React.Fragment>
      ))}

      {/* CREDITS */}
      <CreditsBlock />

    </div>
  );
}

window.CaseStudyMetDubfire = CaseStudyA;

})();
