// Résonance — Journal detail, Écho, Settings, empty states, errors

const { useState: uSt, useEffect: uEf } = React;

// ═════════════════════════════════════════════════════════════
// S12 — Session detail
// ═════════════════════════════════════════════════════════════
function S12_Detail({ go, ctx }) {
  const s = ctx?.session || MOCK_SESSIONS[0];
  const hasState = !!s.state;
  const m = hasState ? STATE_META[s.state] : null;
  return (
    <Screen intent={hasState ? m.tag : 'journal'}>
      <TopBar onBack={() => go('S5_Journal')} trailing={<div style={{ padding:8 }}><Icon name="share" size={18}/></div>}/>
      <div style={{ padding: '0 20px 40px' }}>
        {hasState && (
          <div style={{ textAlign: 'center', margin: '0 auto 20px' }}>
            <NuanceViz state={s.state} size={180} animated={false}/>
          </div>
        )}
        <div style={{ textAlign: 'center', marginBottom: 28 }}>
          {hasState && <StateBadge state={s.state} size="lg"/>}
          <div style={{ fontSize: 22, fontWeight: 700, color: RZ.fg1, letterSpacing: -0.3, marginTop: hasState ? 12 : 0 }}>{s.title}</div>
          <div style={{ fontSize: 12, color: RZ.fg3, marginTop: 4 }}>{s.date}</div>
        </div>

        <Glass style={{ padding: 16, marginBottom: 12 }}>
          <div style={{ fontSize: 10, fontWeight: 600, color: '#A82E1A', textTransform: 'uppercase', letterSpacing: 1, marginBottom: 12 }}>Corps · mesuré par Strava</div>
          <div style={{ display: 'flex', gap: 20, flexWrap: 'wrap' }}>
            {[['Distance', s.dist], ['Durée', s.dur], s.hr && ['FC moy.', s.hr], ['Allure', s.type === 'run' ? '5:06/km' : s.type === 'bike' ? '26 km/h' : '—']].filter(Boolean).map(([l,v]) => (
              <div key={l}>
                <div style={{ fontSize: 18, fontWeight: 600, color: RZ.fg1, letterSpacing: -0.2 }}>{v}</div>
                <div style={{ fontSize: 10, color: RZ.fg3, textTransform: 'uppercase', letterSpacing: 0.6 }}>{l}</div>
              </div>
            ))}
          </div>
        </Glass>

        {s.transcript && (
          <Glass style={{ padding: 16, marginBottom: 12 }}>
            <div style={{ fontSize: 10, fontWeight: 600, color: RZ.blue, textTransform: 'uppercase', letterSpacing: 1, marginBottom: 10, display:'flex', alignItems:'center', gap:6 }}>
              <Icon name="mic" size={12} color={RZ.blue}/> Esprit · ressenti vocal
            </div>
            <div style={{ fontSize: 14, color: RZ.fg1, lineHeight: 1.6, fontStyle: 'italic' }}>« {s.transcript} »</div>
            <div style={{ marginTop: 12, display: 'inline-flex', alignItems: 'center', gap: 8, padding: '8px 14px', background: 'rgba(24,20,15,0.05)', borderRadius: 20, cursor: 'pointer' }}>
              <Icon name="play" size={12}/>
              <span style={{ fontSize: 11, fontWeight: 500, color: RZ.fg1 }}>Écouter (0:47)</span>
            </div>
          </Glass>
        )}

        {s.reflection && (
          <Glass raised style={{ padding: 16, marginBottom: 12 }}>
            <div style={{ fontSize: 10, fontWeight: 600, color: RZ.mauve, textTransform: 'uppercase', letterSpacing: 1, marginBottom: 10, display:'flex', alignItems:'center', gap:6 }}>
              <Icon name="sparkle" size={12} color={RZ.mauve}/> Réflexion
            </div>
            <div style={{ fontSize: 14, color: RZ.fg1, lineHeight: 1.65 }}>{s.reflection}</div>
          </Glass>
        )}

        {s.question && (
          <Glass style={{ padding: 16, marginBottom: 12 }}>
            <div style={{ fontSize: 10, fontWeight: 600, color: RZ.fg3, textTransform: 'uppercase', letterSpacing: 1, marginBottom: 8 }}>Question restée ouverte</div>
            <div style={{ fontSize: 14, color: RZ.fg1, lineHeight: 1.55, fontStyle: 'italic' }}>« {s.question} »</div>
          </Glass>
        )}

        {!hasState && (
          <PrimaryBtn onClick={() => go('S6_Selector')} style={{ marginTop: 12 }}>
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}><Icon name="mic" size={16} color={RZ.white}/> Déposer une nuance</span>
          </PrimaryBtn>
        )}
      </div>
    </Screen>
  );
}

