// screens.jsx — Scene components for Hola taxi avatar.
// Scenes: welcome → conversation → seatbelt → ride → poi (rotates) → promo
// Every scene shares the LangSwitcher (top-right overlay) so passengers can
// change language at any moment without going back to the start.

/* ─── Status bar (top of tablet UI) ─── */
function StatusBar({ lang }) {
  return (
    <div className="statusbar">
      <div className="left">
        <span className="brand-mini">Hola</span>
        <span style={{ opacity: .5 }}>·</span>
        <span>{t('rideStatus', lang)}</span>
      </div>
      <div className="right">
        <span>21:34</span>
        <span className="signal"><i></i><i></i><i></i><i></i></span>
      </div>
    </div>
  );
}

/* ─── Floating controls (mute + volume + brightness) ─── */
function ControlsPanel({ voiceOn, volume, brightness, onToggleVoice, onVolume, onBrightness }) {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const handler = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('pointerdown', handler);
    return () => document.removeEventListener('pointerdown', handler);
  }, [open]);

  return (
    <div ref={ref} className="ctrl-panel">
      <button className="ctrl-btn" onClick={onToggleVoice} title={voiceOn ? 'Silenciar avatar' : 'Activar voz'}>
        {voiceOn
          ? <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/></svg>
          : <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><line x1="22" y1="9" x2="16" y2="15"/><line x1="16" y1="9" x2="22" y2="15"/></svg>}
      </button>
      <button className="ctrl-btn" onClick={() => setOpen(o => !o)} title="Ajustes" aria-expanded={open}>
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
          <circle cx="12" cy="12" r="3"/>
          <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.6 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
        </svg>
      </button>

      {open && (
        <div className="ctrl-pop">
          <div className="ctrl-sect">
            <div className="ctrl-lbl">
              <span>Volumen</span>
              <span className="ctrl-val">{Math.round(volume * 100)}</span>
            </div>
            <div className="ctrl-slider-row">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/></svg>
              <input type="range" min="0" max="100" value={Math.round(volume * 100)}
                onChange={(e) => onVolume(Number(e.target.value) / 100)} />
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/></svg>
            </div>
          </div>
          <div className="ctrl-sect">
            <div className="ctrl-lbl">
              <span>Brillo</span>
              <span className="ctrl-val">{Math.round(brightness * 100)}%</span>
            </div>
            <div className="ctrl-slider-row">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="3"/><line x1="12" y1="3" x2="12" y2="5"/><line x1="12" y1="19" x2="12" y2="21"/><line x1="3" y1="12" x2="5" y2="12"/><line x1="19" y1="12" x2="21" y2="12"/></svg>
              <input type="range" min="40" max="140" value={Math.round(brightness * 100)}
                onChange={(e) => onBrightness(Number(e.target.value) / 100)} />
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

/* ─── Floating language switcher (overlay on every scene) ─── */
function LangSwitcher({ lang, onChange }) {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const handler = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('pointerdown', handler);
    return () => document.removeEventListener('pointerdown', handler);
  }, [open]);

  return (
    <div ref={ref} className="lang-switcher">
      <button className="lang-switch-btn" onClick={() => setOpen(o => !o)} title={t('changeLang', lang)}>
        <Flag code={lang} className="lang-flag-circle" />
        <span className="lang-switch-label">{lang.toUpperCase()}</span>
        <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
          <polyline points="6 9 12 15 18 9" />
        </svg>
      </button>
      {open && (
        <div className="lang-switch-pop">
          <div className="lsp-title">{t('changeLang', lang)}</div>
          <div className="lsp-grid">
            {LANGUAGES.map(l => (
              <button key={l.code}
                className={`lang-switch-item ${l.code === lang ? 'active' : ''}`}
                onClick={() => { onChange(l.code); setOpen(false); }}>
                <Flag code={l.code} className="lang-flag-circle" />
                <span>{l.name}</span>
              </button>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

/* ─── Caption (always-visible subtitle pair, for the ride & monologues) ─── */
function Caption({ lang, primary, secondary, showSpanish = true, captionMode }) {
  if (captionMode === 'voice') return null; // hide subtitles in voice-only mode
  return (
    <div className="caption-block fade-in">
      <div className="cap-primary">{primary}</div>
      {showSpanish && lang !== 'es' && secondary && (
        <div className="cap-secondary">{secondary}</div>
      )}
    </div>
  );
}

/* Small "Reproducir saludo" play button */
function PlayBtn({ lang, onClick, active, disabled }) {
  return (
    <button className={`play-btn ${active ? 'live' : ''}`} onClick={onClick} disabled={disabled} title={disabled ? 'Voz silenciada' : t('playGreeting', lang)}>
      <span className="pb-icon">
        {active
          ? <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="5" width="4" height="14"/><rect x="14" y="5" width="4" height="14"/></svg>
          : <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><polygon points="6 4 20 12 6 20 6 4"/></svg>}
      </span>
      <span>{t('playGreeting', lang)}</span>
    </button>
  );
}

/* ─── Scene 1: Welcome + language select ─── */
function WelcomeScene({ active, lang, onPickLang, avatarMode, onPlay, isSpeaking, voiceOn }) {
  return (
    <div className="scene" data-active={active}>
      <StatusBar lang={lang} />
      <div className="welcome v2">
        <div className="welcome-portrait fade-in">
          <Avatar mode={avatarMode} size="hero" name={AVATAR_NAME} role={t('advisorRole', lang)} />
        </div>
        <div className="welcome-content">
          <div className="welcome-eyebrow fade-in">{t('welcomeEyebrow', lang)}</div>
          <h1 className="welcome-title fade-in" style={{ animationDelay: '.08s' }}>
            {t('welcomeTitle', lang)}<br />
            <em>{t('welcomeTitle2', lang)}</em>
          </h1>
          <p className="welcome-sub fade-in" style={{ animationDelay: '.18s' }}>
            {t('welcomeSub', lang)}
          </p>
          <div className="lang-grid slide-up" style={{ animationDelay: '.22s' }}>
            {LANGUAGES.map((l) => (
              <button key={l.code}
                className={`lang-btn ${lang === l.code ? 'active' : ''}`}
                onClick={() => onPickLang(l.code)}>
                <Flag code={l.code} className="lang-flag-lg" />
                <span className="lang-name">{l.name}</span>
                <span className="lang-native">{l.native}</span>
              </button>
            ))}
          </div>
          <div className="welcome-actions fade-in" style={{ animationDelay: '.3s' }}>
            <PlayBtn lang={lang} onClick={onPlay} active={isSpeaking} disabled={!voiceOn} />
          </div>
        </div>
      </div>
    </div>
  );
}

/* ─── Scene 2: Live translation — passenger ↔ driver ─── */
function ConversationScene({ active, lang, avatarMode, isSpeaking, voiceOn, micActive, onMic, captionMode }) {
  const [mode, setMode]           = React.useState('passenger');
  // Listen for driver messages sent from driver's phone
  React.useEffect(() => {
    const handler = (e) => {
      const { source, target, lang } = e.detail;
      setHistory(h => [...h, { role: 'driver', source, target, srcLang: 'es', tgtLang: lang }]);
    };
    window.addEventListener('driver_message', handler);
    return () => window.removeEventListener('driver_message', handler);
  }, []);
  const [partial, setPartial]     = React.useState('');
  const [history, setHistory]     = React.useState([]); // {role, source, target, srcLang, tgtLang}
  const [listening, setListening] = React.useState(false);
  const [translating, setTranslating] = React.useState(false);
  const processedRef = React.useRef(false);

  const sourceLang = mode === 'passenger' ? lang : 'es';
  const targetLang = mode === 'passenger' ? 'es'  : lang;

  // Stop mic when changing mode
  const handleModeChange = (newMode) => {
    if (listening) {
      window.stopListening && window.stopListening();
      setListening(false);
      onMic && onMic(false);
    }
    setPartial('');
    setMode(newMode);
  };

  const handleFinal = async (text) => {
    if (!text || processedRef.current) return;
    processedRef.current = true;
    setListening(false);
    setPartial('');
    setTranslating(true);

    const translated = await window.translate(text, sourceLang, targetLang);
    setTranslating(false);
    const entry = { role: mode, source: text, target: translated, srcLang: sourceLang, tgtLang: targetLang };
    setHistory(h => [...h, entry]);

    // Notify driver's phone in real-time
    if (window.publishTranslation) window.publishTranslation(entry);

    // Speak the translation with browser TTS (avoids ElevenLabs concurrency limits)
    if (voiceOn && 'speechSynthesis' in window) {
      window.speechSynthesis.cancel();
      const utt = new SpeechSynthesisUtterance(translated);
      utt.lang = (window.SPEECH_LOCALE && window.SPEECH_LOCALE[targetLang]) || targetLang + '-' + targetLang.toUpperCase();
      utt.rate = 0.92;
      utt.pitch = mode === 'driver' ? 0.85 : 1.0; // slightly lower for driver→passenger
      window.speechSynthesis.speak(utt);
    }
  };

  const lastPartialRef = React.useRef('');

  const startMic = () => {
    if (listening) return;
    processedRef.current = false;
    lastPartialRef.current = '';
    setPartial('');
    setListening(true);
    onMic && onMic(true);
    if (window.stopSpeaking) window.stopSpeaking();
    window.speechSynthesis && window.speechSynthesis.cancel();
    window.startListening({
      lang: sourceLang,
      onPartial: (t) => { lastPartialRef.current = t; setPartial(t); },
      onFinal:   (t) => { lastPartialRef.current = t; setPartial(t); },
      onError:   (e) => { setListening(false); onMic && onMic(false); console.warn('STT error:', e); },
    });
  };

  const stopMic = () => {
    window.stopListening && window.stopListening();
    setListening(false);
    onMic && onMic(false);
    // Process whatever was captured
    const text = lastPartialRef.current;
    if (text && !processedRef.current) handleFinal(text);
  };

  return (
    <div className="scene" data-active={active}>
      <StatusBar lang={lang} />
      <div className="convo v2">
        <div className="convo-side fade-in">
          <div className="convo-header">
            <div className="convo-eyebrow">TRADUCCIÓN EN VIVO · LEO</div>
            <div className="convo-title">{mode === 'passenger' ? t('talkToDriver', lang) : 'Conductor habla'}</div>
          </div>

          {/* Mode toggle — hidden in kiosk (driver has own phone) */}
          {!window.KIOSK && (
            <div style={{ display: 'flex', gap: 8, marginBottom: 16, padding: 4, background: 'var(--surface)', borderRadius: 12, border: '1px solid var(--line)' }}>
              <button onClick={() => handleModeChange('passenger')} style={{ flex: 1, padding: '10px 14px', borderRadius: 9, border: 'none', background: mode === 'passenger' ? 'var(--accent)' : 'transparent', color: mode === 'passenger' ? 'white' : 'var(--fg)', fontWeight: 600, fontSize: 13, cursor: 'pointer', fontFamily: 'var(--font-body)' }}>
                🧳 Pasajero ({lang.toUpperCase()})
              </button>
              <button onClick={() => handleModeChange('driver')} style={{ flex: 1, padding: '10px 14px', borderRadius: 9, border: 'none', background: mode === 'driver' ? 'var(--accent-2)' : 'transparent', color: mode === 'driver' ? 'white' : 'var(--fg)', fontWeight: 600, fontSize: 13, cursor: 'pointer', fontFamily: 'var(--font-body)' }}>
                🚖 Conductor (ES)
              </button>
            </div>
          )}

          {/* History */}
          <div style={{ flex: 1, minHeight: 0, overflowY: 'auto', marginBottom: 16 }}>
            {history.length === 0 && !listening && !partial && (
              <div style={{ color: 'var(--fg-mute)', fontSize: 14, padding: '12px 4px', fontStyle: 'italic' }}>
                Pulsa el micro y habla. Leo traduce al instante.
              </div>
            )}
            {history.map((turn, i) => (
              <div key={i} className="convo-turn fade-in" style={{ marginBottom: 12 }}>
                <div className={`speaker-card ${turn.role === 'driver' ? '' : 'passenger'}`}>
                  <div className={`speaker-avatar ${turn.role === 'driver' ? 'driver' : 'guest'}`}>
                    {turn.role === 'driver' ? 'D' : <Flag code={turn.srcLang} className="flag" />}
                  </div>
                  <div className="speaker-meta">
                    <div className="speaker-role">{turn.role === 'driver' ? 'CONDUCTOR · ES' : `PASAJERO · ${turn.srcLang.toUpperCase()}`}</div>
                    <div className="speaker-line">{turn.source}</div>
                  </div>
                </div>
                <div className="turn-translation">
                  <span className="tt-arrow">↳</span>
                  <span className="tt-meta">LEO → {turn.tgtLang.toUpperCase()}</span>
                  <span className="tt-text">{turn.target}</span>
                </div>
              </div>
            ))}
            {(listening || partial) && (
              <div className="speaker-card" style={{ background: 'oklch(94% 0.05 80)', border: '2px dashed var(--accent)' }}>
                <div className="speaker-avatar guest" style={{ background: 'var(--accent)' }}>
                  <svg width="16" height="16" viewBox="0 0 24 24" fill="white"><rect x="9" y="2" width="6" height="12" rx="3"/><path d="M5 10a7 7 0 0 0 14 0" fill="none" stroke="white" strokeWidth="2"/></svg>
                </div>
                <div className="speaker-meta">
                  <div className="speaker-role">ESCUCHANDO · {sourceLang.toUpperCase()}</div>
                  <div className="speaker-line">{partial || '…'}</div>
                </div>
              </div>
            )}
            {translating && (
              <div style={{ color: 'var(--accent)', fontSize: 13, padding: '8px 4px', fontStyle: 'italic' }}>
                Traduciendo…
              </div>
            )}
          </div>

          {/* Confirm destination → advance to seatbelt */}
          <button
              onClick={() => window.__onDestinationConfirmed && window.__onDestinationConfirmed()}
              style={{
                width: '100%', padding: '12px', marginBottom: 12,
                borderRadius: 12, border: 'none',
                background: 'var(--accent)', color: '#111',
                fontWeight: 700, fontSize: 14, cursor: 'pointer',
                display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
              }}>
              ✓ {lang === 'es' ? 'Destino confirmado' : lang === 'en' ? 'Destination confirmed' : lang === 'fr' ? 'Destination confirmée' : lang === 'de' ? 'Ziel bestätigt' : lang === 'it' ? 'Destinazione confermata' : lang === 'pt' ? 'Destino confirmado' : lang === 'zh' ? '确认目的地' : 'Место назначения подтверждено'}
            </button>

          {/* Big mic button — tap to start / tap to stop */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
            <button
              onClick={() => listening ? stopMic() : startMic()}
              style={{
                width: 72, height: 72, borderRadius: '50%', border: 'none',
                background: listening ? 'oklch(58% 0.18 30)' : (mode === 'passenger' ? 'var(--accent)' : 'var(--accent-2)'),
                color: 'white', cursor: 'pointer',
                boxShadow: listening ? '0 0 0 8px oklch(58% 0.18 30 / .25), 0 12px 32px -8px oklch(58% 0.18 30 / .6)' : '0 8px 20px -6px rgba(0,0,0,.3)',
                transition: 'all .2s ease', flexShrink: 0,
              }}>
              {listening
                ? <svg width="28" height="28" viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="6" width="12" height="12" rx="2"/></svg>
                : <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                    <rect x="9" y="2" width="6" height="12" rx="3"/>
                    <path d="M5 10a7 7 0 0 0 14 0"/>
                    <line x1="12" y1="19" x2="12" y2="22"/>
                  </svg>}
            </button>
            <div>
              <div style={{ fontWeight: 600, fontSize: 15 }}>
                {listening ? '⏹ Toca para parar' : '🎙 Toca para hablar'}
              </div>
              <div style={{ fontSize: 12, color: 'var(--fg-mute)', marginTop: 2 }}>
                {mode === 'passenger'
                  ? `Habla en ${langName(lang)} → Leo traduce al español`
                  : 'Habla en español → Leo traduce al pasajero'}
              </div>
            </div>
          </div>
        </div>

        <div className="convo-portrait fade-in" style={{ animationDelay: '.18s' }}>
          <Avatar mode={listening ? 'listening' : (isSpeaking ? 'speaking' : 'idle')} size="hero" name={AVATAR_NAME} role={t('advisorRole', lang)} />
        </div>
      </div>
    </div>
  );
}

function langName(code) {
  return (LANGUAGES.find(l => l.code === code) || {}).name || code;
}

function ConvoTurn({ turn, lang, captionMode, delay = 0 }) {
  const isDriver = turn.side === 'driver';
  // Driver always speaks ES; passenger speaks in their lang.
  const sourceLang = isDriver ? 'es' : lang;
  const targetLang = isDriver ? lang : 'es';

  const source = isDriver ? turn.text : (turn.text[lang] || turn.text.en);
  const target = isDriver
    ? (turn.translation[lang] || turn.translation.en)
    : (typeof turn.translation === 'string' ? turn.translation : turn.translation[targetLang] || turn.translation);

  return (
    <div className="convo-turn fade-in" style={{ animationDelay: `${0.05 + delay}s` }}>
      <div className={`speaker-card ${isDriver ? '' : 'passenger'}`}>
        <div className={`speaker-avatar ${isDriver ? 'driver' : 'guest'}`}>
          {isDriver ? 'D' : <Flag code={lang} className="flag" />}
        </div>
        <div className="speaker-meta">
          <div className="speaker-role">{isDriver ? 'CONDUCTOR · ES' : `PASAJERO · ${lang.toUpperCase()}`}</div>
          <div className="speaker-line">{source}</div>
        </div>
      </div>
      {captionMode !== 'voice' && (
        <div className="turn-translation">
          <span className="tt-arrow">↳</span>
          <span className="tt-meta">{isDriver ? `HOLA → ${lang.toUpperCase()}` : 'HOLA → ES'}</span>
          <span className="tt-text">{target}</span>
        </div>
      )}
    </div>
  );
}

/* ─── Scene 3: Seatbelt monologue ─── */
function SeatbeltScene({ active, lang, avatarMode, onPlay, isSpeaking, voiceOn, captionMode }) {
  return (
    <div className="scene" data-active={active}>
      <StatusBar lang={lang} />
      <div className="monologue">
        <div className="monologue-portrait fade-in">
          <Avatar mode={avatarMode} size="hero" name={AVATAR_NAME} role={t('advisorRole', lang)} />
        </div>
        <div className="monologue-body fade-in" style={{ animationDelay: '.15s' }}>
          <div className="mono-eyebrow">EN VIVO · ES → {lang.toUpperCase()}</div>
          {captionMode !== 'voice' ? (
            <>
              <div className="mono-line">{t('seatbelt', lang)}</div>
              {lang !== 'es' && (
                <div className="mono-line-alt">{t('seatbelt', 'es')}</div>
              )}
            </>
          ) : (
            <div className="mono-line muted-line">[voz activa · subtítulos desactivados]</div>
          )}
          <div className="mono-actions">
            <PlayBtn lang={lang} onClick={onPlay} active={isSpeaking} disabled={!voiceOn} />
          </div>
        </div>
      </div>
    </div>
  );
}

/* ─── Scene 4: Ride (avatar + map) ─── */
function RideScene({ active, lang, layout, swap, muted, onSwap, onMute, micActive, onMic, avatarMode, onPlay, isSpeaking, voiceOn, captionMode }) {
  return (
    <div className="scene" data-active={active}>
      <StatusBar lang={lang} />
      <div className="ride" data-layout={layout} data-swap={swap}>
        <div className="avatar-stage">
          <Avatar mode={micActive ? 'listening' : avatarMode} size={swap ? 'sm' : 'hero'} name={AVATAR_NAME} role={t('advisorRole', lang)} />
        </div>

        {!swap && captionMode !== 'voice' && (
          <div className="ride-caption fade-in">
            <div className="cap-line">{t('rideIdle', lang)}</div>
            {lang !== 'es' && <div className="cap-line-alt">{t('rideIdle', 'es')}</div>}
            <div className="cap-actions">
              <PlayBtn lang={lang} onClick={onPlay} active={isSpeaking} disabled={!voiceOn} />
            </div>
          </div>
        )}

        <div className="ride-map" onClick={onSwap}>
          <StylizedMap eta="12 min" />
        </div>

        {layout === 'stage' && !swap && <div className="ride-dock"></div>}

        <div className="mic-bar" style={layout === 'stage' && !swap ? { bottom: '124px' } : {}}>
          <span className="mic-label">{t('micHint', lang)}</span>
          <button
            className={`mic-btn ${micActive ? 'live' : ''}`}
            onMouseDown={() => onMic(true)} onMouseUp={() => onMic(false)} onMouseLeave={() => onMic(false)}
            onTouchStart={() => onMic(true)} onTouchEnd={() => onMic(false)}
          >
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <rect x="9" y="2" width="6" height="12" rx="3"/>
              <path d="M5 10a7 7 0 0 0 14 0"/>
              <line x1="12" y1="19" x2="12" y2="22"/>
            </svg>
          </button>
        </div>
      </div>
    </div>
  );
}

/* ─── Scene 5 v2: Curiosity / Trivia — full-panel redesign ─── */
const POI_VISUALS = {
  larios:     {
    gradient: 'linear-gradient(145deg, oklch(74% 0.13 78) 0%, oklch(60% 0.14 58) 100%)',
    icon: '🏛️',
    imgUrl: 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=900&q=80&auto=format&fit=crop',
  },
  catedral:   {
    gradient: 'linear-gradient(145deg, oklch(68% 0.07 240) 0%, oklch(50% 0.10 220) 100%)',
    icon: '⛪',
    imgUrl: 'https://images.unsplash.com/photo-1509233725247-49e657c54213?w=900&q=80&auto=format&fit=crop',
  },
  atarazanas: {
    gradient: 'linear-gradient(145deg, oklch(70% 0.13 40) 0%, oklch(52% 0.14 28) 100%)',
    icon: '🏪',
    imgUrl: 'https://images.unsplash.com/photo-1555881400-74d7acaacd8b?w=900&q=80&auto=format&fit=crop',
  },
  malagueta:  {
    gradient: 'linear-gradient(145deg, oklch(74% 0.11 216) 0%, oklch(54% 0.13 200) 100%)',
    icon: '🏖️',
    imgUrl: 'https://images.unsplash.com/photo-1507525428034-b723cf961d3e?w=900&q=80&auto=format&fit=crop',
  },
};

function PoiScene({ active, lang, layout, swap, avatarMode, onPlay, isSpeaking, voiceOn, captionMode, triviaIdx, onNextTrivia }) {
  const item = TRIVIA[triviaIdx % TRIVIA.length];
  const visual = POI_VISUALS[item.id] || POI_VISUALS.larios;
  const [imgOk, setImgOk] = React.useState(true);

  return (
    <div className="scene" data-active={active}>
      <StatusBar lang={lang} />
      <div className="poi-full">

        {/* Left: large content card */}
        <div className="poi-content-side">
          <div className="poi-card-v2 slide-up" key={item.id}>

            {/* Hero image / gradient */}
            <div className="poi-hero" style={!imgOk ? { background: visual.gradient } : {}}>
              {imgOk && (
                <img
                  className="poi-hero-img"
                  src={visual.imgUrl}
                  alt=""
                  draggable="false"
                  onError={() => setImgOk(false)}
                />
              )}
              <div className="poi-hero-overlay" />
              <div className="poi-hero-icon">{visual.icon}</div>
              <div className="poi-hero-text">
                <div className="poi-hero-kind">{item.kind[lang] || item.kind.en}</div>
                <div className="poi-hero-title">{item.title[lang] || item.title.en}</div>
              </div>
            </div>

            {/* Body */}
            <div className="poi-body-v2">
              {captionMode !== 'voice' ? (
                <p className="poi-blurb-v2">{item.blurb[lang] || item.blurb.en}</p>
              ) : (
                <p className="poi-blurb-v2 muted-line">[voz activa · subtítulos desactivados]</p>
              )}

              <div className="poi-footer-v2">
                <div className="poi-progress-v2">
                  {TRIVIA.map((_, i) => (
                    <span key={i} className={`pp-dot ${i === triviaIdx % TRIVIA.length ? 'on' : ''}`} />
                  ))}
                </div>
                <div className="poi-controls-v2">
                  <PlayBtn lang={lang} onClick={onPlay} active={isSpeaking} disabled={!voiceOn} />
                  <button className="poi-next" onClick={onNextTrivia}>
                    <span>Siguiente</span>
                    <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><polyline points="9 18 15 12 9 6"/></svg>
                  </button>
                </div>
              </div>
            </div>
          </div>
        </div>

        {/* Right: avatar */}
        <div className="poi-avatar-side">
          <Avatar mode={avatarMode} size="hero" name={AVATAR_NAME} role={t('advisorRole', lang)} />
        </div>

      </div>
    </div>
  );
}

/* ─── Scene 6 v2: Promo / QR — full-panel redesign ─── */
function PromoScene({ active, lang, layout, swap, qrAnimate, avatarMode, onPlay, isSpeaking, voiceOn, captionMode }) {
  const QR_PATTERN = useQR();
  return (
    <div className="scene" data-active={active}>
      <StatusBar lang={lang} />
      <div className="promo-full">

        {/* Left: large promo card */}
        <div className="promo-content-side">
          <div className="promo-card-v2 slide-up">

            {/* Hero banner */}
            <div className="promo-hero-v2">
              <div className="promo-hero-art" />
              <div className="promo-merchant-badge">Tapeo El Pimpi · Málaga</div>
              <div className="promo-hero-kind-v2">{t('promoKind', lang)}</div>
              <div className="promo-hero-title-v2">{t('promoTitle', lang)}</div>
            </div>

            {/* Body: text + QR */}
            <div className="promo-body-v2">
              <div className="promo-text-col">
                {captionMode !== 'voice' ? (
                  <p className="promo-text-v2">{t('promoBlurb', lang)}</p>
                ) : (
                  <p className="promo-text-v2 muted-line">[voz activa · subtítulos desactivados]</p>
                )}
                <div className="promo-cta-v2">↗ {t('scanCta', lang)}</div>
                <div style={{ marginTop: 10 }}>
                  <PlayBtn lang={lang} onClick={onPlay} active={isSpeaking} disabled={!voiceOn} />
                </div>
              </div>

              <div className="promo-qr-col">
                <div className={`qr-v2 ${qrAnimate ? 'animating' : ''}`}>
                  {QR_PATTERN.map((on, i) => (
                    <i key={i} className={on ? 'on' : ''}
                       style={qrAnimate ? { animationDelay: `${(i % 11) * 0.012 + Math.floor(i / 11) * 0.012}s` } : {}} />
                  ))}
                </div>
                <div className="qr-hint">Scan · Escanea<br />para canjear</div>
              </div>
            </div>

            {/* Footer */}
            <div className="promo-foot-v2">
              <span>HOLA · OFFER #M-2406</span>
              <span>Válido solo durante este viaje</span>
            </div>

          </div>
        </div>

        {/* Right: avatar */}
        <div className="promo-avatar-side">
          <Avatar mode={avatarMode} size="hero" name={AVATAR_NAME} role={t('advisorRole', lang)} />
        </div>

      </div>
    </div>
  );
}

function useQR() {
  return React.useMemo(() => {
    const SIZE = 11;
    const arr = Array(SIZE * SIZE).fill(false);
    const set = (x, y, v = true) => { arr[y * SIZE + x] = v; };
    const isFinder = (x, y) =>
      ((x < 3 && y < 3) || (x < 3 && y > SIZE - 4) || (x > SIZE - 4 && y < 3));
    [[0,0],[0,SIZE-3],[SIZE-3,0]].forEach(([fx, fy]) => {
      for (let y = 0; y < 3; y++)
        for (let x = 0; x < 3; x++)
          if (x === 0 || x === 2 || y === 0 || y === 2 || (x === 1 && y === 1))
            set(fx + x, fy + y);
    });
    let seed = 919;
    const rnd = () => { seed = (seed * 1103515245 + 12345) & 0x7fffffff; return seed; };
    for (let y = 0; y < SIZE; y++) {
      for (let x = 0; x < SIZE; x++) {
        if (isFinder(x, y)) continue;
        if (rnd() % 100 < 48) set(x, y);
      }
    }
    return arr;
  }, []);
}

/* ─── Floating mic button — always accessible on all scenes ─── */
function FloatingMic({ lang, voiceOn }) {
  const [open, setOpen]           = React.useState(false);
  const [listening, setListening] = React.useState(false);
  const [mode, setMode]           = React.useState('passenger');
  const [partial, setPartial]     = React.useState('');
  const [result, setResult]       = React.useState(null);
  const lastRef = React.useRef('');

  const sourceLang = mode === 'passenger' ? lang : 'es';
  const targetLang = mode === 'passenger' ? 'es'  : lang;

  const startMic = () => {
    lastRef.current = '';
    setPartial('');
    setResult(null);
    setListening(true);
    window.stopSpeaking && window.stopSpeaking();
    window.speechSynthesis && window.speechSynthesis.cancel();
    window.startListening({
      lang: sourceLang,
      onPartial: (t) => { lastRef.current = t; setPartial(t); },
      onFinal:   (t) => { lastRef.current = t; setPartial(t); },
      onError:   () => setListening(false),
    });
  };

  const stopMic = async () => {
    window.stopListening && window.stopListening();
    setListening(false);
    const text = lastRef.current;
    if (!text) return;
    const translated = await window.translate(text, sourceLang, targetLang);
    const entry = { role: mode, source: text, target: translated, srcLang: sourceLang, tgtLang: targetLang };
    setResult({ source: text, target: translated, targetLang });
    if (window.publishTranslation) window.publishTranslation(entry);
    if (voiceOn && 'speechSynthesis' in window) {
      window.speechSynthesis.cancel();
      const utt = new SpeechSynthesisUtterance(translated);
      utt.lang = (window.SPEECH_LOCALE || {})[targetLang] || targetLang;
      utt.rate = 0.92;
      window.speechSynthesis.speak(utt);
    }
  };

  const handleMicTap = () => listening ? stopMic() : startMic();

  return (
    <div style={{ position: 'absolute', bottom: 80, left: 14, zIndex: 20 }}>
      {/* Translation popup */}
      {open && (
        <div style={{
          position: 'absolute', bottom: 64, left: 0,
          width: 260, background: 'var(--surface)',
          border: '1px solid var(--line)', borderRadius: 16,
          padding: 14, boxShadow: '0 8px 32px -8px rgba(0,0,0,.25)',
        }}>
          {/* Mode toggle */}
          <div style={{ display: 'flex', gap: 6, marginBottom: 12 }}>
            {['passenger','driver'].map(m => (
              <button key={m} onClick={() => { if (listening) stopMic(); setMode(m); setResult(null); }}
                style={{
                  flex: 1, padding: '6px 8px', borderRadius: 8, border: 'none',
                  background: mode === m ? 'var(--accent)' : 'var(--bg-2)',
                  color: mode === m ? 'white' : 'var(--fg)',
                  fontSize: 11, fontWeight: 600, cursor: 'pointer',
                }}>
                {m === 'passenger' ? `🧳 ${lang.toUpperCase()}` : '🚖 ES'}
              </button>
            ))}
          </div>

          {/* Mic button */}
          <button onClick={handleMicTap} style={{
            width: '100%', padding: '10px', borderRadius: 12, border: 'none',
            background: listening ? 'oklch(58% 0.18 30)' : 'var(--accent)',
            color: 'white', cursor: 'pointer', fontWeight: 600, fontSize: 13,
            display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
          }}>
            {listening
              ? <><svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="6" width="12" height="12" rx="2"/></svg> Parar</>
              : <><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="9" y="2" width="6" height="12" rx="3"/><path d="M5 10a7 7 0 0 0 14 0"/></svg> Hablar</>
            }
          </button>

          {/* Transcript */}
          {partial && !result && (
            <div style={{ marginTop: 10, fontSize: 12, color: 'var(--fg-soft)' }}>
              <div style={{ opacity: 0.6, marginBottom: 3 }}>{sourceLang.toUpperCase()}</div>
              <div>{partial}</div>
            </div>
          )}
          {result && (
            <div style={{ marginTop: 10 }}>
              <div style={{ fontSize: 11, color: 'var(--fg-mute)' }}>{sourceLang.toUpperCase()} → {targetLang.toUpperCase()}</div>
              <div style={{ fontSize: 12, color: 'var(--fg)', marginTop: 4, fontStyle: 'italic' }}>{result.source}</div>
              <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--accent)', marginTop: 4 }}>{result.target}</div>
            </div>
          )}
        </div>
      )}

      {/* Floating button */}
      <button onClick={() => setOpen(o => !o)} style={{
        width: 44, height: 44, borderRadius: '50%', border: 'none',
        background: open ? 'var(--accent)' : 'rgba(0,0,0,.45)',
        backdropFilter: 'blur(8px)',
        color: 'white', cursor: 'pointer',
        boxShadow: '0 4px 12px -4px rgba(0,0,0,.4)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        transition: 'background .2s',
      }} title="Traducción rápida">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
          <rect x="9" y="2" width="6" height="12" rx="3"/>
          <path d="M5 10a7 7 0 0 0 14 0"/>
          <line x1="12" y1="19" x2="12" y2="22"/>
        </svg>
      </button>
    </div>
  );
}

/* ─── Replay button — repeat current Leo speech ─── */
function ReplayBtn({ onPlay, isSpeaking }) {
  return (
    <button onClick={onPlay} style={{
      position: 'absolute', bottom: 80, right: 14, zIndex: 20,
      width: 44, height: 44, borderRadius: '50%', border: 'none',
      background: isSpeaking ? 'var(--accent)' : 'rgba(0,0,0,.45)',
      backdropFilter: 'blur(8px)',
      color: 'white', cursor: 'pointer',
      boxShadow: '0 4px 12px -4px rgba(0,0,0,.4)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      transition: 'background .2s',
    }} title="Repetir mensaje de Leo">
      {isSpeaking
        ? <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/></svg>
        : <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 .49-3.83"/></svg>
      }
    </button>
  );
}

/* ─── Trip End Scene ─── */
const GOODBYE = {
  es: (f) => f ? `El importe del viaje es ${f}€. ¡Ha sido un placer acompañarte! Que disfrutes Málaga.` : '¡Ha sido un placer acompañarte! Que disfrutes Málaga.',
  en: (f) => f ? `Your fare is €${f}. It's been a pleasure travelling with you! Enjoy Málaga.` : 'It\'s been a pleasure travelling with you! Enjoy Málaga.',
  fr: (f) => f ? `Le montant de votre course est ${f}€. Ce fut un plaisir ! Profitez bien de Málaga.` : 'Ce fut un plaisir ! Profitez bien de Málaga.',
  de: (f) => f ? `Ihr Fahrpreis beträgt ${f}€. Es war mir eine Freude! Viel Spaß in Málaga.` : 'Es war mir eine Freude! Viel Spaß in Málaga.',
  it: (f) => f ? `La sua corsa è di ${f}€. È stato un piacere! Godetevi Málaga.` : 'È stato un piacere! Godetevi Málaga.',
  pt: (f) => f ? `A sua corrida é de ${f}€. Foi um prazer! Aproveite Málaga.` : 'Foi um prazer! Aproveite Málaga.',
  zh: (f) => f ? `您的车费是${f}欧元。很高兴陪伴您！祝您在马拉加玩得愉快。` : '很高兴陪伴您！祝您在马拉加玩得愉快。',
  ru: (f) => f ? `Стоимость поездки — ${f}€. Было приятно! Наслаждайтесь Малагой.` : 'Было приятно! Наслаждайтесь Малагой.',
};

function TripEndScene({ active, lang, onReset, voiceOn }) {
  const [stars,     setStars]     = React.useState(0);
  const [hovered,   setHovered]   = React.useState(0);
  const [submitted, setSubmitted] = React.useState(false);
  const timerRef = React.useRef(null);

  React.useEffect(() => {
    if (!active) { setStars(0); setSubmitted(false); return; }
    const fare     = window.__rideFare || null;
    const goodbyeFn = GOODBYE[lang] || GOODBYE.en;
    const msg      = goodbyeFn(fare);
    if (voiceOn && window.speak) {
      setTimeout(() => window.speak(msg, lang, { volume: 1 }), 600);
    }
    // Auto-reset after 25s
    timerRef.current = setTimeout(() => onReset && onReset(), 25000);
    return () => clearTimeout(timerRef.current);
  }, [active]);

  const rate = (n) => {
    setStars(n);
    setSubmitted(true);
    clearTimeout(timerRef.current);
    setTimeout(() => onReset && onReset(), 4000);
  };

  if (!active) return null;

  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: 'linear-gradient(160deg, oklch(22% 0.04 232) 0%, oklch(15% 0.02 240) 100%)',
      display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
      gap: 28, padding: 32, textAlign: 'center',
    }}>
      {/* Leo */}
      <div style={{ width: 140, height: 170 }}>
        <Avatar mode="idle" size="sm" name={AVATAR_NAME} role="" />
      </div>

      {/* Goodbye message */}
      <div>
        <div style={{ fontSize: 11, letterSpacing: '.12em', color: 'rgba(255,255,255,.4)', marginBottom: 10, fontFamily: 'var(--font-mono)' }}>
          LEO · FIN DEL TRAYECTO
        </div>
        {window.__rideFare && (
          <div style={{ fontSize: 32, fontWeight: 800, color: '#4ade80', marginBottom: 4 }}>
            {window.__rideFare}€
          </div>
        )}
        <div style={{ fontSize: 22, fontWeight: 700, color: 'white', fontFamily: 'var(--font-display)', lineHeight: 1.3, maxWidth: 480 }}>
          {(GOODBYE[lang] || GOODBYE.en)(window.__rideFare)}
        </div>
      </div>

      {/* Star rating */}
      {!submitted ? (
        <div>
          <div style={{ fontSize: 13, color: 'rgba(255,255,255,.6)', marginBottom: 14 }}>
            {lang === 'es' ? '¿Cómo fue tu experiencia?' :
             lang === 'en' ? 'How was your experience?' :
             lang === 'fr' ? 'Comment était votre expérience ?' :
             lang === 'de' ? 'Wie war Ihre Erfahrung?' :
             lang === 'it' ? 'Com\'è stata la tua esperienza?' :
             lang === 'pt' ? 'Como foi a sua experiência?' :
             lang === 'zh' ? '您的体验如何？' : 'Как вам поездка?'}
          </div>
          <div style={{ display: 'flex', gap: 12, justifyContent: 'center' }}>
            {[1,2,3,4,5].map(n => (
              <button key={n}
                onMouseEnter={() => setHovered(n)}
                onMouseLeave={() => setHovered(0)}
                onClick={() => rate(n)}
                style={{
                  background: 'none', border: 'none', cursor: 'pointer',
                  fontSize: 40, lineHeight: 1, padding: 4,
                  filter: n <= (hovered || stars) ? 'none' : 'grayscale(1) opacity(.4)',
                  transform: n <= (hovered || stars) ? 'scale(1.15)' : 'scale(1)',
                  transition: 'all .15s',
                }}>
                ⭐
              </button>
            ))}
          </div>
        </div>
      ) : (
        <div style={{ fontSize: 18, color: '#4ade80', fontWeight: 700 }}>
          {'⭐'.repeat(stars)} {'¡Gracias!'}
        </div>
      )}

      {/* Auto-reset hint */}
      <div style={{ fontSize: 11, color: 'rgba(255,255,255,.25)', fontFamily: 'var(--font-mono)' }}>
        {lang === 'es' ? 'Volviendo al inicio en breve…' : 'Returning to start shortly…'}
      </div>
    </div>
  );
}

Object.assign(window, { WelcomeScene, ConversationScene, SeatbeltScene, RideScene, PoiScene, PromoScene, StatusBar, PlayBtn, LangSwitcher, ControlsPanel, Caption, FloatingMic, ReplayBtn, TripEndScene });
