// onboarding.jsx — splash, first-run onboarding, session-complete,
// achievement banner, share card & review prompt (exported to window)
// NOTE: useState/useRef are already declared globally by sphere.jsx — alias here.
const { useState: oUS, useEffect: oUE, useRef: oUR } = React;

// ── Splash ────────────────────────────────────────────────
// Premium boot screen: living sphere + wordmark, an elegant fade, then it dissolves.
function Splash({ onDone, hold = 2000 }) {
  const [leaving, setLeaving] = oUS(false);
  oUE(() => {
    const a = setTimeout(() => setLeaving(true), hold);
    const b = setTimeout(() => onDone && onDone(), hold + 650);
    return () => { clearTimeout(a); clearTimeout(b); };
  }, []);
  return (
    <div className={leaving ? 'lm-splash-fade' : ''} style={{
      position: 'absolute', inset: 0, zIndex: 200,
      background: 'radial-gradient(1100px 760px at 50% -8%, #14101f 0%, #0a0a11 46%, #050507 100%)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
    }}>
      <img src={window.EME_WORDMARK_SRC} alt="EMEO" className="ob-in ob-in-1" style={{
        width: 'min(72%, 300px)', height: 'auto', objectFit: 'contain', userSelect: 'none', pointerEvents: 'none',
        filter: 'drop-shadow(0 0 30px rgba(140,180,255,.32))',
      }} />
    </div>
  );
}

// ── Onboarding (max 3 screens) ────────────────────────────
function Dots({ n, i, accent }) {
  return (
    <div style={{ display: 'flex', gap: 8, justifyContent: 'center' }}>
      {Array.from({ length: n }).map((_, k) => (
        <span key={k} style={{
          width: k === i ? 22 : 7, height: 7, borderRadius: 99,
          background: k === i ? `linear-gradient(90deg,${accent[0]},${accent[1]})` : 'rgba(255,255,255,.22)',
          transition: 'width .3s ease, background .3s ease',
        }} />
      ))}
    </div>
  );
}