// ═════════════════════════════════════════════════════════════
// S13 — Écho (orb cluster)
// ═════════════════════════════════════════════════════════════
const ECHO_POINTS = [
  { day: 'Lun', state: 'resonance', x: 0.52, y: 0.48 },
  { day: 'Mar', state: 'equilibre', x: 0.42, y: 0.38 },
  { day: 'Mer', state: 'tension', x: 0.28, y: 0.58 },
  { day: 'Jeu', state: 'dissonance', x: 0.18, y: 0.72 },
  { day: 'Ven', state: 'tension', x: 0.36, y: 0.52 },
  { day: 'Sam', state: 'resonance', x: 0.58, y: 0.42 },
  { day: 'Dim', state: 'resonance', x: 0.54, y: 0.50 },
];

function S13_Echo({ go }) {
  const variant = window.__rzTweaks?.echoVariant || 'cluster';
  const consultShown = window.__rzTweaks?.consultVisible ?? true;
  const streakShown = window.__rzTweaks?.streakVisible ?? true;
  const currentState = window.__rzTweaks?.resultState || 'resonance';
  const [period, setPeriod] = uSt('7j');
  const [view, setView] = uSt('actuel'); // actuel | nuage | horizon
  const [selected, setSelected] = uSt(null);

  // Period → available views. Each period defaults to the most natural one.
  // Users can cross views to compare (Nuage available in all three).
  const viewsByPeriod = {
    '7j':    [{ id: 'actuel',  label: 'Actuel' },  { id: 'nuage',   label: 'Nuage' }],
    '30j':   [{ id: 'nuage',   label: 'Nuage' },   { id: 'horizon', label: 'Horizon' }],
    '3 mois':[{ id: 'horizon', label: 'Horizon' }, { id: 'nuage',   label: 'Nuage' }],
  };
  const availableViews = viewsByPeriod[period];
  uEf(() => {
    if (!availableViews.find(v => v.id === view)) setView(availableViews[0].id);
  }, [period]);

  // Cycle through states on tap of the hero — fun demo of the spectrum
  const cycleState = () => {
    const order = ['resonance','equilibre','tension','dissonance','alerte'];
    const next = order[(order.indexOf(currentState) + 1) % order.length];
    window.__rzTweaks.resultState = next;
    window.parent.postMessage({ type: '__edit_mode_set_keys', edits: { resultState: next } }, '*');
    setPeriod(p => p); // force re-render
  };

  return (
    <Screen intent="echo" tabBar={<TabBar active="echo" onChange={id => go(id === 'journal' ? 'S5_Journal' : id === 'nuance' ? 'S6_Selector' : 'S13_Echo')}/>}>
      <TopBar
        trailing={<div onClick={() => go('S15_Settings')} style={{ width:36, height:36, borderRadius:'50%', background:'rgba(255,255,255,0.6)', border:'1px solid rgba(255,255,255,0.7)', display:'flex', alignItems:'center', justifyContent:'center', cursor:'pointer' }}><Icon name="settings" size={18}/></div>}
      />
      <div style={{ padding: '0 20px 120px' }}>
        <div style={{ fontSize: 32, fontWeight: 700, color: RZ.fg1, letterSpacing: 2, marginBottom: 4 }}>ÉCHO</div>
        <div style={{ fontSize: 13, color: RZ.fg2, marginBottom: 20 }}>Les patterns qui émergent au fil de tes nuances.</div>

        <div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>
          {['7j', '30j', '3 mois'].map(p => <Chip key={p} on={period === p} onClick={() => setPeriod(p)}>{p}</Chip>)}
        </div>

        {/* View selector — quiet segmented control, text only */}
        <div style={{
          display: 'flex', gap: 4, marginBottom: 20,
          background: 'rgba(24,20,15,0.04)',
          borderRadius: 10, padding: 3,
          width: 'fit-content',
        }}>
          {availableViews.map(v => (
            <div key={v.id} onClick={() => setView(v.id)} style={{
              padding: '6px 14px', borderRadius: 8, cursor: 'pointer',
              fontSize: 11, fontWeight: 600, letterSpacing: 0.2,
              color: view === v.id ? RZ.fg1 : RZ.fg3,
              background: view === v.id ? 'rgba(255,255,255,0.85)' : 'transparent',
              boxShadow: view === v.id ? '0 1px 3px rgba(24,20,15,0.08)' : 'none',
              transition: 'all 180ms ease',
            }}>{v.label}</div>
          ))}
        </div>

        {view === 'actuel'  && <EmotionalWeather state={currentState} height={260} onCycleState={cycleState}/>}
        {view === 'nuage'   && <EmotionalCloud days={period === '7j' ? 7 : period === '30j' ? 30 : 90} periodLabel={period === '7j' ? '7 jours' : period === '30j' ? '30 jours' : '3 mois'} height={260}/>}
        {view === 'horizon' && <EmotionalHorizon weeks={period === '30j' ? 5 : 13} periodLabel={period === '30j' ? '30 jours' : '3 mois'} height={260}/>}

        {variant === 'cluster' && <EchoCluster selected={selected} setSelected={setSelected}/>}
        {variant === 'timeline' && <EchoTimeline selected={selected} setSelected={setSelected}/>}
        {variant === 'ribbon' && <EchoRibbon/>}

        {streakShown && <StreakCard go={go}/>}
        {consultShown && <ConsultCard go={go}/>}

        <Glass raised style={{ padding: 18, marginTop: 20 }}>
          <div style={{ fontSize: 10, fontWeight: 600, color: RZ.mauve, textTransform: 'uppercase', letterSpacing: 1, marginBottom: 10, display:'flex', alignItems:'center', gap:6 }}>
            <Icon name="sparkle" size={12} color={RZ.mauve}/> Pattern détecté
          </div>
          <div style={{ fontSize: 14, color: RZ.fg1, lineHeight: 1.6 }}>
            Tes matins de semaine portent souvent une <b>Harmonie</b>. En milieu de semaine, je remarque plus de tension — peut-être la charge qui s'accumule.
          </div>
        </Glass>

        <div style={{ marginTop: 18 }}>
          <div style={{ fontSize: 12, fontWeight: 500, color: RZ.fg3, textTransform: 'uppercase', letterSpacing: 0.8, marginBottom: 10 }}>Distribution</div>
          <Glass style={{ padding: 14 }}>
            {[
              ['resonance', 3], ['equilibre', 1], ['tension', 2], ['dissonance', 1], ['alerte', 0],
            ].map(([k, n]) => {
              const meta = STATE_META[k];
              return (
                <div key={k} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '6px 0' }}>
                  <div style={{ width: 8, height: 8, borderRadius: '50%', background: meta.color }}/>
                  <div style={{ flex: 1, fontSize: 12, color: RZ.fg1 }}>{meta.label}</div>
                  <div style={{ display: 'flex', gap: 3 }}>
                    {[...Array(7)].map((_, i) => <div key={i} style={{ width: 6, height: 6, borderRadius: 2, background: i < n ? meta.color : 'rgba(24,20,15,0.06)' }}/>)}
                  </div>
                </div>
              );
            })}
          </Glass>
        </div>

        <Glass style={{ padding: 18, marginTop: 14 }}>
          <div style={{ fontSize: 10, fontWeight: 600, color: RZ.fg3, textTransform: 'uppercase', letterSpacing: 1, marginBottom: 8 }}>Une question pour toi</div>
          <div style={{ fontSize: 14, color: RZ.fg1, lineHeight: 1.55, fontStyle: 'italic', marginBottom: 12 }}>
            « Qu'est-ce qui, cette semaine, t'a fait sentir le plus vivant·e ? »
          </div>
          <div onClick={() => go('S6_Selector')} style={{ display:'inline-flex', alignItems:'center', gap:8, padding:'10px 16px', background:'rgba(255,255,255,0.6)', border:'1px solid rgba(24,20,15,0.10)', borderRadius:20, cursor:'pointer' }}>
            <Icon name="mic" size={14}/><span style={{ fontSize: 13, fontWeight: 500 }}>Répondre</span>
          </div>
        </Glass>
      </div>
    </Screen>
  );
}

