// contact.jsx — Get In Touch page for Digital Immersive Box
// Standalone page: loads after tweaks-panel.jsx + dib-i18n.jsx.
// No external assets required — all atoms defined inline.
const { useEffect, useRef, useState, useMemo } = React;

/* ─── Constants (mirrors dib-app.jsx) ──────────────────────────────────── */
const ACCENT_PRESETS = {
  cyan:   '#22e3ff',
  blue:   '#5b8cff',
  purple: '#a45bff',
  mint:   '#3df0b3',
  amber:  '#ffb547',
  pink:   '#ff5b9c',
};

const TYPEFACES = {
  sora:   { display: "'Sora', system-ui, sans-serif",          body: "'Inter', system-ui, sans-serif" },
  inter:  { display: "'Inter', system-ui, sans-serif",         body: "'Inter', system-ui, sans-serif" },
  grotesk:{ display: "'Space Grotesk', system-ui, sans-serif", body: "'Inter', system-ui, sans-serif" },
};

const LANGS = [
  { value: 'en', label: 'English',  flag: '🇬🇧' },
  { value: 'de', label: 'Deutsch',  flag: '🇩🇪' },
  { value: 'ro', label: 'Română',   flag: '🇷🇴' },
  { value: 'fr', label: 'Français', flag: '🇫🇷' },
  { value: 'it', label: 'Italiano', flag: '🇮🇹' },
  { value: 'es', label: 'Español',  flag: '🇪🇸' },
];

const TWEAK_DEFAULTS = {
  accent: 'cyan', customColor: '#22e3ff', glowIntensity: 35,
  typeface: 'sora', motion: 'medium', language: 'en', theme: 'dark',
};

/* ─── Static studio contact data ────────────────────────────────────────── */
const STUDIO = {
  email:   'hello@digitalimmersivebox.com',
  phone:   '+40 752 931 873',
  address: 'Cluj-Napoca · Romania',
  hours:   'Mon–Fri · 09:00–18:00 EET',
  /** Project type chips — these are product/technical terms, kept in English. */
  projectTypes: [
    'VR training / simulation',
    'AR mobile experience',
    'Interactive installation',
    'Web 3D / configurator',
    'AI integration',
    'Something else',
  ],
};

/* ─── Helpers ────────────────────────────────────────────────────────────── */
/** Convert a CSS hex colour to an "R, G, B" string for rgba() usage. */
function hexToRgb(hex) {
  const h = hex.replace('#', '');
  return `${parseInt(h.slice(0,2),16)}, ${parseInt(h.slice(2,4),16)}, ${parseInt(h.slice(4,6),16)}`;
}

/**
 * Push all tweaks to CSS custom properties and body classes.
 * Keeps the page in sync with the shared localStorage tweaks store.
 */
function applyTweaks(t) {
  const root  = document.documentElement;
  const color = t.accent === 'custom' ? t.customColor : (ACCENT_PRESETS[t.accent] || ACCENT_PRESETS.cyan);
  const rgb   = hexToRgb(color);
  const alpha = ((t.glowIntensity ?? 35) / 100).toFixed(2);

  root.style.setProperty('--accent',      color);
  root.style.setProperty('--accent-dim',  `rgba(${rgb}, 0.20)`);
  root.style.setProperty('--accent-glow', `rgba(${rgb}, ${alpha})`);
  root.style.setProperty('--accent-soft', `rgba(${rgb}, 0.08)`);

  const tp = TYPEFACES[t.typeface] || TYPEFACES.sora;
  root.style.setProperty('--display', tp.display);
  root.style.setProperty('--body',    tp.body);

  document.body.classList.remove('motion-low', 'motion-medium', 'motion-high');
  document.body.classList.add(`motion-${t.motion}`);

  document.documentElement.lang = t.language || 'en';
  document.documentElement.setAttribute('data-theme', t.theme || 'dark');
}