// ── Onboarding (3 screens) ────────────────────────────
// ── Onboarding V5 — interactive, minimal, activation-focused (5 screens) ──────────
// Same visual identity (violet, glows, generous spacing). No premium content anywhere.
function Onboarding({ th, accent, onComplete }) {
  const { t, dir } = useI18n();
  const [step, setStep] = oUS(0);
  const [goals, setGoals] = oUS([]);          // S1 multi
  const [capacity, setCapacity] = oUS(null);  // S2 single
  const [activity, setActivity] = oUS(null);  // S3 single
  const [milestone, setMilestone] = oUS(35);  // S4 single
  const [mode, setMode] = oUS('pomo');        // S5 single

  const finish = (start) => { haptic([0, 24], true); onComplete && onComplete({ goals, capacity, activity, milestone, mode, start }); };
  const next = () => { haptic(12, true); setStep((s) => s + 1); };
  const toggleGoal = (g) => { haptic(10, true); setGoals((arr) => arr.includes(g) ? arr.filter((x) => x !== g) : [...arr, g]); };

  // ── option card (purple glow when selected) ──
  const OptCard = ({ selected, onClick, icon, label, sub }) => (
    <button onClick={onClick} data-haptic="medium" style={{
      width: '100%', textAlign: 'start', fontFamily: 'inherit', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 13,
      padding: '16px 17px', borderRadius: 17, color: th.text,
      border: '1px solid ' + (selected ? accent[0] + 'cc' : 'rgba(255,255,255,.10)'),
      background: selected ? `linear-gradient(135deg, ${accent[0]}26, ${accent[1]}12)` : th.surface,
      boxShadow: selected ? `0 0 0 1px ${accent[0]}55, 0 10px 30px ${accent[0]}22` : 'none',
      transition: 'border-color .22s, background .22s, box-shadow .22s',
    }}>
      {icon && <span style={{ width: 38, height: 38, borderRadius: 12, flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', background: `linear-gradient(140deg, ${accent[0]}33, ${accent[1]}1f)`, color: accent[0] }}>{icon}</span>}
      <span style={{ flex: 1, minWidth: 0 }}>
        <span style={{ fontSize: 15.5, fontWeight: 400 }}>{label}</span>
        {sub && <span style={{ display: 'block', fontSize: 12.5, color: th.dim, marginTop: 3 }}>{sub}</span>}
      </span>
      {selected && <span style={{ color: accent[0], display: 'flex', flexShrink: 0 }}><IconCheck size={20} /></span>}
    </button>
  );

  const Q = ({ title, sub }) => (
    <div style={{ marginBottom: 22 }}>
      <div style={{ fontSize: 26, lineHeight: 1.22, fontWeight: 300, color: th.text, textWrap: 'balance' }}>{title}</div>
      {sub && <div style={{ fontSize: 14.5, color: th.dim, marginTop: 10, fontWeight: 300 }}>{sub}</div>}
    </div>
  );
  const cta = (label, onClick, disabled) => (
    <button onClick={onClick} disabled={disabled} className="prem-cta" style={{
      width: '100%', padding: '16px', borderRadius: 16, border: 'none', cursor: disabled ? 'default' : 'pointer', fontFamily: 'inherit',
      fontSize: 15.5, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 9,
      background: `linear-gradient(135deg,${accent[0]},${accent[1]})`, boxShadow: disabled ? 'none' : `0 10px 30px ${accent[0]}44`, opacity: disabled ? 0.4 : 1,
    }}>{label}<span style={{ display: 'flex', transform: dir === 'rtl' ? 'scaleX(-1)' : 'none' }}><IconArrowRight size={18} /></span></button>
  );

  // Screen 5 mode preview
  const modePreview = mode === 'pomo' ? '25:00' : mode === 'deep' ? '50:00' : '∞';
  const milestones = [5, 35, 75, 150];
  const mileDesc = { 5: t('ob4_d5'), 35: t('ob4_d35'), 75: t('ob4_d75'), 150: t('ob4_d150') };

  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 180, display: 'flex', flexDirection: 'column',
      background: 'radial-gradient(1100px 820px at 50% -6%, #15111f 0%, #0a0a11 50%, #050507 100%)',
      padding: '58px 26px 38px',
    }}>
      {/* top progress bar */}
      <div style={{ display: 'flex', gap: 6, height: 4, marginBottom: 26 }}>
        {[0, 1, 2, 3, 4].map((k) => (
          <div key={k} style={{ flex: 1, height: 4, borderRadius: 99, background: k <= step ? `linear-gradient(90deg, ${accent[0]}, ${accent[1]})` : 'rgba(255,255,255,.10)', transition: 'background .3s' }} />
        ))}
      </div>

      <div key={'ob' + step} className="ob-in ob-in-2" style={{ flex: 1, minHeight: 0, overflowY: 'auto', display: 'flex', flexDirection: 'column' }}>
        {step === 0 && (<>
          <Q title={t('ob1_q')} sub={t('ob1_sub')} />
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            {[['focus', t('ob1_a1')], ['distract', t('ob1_a2')], ['discipline', t('ob1_a3')], ['study', t('ob1_a4')], ['work', t('ob1_a5')]].map(([k, label]) => (
              <OptCard key={k} selected={goals.includes(k)} onClick={() => toggleGoal(k)} label={label} />
            ))}
          </div>
        </>)}

        {step === 1 && (<>
          <Q title={t('ob2_q')} />
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            {[['<15', t('ob2_a1')], ['15-30', t('ob2_a2')], ['30-60', t('ob2_a3')], ['>60', t('ob2_a4')]].map(([k, label]) => (
              <OptCard key={k} selected={capacity === k} onClick={() => { setCapacity(k); haptic(12, true); }} label={label} />
            ))}
          </div>
        </>)}

        {step === 2 && (<>
          <Q title={t('ob3_q')} />
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            {[['work', t('ob3_a1'), <IconBolt size={19} />], ['studies', t('ob3_a2'), <IconChart size={19} />], ['reading', t('ob3_a3'), <IconBook size={19} />], ['projects', t('ob3_a4'), <IconTarget size={19} />], ['other', t('ob3_a5'), <IconSparkle size={19} />]].map(([k, label, ic]) => (
              <OptCard key={k} selected={activity === k} onClick={() => { setActivity(k); haptic(12, true); }} icon={ic} label={label} />
            ))}
          </div>
        </>)}

        {step === 3 && (<>
          <Q title={t('ob4_q')} sub={t('ob4_sub')} />
          {/* horizontal progression path with rank previews */}
          <div style={{ position: 'relative', display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', margin: '26px 2px 0' }}>
            {milestones.map((h) => {
              const sel = milestone === h;
              const rank = (window.LEVELS && window.levelForHours) ? (LEVELS[levelForHours(h)] || {}).name : '';
              return (
                <button key={h} onClick={() => { setMilestone(h); haptic(12, true); }} data-haptic="medium" style={{
                  position: 'relative', background: 'none', border: 'none', cursor: 'pointer', fontFamily: 'inherit',
                  display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 9, flex: 1,
                }}>
                  <span style={{
                    width: 50, height: 50, borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13.5, fontWeight: 500,
                    color: sel ? '#fff' : th.dim,
                    background: sel ? `linear-gradient(135deg, ${accent[0]}, ${accent[1]})` : th.surface,
                    border: '1px solid ' + (sel ? accent[0] : th.border2),
                    boxShadow: sel ? `0 0 24px ${accent[0]}77` : 'none', transform: sel ? 'scale(1.08)' : 'scale(1)', transition: 'all .24s ease',
                  }}>{h}h</span>
                  <span style={{ fontSize: 11.5, color: sel ? accent[0] : th.faint, fontWeight: 500, letterSpacing: .3 }}>{rank}</span>
                </button>
              );
            })}
          </div>
          {/* selected milestone description (animated highlight) */}
          <div key={'mile' + milestone} className="ob-in ob-in-2" style={{ marginTop: 30, textAlign: 'center' }}>
            <div style={{ fontSize: 19, fontWeight: 300, color: th.text }}>{t('ob_hours', { n: milestone })}</div>
            <div style={{ fontSize: 14.5, color: th.dim, marginTop: 8, fontWeight: 300 }}>{mileDesc[milestone]}</div>
          </div>
        </>)}

        {step === 4 && (<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center' }}>
          <div style={{ width: 188, height: 188, position: 'relative', display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '6px 0 22px' }}>
            {typeof RingParticles === 'function' && <RingParticles active count={12} radius={104} />}
            {[0, 1, 2].map((k) => (<div key={k} style={{ position: 'absolute', width: 96 + k * 42, height: 96 + k * 42, borderRadius: '50%', border: '1px solid ' + accent[0] + (k === 0 ? '55' : k === 1 ? '33' : '1e') }} />))}
            <div style={{ width: 120, height: 120, borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', background: `radial-gradient(circle at 50% 32%, ${accent[0]}33, rgba(12,10,22,.92) 72%)`, boxShadow: `0 0 40px ${accent[0]}55, inset 0 0 22px ${accent[0]}2a`, color: th.text, fontSize: 30, fontWeight: 200, letterSpacing: 1 }}>{modePreview}</div>
          </div>
          <div style={{ fontSize: 25, lineHeight: 1.22, fontWeight: 300, color: th.text, textWrap: 'balance', maxWidth: 320 }}>{t('ob5_title')}</div>
          <div style={{ fontSize: 14.5, color: th.dim, marginTop: 10, fontWeight: 300, maxWidth: 300 }}>{t('ob5_sub')}</div>
          <div style={{ display: 'flex', gap: 8, marginTop: 22, width: '100%' }}>
            {[['pomo', t('ob5_m1')], ['deep', t('ob5_m2')], ['countup', t('ob5_m3')]].map(([k, label]) => (
              <button key={k} onClick={() => { setMode(k); haptic(12, true); }} data-haptic="medium" style={{
                flex: 1, padding: '12px 6px', borderRadius: 14, cursor: 'pointer', fontFamily: 'inherit', fontSize: 12.5, lineHeight: 1.3,
                border: '1px solid ' + (mode === k ? accent[0] + 'cc' : 'rgba(255,255,255,.10)'),
                background: mode === k ? `linear-gradient(135deg, ${accent[0]}26, ${accent[1]}12)` : th.surface, color: mode === k ? th.text : th.dim,
              }}>{label}</button>
            ))}
          </div>
        </div>)}
      </div>

      {/* footer CTAs */}
      <div className="ob-in ob-in-4" style={{ marginTop: 22 }}>
        {step === 0 && cta(t('obv_continue'), next, goals.length === 0)}
        {step === 1 && cta(t('obv_continue'), next, !capacity)}
        {step === 2 && cta(t('obv_continue'), next, !activity)}
        {step === 3 && cta(t('obv_continue'), next, false)}
        {step === 4 && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
            <button onClick={() => finish(true)} className="prem-cta" style={{
              width: '100%', padding: '16px', borderRadius: 16, border: 'none', cursor: 'pointer', fontFamily: 'inherit',
              fontSize: 15.5, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 9,
              background: `linear-gradient(135deg,${accent[0]},${accent[1]})`, boxShadow: `0 12px 30px ${accent[0]}44`,
            }}><IconPlay size={17} />{t('ob_start_session')}</button>
            <button onClick={() => finish(false)} style={{ width: '100%', padding: '13px', borderRadius: 16, cursor: 'pointer',
              fontFamily: 'inherit', fontSize: 14.5, border: '1px solid ' + th.border2, background: 'transparent', color: th.dim }}>{t('ob_maybe_later')}</button>
          </div>
        )}
      </div>
    </div>
  );
}

// Onboarding marks — same concentric-ring + glowing-circle language as the
// notifications screen (page 3), so all three intro screens share one identity.
function OnboardMark({ kind, accent }) {
  const icon = kind === 'focus' ? <IconTarget size={36} /> : <IconChart size={36} />;
  return (
    <div style={{ width: 200, height: 200, position: 'relative', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      {[0, 1, 2].map((k) => (
        <div key={k} style={{
          position: 'absolute', width: 96 + k * 44, height: 96 + k * 44, borderRadius: '50%',
          border: '1px solid ' + accent[0] + (k === 0 ? '55' : k === 1 ? '33' : '1e'),
        }} />
      ))}
      <div style={{
        width: 92, height: 92, borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center',
        background: `radial-gradient(circle at 50% 32%, ${accent[0]}40, rgba(12,10,22,.9) 72%)`,
        boxShadow: `0 0 34px ${accent[0]}55, inset 0 0 18px ${accent[0]}33`, color: accent[0],
      }}>{icon}</div>
    </div>
  );
}

// Decorative bell + ripple for the notifications screen.
function OnboardBell({ accent }) {
  return (
    <div style={{ width: 200, height: 200, position: 'relative', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      {[0, 1, 2].map((k) => (
        <div key={k} style={{
          position: 'absolute', width: 96 + k * 44, height: 96 + k * 44, borderRadius: '50%',
          border: '1px solid ' + accent[0] + (k === 0 ? '55' : k === 1 ? '33' : '1e'),
        }} />
      ))}
      <div style={{
        width: 92, height: 92, borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center',
        background: `radial-gradient(circle at 50% 32%, ${accent[0]}40, rgba(12,10,22,.9) 72%)`,
        boxShadow: `0 0 34px ${accent[0]}55, inset 0 0 18px ${accent[0]}33`, color: accent[0],
      }}><IconBell size={36} /></div>
    </div>
  );
}

// ── Session Complete ──────────────────────────────────────
function fmtDur(min) {
  const h = Math.floor(min / 60), m = min % 60;
  if (h && m) return { a: h, au: 'h', b: m, bu: 'm' };
  if (h) return { a: h, au: 'h' };
  return { a: m, bu: '', au: 'min' };
}
// ── Session share card (canvas → native share sheet) ──────────────────────────────
// Draws a premium 1080×1350 image and hands it to the OS share sheet (Instagram, WhatsApp,
// X, Messages…). Falls back to a text share, then to downloading the PNG. Exposed on
// window so both SessionComplete and the Session History screen can use it.
function _roundRect(x, X, Y, w, h, r) {
  x.beginPath(); x.moveTo(X + r, Y);
  x.arcTo(X + w, Y, X + w, Y + h, r); x.arcTo(X + w, Y + h, X, Y + h, r);
  x.arcTo(X, Y + h, X, Y, r); x.arcTo(X, Y, X + w, Y, r); x.closePath();
}
async function shareSessionImage(opts) {
  const minutes = opts.minutes, dateLabel = opts.dateLabel || '', typeLabel = (opts.typeLabel || '').toUpperCase();
  const headline = opts.headline || ('Focused for ' + minutes + ' minute' + (minutes === 1 ? '' : 's'));
  const generated = opts.generated || 'Generated with Emeo';
  const W = 1080, H = 1350, FONT = 'Sora, "Space Grotesk", system-ui, sans-serif';
  const c = document.createElement('canvas'); c.width = W; c.height = H;
  const x = c.getContext('2d');
  const bg = x.createLinearGradient(0, 0, 0, H); bg.addColorStop(0, '#0e0b18'); bg.addColorStop(1, '#060509');
  x.fillStyle = bg; x.fillRect(0, 0, W, H);
  const glow = x.createRadialGradient(W / 2, 470, 0, W / 2, 470, 720);
  glow.addColorStop(0, 'rgba(184,92,255,.22)'); glow.addColorStop(1, 'rgba(184,92,255,0)');
  x.fillStyle = glow; x.fillRect(0, 0, W, H);
  x.strokeStyle = 'rgba(255,255,255,.08)'; x.lineWidth = 2; _roundRect(x, 48, 48, W - 96, H - 96, 56); x.stroke();
  x.textAlign = 'center'; x.textBaseline = 'middle';
  // ring + orb
  x.beginPath(); x.arc(W / 2, 470, 168, 0, Math.PI * 2); x.strokeStyle = 'rgba(184,92,255,.55)'; x.lineWidth = 6; x.stroke();
  x.beginPath(); x.arc(W / 2, 470 - 168, 13, 0, Math.PI * 2); x.fillStyle = '#fff'; x.fill();
  x.fillStyle = '#fff'; x.font = '600 138px ' + FONT; x.fillText(String(minutes), W / 2, 462);
  x.fillStyle = 'rgba(255,255,255,.55)'; x.font = '600 32px ' + FONT; x.fillText('MINUTES', W / 2, 560);
  // headline + type + date
  x.fillStyle = '#fff'; x.font = '600 54px ' + FONT; x.fillText(headline, W / 2, 830);
  x.fillStyle = '#C9A6FF'; x.font = '600 30px ' + FONT; x.fillText(typeLabel, W / 2, 902);
  x.fillStyle = 'rgba(255,255,255,.55)'; x.font = '400 38px ' + FONT; x.fillText(dateLabel, W / 2, 966);
  // branding
  x.fillStyle = '#fff'; x.font = '700 46px ' + FONT; x.fillText('EMEO', W / 2, 1190);
  x.fillStyle = 'rgba(255,255,255,.4)'; x.font = '400 28px ' + FONT; x.fillText(generated, W / 2, 1244);

  const blob = await new Promise((r) => c.toBlob(r, 'image/png'));
  if (!blob) { opts.onToast && opts.onToast(opts.toastReady); return { ok: false }; }
  const file = new File([blob], 'emeo-session.png', { type: 'image/png' });
  try {
    if (navigator.canShare && navigator.canShare({ files: [file] })) {
      await navigator.share({ files: [file], title: 'Emeo', text: headline });
      return { ok: true };
    }
    if (navigator.share) { await navigator.share({ title: 'Emeo', text: headline + ' · ' + dateLabel }); return { ok: true }; }
  } catch (e) { if (e && e.name === 'AbortError') return { ok: true }; }
  // fallback: download the PNG
  try { const u = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = u; a.download = 'emeo-session.png'; a.click(); setTimeout(() => URL.revokeObjectURL(u), 1500); } catch (e) {}
  opts.onToast && opts.onToast(opts.toastReady);
  return { ok: true };
}
window.shareSessionImage = shareSessionImage;

function SessionComplete({ level, anim, th, accent, sessionMin, todayMin, mode = 'standard', ts, settings, onShared, onToast, onClose }) {
  const { t } = useI18n();
  const sd = fmtDur(sessionMin), td = fmtDur(todayMin);
  oUE(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);
  const doShare = () => {
    haptic(14, true);
    if (onShared) onShared();
    const dateLabel = new Date(ts || Date.now()).toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' });
    const typeLabel = t(mode === 'pomodoro' ? 'sess_pomodoro' : mode === 'countup' ? 'sess_countup' : 'sess_focus');
    window.shareSessionImage({ minutes: sessionMin, dateLabel, typeLabel,
      headline: t('share_focused', { n: sessionMin }), generated: t('share_generated'),
      onToast, toastReady: t('toast_share_ready') });
  };
  const Stat = ({ label, d }) => (
    <div style={{ flex: 1, textAlign: 'center' }}>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'center', gap: 3 }}>
        <span style={{ fontSize: 34, fontWeight: 200, color: th.text }}>{d.a}</span>
        <span style={{ fontSize: 14, color: th.dim }}>{d.au}</span>
        {d.b != null && <><span style={{ fontSize: 34, fontWeight: 200, color: th.text, marginLeft: 4 }}>{d.b}</span><span style={{ fontSize: 14, color: th.dim }}>{d.bu}</span></>}
      </div>
      <div style={{ fontSize: 11.5, letterSpacing: 1.4, color: th.faint, marginTop: 7, textTransform: 'uppercase' }}>{label}</div>
    </div>
  );
  return (
    <div className="modal-back" style={{
      position: 'absolute', inset: 0, zIndex: 150, background: 'rgba(5,5,9,.86)', backdropFilter: 'blur(10px)',
      display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', padding: 34,
    }}>
      <div style={{ position: 'relative', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <div className="sc-pop"><ProgressRing progress={1} size={178} colors={accent} complete topSphere>
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', lineHeight: 1 }}>
            <span style={{ fontSize: 50, fontWeight: 200, color: th.text, letterSpacing: 0.5 }}>{sessionMin}</span>
            <span style={{ fontSize: 12.5, fontWeight: 500, letterSpacing: 2.4, textTransform: 'uppercase', color: accent[0], marginTop: 7 }}>{t('min_unit')}</span>
          </div>
        </ProgressRing></div>
      </div>
      <div className="sc-card" style={{ width: '100%', maxWidth: 330, textAlign: 'center', marginTop: 30 }}>
        <img src={window.EMEO_LOGO_SRC} alt="EMEO" style={{ display: 'block', height: 26, width: 'auto', margin: '0 auto', objectFit: 'contain', userSelect: 'none', pointerEvents: 'none', filter: 'drop-shadow(0 0 12px rgba(140,180,255,.28))' }} />
        <div style={{ fontSize: 30, fontWeight: 300, color: th.text, marginTop: 14 }}>{t('sc_title')}</div>
        <div style={{ fontSize: 14.5, color: th.dim, marginTop: 8, fontWeight: 300 }}>{t('sc_sub')}</div>
        <div style={{ display: 'flex', gap: 8, marginTop: 26, padding: '18px 14px', borderRadius: 20,
          background: th.surface, border: '1px solid ' + th.border }}>
          <Stat label={t('sc_session')} d={sd} />
          <div style={{ width: 1, background: th.border }} />
          <Stat label={t('sc_today')} d={td} />
        </div>
        <button onClick={doShare} className="prem-cta" data-haptic="medium" style={{
          marginTop: 22, width: '100%', padding: '15px', borderRadius: 16, border: 'none', cursor: 'pointer', fontFamily: 'inherit',
          fontSize: 15, color: '#fff', background: `linear-gradient(135deg,${accent[0]},${accent[1]})`, boxShadow: `0 10px 28px ${accent[0]}44`,
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 9,
        }}><IconShare size={17} />{t('share_session')}</button>
        <button onClick={onClose} style={{
          marginTop: 10, width: '100%', padding: '14px', borderRadius: 16, cursor: 'pointer', fontFamily: 'inherit',
          fontSize: 14.5, color: th.text, background: 'transparent', border: '1px solid ' + th.border2,
        }}>{t('sc_done')}</button>
      </div>
    </div>
  );
}

// ── Achievement banner (slides down from the top) ─────────
function AchievementBanner({ th, accent, title, onDone }) {
  const { t } = useI18n();
  const [shown, setShown] = oUS(false);
  oUE(() => {
    const a = setTimeout(() => setShown(true), 40);
    const b = setTimeout(() => setShown(false), 3400);
    const c = setTimeout(() => onDone && onDone(), 3850);
    return () => { [a, b, c].forEach(clearTimeout); };
  }, []);
  return (
    <div style={{ position: 'absolute', top: 0, left: 0, right: 0, zIndex: 160, display: 'flex', justifyContent: 'center',
      padding: '52px 16px 0', pointerEvents: 'none' }}>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 13, padding: '13px 18px', borderRadius: 18, width: '100%', maxWidth: 360,
        background: 'linear-gradient(135deg, rgba(28,24,40,.96), rgba(16,14,24,.96))',
        border: '1px solid ' + accent[0] + '55', boxShadow: `0 16px 40px rgba(0,0,0,.5), 0 0 0 1px ${accent[0]}22`,
        backdropFilter: 'blur(14px)', transform: shown ? 'translateY(0)' : 'translateY(-150%)', opacity: shown ? 1 : 0,
        transition: 'transform .5s cubic-bezier(.2,.9,.25,1), opacity .4s ease',
      }}>
        <span style={{ width: 40, height: 40, borderRadius: 12, flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center',
          background: `linear-gradient(140deg, ${accent[0]}44, ${accent[1]}33)`, color: accent[0], filter: `drop-shadow(0 0 8px ${accent[0]}88)` }}>
          <IconTrophy size={21} />
        </span>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 10.5, letterSpacing: 1.6, color: accent[0], fontWeight: 600, textTransform: 'uppercase' }}>{t('ab_unlocked')}</div>
          <div style={{ fontSize: 15.5, fontWeight: 300, color: th.text, marginTop: 2, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{title}</div>
        </div>
        <span style={{ color: accent[0], display: 'flex', flexShrink: 0 }}><IconSparkle size={18} /></span>
      </div>
    </div>
  );
}

// ── Share card ────────────────────────────────────────────
function ShareCard({ th, accent, level, stats, totalHours, kind = 'rank', onShared, onClose, onToast }) {
  const { t, dir } = useI18n();
  const doShare = async () => {
    haptic(14, true);
    if (onShared) onShared(kind);   // counts toward the Sharing & Community achievements
    const text = `${fmtHours(totalHours)}h ${t('share_caption')} · ${level.name}`;
    try {
      if (navigator.share) { await navigator.share({ title: 'Emeo', text }); return; }
    } catch (e) {}
    onToast && onToast(t('toast_share_ready'));
  };
  const Metric = ({ value, label }) => (
    <div style={{ flex: 1, textAlign: 'center' }}>
      <div style={{ fontSize: 22, fontWeight: 300, color: th.text }}>{value}</div>
      <div style={{ fontSize: 10.5, letterSpacing: .8, color: th.faint, marginTop: 4 }}>{label}</div>
    </div>
  );
  return (
    <div onClick={onClose} style={{ position: 'absolute', inset: 0, zIndex: 140, background: 'rgba(4,4,8,.72)', backdropFilter: 'blur(8px)',
      display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 28 }}>
      <div onClick={(e) => e.stopPropagation()} className="sc-card" style={{ width: '100%', maxWidth: 340 }}>
        {/* the shareable card */}
        <div style={{ position: 'relative', overflow: 'hidden', borderRadius: 28, padding: '34px 26px 30px', textAlign: 'center',
          background: `radial-gradient(120% 90% at 50% 0%, ${level.glow}30, #0c0b14 60%)`, border: '1px solid ' + level.glow + '44' }}>
          <div style={{ position: 'absolute', inset: 0, background: `radial-gradient(60% 40% at 50% 8%, ${level.left}22, transparent 70%)`, pointerEvents: 'none' }} />
          <div style={{ position: 'relative' }}>
            {/* clean Emeo wordmark — no surrounding ring, slightly larger */}
            <div style={{ display: 'flex', justifyContent: 'center', marginTop: 6 }}>
              <img src={window.EME_WORDMARK_SRC} alt="EMEO" style={{ width: 'min(72%, 220px)', height: 'auto', objectFit: 'contain',
                filter: 'drop-shadow(0 0 24px rgba(140,180,255,.3))', userSelect: 'none', pointerEvents: 'none' }} />
            </div>
            <div style={{ fontSize: 11, letterSpacing: 3, color: level.glow, fontWeight: 600, marginTop: 22, textTransform: 'uppercase' }}>{t('share_level_label')}</div>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 11, marginTop: 8 }}>
              <RankBadge levelIdx={LEVELS.findIndex((l) => l.key === level.key)} size={30} />
              <div style={{ fontSize: 30, fontWeight: 300, color: th.text }}>{level.name}</div>
            </div>
            <div style={{ display: 'flex', gap: 6, marginTop: 22, padding: '14px 8px', borderRadius: 16, background: 'rgba(255,255,255,.04)', border: '1px solid ' + th.border }}>
              <Metric value={fmtHours(totalHours)} label={t('share_total')} />
              <div style={{ width: 1, background: th.border }} />
              <Metric value={stats.currentStreak} label={t('share_streak_label')} />
              <div style={{ width: 1, background: th.border }} />
              <Metric value={stats.sessions} label={t('share_sessions')} />
            </div>
          </div>
        </div>
        <div style={{ display: 'flex', gap: 10, marginTop: 16 }}>
          <button onClick={onClose} style={{ flex: 1, padding: '14px', borderRadius: 15, cursor: 'pointer', fontFamily: 'inherit', fontSize: 14.5,
            border: '1px solid ' + th.border2, background: 'transparent', color: th.text }}>{t('np_close')}</button>
          <button onClick={doShare} className="prem-cta" style={{ flex: 1.4, padding: '14px', borderRadius: 15, cursor: 'pointer', fontFamily: 'inherit', fontSize: 14.5,
            border: 'none', color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
            background: `linear-gradient(135deg,${accent[0]},${accent[1]})`, boxShadow: `0 8px 22px ${accent[0]}44` }}>
            <IconShare size={17} />{t('share')}</button>
        </div>
      </div>
    </div>
  );
}

// ── Review prompt (after ~5 sessions, non-intrusive) ──────
function ReviewPrompt({ th, accent, onRate, onClose, onNever }) {
  const { t } = useI18n();
  const [rating, setRating] = oUS(0);
  return (
    <div onClick={onClose} className="modal-back" style={{ position: 'absolute', inset: 0, zIndex: 130, background: 'rgba(4,4,8,.7)', backdropFilter: 'blur(5px)',
      display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 32 }}>
      <div onClick={(e) => e.stopPropagation()} className="sc-card modal-card" style={{ width: '100%', maxWidth: 320, textAlign: 'center',
        background: th.modal, borderRadius: 24, padding: '28px 24px', border: '1px solid ' + th.border2 }}>
        <div style={{ display: 'flex', justifyContent: 'center', gap: 7, color: accent[0] }}>
          {[1, 2, 3, 4, 5].map((k) => (
            <button key={k} onMouseEnter={() => setRating(k)} onClick={() => { setRating(k); haptic(10, true); }} style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 2,
              color: k <= rating ? accent[0] : th.ghost, filter: k <= rating ? `drop-shadow(0 0 6px ${accent[0]}aa)` : 'none', transition: 'color .15s' }}>
              <IconStar size={26} />
            </button>
          ))}
        </div>
        <div style={{ fontSize: 21, fontWeight: 400, color: th.text, marginTop: 20 }}>{t('rv_title')}</div>
        <div style={{ fontSize: 14, color: th.dim, marginTop: 8, lineHeight: 1.5, fontWeight: 300 }}>{t('rv_body')}</div>
        <button onClick={() => onRate(rating)} className="prem-cta" style={{ marginTop: 22, width: '100%', padding: '14px', borderRadius: 15, border: 'none', cursor: 'pointer',
          fontFamily: 'inherit', fontSize: 15, color: '#fff', background: `linear-gradient(135deg,${accent[0]},${accent[1]})`, boxShadow: `0 8px 22px ${accent[0]}44` }}>{t('rv_rate')}</button>
        <button onClick={onClose} style={{ marginTop: 10, width: '100%', padding: '11px', borderRadius: 15, cursor: 'pointer',
          fontFamily: 'inherit', fontSize: 14, border: 'none', background: 'transparent', color: th.faint }}>{t('rv_later')}</button>
        <button onClick={() => (onNever ? onNever() : onClose())} style={{ marginTop: 2, width: '100%', padding: '9px', borderRadius: 15, cursor: 'pointer',
          fontFamily: 'inherit', fontSize: 12.5, border: 'none', background: 'transparent', color: th.ghost }}>{t('rv_never')}</button>
      </div>
    </div>
  );
}

Object.assign(window, { Splash, Onboarding, SessionComplete, AchievementBanner, ShareCard, ReviewPrompt });

  