function EchoCluster({ selected, setSelected }) {
  // 2D space: x = body dominance, y = mind dominance. Proximity to center = alignment.
  const W = 335, H = 280;
  return (
    <Glass style={{ padding: 16, position: 'relative', overflow: 'hidden' }}>
      <div style={{ position: 'relative', width: '100%', height: H }}>
        {/* axes */}
        <div style={{ position:'absolute', left:'50%', top:10, bottom:10, width:1, background:'rgba(24,20,15,0.05)' }}/>
        <div style={{ position:'absolute', top:'50%', left:10, right:10, height:1, background:'rgba(24,20,15,0.05)' }}/>
        {/* labels */}
        <div style={{ position:'absolute', top:4, left:'50%', transform:'translateX(-50%)', fontSize:9, color:RZ.fg3, textTransform:'uppercase', letterSpacing:0.8 }}>Esprit</div>
        <div style={{ position:'absolute', bottom:4, left:'50%', transform:'translateX(-50%)', fontSize:9, color:RZ.fg3, textTransform:'uppercase', letterSpacing:0.8 }}>Corps</div>
        <div style={{ position:'absolute', left:4, top:'50%', transform:'translateY(-50%) rotate(-90deg)', transformOrigin:'left', fontSize:9, color:RZ.fg3, textTransform:'uppercase', letterSpacing:0.8 }}>Intensité</div>
        {/* center resonance zone */}
        <div style={{ position:'absolute', left:'50%', top:'50%', transform:'translate(-50%,-50%)', width:120, height:120, borderRadius:'50%', border:`1px dashed ${RZ.mauve}40`, opacity:0.5 }}/>

        {/* points */}
        {ECHO_POINTS.map((p, i) => {
          const meta = STATE_META[p.state];
          const size = selected === i ? 48 : 34;
          return (
            <div key={i} onClick={() => setSelected(i === selected ? null : i)} style={{
              position: 'absolute',
              left: `calc(${p.x * 100}% - ${size/2}px)`,
              top: `calc(${p.y * 100}% - ${size/2}px)`,
              width: size, height: size,
              cursor: 'pointer',
              transition: 'all 300ms ease',
            }}>
              <div style={{
                width: '100%', height: '100%', borderRadius: '50%',
                background: `radial-gradient(circle at 35% 30%, ${meta.color}ee 0%, ${meta.color}60 60%, ${meta.color}20 100%)`,
                boxShadow: `0 4px 16px -4px ${meta.color}60, inset 0 0 12px rgba(255,255,255,0.3)`,
                filter: selected === i ? 'none' : 'blur(0.4px)',
              }}/>
              <div style={{ position:'absolute', bottom:-14, left:'50%', transform:'translateX(-50%)', fontSize:9, fontWeight:600, color:RZ.fg2, letterSpacing:0.4 }}>{p.day}</div>
            </div>
          );
        })}
      </div>

      {selected !== null && (
        <div style={{ marginTop: 20, padding: '12px 14px', background: 'rgba(255,255,255,0.7)', borderRadius: 12, display: 'flex', alignItems: 'center', gap: 12, animation: 'rz-slide-up 280ms ease-out' }}>
          <StateBadge state={ECHO_POINTS[selected].state}/>
          <div style={{ fontSize: 12, color: RZ.fg2, flex: 1 }}>{ECHO_POINTS[selected].day}. Une séance de course — corps et esprit {ECHO_POINTS[selected].state === 'resonance' ? 'alignés' : 'en dialogue'}.</div>
        </div>
      )}
    </Glass>
  );
}

