// home-services-overlay-video.jsx
// A 15-second video edit: plays hero-bg.mp4 as the background and layers
// animated overlays (captions, lower-thirds, badges, end card) synced to
// the video's currentTime. Looped, muted, autoplay.

const OV_CREAM    = '#F7F2E8';
const OV_CREAM_2  = '#F1ECDF';
const OV_CREAM_3  = '#FAF6EC';
const OV_INK      = '#1B1814';
const OV_INK_2    = '#5B544A';
const OV_INK_3    = '#8A8275';
const OV_GOLD     = '#C7A24A';
const OV_GOLD_DK  = '#A88431';
const OV_GOLD_SOFT = '#F4E6BE';
const OV_RED      = '#C84B3C';
const OV_GREEN    = '#2F7A4D';

const OV_SERIF = "'Instrument Serif', Georgia, serif";
const OV_SANS  = "'Inter', -apple-system, BlinkMacSystemFont, sans-serif";

// Easings (mirror animations.jsx so file is standalone-ish)
const ovEase = {
  outCubic: (t) => 1 - Math.pow(1 - t, 3),
  inCubic:  (t) => t * t * t,
  outBack:  (t) => { const c1=1.70158, c3=c1+1; return 1 + c3*Math.pow(t-1,3) + c1*Math.pow(t-1,2); },
  outQuart: (t) => 1 - Math.pow(1 - t, 4),
};
const ovClamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));