/* ─── SVG atoms ──────────────────────────────────────────────────────────── */
/** DIB isometric cube wordmark. Used in the nav and as a standalone mark. */
function DibMark({ size = 22 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" aria-hidden="true">
      <g stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round" strokeLinecap="round">
        <path d="M12 3 L21 7.5 L21 16.5 L12 21 L3 16.5 L3 7.5 Z" />
        <path d="M3 7.5 L12 12 L21 7.5" />
        <path d="M12 12 L12 21" opacity="0.6" />
      </g>
    </svg>
  );
}

/** Right-pointing arrow; receives .arrow class for the btn hover translate. */
function Arrow({ size = 16 }) {
  return (
    <svg className="arrow" width={size} height={size} viewBox="0 0 16 16" fill="none" aria-hidden="true">
      <path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" strokeWidth="1.5"
            strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

/* ─── MiniLattice canvas ─────────────────────────────────────────────────── */
/**
 * Animated isometric cube-lattice on a <canvas>. Used as an ambient hero bg.
 * Reads --accent from CSS at runtime so it follows theme/accent tweaks.
 * No-ops on prefers-reduced-motion: reduce.
 */
function MiniLattice({ opacity = 0.45 }) {
  const canvasRef = useRef(null);
  const reduced   = useMemo(() => window.matchMedia('(prefers-reduced-motion: reduce)').matches, []);

  useEffect(() => {
    if (reduced) return;
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let w = 0, h = 0, raf;
    const dpr = Math.min(window.devicePixelRatio || 1, 2);

    const resize = () => {
      const r = canvas.getBoundingClientRect();
      w = r.width; h = r.height;
      canvas.width  = Math.max(2, w * dpr);
      canvas.height = Math.max(2, h * dpr);
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    };
    resize();
    const ro = new ResizeObserver(resize);
    ro.observe(canvas);

    // Cube geometry
    const HALF = 0.45;
    const verts = [
      [-1,-1,-1],[1,-1,-1],[1,1,-1],[-1,1,-1],
      [-1,-1, 1],[1,-1, 1],[1,1, 1],[-1,1, 1],
    ].map(v => v.map(c => c * HALF));
    const edges = [
      [0,1],[1,2],[2,3],[3,0],
      [4,5],[5,6],[6,7],[7,4],
      [0,4],[1,5],[2,6],[3,7],
    ];

    // Cube grid
    const GRID = 3, STEP = 1.5;
    const cubes = [];
    for (let x = 0; x < GRID; x++)
      for (let y = 0; y < GRID; y++)
        for (let z = 0; z < GRID; z++)
          cubes.push({
            p: [(x-(GRID-1)/2)*STEP, (y-(GRID-1)/2)*STEP, (z-(GRID-1)/2)*STEP],
            active: Math.random() < 0.22,
            phase:  Math.random() * Math.PI * 2,
            speed:  0.4 + Math.random() * 0.6,
          });

    // Projection & rotation helpers
    const FOCAL = 5.5;
    const proj = (x, y, z, cx, cy, f0) => {
      const f = FOCAL / (FOCAL + z);
      return [cx + x * f * f0, cy + y * f * f0, f];
    };
    const rot = ([x, y, z], rx, ry) => {
      const cy0 = Math.cos(rx), sy0 = Math.sin(rx);
      let ny = y * cy0 - z * sy0, nz = y * sy0 + z * cy0;
      y = ny; z = nz;
      const cx0 = Math.cos(ry), sx0 = Math.sin(ry);
      let nx = x * cx0 + z * sx0; nz = -x * sx0 + z * cx0;
      return [nx, y, nz];
    };

    const start = performance.now();

    const tick = (now) => {
      const t     = (now - start) / 1000;
      const cx    = w / 2, cy = h / 2;
      const focal = Math.min(w, h) * 0.13;
      const rx    = Math.sin(t * 0.18) * 0.45 + 0.55;
      const ry    = t * 0.18;
      // Read the live accent colour so it responds to tweaks in real-time.
      const accentCol = getComputedStyle(document.documentElement)
                          .getPropertyValue('--accent').trim() || '#22e3ff';

      ctx.clearRect(0, 0, w, h);

      cubes
        .map(c => ({ c, rp: rot(c.p, rx, ry) }))
        .sort((a, b) => b.rp[2] - a.rp[2])
        .forEach(({ c, rp }) => {
          const pulse = c.active ? 0.6 + 0.4 * Math.sin(t * c.speed * 2 + c.phase) : 0;
          ctx.lineWidth = c.active ? 1.1 : 0.6;

          for (const [a, b] of edges) {
            const va = rot([c.p[0]+verts[a][0], c.p[1]+verts[a][1], c.p[2]+verts[a][2]], rx, ry);
            const vb = rot([c.p[0]+verts[b][0], c.p[1]+verts[b][1], c.p[2]+verts[b][2]], rx, ry);
            const [ax, ay, af] = proj(va[0], va[1], va[2], cx, cy, focal);
            const [bx, by, bf] = proj(vb[0], vb[1], vb[2], cx, cy, focal);
            const depth     = (af + bf) / 2;
            const baseAlpha = Math.max(0.05, Math.min(1, (depth - 0.6) * 1.4));

            if (c.active) {
              ctx.strokeStyle = accentCol;
              ctx.globalAlpha = baseAlpha * (0.4 + pulse * 0.6);
              ctx.shadowColor = accentCol;
              ctx.shadowBlur  = 12 * pulse;
            } else {
              ctx.strokeStyle = '#a1a1aa';
              ctx.globalAlpha = baseAlpha * 0.32;
              ctx.shadowBlur  = 0;
            }
            ctx.beginPath();
            ctx.moveTo(ax, ay);
            ctx.lineTo(bx, by);
            ctx.stroke();
          }

          if (c.active) {
            const [cpx, cpy] = proj(rp[0], rp[1], rp[2], cx, cy, focal);
            ctx.globalAlpha = 0.55 + pulse * 0.4;
            ctx.fillStyle   = accentCol;
            ctx.shadowColor = accentCol;
            ctx.shadowBlur  = 18;
            ctx.beginPath();
            ctx.arc(cpx, cpy, 1.8 + pulse * 1.4, 0, Math.PI * 2);
            ctx.fill();
          }
        });

      ctx.globalAlpha = 1;
      ctx.shadowBlur  = 0;
      raf = requestAnimationFrame(tick);
    };

    raf = requestAnimationFrame(tick);
    return () => { cancelAnimationFrame(raf); ro.disconnect(); };
  }, []);

  if (reduced) return null;

  return (
    <div aria-hidden="true" style={{ position: 'absolute', inset: 0, opacity, pointerEvents: 'none' }}>
      <canvas ref={canvasRef} style={{ width: '100%', height: '100%', display: 'block' }} />
      {/* Radial vignette: fades the lattice into the section background */}
      <div style={{
        position: 'absolute', inset: 0,
        background: 'radial-gradient(ellipse at center, transparent 30%, var(--bg) 100%)',
        pointerEvents: 'none',
      }} />
    </div>
  );
}

/* ─── Contact Nav ────────────────────────────────────────────────────────── */
/**
 * Pixel-identical replica of the main site's Nav component.
 * Middle links: "Home" (→ index.html) + the current page title (accent, non-link).
 * Right side: appearance dropdown (theme + accent + glow) + language dropdown.
 * Uses the full language object (tFull) for dropdown labels so they translate too.
 */
function ContactNav({ t, tFull, tweaks, setTweak, langs, presets }) {
  const [langOpen,   setLangOpen]   = useState(false);
  const [appearOpen, setAppearOpen] = useState(false);
  const langRef   = useRef(null);
  const appearRef = useRef(null);

  // Close dropdowns on outside click
  useEffect(() => {
    const onDoc = e => {
      if (langRef.current   && !langRef.current.contains(e.target))   setLangOpen(false);
      if (appearRef.current && !appearRef.current.contains(e.target)) setAppearOpen(false);
    };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, []);

  const currentLang  = langs.find(l => l.value === tweaks.language) || langs[0];
  const currentColor = tweaks.accent === 'custom'
    ? tweaks.customColor
    : (presets[tweaks.accent] || presets.cyan);
  const isLight = tweaks.theme === 'light';

  return (
    <nav className="nav" aria-label="Main navigation">

      {/* Logo */}
      <a href="index.html" className="nav__logo" aria-label="Digital Immersive Box — home">
        <span className="nav__mark">
          <img src="dib_solo.png" alt="dib" width="28" height="28"
               style={{ objectFit: 'contain', display: 'block' }} />
        </span>
        Digital Immersive Box
      </a>

      {/* Middle links: Home + current page */}
      <div className="nav__links">
        <a href="index.html">Home</a>
        <span className="nav__links-current" aria-current="page">{t.eyebrow}</span>
      </div>

      {/* Right controls */}
      <div className="nav__right">

        {/* ── Appearance: theme + accent + glow ── */}
        <div className="nav__pop" ref={appearRef}>
          <button
            className="nav__icon-btn nav__icon-btn--appear"
            onClick={() => { setAppearOpen(o => !o); setLangOpen(false); }}
            aria-label="Appearance settings"
            aria-expanded={appearOpen}
          >
            <span className={`nav__theme-icon ${isLight ? 'is-light' : 'is-dark'}`}>
              {isLight ? (
                /* moon */
                <svg width="14" height="14" viewBox="0 0 16 16" fill="none" aria-hidden="true">
                  <path d="M13 9.5A5.5 5.5 0 0 1 6.5 3a5.5 5.5 0 1 0 6.5 6.5z" fill="currentColor"/>
                </svg>
              ) : (
                /* sun */
                <svg width="14" height="14" viewBox="0 0 16 16" fill="none" aria-hidden="true">
                  <circle cx="8" cy="8" r="3" fill="currentColor"/>
                  <g stroke="currentColor" strokeWidth="1.4" strokeLinecap="round">
                    <line x1="8" y1="1" x2="8" y2="3"/>
                    <line x1="8" y1="13" x2="8" y2="15"/>
                    <line x1="1" y1="8" x2="3" y2="8"/>
                    <line x1="13" y1="8" x2="15" y2="8"/>
                    <line x1="3" y1="3" x2="4.4" y2="4.4"/>
                    <line x1="11.6" y1="11.6" x2="13" y2="13"/>
                    <line x1="3" y1="13" x2="4.4" y2="11.6"/>
                    <line x1="11.6" y1="4.4" x2="13" y2="3"/>
                  </g>
                </svg>
              )}
            </span>
            <span className="nav__color-dot" style={{ background: currentColor }} />
          </button>

          {appearOpen && (
            <div className="nav__menu nav__menu--appear">
              {/* Theme toggle */}
              <div className="nav__theme-row">
                <span className="nav__appear-label">Theme</span>
                <div className="nav__theme-btns">
                  <button
                    className={`nav__theme-opt ${!isLight ? 'on' : ''}`}
                    onClick={() => setTweak('theme', 'dark')}
                  >Dark</button>
                  <button
                    className={`nav__theme-opt ${isLight ? 'on' : ''}`}
                    onClick={() => setTweak('theme', 'light')}
                  >Light</button>
                </div>
              </div>

              {/* Accent swatches */}
              <div className="nav__swatches">
                {Object.entries(presets).map(([key, color]) => (
                  <button
                    key={key}
                    className={`nav__swatch ${tweaks.accent === key ? 'on' : ''}`}
                    style={{
                      background: color,
                      boxShadow: tweaks.accent === key
                        ? `0 0 0 2px var(--bg-2), 0 0 0 4px ${color}` : undefined,
                    }}
                    onClick={() => setTweak('accent', key)}
                    aria-label={key} title={key}
                  />
                ))}
              </div>

              {/* Custom colour picker */}
              <label className="nav__custom">
                <span>{tFull.tweaks.custom}</span>
                <input
                  type="color"
                  value={tweaks.customColor}
                  onChange={e => setTweak({ accent: 'custom', customColor: e.target.value })}
                />
                <span className="nav__custom-hex">{tweaks.customColor}</span>
              </label>

              {/* Glow intensity */}
              <div className="nav__glow-row">
                <span>{tFull.tweaks.glow}</span>
                <input
                  type="range"
                  className="nav__glow-slider"
                  min="0" max="100" step="1"
                  value={tweaks.glowIntensity ?? 35}
                  onChange={e => setTweak('glowIntensity', Number(e.target.value))}
                />
                <span className="nav__glow-val">{tweaks.glowIntensity ?? 35}%</span>
              </div>
            </div>
          )}
        </div>

        {/* ── Language picker ── */}
        <div className="nav__pop" ref={langRef}>
          <button
            className="nav__icon-btn"
            onClick={() => { setLangOpen(o => !o); setAppearOpen(false); }}
            aria-label="Language"
            aria-expanded={langOpen}
          >
            <span className="nav__flag">{currentLang.flag}</span>
            <span className="nav__code">{currentLang.value.toUpperCase()}</span>
            <svg width="10" height="10" viewBox="0 0 10 10" aria-hidden="true">
              <path d="M2 4l3 3 3-3" stroke="currentColor" strokeWidth="1.4"
                    fill="none" strokeLinecap="round" strokeLinejoin="round"/>
            </svg>
          </button>

          {langOpen && (
            <div className="nav__menu">
              {langs.map(l => (
                <button
                  key={l.value}
                  className={`nav__menu-item ${tweaks.language === l.value ? 'on' : ''}`}
                  onClick={() => { setTweak('language', l.value); setLangOpen(false); }}
                >
                  <span className="nav__flag">{l.flag}</span>
                  <span>{l.label}</span>
                  <span className="nav__menu-code">{l.value.toUpperCase()}</span>
                </button>
              ))}
            </div>
          )}
        </div>

      </div>
    </nav>
  );
}

/* ─── Contact Page ───────────────────────────────────────────────────────── */
/**
 * Main page component. Renders hero → form split → next steps → closing.
 * Wires up IntersectionObserver for .reveal classes on each language change.
 */
function ContactPage({ t }) {
  const [proj, setProj]           = useState(null);
  const [submitted, setSubmitted] = useState(false);

  // Re-bind scroll-reveal when language changes (DOM strings rebuild).
  useEffect(() => {
    const els = document.querySelectorAll('.reveal:not(.in)');
    const io  = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); }
      });
    }, { threshold: 0.1, rootMargin: '0px 0px -40px 0px' });
    els.forEach(el => io.observe(el));
    return () => io.disconnect();
  }, [t]);

  const handleSubmit = (e) => {
    e.preventDefault();
    setSubmitted(true);
  };

  return (
    <main>

      {/* ── Hero ──────────────────────────────────────────────────────────── */}
      <header className="contact-hero">
        {/* Ambient cube lattice — purely decorative */}
        <div style={{ position: 'absolute', inset: 0, opacity: 0.45, pointerEvents: 'none' }}>
          <MiniLattice opacity={1} />
        </div>

        <div className="contact-hero__inner">
          {/* Left: title */}
          <div className="reveal">
            <span style={{
              fontFamily: 'var(--mono)', fontSize: 12,
              letterSpacing: '0.2em', textTransform: 'uppercase',
              color: 'var(--accent)', marginBottom: 24, display: 'block',
            }}>
              {t.eyebrow}
            </span>
            <h1 style={{
              fontFamily: 'var(--display)', fontWeight: 600,
              fontSize: 'clamp(52px, 7.5vw, 100px)',
              lineHeight: 0.95, letterSpacing: '-0.035em', margin: 0,
            }}>
              <span dangerouslySetInnerHTML={{ __html: t.hero_title_1 }} />
              <br />
              <em style={{
                fontWeight: 300, fontStyle: 'italic',
                color: 'var(--accent)',
                textShadow: '0 0 60px var(--accent-glow)',
              }}>
                {t.hero_title_italic}
              </em>
            </h1>
          </div>

          {/* Right: intro */}
          <p className="reveal delay-1" style={{
            fontFamily: 'var(--display)', fontWeight: 300,
            fontSize: 'clamp(17px, 1.5vw, 22px)', lineHeight: 1.45,
            color: 'var(--fg-dim)', margin: 0, maxWidth: '40ch',
          }}>
            {t.hero_intro}
          </p>
        </div>
      </header>

      {/* ── Main split: contact info + form ─────────────────────────────── */}
      <section style={{ borderBottom: '1px solid var(--line)' }}>
        <div className="contact-main">

          {/* Aside: studio details */}
          <aside className="reveal">
            <h2 style={{
              fontFamily: 'var(--display)', fontWeight: 500, fontSize: 28,
              letterSpacing: '-0.015em', margin: '0 0 18px',
            }}>{t.aside_title}</h2>
            <p style={{
              fontSize: 15, lineHeight: 1.65, color: 'var(--fg-dim)',
              margin: '0 0 36px', maxWidth: '38ch',
            }}>{t.aside_text}</p>

            <dl style={{
              display: 'flex', flexDirection: 'column', gap: 24,
              borderTop: '1px solid var(--line)', paddingTop: 32,
              margin: 0,
            }}>
              {[
                { k: t.label_email,  v: STUDIO.email,   href: `mailto:${STUDIO.email}` },
                { k: t.label_phone,  v: STUDIO.phone   },
                { k: t.label_studio, v: STUDIO.address },
              ].map(({ k, v, href }) => (
                <div key={k} style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
                  <dt style={{
                    fontFamily: 'var(--mono)', fontSize: 10,
                    letterSpacing: '0.18em', textTransform: 'uppercase',
                    color: 'var(--fg-faint)',
                  }}>{k}</dt>
                  <dd style={{ margin: 0 }}>
                    {href
                      ? <a href={href} style={{
                          fontFamily: 'var(--display)', fontSize: 20, fontWeight: 500,
                          letterSpacing: '-0.01em',
                          transition: 'color 0.2s ease',
                        }}
                        onMouseEnter={e => e.currentTarget.style.color = 'var(--accent)'}
                        onMouseLeave={e => e.currentTarget.style.color = 'var(--fg)'}>
                          {v}
                        </a>
                      : <span style={{
                          fontFamily: 'var(--display)', fontSize: 20, fontWeight: 500,
                          letterSpacing: '-0.01em',
                        }}>{v}</span>
                    }
                  </dd>
                </div>
              ))}
            </dl>
          </aside>

          {/* Form box */}
          <div className="reveal delay-1" style={{
            border: '1px solid var(--line)',
            borderRadius: 16,
            padding: 'clamp(28px, 3vw, 44px)',
            background: 'rgba(255, 255, 255, 0.015)',
          }}>

            {submitted ? (
              /* ── Success state ─────────────────────────────────────────── */
              <div style={{ textAlign: 'center', padding: '48px 24px' }}>
                <div style={{
                  width: 56, height: 56, borderRadius: '50%',
                  background: 'var(--accent-soft)', border: '1px solid var(--accent)',
                  display: 'grid', placeItems: 'center', margin: '0 auto 24px',
                }}>
                  <svg width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true">
                    <path d="M5 12l5 5L19 7" stroke="var(--accent)" strokeWidth="2"
                          strokeLinecap="round" strokeLinejoin="round" />
                  </svg>
                </div>
                <h3 style={{
                  fontFamily: 'var(--display)', fontWeight: 500, fontSize: 22,
                  margin: '0 0 12px', letterSpacing: '-0.01em',
                }}>{t.success_title}</h3>
                <p style={{ color: 'var(--fg-dim)', fontSize: 14, lineHeight: 1.6, margin: '0 0 28px' }}>
                  {t.response}
                </p>
                <button className="btn" onClick={() => setSubmitted(false)}>
                  {t.success_another}
                </button>
              </div>

            ) : (
              /* ── Form ──────────────────────────────────────────────────── */
              <>
                <div style={{
                  display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
                  marginBottom: 28, paddingBottom: 24, borderBottom: '1px solid var(--line)',
                }}>
                  <h3 style={{
                    fontFamily: 'var(--display)', fontWeight: 500, fontSize: 22,
                    margin: 0, letterSpacing: '-0.01em',
                  }}>{t.form_title}</h3>
                  <span style={{
                    fontFamily: 'var(--mono)', fontSize: 10,
                    letterSpacing: '0.18em', textTransform: 'uppercase',
                    color: 'var(--fg-faint)',
                  }}>{t.form_id}</span>
                </div>

                <form className="form" onSubmit={handleSubmit} noValidate>
                  {/* Name row */}
                  <div className="field--row">
                    <div className="field">
                      <label htmlFor="contact-fname">{t.fname}</label>
                      <input id="contact-fname" type="text"
                             placeholder={t.fname_ph} required autoComplete="given-name" />
                    </div>
                    <div className="field">
                      <label htmlFor="contact-lname">{t.lname}</label>
                      <input id="contact-lname" type="text"
                             placeholder={t.lname_ph} required autoComplete="family-name" />
                    </div>
                  </div>

                  {/* Email */}
                  <div className="field">
                    <label htmlFor="contact-email">{t.form_email}</label>
                    <input id="contact-email" type="email"
                           placeholder={t.form_email_ph} required autoComplete="email" />
                  </div>

                  {/* Company */}
                  <div className="field">
                    <label htmlFor="contact-company">{t.company}</label>
                    <input id="contact-company" type="text"
                           placeholder={t.company_ph} autoComplete="organization" />
                  </div>

                  {/* Project type chips */}
                  <div>
                    <span style={{
                      fontFamily: 'var(--mono)', fontSize: 10,
                      letterSpacing: '0.18em', textTransform: 'uppercase',
                      color: 'var(--fg-faint)', marginBottom: 10, display: 'block',
                    }}>{t.proj_type}</span>
                    <div className="chip-row" role="group" aria-label={t.proj_type}>
                      {STUDIO.projectTypes.map(type => (
                        <button
                          key={type} type="button"
                          className={`chip ${proj === type ? 'on' : ''}`}
                          aria-pressed={proj === type}
                          onClick={() => setProj(type === proj ? null : type)}
                        >{type}</button>
                      ))}
                    </div>
                  </div>

                  {/* Brief */}
                  <div className="field">
                    <label htmlFor="contact-brief">{t.brief}</label>
                    <textarea id="contact-brief"
                              placeholder={t.brief_ph} required />
                  </div>

                  {/* Submit row */}
                  <div style={{
                    display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                    marginTop: 28, paddingTop: 20, borderTop: '1px solid var(--line)',
                    flexWrap: 'wrap', gap: 16,
                  }}>
                    <span style={{
                      fontFamily: 'var(--mono)', fontSize: 10,
                      letterSpacing: '0.14em', textTransform: 'uppercase',
                      color: 'var(--fg-faint)',
                    }}>{t.response}</span>
                    <button className="btn btn--primary" type="submit">
                      {t.submit} <Arrow />
                    </button>
                  </div>
                </form>
              </>
            )}
          </div>
        </div>
      </section>

      {/* ── What happens next ─────────────────────────────────────────────── */}
      <section style={{ borderBottom: '1px solid var(--line)' }}>
        <div className="contact-next">
          {/* Section header */}
          <div className="contact-next__head reveal">
            <div>
              <span style={{
                fontFamily: 'var(--mono)', fontSize: 12,
                letterSpacing: '0.2em', textTransform: 'uppercase',
                color: 'var(--accent)', marginBottom: 16, display: 'block',
              }}>{t.next_eyebrow}</span>
              <h2 style={{
                fontFamily: 'var(--display)', fontWeight: 500,
                fontSize: 'clamp(34px, 4vw, 52px)',
                lineHeight: 1.0, letterSpacing: '-0.025em',
                margin: 0, maxWidth: '16ch',
              }}>{t.next_title}</h2>
            </div>
            <p style={{ fontSize: 15, lineHeight: 1.6, color: 'var(--fg-dim)', margin: 0, maxWidth: '46ch' }}>
              {t.next_lede}
            </p>
          </div>

          {/* Step cards */}
          <div className="contact-next__grid">
            {t.next.map((step, i) => (
              <article key={step.idx} className={`reveal delay-${i + 1}`} style={{
                border: '1px solid var(--line)', borderRadius: 14,
                padding: '32px 28px',
                display: 'flex', flexDirection: 'column', gap: 16,
                background: 'rgba(255, 255, 255, 0.015)',
                minHeight: 200,
              }}>
                <span style={{
                  fontFamily: 'var(--mono)', fontSize: 11,
                  letterSpacing: '0.18em', color: 'var(--accent)',
                }}>{step.idx}</span>
                <h3 style={{
                  fontFamily: 'var(--display)', fontWeight: 500, fontSize: 22,
                  letterSpacing: '-0.01em', margin: 0,
                }}>{step.t}</h3>
                <p style={{ fontSize: 13, lineHeight: 1.65, color: 'var(--fg-dim)', margin: 0 }}>
                  {step.d}
                </p>
              </article>
            ))}
          </div>
        </div>
      </section>

      {/* ── Closing strip ─────────────────────────────────────────────────── */}
      <section className="contact-closing">
        <p className="reveal" style={{
          fontFamily: 'var(--display)', fontStyle: 'italic', fontWeight: 300,
          fontSize: 'clamp(22px, 3.5vw, 36px)', color: 'var(--fg-dim)', margin: 0,
        }}>
          {t.closing}{' — '}
          <span style={{ color: 'var(--accent)' }}>dib</span>
        </p>
      </section>

      {/* ── Footer ────────────────────────────────────────────────────────── */}
      <footer className="contact-footer">
        <span style={{
          fontFamily: 'var(--mono)', fontSize: 11,
          letterSpacing: '0.1em', textTransform: 'uppercase',
          color: 'var(--fg-faint)',
        }}>
          © 2026 Digital Immersive Box
        </span>
        <a
          href="index.html"
          style={{
            fontFamily: 'var(--mono)', fontSize: 11,
            letterSpacing: '0.14em', textTransform: 'uppercase',
            color: 'var(--fg-faint)', display: 'flex', alignItems: 'center', gap: 8,
            transition: 'color 0.2s ease',
          }}
          onMouseEnter={e => e.currentTarget.style.color = 'var(--accent)'}
          onMouseLeave={e => e.currentTarget.style.color = 'var(--fg-faint)'}
        >
          ← digitalimmersivebox.com
        </a>
      </footer>

    </main>
  );
}

/* ─── Root App ───────────────────────────────────────────────────────────── */
/**
 * Root wrapper: owns the useTweaks state, applies tweaks to the DOM, and
 * resolves both the full language object (for nav dropdown labels) and the
 * contact-specific translation object (for page content).
 */
function ContactApp() {
  const [tweaks, setTweak] = window.useTweaks(TWEAK_DEFAULTS);

  // Sync CSS custom properties whenever any tweak changes.
  useEffect(() => { applyTweaks(tweaks); }, [tweaks]);

  // Full language object — needed by ContactNav for dropdown labels.
  const tFull = useMemo(() => window.I18N[tweaks.language] || window.I18N.en, [tweaks.language]);

  // Contact-specific strings — used by the page body.
  const t = useMemo(() => tFull.contact || window.I18N.en.contact, [tFull]);

  return (
    <>
      <ContactNav
        t={t}
        tFull={tFull}
        tweaks={tweaks}
        setTweak={setTweak}
        langs={LANGS}
        presets={ACCENT_PRESETS}
      />
      <ContactPage t={t} />
    </>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<ContactApp />);