function EchoTimeline({ selected, setSelected }) {
  return (
    <Glass style={{ padding: 16, paddingTop: 24, paddingBottom: 24 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', position: 'relative' }}>
        <div style={{ position: 'absolute', left: 14, right: 14, top: 18, height: 1, background: 'rgba(24,20,15,0.08)' }}/>
        {ECHO_POINTS.map((p, i) => {
          const meta = STATE_META[p.state];
          return (
            <div key={i} onClick={() => setSelected(i === selected ? null : i)} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 10, cursor: 'pointer', zIndex: 1 }}>
              <div style={{ width: selected === i ? 22 : 14, height: selected === i ? 22 : 14, borderRadius: '50%', background: `radial-gradient(circle at 35% 30%, ${meta.color}ee, ${meta.color}60)`, boxShadow: `0 2px 8px -2px ${meta.color}70`, transition: 'all 200ms' }}/>
              <div style={{ fontSize: 9, color: RZ.fg3, letterSpacing: 0.4 }}>{p.day}</div>
            </div>
          );
        })}
      </div>
    </Glass>
  );
}

function EchoRibbon() {
  // Orange + Blue paths weaving
  return (
    <Glass style={{ padding: 16 }}>
      <svg viewBox="0 0 300 160" style={{ width: '100%', height: 160 }}>
        <defs>
          <linearGradient id="og" x1="0" x2="1"><stop offset="0" stopColor={RZ.orange} stopOpacity="0.2"/><stop offset="0.5" stopColor={RZ.orange}/><stop offset="1" stopColor={RZ.orange} stopOpacity="0.2"/></linearGradient>
          <linearGradient id="bg" x1="0" x2="1"><stop offset="0" stopColor={RZ.blue} stopOpacity="0.2"/><stop offset="0.5" stopColor={RZ.blue}/><stop offset="1" stopColor={RZ.blue} stopOpacity="0.2"/></linearGradient>
        </defs>
        <path d="M10 90 C 60 40, 90 120, 150 80 S 240 60, 290 90" stroke="url(#og)" strokeWidth="4" fill="none" strokeLinecap="round"/>
        <path d="M10 70 C 60 110, 90 40, 150 80 S 240 110, 290 70" stroke="url(#bg)" strokeWidth="4" fill="none" strokeLinecap="round"/>
        {['Lun','Mar','Mer','Jeu','Ven','Sam','Dim'].map((d, i) => (
          <text key={d} x={10 + i * 47} y={150} fontSize="9" fill={RZ.fg3} textAnchor="middle" fontFamily="Inter">{d}</text>
        ))}
      </svg>
    </Glass>
  );
}