// ── Time hook: drives off the actual <video> element ────────────────────
function useVideoTime(videoRef) {
  const [t, setT] = React.useState(0);
  React.useEffect(() => {
    let raf;
    const tick = () => {
      const v = videoRef.current;
      if (v) setT(v.currentTime);
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [videoRef]);
  return t;
}

// ── Time-window helper: returns {in, out, eased} given t and a window ───
function windowFade(t, start, end, fadeIn = 0.35, fadeOut = 0.35) {
  if (t < start || t > end) return { visible: false, opacity: 0, eased: 0 };
  const local = t - start;
  const span = end - start;
  let opacity = 1;
  if (local < fadeIn) opacity = ovEase.outCubic(local / fadeIn);
  else if (local > span - fadeOut) opacity = ovEase.outCubic((span - local) / fadeOut);
  return { visible: true, opacity, eased: ovEase.outCubic(ovClamp(local / span, 0, 1)), local, span };
}

// ── Cinematic letterbox bars (slide in/out at edges) ────────────────────
function Letterbox({ t }) {
  // appear immediately, retract for the end card moment (last 2s) for impact
  const intro = ovEase.outCubic(ovClamp(t / 0.6, 0, 1));
  const outro = ovEase.outCubic(ovClamp((t - 13) / 1.5, 0, 1));
  const h = 56 * intro * (1 - outro);
  return (
    <>
      <div style={{position:'absolute', top:0, left:0, right:0, height: h, background: '#000', zIndex: 2, pointerEvents:'none'}}/>
      <div style={{position:'absolute', bottom:0, left:0, right:0, height: h, background: '#000', zIndex: 2, pointerEvents:'none'}}/>
    </>
  );
}

// ── Top-left brand watermark (always on, fades for end card) ────────────
function Watermark({ t }) {
  const opacity = t < 13 ? 1 : ovClamp(1 - (t - 13) / 0.8, 0, 1);
  return (
    <div style={{
      position:'absolute', top: 24, left: 28, zIndex: 5,
      display:'flex', alignItems:'center', gap: 10,
      opacity,
      transition: 'opacity 0.3s',
    }}>
      <img src="../logo-mark-light.png" alt="" style={{height: 28, display:'block', filter:'drop-shadow(0 2px 6px rgba(0,0,0,0.4))'}}/>
      <div style={{
        fontFamily: OV_SANS, color:'#fff', fontSize: 12, fontWeight: 700,
        letterSpacing: '0.16em', textTransform:'uppercase',
        textShadow:'0 1px 4px rgba(0,0,0,0.6)',
      }}>{window.t ? window.t('v.brand') : 'FastFix · Home services'}</div>
    </div>
  );
}

// ── Bottom-right timestamp counter (cinematic detail) ───────────────────
function TimeStamp({ t }) {
  const opacity = t < 13 ? 0.7 : ovClamp(1 - (t - 13) / 0.8, 0, 0.7);
  return (
    <div style={{
      position:'absolute', top: 24, right: 28, zIndex: 5,
      fontFamily: 'ui-monospace, Menlo, monospace', color:'#fff',
      fontSize: 11, letterSpacing:'0.1em', fontWeight: 600,
      background:'rgba(0,0,0,0.35)', padding:'6px 10px', borderRadius: 4,
      backdropFilter:'blur(4px)',
      opacity,
    }}>
      REC ● 00:{String(Math.floor(t)).padStart(2,'0')}:{String(Math.floor((t%1)*100)).padStart(2,'0')}
    </div>
  );
}

// ── Scene A (0–3s): Hook caption — "It's late. Your phone won't stop." ─
function SceneHook({ t }) {
  const w = windowFade(t, 0.3, 3.2, 0.5, 0.5);
  if (!w.visible) return null;
  const rise = (1 - w.opacity) * 14;
  return (
    <div style={{
      position:'absolute', left: 60, bottom: 110, zIndex: 4,
      opacity: w.opacity, transform: `translateY(${rise}px)`,
      maxWidth: 720,
    }}>
      <div style={{
        fontFamily: OV_SANS, fontSize: 12, fontWeight: 700,
        letterSpacing:'0.18em', textTransform:'uppercase',
        color: OV_GOLD, marginBottom: 10,
        textShadow:'0 1px 6px rgba(0,0,0,0.6)',
      }}>
        <span style={{display:'inline-block', width:6, height:6, background: OV_GOLD, borderRadius:'50%', marginRight:8, transform:'translateY(-2px)'}}/>
        {window.t ? window.t('v.chapter1') : 'Chapter 01 · The bottleneck'}
      </div>
      <div
        dangerouslySetInnerHTML={{__html: window.t ? window.t('v.hook') : "It's late. Your phone <em style=\"color:#C7A24A;font-style:italic\">won't stop.</em>"}}
        style={{
        fontFamily: OV_SERIF, fontStyle:'italic',
        fontSize: 76, color:'#fff', lineHeight: 0.98,
        letterSpacing:'-0.02em',
        textShadow:'0 4px 24px rgba(0,0,0,0.5)',
      }}/>
    </div>
  );
}

// ── Scene B (3–6s): Missed-call HUD ─────────────────────────────────────
function SceneMissed({ t }) {
  const w = windowFade(t, 3.0, 6.2, 0.4, 0.5);
  if (!w.visible) return null;
  const calls = Math.min(7, Math.floor((t - 3.0) * 2.2));
  const dollars = Math.min(4800, Math.floor((t - 3.0) * 1900));
  return (
    <>
      {/* Top callout pill */}
      <div style={{
        position:'absolute', right: 28, top: 80, zIndex: 4,
        opacity: w.opacity,
        transform: `translateX(${(1 - w.opacity) * 24}px)`,
        display:'flex', alignItems:'center', gap: 10,
        background:'rgba(200,75,60,0.95)', color:'#fff',
        padding:'10px 16px 10px 12px', borderRadius: 999,
        fontFamily: OV_SANS, fontWeight: 700, fontSize: 15,
        boxShadow:'0 14px 28px rgba(200,75,60,0.35), inset 0 -1px 0 rgba(0,0,0,0.2)',
        border:'1px solid rgba(255,255,255,0.25)',
      }}>
        <span style={{
          width: 22, height: 22, borderRadius: '50%',
          background:'rgba(0,0,0,0.25)', display:'grid', placeItems:'center',
          fontSize: 12,
        }}>☎</span>
        <span style={{
          width: 6, height: 6, borderRadius:'50%', background:'#fff',
          opacity: 0.4 + 0.6 * Math.abs(Math.sin(t * 8)),
        }}/>
        {calls} missed calls · last 24h
      </div>

      {/* Big lower-third caption */}
      <div style={{
        position:'absolute', left: 60, bottom: 110, zIndex: 4,
        opacity: w.opacity,
        transform: `translateY(${(1 - w.opacity) * 14}px)`,
        maxWidth: 800,
      }}>
        <div style={{
          fontFamily: OV_SANS, fontSize: 11, fontWeight: 700,
          letterSpacing:'0.18em', textTransform:'uppercase',
          color:'#fff', opacity: 0.7, marginBottom: 10,
          textShadow:'0 1px 6px rgba(0,0,0,0.6)',
        }}>{window.t ? window.t('v.missed') : 'Every voicemail is a job your competitor closes'}</div>
        <div style={{
          display:'flex', alignItems:'baseline', gap: 18,
          fontFamily: OV_SERIF, fontStyle:'italic',
          color: OV_RED, lineHeight: 0.95,
        }}>
          <div style={{fontSize: 140, letterSpacing:'-0.04em',
            textShadow:'0 6px 24px rgba(0,0,0,0.4)'}}>
            ${dollars.toLocaleString()}
          </div>
          <div style={{
            fontFamily: OV_SANS, fontStyle:'normal',
            fontSize: 18, color:'#fff', fontWeight: 600,
            maxWidth: 220, lineHeight: 1.25,
            textShadow:'0 1px 6px rgba(0,0,0,0.6)',
          }}>{window.t ? window.t('v.missed.unit') : 'walking out the door every week.'}</div>
        </div>
      </div>
    </>
  );
}

// ── Scene C (6–9.5s): Brand reveal — "We solve your bottlenecks." ──────
function SceneBrand({ t }) {
  const w = windowFade(t, 6.0, 9.6, 0.6, 0.5);
  if (!w.visible) return null;
  // Stagger the two lines
  const local = t - 6.0;
  const line1 = ovEase.outCubic(ovClamp(local / 0.7, 0, 1));
  const line2 = ovEase.outCubic(ovClamp((local - 0.4) / 0.7, 0, 1));
  const swipe = ovEase.outQuart(ovClamp(local / 0.9, 0, 1));
  return (
    <>
      {/* Gold sweep underline */}
      <div style={{
        position:'absolute', left: 60, bottom: 220, zIndex: 3,
        height: 2, width: 720 * swipe,
        background: `linear-gradient(90deg, ${OV_GOLD}, transparent)`,
        opacity: w.opacity,
      }}/>
      <div style={{
        position:'absolute', left: 60, bottom: 110, zIndex: 4,
        opacity: w.opacity,
      }}>
        <div style={{
          fontFamily: OV_SANS, fontSize: 12, fontWeight: 700,
          letterSpacing:'0.18em', textTransform:'uppercase',
          color: OV_GOLD, marginBottom: 14,
          opacity: line1,
          transform: `translateY(${(1 - line1) * 10}px)`,
          textShadow:'0 1px 6px rgba(0,0,0,0.6)',
        }}>
          <span style={{display:'inline-block', width:6, height:6, background: OV_GOLD, borderRadius:'50%', marginRight:8, transform:'translateY(-2px)'}}/>
          {window.t ? window.t('v.chapter2') : 'Chapter 02 · The shift'}
        </div>
        <div style={{
          fontFamily: OV_SERIF, fontStyle:'italic',
          fontSize: 88, color:'#fff', lineHeight: 0.95,
          letterSpacing:'-0.02em',
          textShadow:'0 4px 28px rgba(0,0,0,0.5)',
        }}>
          <div style={{opacity: line1, transform: `translateY(${(1-line1)*14}px)`}}>
            {window.t ? window.t('v.brand.l1') : 'We solve your'}
          </div>
          <div style={{opacity: line2, transform: `translateY(${(1-line2)*14}px)`, color: OV_GOLD}}>
            {window.t ? window.t('v.brand.l2') : 'bottlenecks.'}
          </div>
        </div>
      </div>
    </>
  );
}

// ── Scene D (9.5–13s): Bottleneck chips flip red → green ────────────────
function SceneFlip({ t }) {
  const w = windowFade(t, 9.4, 13.2, 0.5, 0.6);
  if (!w.visible) return null;
  const items = window.t ? [
    window.t('v.flip.b1'),
    window.t('v.flip.b2'),
    window.t('v.flip.b3'),
    window.t('v.flip.b4'),
    window.t('v.flip.b5'),
    window.t('v.flip.b6'),
  ] : [
    'Missed calls',
    'Inbox chaos',
    'No funnel',
    'Silent socials',
    'Invisible on Google',
    'Crew confusion',
  ];
  const local = t - 9.4;
  return (
    <>
      <div style={{
        position:'absolute', right: 28, top: 80, bottom: 80, zIndex: 4,
        width: 360,
        opacity: w.opacity,
        display:'flex', flexDirection:'column', justifyContent:'center', gap: 9,
      }}>
        <div style={{
          fontFamily: OV_SANS, fontSize: 11, fontWeight: 700,
          letterSpacing:'0.18em', textTransform:'uppercase',
          color: OV_GOLD, marginBottom: 6,
          textShadow:'0 1px 6px rgba(0,0,0,0.6)',
        }}>
          {window.t ? window.t('v.flip.h') : 'Bottlenecks → systems'}
        </div>
        {items.map((label, i) => {
          const flipStart = 0.25 + i * 0.32;
          const flipT = ovEase.outCubic(ovClamp((local - flipStart) / 0.45, 0, 1));
          const appear = ovEase.outCubic(ovClamp((local - flipStart + 0.3) / 0.5, 0, 1));
          const flipped = flipT > 0.5;
          return (
            <div key={i} style={{
              display:'flex', alignItems:'center', justifyContent:'space-between',
              padding:'10px 14px', borderRadius: 10,
              background: flipped
                ? `linear-gradient(135deg, ${OV_GOLD}, ${OV_GOLD_DK})`
                : 'rgba(200,75,60,0.85)',
              border: `1px solid ${flipped ? OV_GOLD_SOFT : 'rgba(255,255,255,0.18)'}`,
              fontFamily: OV_SANS, fontSize: 14, fontWeight: 600,
              color: flipped ? OV_INK : '#fff',
              opacity: appear,
              transform: `translateX(${(1 - appear) * 30}px) rotateX(${(1 - flipT) * 0}deg)`,
              boxShadow: flipped
                ? '0 8px 20px rgba(167,131,49,0.4)'
                : '0 6px 14px rgba(0,0,0,0.3)',
              transition: 'background 0.3s, color 0.3s',
            }}>
              <span style={{
                textDecoration: flipped ? 'none' : 'line-through',
                textDecorationColor: 'rgba(255,255,255,0.6)',
              }}>{label}</span>
              <span style={{fontSize: 12, fontWeight: 800, letterSpacing:'0.04em'}}>
                {flipped ? (window.t ? window.t('v.flip.solved') : '✓ solved') : '✕'}
              </span>
            </div>
          );
        })}
      </div>

      {/* Left lower-third caption */}
      <div style={{
        position:'absolute', left: 60, bottom: 110, zIndex: 4,
        maxWidth: 520,
        opacity: w.opacity,
      }}>
        <div style={{
          fontFamily: OV_SANS, fontSize: 11, fontWeight: 700,
          letterSpacing:'0.18em', textTransform:'uppercase',
          color:'#fff', opacity: 0.7, marginBottom: 10,
          textShadow:'0 1px 6px rgba(0,0,0,0.6)',
        }}>{window.t ? window.t('v.flip.cap') : 'One stack · one team · one price'}</div>
        <div style={{
          fontFamily: OV_SERIF, fontStyle:'italic',
          fontSize: 52, color:'#fff', lineHeight: 1,
          letterSpacing:'-0.015em',
          textShadow:'0 4px 24px rgba(0,0,0,0.5)',
        }}>
          {window.t ? window.t('v.flip.t1') : 'Seven systems'}<br/>
          <span style={{color: OV_GOLD}}>{window.t ? window.t('v.flip.t2') : 'that compound.'}</span>
        </div>
      </div>
    </>
  );
}

// ── Scene E (13–15s): End card — logo, slogan, CTA ──────────────────────
function SceneEndCard({ t }) {
  const local = t - 13.0;
  if (local < 0) return null;
  const veil = ovEase.outCubic(ovClamp(local / 0.8, 0, 1));
  const t1 = ovEase.outCubic(ovClamp((local - 0.2) / 0.6, 0, 1));
  const t2 = ovEase.outCubic(ovClamp((local - 0.5) / 0.6, 0, 1));
  const t3 = ovEase.outBack(ovClamp((local - 0.9) / 0.6, 0, 1));
  return (
    <div style={{
      position:'absolute', inset: 0, zIndex: 6,
      background: `rgba(27,24,20,${veil * 0.92})`,
      backdropFilter: `blur(${veil * 6}px)`,
      display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center',
      gap: 28,
    }}>
      <div style={{opacity: t1, transform: `translateY(${(1-t1)*14}px)`}}>
        <img src="../logo-light.png" alt="FastFix.ai" style={{height: 60, display:'block'}}/>
      </div>
      <div style={{
        opacity: t2, transform: `translateY(${(1-t2)*14}px)`,
        fontFamily: OV_SERIF, fontStyle:'italic',
        fontSize: 76, color: OV_CREAM_3, lineHeight: 1,
        letterSpacing:'-0.02em', textAlign:'center',
      }}>
        {window.t ? window.t('v.end.l1') : 'We solve your'} <span style={{color: OV_GOLD}}>{window.t ? window.t('v.end.l2') : 'bottlenecks.'}</span>
      </div>
      <div style={{
        opacity: t2,
        fontFamily: OV_SANS, fontSize: 14, fontWeight: 600,
        color:'rgba(250,246,236,0.55)',
        letterSpacing:'0.18em', textTransform:'uppercase',
      }}>
        {window.t ? window.t('v.end.tag') : 'Home services · Free 14 day trial'}
      </div>
      <div style={{
        opacity: t3, transform: `translateY(${(1-t3)*14}px) scale(${0.9 + t3 * 0.1})`,
        background: OV_GOLD, color: OV_INK,
        padding:'18px 32px', borderRadius: 999,
        fontFamily: OV_SANS, fontWeight: 700, fontSize: 18,
        boxShadow:'0 14px 36px rgba(167,131,49,0.5)',
        marginTop: 8,
      }}>
        {window.t ? window.t('v.end.cta') : 'Claim your bottleneck audit →'}
      </div>
    </div>
  );
}

// ── Voice loader: pulls cached MP3 from IndexedDB (or fetches from ElevenLabs) ──
async function loadAudioBlob(key) {
  // 1. Try IndexedDB cache
  try {
    const blob = await new Promise((resolve) => {
      const req = indexedDB.open('fastfix-voice', 1);
      req.onupgradeneeded = () => req.result.createObjectStore('audio');
      req.onsuccess = () => {
        const tx = req.result.transaction('audio', 'readonly');
        const g = tx.objectStore('audio').get(key);
        g.onsuccess = () => resolve(g.result || null);
        g.onerror = () => resolve(null);
      };
      req.onerror = () => resolve(null);
    });
    return blob;
  } catch { return null; }
}

// ── Master ──────────────────────────────────────────────────────────────
function HomeServicesOverlayVideo() {
  const videoRef = React.useRef(null);
  const audioRef = React.useRef(null);
  const musicRef = React.useRef(null);
  const t = useVideoTime(videoRef);
  const [playing, setPlaying] = React.useState(true);
  const [muted, setMuted] = React.useState(true);
  const [duration, setDuration] = React.useState(15);
  const [showChrome, setShowChrome] = React.useState(true);
  const [voiceReady, setVoiceReady] = React.useState(false);
  // Re-render on language change so overlay text refreshes
  const [, setLangVer] = React.useState(0);
  React.useEffect(() => {
    const onLang = () => setLangVer(v => v + 1);
    window.addEventListener('langchange', onLang);
    return () => window.removeEventListener('langchange', onLang);
  }, []);
  const hideTimerRef = React.useRef(null);

  // Load voice + music from IndexedDB on mount
  React.useEffect(() => {
    let cancelled = false;
    const urls = [];
    Promise.all([loadAudioBlob('hero-bg-voice'), loadAudioBlob('hero-bg-music')]).then(([voiceBlob, musicBlob]) => {
      if (cancelled) return;
      if (voiceBlob && audioRef.current) {
        const u = URL.createObjectURL(voiceBlob);
        urls.push(u);
        audioRef.current.src = u;
        audioRef.current.load();
        setVoiceReady(true);
      }
      if (musicBlob && musicRef.current) {
        const u = URL.createObjectURL(musicBlob);
        urls.push(u);
        musicRef.current.src = u;
        musicRef.current.volume = 0.32; // ducked under VO
        musicRef.current.load();
      }
    });
    return () => {
      cancelled = true;
      urls.forEach((u) => URL.revokeObjectURL(u));
    };
  }, []);

  // Keep both audio tracks synced with the video on play/pause/drift
  React.useEffect(() => {
    const v = videoRef.current; const a = audioRef.current; const m = musicRef.current;
    if (!v) return;
    [a, m].forEach((el) => {
      if (!el || !el.src) return;
      el.muted = muted;
      if (!v.paused && playing) {
        if (Math.abs(el.currentTime - v.currentTime) > 0.25) el.currentTime = v.currentTime;
        if (el.paused) el.play().catch(() => {});
      } else {
        if (!el.paused) el.pause();
      }
    });
  });

  // When user scrubs the video, seek both tracks too
  React.useEffect(() => {
    const v = videoRef.current; const a = audioRef.current; const m = musicRef.current;
    if (!v) return;
    const onSeek = () => {
      if (a && a.src) a.currentTime = v.currentTime;
      if (m && m.src) m.currentTime = v.currentTime;
    };
    v.addEventListener('seeked', onSeek);
    return () => v.removeEventListener('seeked', onSeek);
  }, [voiceReady]);

  // Loop the video manually (so we can also handle weird browsers)
  React.useEffect(() => {
    const v = videoRef.current;
    if (!v) return;
    const tryPlay = () => v.play().then(() => setPlaying(true)).catch(() => {});
    const onMeta = () => { setDuration(v.duration || 15); tryPlay(); };
    const onPlay = () => setPlaying(true);
    const onPause = () => setPlaying(false);
    v.addEventListener('loadedmetadata', onMeta);
    v.addEventListener('play', onPlay);
    v.addEventListener('pause', onPause);
    tryPlay();
    return () => {
      v.removeEventListener('loadedmetadata', onMeta);
      v.removeEventListener('play', onPlay);
      v.removeEventListener('pause', onPause);
    };
  }, []);

  // Auto-hide chrome after a few seconds of no movement
  const bumpChrome = React.useCallback(() => {
    setShowChrome(true);
    if (hideTimerRef.current) clearTimeout(hideTimerRef.current);
    hideTimerRef.current = setTimeout(() => setShowChrome(false), 2400);
  }, []);
  React.useEffect(() => { bumpChrome(); return () => clearTimeout(hideTimerRef.current); }, [bumpChrome]);

  const togglePlay = () => {
    const v = videoRef.current; if (!v) return;
    if (v.paused) v.play(); else v.pause();
    bumpChrome();
  };
  const toggleMute = () => {
    const a = audioRef.current; const m = musicRef.current;
    const next = !muted;
    setMuted(next);
    [a, m].forEach((el) => {
      if (!el) return;
      el.muted = next;
      if (!next && el.src) {
        el.currentTime = videoRef.current?.currentTime || 0;
        el.play().catch(() => {});
      }
    });
    // Toggle browser SpeechSynthesis narration too (works without external audio files)
    if (typeof window.toggleVoiceover === 'function') {
      if (next) window.stopVoiceover && window.stopVoiceover();
      else window.startVoiceover && window.startVoiceover();
    }
    bumpChrome();
  };
  const seek = (newT) => {
    const v = videoRef.current; if (!v) return;
    v.currentTime = Math.max(0, Math.min(duration - 0.05, newT));
    bumpChrome();
  };

  // Keyboard shortcuts: space play/pause, ← → seek, m mute
  React.useEffect(() => {
    const onKey = (e) => {
      if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
      if (e.code === 'Space') { e.preventDefault(); togglePlay(); }
      else if (e.code === 'ArrowLeft') { e.preventDefault(); seek((videoRef.current?.currentTime || 0) - (e.shiftKey ? 1 : 0.2)); }
      else if (e.code === 'ArrowRight') { e.preventDefault(); seek((videoRef.current?.currentTime || 0) + (e.shiftKey ? 1 : 0.2)); }
      else if (e.key === 'm' || e.key === 'M') { toggleMute(); }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [duration]);

  return (
    <div style={{
      position:'absolute', inset:0,
      background:'#000', overflow:'hidden',
      fontFamily: OV_SANS,
    }}>
      <video
        ref={videoRef}
        src="hero-bg.mp4"
        muted
        autoPlay
        loop
        playsInline
        preload="auto"
        style={{
          position:'absolute', inset: 0,
          width:'100%', height:'100%',
          objectFit:'cover',
          // a subtle filter so the overlay text contrasts
          filter:'brightness(0.78) saturate(0.92) contrast(1.04)',
        }}
      />
      {/* Voiceover audio + music bed — srcs injected from IndexedDB on mount */}
      <audio ref={audioRef} preload="auto" loop muted />
      <audio ref={musicRef} preload="auto" loop muted />
      {/* Soft vignette + bottom gradient for caption legibility */}
      <div style={{
        position:'absolute', inset:0, pointerEvents:'none', zIndex: 1,
        background:
          'radial-gradient(ellipse at center, rgba(0,0,0,0) 40%, rgba(0,0,0,0.5) 100%),' +
          'linear-gradient(180deg, rgba(0,0,0,0.45) 0%, transparent 25%, transparent 60%, rgba(0,0,0,0.65) 100%)',
      }}/>

      <Letterbox t={t}/>
      <Watermark t={t}/>
      <TimeStamp t={t}/>

      <SceneHook    t={t}/>
      <SceneMissed  t={t}/>
      <SceneBrand   t={t}/>
      <SceneFlip    t={t}/>
      <SceneEndCard t={t}/>

      {/* Mouse activity surface — click toggles play, motion shows chrome */}
      <div
        onClick={togglePlay}
        onMouseMove={bumpChrome}
        style={{position:'absolute', inset:0, zIndex: 8, cursor: playing ? 'pointer' : 'pointer'}}
      />

      {/* Center play indicator when paused */}
      {!playing && (
        <div style={{
          position:'absolute', left:'50%', top:'50%',
          transform:'translate(-50%, -50%)', zIndex: 9,
          color:'#fff', pointerEvents:'none',
          filter:'drop-shadow(0 4px 18px rgba(0,0,0,0.6))',
          opacity: 0.95,
        }}>
          <svg width="68" height="68" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>
        </div>
      )}

      {/* Voiceover hint pill — shown briefly when video is muted */}
      {muted && (
        <button
          onClick={toggleMute}
          style={{
            position:'absolute', left:'50%', bottom: 90, zIndex: 11,
            transform:'translateX(-50%)',
            background:'rgba(199,162,74,0.95)', color: OV_INK,
            border:'1px solid rgba(255,255,255,0.3)',
            padding:'10px 18px 10px 14px', borderRadius: 999,
            fontFamily: OV_SANS, fontWeight: 700, fontSize: 13,
            letterSpacing:'0.04em', cursor:'pointer',
            display:'flex', alignItems:'center', gap: 8,
            boxShadow:'0 10px 28px rgba(0,0,0,0.4)',
            opacity: showChrome ? 1 : 0.7,
            transition:'opacity 0.3s',
          }}
        >
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M11 5L6 9H2v6h4l5 4V5z"/><path d="M15.5 8.5a5 5 0 0 1 0 7"/><path d="M18.5 5.5a9 9 0 0 1 0 13"/></svg>
          {window.t ? window.t('v.click.sound') : 'Click for sound'}
        </button>
      )}

      {/* Custom control bar */}
      <ControlBar
        t={t}
        duration={duration}
        playing={playing}
        muted={muted}
        visible={showChrome || !playing}
        onTogglePlay={togglePlay}
        onToggleMute={toggleMute}
        onSeek={seek}
        onReplay={() => { seek(0); const v = videoRef.current; if (v) v.play(); }}
      />
    </div>
  );
}

// ── Control bar ─────────────────────────────────────────────────────────
function ControlBar({ t, duration, playing, muted, visible, onTogglePlay, onToggleMute, onSeek, onReplay }) {
  const trackRef = React.useRef(null);
  const [hover, setHover] = React.useState(null);
  const [dragging, setDragging] = React.useState(false);

  const pct = duration > 0 ? (t / duration) * 100 : 0;

  const xToTime = (clientX) => {
    const r = trackRef.current.getBoundingClientRect();
    const x = (clientX - r.left) / r.width;
    return Math.max(0, Math.min(1, x)) * duration;
  };

  React.useEffect(() => {
    if (!dragging) return;
    const onMove = (e) => onSeek(xToTime(e.clientX));
    const onUp = () => setDragging(false);
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseup', onUp);
    return () => {
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseup', onUp);
    };
  }, [dragging, duration]);

  const fmt = (s) => {
    if (!isFinite(s)) s = 0;
    const m = Math.floor(s / 60);
    const sec = Math.floor(s % 60);
    return `${m}:${String(sec).padStart(2,'0')}`;
  };

  return (
    <div
      onClick={(e) => e.stopPropagation()}
      style={{
        position:'absolute', left: 16, right: 16, bottom: 16, zIndex: 11,
        opacity: visible ? 1 : 0,
        transform: visible ? 'translateY(0)' : 'translateY(12px)',
        transition: 'opacity 0.3s, transform 0.3s',
        pointerEvents: visible ? 'auto' : 'none',
        display:'flex', alignItems:'center', gap: 12,
        padding:'10px 14px',
        background:'rgba(15,12,10,0.65)',
        border:'1px solid rgba(255,255,255,0.12)',
        borderRadius: 14,
        backdropFilter:'blur(14px)',
        WebkitBackdropFilter:'blur(14px)',
        color:'#fff',
        fontFamily: OV_SANS,
      }}
    >
      {/* Play / pause */}
      <CtrlButton onClick={onTogglePlay} title={playing ? 'Pause (space)' : 'Play (space)'}>
        {playing
          ? <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor"><rect x="3" y="2" width="3" height="10"/><rect x="8" y="2" width="3" height="10"/></svg>
          : <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor"><path d="M3 2l9 5-9 5V2z"/></svg>}
      </CtrlButton>

      {/* Replay */}
      <CtrlButton onClick={onReplay} title="Restart">
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M3 12a9 9 0 1 0 3-6.7"/><path d="M3 4v5h5"/></svg>
      </CtrlButton>

      {/* Time */}
      <div style={{
        fontFamily:'ui-monospace, Menlo, monospace',
        fontSize: 11, letterSpacing:'0.04em',
        color:'rgba(255,255,255,0.85)', minWidth: 78,
      }}>
        {fmt(t)} <span style={{opacity:0.45}}>/ {fmt(duration)}</span>
      </div>

      {/* Scrubber */}
      <div
        ref={trackRef}
        onMouseDown={(e) => { setDragging(true); onSeek(xToTime(e.clientX)); }}
        onMouseMove={(e) => setHover(xToTime(e.clientX))}
        onMouseLeave={() => setHover(null)}
        style={{
          flex: 1, height: 22, position:'relative', cursor:'pointer',
          display:'flex', alignItems:'center',
        }}
      >
        {/* Track */}
        <div style={{position:'absolute', left:0, right:0, height: 4, background:'rgba(255,255,255,0.18)', borderRadius: 999}}/>
        {/* Hover preview */}
        {hover != null && (
          <div style={{
            position:'absolute', left: `${(hover/duration)*100}%`, height: 4,
            width: 2, background:'rgba(255,255,255,0.4)',
            transform:'translateX(-1px)',
          }}/>
        )}
        {/* Fill */}
        <div style={{
          position:'absolute', left: 0, height: 4,
          width: `${pct}%`,
          background: `linear-gradient(90deg, ${OV_GOLD_DK}, ${OV_GOLD})`,
          borderRadius: 999,
        }}/>
        {/* Thumb */}
        <div style={{
          position:'absolute', left: `${pct}%`,
          width: 14, height: 14, borderRadius:'50%',
          background:'#fff',
          transform:'translate(-50%, 0)',
          boxShadow:'0 2px 8px rgba(0,0,0,0.4)',
          border: `2px solid ${OV_GOLD}`,
        }}/>
      </div>

      {/* Mute */}
      <CtrlButton onClick={onToggleMute} title={muted ? 'Unmute (m)' : 'Mute (m)'}>
        {muted ? (
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M11 5L6 9H2v6h4l5 4V5z"/><line x1="23" y1="9" x2="17" y2="15"/><line x1="17" y1="9" x2="23" y2="15"/></svg>
        ) : (
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M11 5L6 9H2v6h4l5 4V5z"/><path d="M15.5 8.5a5 5 0 0 1 0 7"/><path d="M18.5 5.5a9 9 0 0 1 0 13"/></svg>
        )}
      </CtrlButton>
    </div>
  );
}

function CtrlButton({ children, onClick, title }) {
  const [hover, setHover] = React.useState(false);
  return (
    <button
      onClick={onClick}
      title={title}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        width: 32, height: 32, borderRadius: 8,
        display:'grid', placeItems:'center',
        background: hover ? 'rgba(255,255,255,0.15)' : 'rgba(255,255,255,0.06)',
        border:'1px solid rgba(255,255,255,0.14)',
        color:'#fff', cursor:'pointer',
        transition:'background 0.15s',
        padding: 0,
      }}
    >{children}</button>
  );
}

Object.assign(window, { HomeServicesOverlayVideo });