// ═════════════════════════════════════════════════════════════
// S15 — Settings
// ═════════════════════════════════════════════════════════════
function S15_Settings({ go }) {
  return (
    <Screen intent="settings" tabBar={<TabBar active="journal" onChange={id => go(id === 'journal' ? 'S5_Journal' : id === 'nuance' ? 'S6_Selector' : 'S13_Echo')}/>}>
      <TopBar onBack={() => go('S5_Journal')} title="Paramètres"/>
      <div style={{ padding: '0 16px 120px' }}>
        <div style={{ textAlign: 'center', padding: '12px 0 24px' }}>
          <div style={{ width: 72, height: 72, margin: '0 auto 12px' }}><NuanceViz state="resonance" size={72}/></div>
          <div style={{ fontSize: 16, fontWeight: 600, color: RZ.fg1 }}>Nayoul</div>
          <div style={{ fontSize: 11, color: RZ.fg3 }}>Membre depuis avril 2026</div>
        </div>

        <SettingsSection title="Mon profil">
          <Row label="Sports" value="Course, Vélo, Trail"/>
          <Row label="Volume" value="3 – 5 h / semaine"/>
          <Row label="Objectif" value="Bien-être"/>
        </SettingsSection>

        <SettingsSection title="Connexions">
          <Row label="Strava" value={<span style={{ color: RZ.mauve, display: 'inline-flex', gap: 4, alignItems: 'center' }}><span style={{ width:6, height:6, borderRadius:'50%', background:RZ.mauve }}/> Connecté</span>} onClick={() => go('S4_Strava', { from: 'settings' })}/>
        </SettingsSection>

        <SettingsSection title="Notifications">
          <Toggle label="Activités détectées" on/>
          <Toggle label="Inactivité (3 jours)" on/>
          <Toggle label="Résumé hebdomadaire" on={false}/>
          <Row label="Plage horaire" value="8h – 22h"/>
        </SettingsSection>

        <SettingsSection title="Confidentialité">
          <div style={{ padding: '12px 16px', fontSize: 12, color: RZ.fg2, lineHeight: 1.55 }}>
            Tes données sont stockées en privé. Résonance ne partage rien avec Strava ni qui que ce soit.
          </div>
          <Row label="Exporter mes données" chev/>
          <Row label={<span style={{ color: RZ.orange }}>Supprimer mes données</span>} chev={false}/>
        </SettingsSection>

        <div style={{ textAlign: 'center', fontSize: 11, color: RZ.fg3, marginTop: 20 }}>Résonance · v0.1.0 (beta)</div>
      </div>
    </Screen>
  );
}

function SettingsSection({ title, children }) {
  return (
    <div style={{ marginBottom: 20 }}>
      <div style={{ fontSize: 10, fontWeight: 600, color: RZ.fg3, textTransform: 'uppercase', letterSpacing: 1, padding: '0 16px 8px' }}>{title}</div>
      <Glass style={{ padding: 0, overflow: 'hidden' }}>
        {children}
      </Glass>
    </div>
  );
}
function Row({ label, value, chev = true, onClick }) {
  return (
    <div onClick={onClick} style={{ display: 'flex', alignItems: 'center', padding: '12px 16px', borderBottom: '1px solid rgba(24,20,15,0.05)', cursor: onClick ? 'pointer' : 'default' }}>
      <div style={{ flex: 1, fontSize: 14, color: RZ.fg1 }}>{label}</div>
      {value && <div style={{ fontSize: 13, color: RZ.fg2, marginRight: chev ? 8 : 0 }}>{value}</div>}
      {chev && <Icon name="chev" size={14} color={RZ.fg3}/>}
    </div>
  );
}
function Toggle({ label, on }) {
  const [v, setV] = uSt(on);
  return (
    <div onClick={() => setV(!v)} style={{ display: 'flex', alignItems: 'center', padding: '12px 16px', borderBottom: '1px solid rgba(24,20,15,0.05)', cursor: 'pointer' }}>
      <div style={{ flex: 1, fontSize: 14, color: RZ.fg1 }}>{label}</div>
      <div style={{ width: 42, height: 24, borderRadius: 12, background: v ? RZ.mauve : 'rgba(24,20,15,0.12)', position: 'relative', transition: 'background 200ms' }}>
        <div style={{ position: 'absolute', top: 2, left: v ? 20 : 2, width: 20, height: 20, borderRadius: '50%', background: '#fff', transition: 'left 200ms', boxShadow: '0 2px 4px rgba(0,0,0,0.15)' }}/>
      </div>
    </div>
  );
}

// ═════════════════════════════════════════════════════════════
// Empty + Error states
// ═════════════════════════════════════════════════════════════
function EV2_EchoEmpty({ go }) {
  return (
    <Screen intent="echo" tabBar={<TabBar active="echo" onChange={id => go(id === 'journal' ? 'S5_Journal' : id === 'nuance' ? 'S6_Selector' : 'S13_Echo')}/>}>
      <TopBar/>
      <div style={{ padding: '0 24px', textAlign: 'center', display: 'flex', flexDirection: 'column', alignItems: 'center', height: 'calc(100% - 100px)', justifyContent: 'center' }}>
        <div style={{ margin: '0 auto 24px' }}><NuanceViz state="equilibre" size={160}/></div>
        <div style={{ fontSize: 20, fontWeight: 700, color: RZ.fg1, letterSpacing: -0.3, marginBottom: 10 }}>Les patterns arrivent<br/>avec le temps.</div>
        <div style={{ fontSize: 13, color: RZ.fg2, lineHeight: 1.55, marginBottom: 20, maxWidth: 280 }}>
          Tu as 2 nuances pour l'instant — il m'en faut encore quelques-unes pour commencer à détecter ce qui résonne pour toi.
        </div>
        <div style={{ display: 'flex', gap: 6, marginBottom: 28 }}>
          {[1,1,0,0,0].map((v,i) => <div key={i} style={{ width: 10, height: 10, borderRadius:'50%', background: v ? RZ.mauve : 'rgba(138,91,149,0.18)' }}/>)}
        </div>
        <PrimaryBtn onClick={() => go('S6_Selector')} style={{ maxWidth: 260 }}>
          <span style={{ display:'inline-flex', alignItems:'center', gap:8 }}><Icon name="mic" size={16} color={RZ.white}/> Déposer une nuance</span>
        </PrimaryBtn>
      </div>
    </Screen>
  );
}

function ER1_MicDenied({ go }) {
  return (
    <Screen intent="error">
      <TopBar onBack={() => go('S6_Selector')}/>
      <div style={{ padding: '20px 24px', textAlign: 'center', height: 'calc(100% - 80px)', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
        <div style={{ width: 72, height: 72, borderRadius: 20, background: 'rgba(252,68,44,0.14)', display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 24 }}>
          <Icon name="mic" size={32} color={RZ.orange}/>
        </div>
        <div style={{ fontSize: 20, fontWeight: 700, color: RZ.fg1, letterSpacing: -0.3, marginBottom: 10 }}>J'ai besoin<br/>de ton microphone</div>
        <div style={{ fontSize: 14, color: RZ.fg2, lineHeight: 1.55, marginBottom: 28, maxWidth: 280 }}>
          Pour t'écouter, va dans Réglages → Résonance → Microphone.
        </div>
        <PrimaryBtn onClick={() => go('S6_Selector')} style={{ maxWidth: 260 }}>Ouvrir les réglages</PrimaryBtn>
        <GhostBtn onClick={() => go('S6_Selector')} style={{ marginTop: 6 }}>Annuler</GhostBtn>
      </div>
    </Screen>
  );
}

function ER2_Timeout({ go }) {
  return (
    <Screen intent="error">
      <TopBar onBack={() => go('S7_Record')}/>
      <div style={{ padding: '20px 24px', textAlign: 'center', height: 'calc(100% - 80px)', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
        <div style={{ width: 72, height: 72, borderRadius: 20, background: 'rgba(24,20,15,0.06)', display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 24 }}>
          <Icon name="wifi" size={32} color={RZ.fg2}/>
        </div>
        <div style={{ fontSize: 20, fontWeight: 700, color: RZ.fg1, letterSpacing: -0.3, marginBottom: 10 }}>La connexion<br/>a pris trop de temps.</div>
        <div style={{ fontSize: 14, color: RZ.fg2, lineHeight: 1.55, marginBottom: 28, maxWidth: 280 }}>
          Ton audio est en sécurité. Veux-tu que je relance l'analyse ?
        </div>
        <PrimaryBtn onClick={() => go('S8_Analyze')} style={{ maxWidth: 260 }}>Réessayer</PrimaryBtn>
        <GhostBtn onClick={() => go('S5_Journal')} style={{ marginTop: 6 }}>Sauvegarder sans analyse</GhostBtn>
      </div>
    </Screen>
  );
}

// ═════════════════════════════════════════════════════════════
// S14 — Detail overlay (bottom sheet) — inline in Écho, but also a route
// ═════════════════════════════════════════════════════════════
function S14_EchoDetail({ go, ctx }) {
  const state = ctx?.state || 'resonance';
  const m = STATE_META[state];
  return (
    <Screen intent={m.tag}>
      <TopBar onBack={() => go('S13_Echo')}/>
      <div style={{ padding: '40px 24px', textAlign: 'center' }}>
        <div style={{ margin: '0 auto 20px' }}><NuanceViz state={state} size={180}/></div>
        <StateBadge state={state} size="lg"/>
        <div style={{ fontSize: 12, color: RZ.fg3, marginTop: 8, marginBottom: 20 }}>Mercredi · 10 km de course</div>
        <Glass style={{ padding: 16, textAlign: 'left' }}>
          <div style={{ fontSize: 14, color: RZ.fg1, lineHeight: 1.6 }}>
            Tu me disais que les jambes étaient lourdes dès l'échauffement, et pourtant les chiffres disent « rythme tenu ».
          </div>
          <div onClick={() => go('S12_Detail', { session: MOCK_SESSIONS[1] })} style={{ marginTop: 14, fontSize: 13, fontWeight: 500, color: RZ.fg1, display: 'inline-flex', alignItems: 'center', gap: 6, cursor: 'pointer' }}>
            Voir le détail <Icon name="arrowRight" size={14}/>
          </div>
        </Glass>
      </div>
    </Screen>
  );
}

Object.assign(window, { S12_Detail, S13_Echo, S14_EchoDetail, S15_Settings, EV2_EchoEmpty, ER1_MicDenied, ER2_Timeout });
