// modals.jsx — Sheet, sélecteur repas, détail repas, Hermès, scan, poids
const { useState: useM, useEffect: useME } = React;

function Sheet({ t, onClose, children, full = false, label }) {
  return (
    <div style={{ position: 'absolute', inset: 0, zIndex: 80, display: 'flex', flexDirection: 'column', justifyContent: 'flex-end' }}>
      <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: 'oklch(0 0 0 / 0.5)',
        backdropFilter: 'blur(2px)', animation: 'fadeIn .25s ease' }} />
      <div style={{ position: 'relative', background: t.bg, borderRadius: full ? 0 : '26px 26px 0 0',
        height: full ? '100%' : 'auto', maxHeight: full ? '100%' : '86%', display: 'flex', flexDirection: 'column',
        boxShadow: '0 -10px 40px oklch(0 0 0 / 0.3)', animation: 'sheetUp .34s cubic-bezier(.2,.7,.2,1)' }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: full ? '52px 18px 8px' : '14px 18px 8px', flexShrink: 0 }}>
          {!full && <div style={{ position: 'absolute', top: 9, left: '50%', transform: 'translateX(-50%)', width: 38, height: 4, borderRadius: 99, background: t.border }} />}
          <span style={{ fontWeight: 700, fontSize: 16, color: t.text }}>{label}</span>
          <button onClick={onClose} style={{ width: 32, height: 32, borderRadius: 99, border: 'none', cursor: 'pointer',
            background: t.surfaceAlt, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <Icon name="close" size={17} color={t.textMuted} sw={2.2} />
          </button>
        </div>
        <div style={{ overflowY: 'auto', padding: '8px 18px 28px', flex: full ? 1 : 'initial' }}>{children}</div>
      </div>
    </div>
  );
}

// ── Sélecteur de repas pour un créneau ────────────────────────
function MealPicker({ t, slotId, onChoose, onClose }) {
  const slot = MEAL_SLOTS.find(s => s.id === slotId);
  const list = MEALS.filter(m => m.type === slotId);
  const pool = list.length ? list : MEALS;
  return (
    <Sheet t={t} onClose={onClose} label={`Choisir — ${slot.label}`}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {pool.map(meal => (
          <button key={meal.id} onClick={() => onChoose(slotId, meal.id)} style={{
            display: 'flex', gap: 12, alignItems: 'center', padding: 12, borderRadius: 16, cursor: 'pointer',
            background: t.surface, border: `1px solid ${t.borderSoft}`, fontFamily: 'inherit', textAlign: 'left' }}>
            <MealTile meal={meal} t={t} />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 14.5, fontWeight: 700, color: t.text, marginBottom: 3 }}>{meal.name}</div>
              <div style={{ fontSize: 12.5, color: t.textMuted }}>
                <b style={{ color: t.green, fontFamily: 'Space Grotesk, sans-serif' }}>{meal.kcal}</b> kcal · <b style={{ color: t.orange, fontFamily: 'Space Grotesk, sans-serif' }}>{meal.prot}g</b> prot.
              </div>
            </div>
            <Icon name="plus" size={20} color={t.green} sw={2.2} />
          </button>
        ))}
      </div>
    </Sheet>
  );
}

// ── Détail repas (recette) ────────────────────────────────────
function MealDetail({ t, meal, onClose }) {
  const macros = [['Calories', meal.kcal, 'kcal', t.green], ['Protéines', meal.prot, 'g', t.orange], ['Glucides', meal.gluc, 'g', t.blue], ['Lipides', meal.lip, 'g', t.amber]];
  return (
    <Sheet t={t} onClose={onClose} label="Recette">
      <div style={{ display: 'flex', gap: 14, alignItems: 'center', marginBottom: 18 }}>
        <MealImage meal={meal} t={t} size={70} radius={18} />
        <h2 style={{ margin: 0, fontSize: 21, fontWeight: 700, color: t.text, letterSpacing: -0.4, lineHeight: 1.2 }}>{meal.name}</h2>
      </div>

      <div style={{ display: 'flex', gap: 8, marginBottom: 20 }}>
        {macros.map(([l, v, u, c]) => (
          <div key={l} style={{ flex: 1, textAlign: 'center', padding: '12px 4px', borderRadius: 14, background: t.surface, border: `1px solid ${t.borderSoft}` }}>
            <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontWeight: 700, fontSize: 18, color: c }}>{v}</div>
            <div style={{ fontSize: 10.5, color: t.textFaint, fontWeight: 600 }}>{l}</div>
          </div>
        ))}
      </div>

      <div style={{ fontSize: 12.5, fontWeight: 700, color: t.textMuted, textTransform: 'uppercase', letterSpacing: 0.3, marginBottom: 10 }}>Ingrédients</div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 1, marginBottom: 22, background: t.surface, borderRadius: 16, overflow: 'hidden', border: `1px solid ${t.borderSoft}` }}>
        {meal.ing.map((ing, i) => (
          <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '11px 14px', borderTop: i ? `1px solid ${t.borderSoft}` : 'none' }}>
            <div style={{ width: 6, height: 6, borderRadius: 99, background: t[meal.tint] }} />
            <span style={{ fontSize: 14, color: t.text }}>{ing}</span>
          </div>
        ))}
      </div>

      <div style={{ fontSize: 12.5, fontWeight: 700, color: t.textMuted, textTransform: 'uppercase', letterSpacing: 0.3, marginBottom: 10 }}>Préparation</div>
      <p style={{ margin: 0, fontSize: 14, color: t.textMuted, lineHeight: 1.6 }}>{meal.recipe}</p>

      <div style={{ display: 'flex', alignItems: 'center', gap: 7, marginTop: 18, padding: '10px 14px', borderRadius: 12,
        background: `color-mix(in srgb, ${t.green} 12%, ${t.surface})`, color: t.green, fontSize: 12.5, fontWeight: 600 }}>
        <Icon name="check" size={16} color={t.green} sw={2.4} /> Zéro sucre ajouté
      </div>
    </Sheet>
  );
}

// ── Saisie poids ──────────────────────────────────────────────
function WeightModal({ t, onClose, current = 104, onSave }) {
  const [w, setW] = useM(current);
  return (
    <Sheet t={t} onClose={onClose} label="Saisir mon poids">
      <div style={{ textAlign: 'center', padding: '14px 0 6px' }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 22 }}>
          <button onClick={() => setW(v => +(v - 0.1).toFixed(1))} style={stepBtn(t)}><Icon name="minus" size={22} color={t.text} sw={2.4} /></button>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 5 }}>
            <span style={{ fontFamily: 'Space Grotesk, sans-serif', fontWeight: 700, fontSize: 52, color: t.text, letterSpacing: -1.5 }}>{w.toFixed(1).replace('.', ',')}</span>
            <span style={{ fontSize: 18, color: t.textMuted, fontWeight: 600 }}>kg</span>
          </div>
          <button onClick={() => setW(v => +(v + 0.1).toFixed(1))} style={stepBtn(t)}><Icon name="plus" size={22} color={t.text} sw={2.4} /></button>
        </div>
        <div style={{ fontSize: 13, color: t.textFaint, marginTop: 10 }}>Dernière saisie : {current.toFixed(1).replace('.', ',')} kg</div>
      </div>
      <button onClick={() => onSave && onSave(+w.toFixed(1))} style={primaryBtn(t)}>Enregistrer</button>
    </Sheet>
  );
}

const stepBtn = (t) => ({ width: 52, height: 52, borderRadius: 99, border: `1px solid ${t.border}`, background: t.surface,
  cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' });
const primaryBtn = (t) => ({ width: '100%', marginTop: 22, padding: '15px', borderRadius: 16, border: 'none', cursor: 'pointer',
  background: t.green, color: t.onAccent, fontWeight: 700, fontSize: 15.5, fontFamily: 'inherit', whiteSpace: 'nowrap' });

// ── Scan produit ──────────────────────────────────────────────
function ScanModal({ t, onClose }) {
  const [step, setStep] = useM('input'); // input | scanning | loading | result | error
  const [manual, setManual] = useM('');
  const [product, setProduct] = useM(null);
  const [errMsg, setErrMsg] = useM('');
  const videoRef = React.useRef(null);
  const controlsRef = React.useRef(null); // contrôleur ZXing (a une méthode .stop())

  const lookup = async (barcode) => {
    setStep('loading');
    try {
      const data = await window.FuelFitAPI.scanBarcode(barcode);
      setProduct(data);
      setStep('result');
    } catch (err) {
      setErrMsg(err.message || 'Produit introuvable.');
      setStep('error');
    }
  };

  const stopCam = () => {
    if (controlsRef.current) { try { controlsRef.current.stop(); } catch (e) {} controlsRef.current = null; }
  };

  // Attend que la balise <video> soit montée après le passage en mode 'scanning'.
  const waitForVideo = () => new Promise((resolve, reject) => {
    let tries = 0;
    const check = () => {
      if (videoRef.current) return resolve(videoRef.current);
      if (++tries > 60) return reject(new Error('video timeout'));
      requestAnimationFrame(check);
    };
    check();
  });

  const startScan = async () => {
    // ZXing décode en JS → fonctionne sur iPhone/Safari (contrairement à BarcodeDetector natif).
    if (!(window.ZXingBrowser && window.ZXingBrowser.BrowserMultiFormatReader)) {
      setErrMsg('Lecteur de code-barres indisponible. Saisis le code à la main.');
      setStep('error');
      return;
    }
    setStep('scanning');
    try {
      const videoEl = await waitForVideo();
      const reader = new window.ZXingBrowser.BrowserMultiFormatReader();
      // decodeFromVideoDevice(null) = caméra par défaut (arrière sur mobile). Callback à chaque frame décodée.
      controlsRef.current = await reader.decodeFromVideoDevice(undefined, videoEl, (result, err, controls) => {
        if (result) {
          const code = result.getText();
          stopCam();
          if (/^[0-9]{8,14}$/.test(code)) lookup(code);
        }
      });
    } catch (e) {
      stopCam();
      setErrMsg('Accès caméra refusé ou indisponible. Tu peux saisir le code à la main.');
      setStep('error');
    }
  };

  React.useEffect(() => () => stopCam(), []);

  const ok = product && product.verdict === 'ok';
  const vc = ok ? t.green : t.red;
  const p100 = product && product.per100g;

  return (
    <Sheet t={t} onClose={() => { stopCam(); onClose(); }} label="Scanner un produit">
      {step === 'input' && (
        <div>
          <button onClick={startScan} style={{ ...primaryBtn(t), marginTop: 0, marginBottom: 16,
            display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 9 }}>
            <Icon name="scan" size={20} color={t.onAccent} /> Scanner avec la caméra
          </button>
          <div style={{ textAlign: 'center', fontSize: 12.5, color: t.textFaint, margin: '4px 0 14px' }}>ou saisis le code-barres</div>
          <div style={{ display: 'flex', gap: 8 }}>
            <input value={manual} onChange={e => setManual(e.target.value.replace(/\D/g, ''))}
              inputMode="numeric" placeholder="3017620422003"
              style={{ flex: 1, padding: '13px 14px', borderRadius: 14, background: t.surface,
                border: `1px solid ${t.border}`, color: t.text, fontFamily: 'inherit', fontSize: 15, outline: 'none', boxSizing: 'border-box' }} />
            <button onClick={() => manual.length >= 8 && lookup(manual)} style={{ padding: '0 18px', borderRadius: 14, border: 'none',
              background: t.green, color: t.onAccent, fontWeight: 700, fontSize: 14.5, cursor: 'pointer', fontFamily: 'inherit' }}>OK</button>
          </div>
        </div>
      )}

      {step === 'scanning' && (
        <div>
          <div style={{ position: 'relative', height: 240, borderRadius: 18, overflow: 'hidden', marginBottom: 16, background: '#000', border: `1px solid ${t.borderSoft}` }}>
            <video ref={videoRef} playsInline muted style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
            <div style={{ position: 'absolute', inset: '50% 12% auto', height: 2, background: t.green, boxShadow: `0 0 12px ${t.green}` }} />
          </div>
          <div style={{ textAlign: 'center', fontSize: 13, color: t.textMuted }}>Vise le code-barres du produit…</div>
          <button onClick={() => { stopCam(); setStep('input'); }} style={{ width: '100%', marginTop: 14, padding: 12, borderRadius: 14,
            border: `1px solid ${t.border}`, background: t.surface, color: t.textMuted, fontWeight: 600, fontSize: 14, cursor: 'pointer', fontFamily: 'inherit' }}>Annuler</button>
        </div>
      )}

      {step === 'loading' && (
        <div style={{ height: 220, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 16 }}>
          <div style={{ width: 56, height: 56, borderRadius: 99, border: `3px solid ${t.ringTrack}`, borderTopColor: t.green, animation: 'spin 0.9s linear infinite' }} />
          <div style={{ fontSize: 14, color: t.textMuted }}>Recherche du produit…</div>
        </div>
      )}

      {step === 'result' && product && (
        <div>
          {product.imageUrl && (
            <div style={{ height: 150, borderRadius: 18, overflow: 'hidden', marginBottom: 16, background: t.surfaceAlt, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <img src={product.imageUrl} alt={product.name} style={{ maxHeight: '100%', maxWidth: '100%', objectFit: 'contain' }} />
            </div>
          )}
          <div style={{ marginBottom: 16 }}>
            {product.brand && <div style={{ fontSize: 12, color: t.textFaint, fontWeight: 600 }}>{product.brand}</div>}
            <div style={{ fontSize: 19, fontWeight: 700, color: t.text }}>{product.name}</div>
          </div>

          <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '13px 15px', borderRadius: 14, marginBottom: 16,
            background: `color-mix(in srgb, ${vc} 14%, ${t.surface})`, border: `1px solid color-mix(in srgb, ${vc} 35%, ${t.surface})` }}>
            <Icon name={ok ? 'check' : 'info'} size={22} color={vc} sw={2.4} fill={!ok} />
            <div>
              <div style={{ fontWeight: 700, fontSize: 14, color: vc }}>{ok ? '✅ Aucun sucre ajouté' : '⚠️ Contient du sucre ajouté'}</div>
              <div style={{ fontSize: 12.5, color: t.textMuted, lineHeight: 1.4 }}>
                {ok ? 'Bon choix pour ton objectif.' : `Détecté : ${(product.detectedSugars || []).join(', ') || 'sucre'}. Repose-le si possible.`}
              </div>
            </div>
          </div>

          {p100 && (
            <>
              <div style={{ fontSize: 11.5, color: t.textFaint, fontWeight: 600, marginBottom: 8 }}>Pour 100 g / ml</div>
              <div style={{ display: 'flex', gap: 8, marginBottom: 20 }}>
                {[['Calories', p100.calories, t.green], ['Protéines', p100.protein, t.orange], ['Sucres', p100.sugars, t.red], ['Lipides', p100.fat, t.amber]].map(([l, v, c]) => (
                  <div key={l} style={{ flex: 1, textAlign: 'center', padding: '12px 4px', borderRadius: 14, background: t.surface, border: `1px solid ${t.borderSoft}` }}>
                    <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontWeight: 700, fontSize: 17, color: c }}>{v}</div>
                    <div style={{ fontSize: 10, color: t.textFaint, fontWeight: 600 }}>{l}</div>
                  </div>
                ))}
              </div>
            </>
          )}

          <button onClick={() => { setProduct(null); setManual(''); setStep('input'); }} style={{ ...primaryBtn(t), marginTop: 0, background: t.surfaceAlt, color: t.text,
            display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8 }}>
            <Icon name="scan" size={19} color={t.text} /> Scanner un autre produit
          </button>
        </div>
      )}

      {step === 'error' && (
        <div style={{ minHeight: 200, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 16, textAlign: 'center', padding: '20px 10px' }}>
          <div style={{ width: 52, height: 52, borderRadius: 99, background: `color-mix(in srgb, ${t.red} 16%, ${t.surface})`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <Icon name="info" size={24} color={t.red} />
          </div>
          <div style={{ fontSize: 13.5, color: t.textMuted, lineHeight: 1.5, maxWidth: 270 }}>{errMsg}</div>
          <button onClick={() => setStep('input')} style={{ ...primaryBtn(t), marginTop: 0, width: 'auto', padding: '12px 24px' }}>Retour</button>
        </div>
      )}
    </Sheet>
  );
}

// ── HERMÈS — analyse IA de l'assiette (photo réelle → backend) ─
function normalizeHermes(data) {
  return {
    foods: Array.isArray(data.foods) ? data.foods.map(f => typeof f === 'string' ? f : f.name).slice(0, 5) : [],
    kcal: Math.round(+data.calories) || 0,
    prot: Math.round(+data.protein) || 0,
    gluc: Math.round(+data.carbs) || 0,
    lip: Math.round(+data.fat) || 0,
    verdict: data.verdict === 'aligne' ? 'ok' : 'warn',
    rawVerdict: data.verdict || 'attention',
    containsAddedSugar: !!data.containsAddedSugar,
    advice: String(data.advice || ''),
  };
}

function HermesModal({ t, targets, onClose, onAdd }) {
  const tg = targets || TARGETS;
  const [step, setStep] = useM('capture'); // capture | analyzing | result | error
  const [grams, setGrams] = useM(350);
  const [photo, setPhoto] = useM(null);
  const [res, setRes] = useM(null);
  const [errMsg, setErrMsg] = useM('');
  const fileRef = React.useRef(null);

  const onPickPhoto = async (e) => {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    const { base64, mediaType } = await window.FuelFitAPI.fileToBase64(file);
    setPhoto({ base64, mediaType, previewUrl: URL.createObjectURL(file) });
  };

  const analyze = async () => {
    if (!photo) { fileRef.current && fileRef.current.click(); return; }
    setStep('analyzing');
    try {
      const data = await window.FuelFitAPI.analyzeMeal(photo.base64, photo.mediaType, grams);
      setRes(normalizeHermes(data));
      setStep('result');
    } catch (err) {
      setErrMsg(err.message || 'Analyse impossible.');
      setStep('error');
    }
  };

  const ok = res ? res.verdict === 'ok' : true;
  const vc = ok ? t.green : t.red;

  return (
    <Sheet t={t} onClose={onClose} full label={<span style={{ display: 'flex', alignItems: 'center', gap: 8, whiteSpace: 'nowrap' }}><Icon name="spark" size={20} color={t.green} fill /> Hermès · Coach IA</span>}>
      {step === 'capture' && (
        <div>
          <input ref={fileRef} type="file" accept="image/*" capture="environment"
            onChange={onPickPhoto} style={{ display: 'none' }} />

          <button onClick={() => fileRef.current && fileRef.current.click()} style={{
            position: 'relative', width: '100%', height: 200, borderRadius: 22, overflow: 'hidden', marginBottom: 16,
            border: photo ? `1px solid ${t.borderSoft}` : `1.5px dashed ${t.border}`, cursor: 'pointer', padding: 0,
            background: photo ? '#000' : `repeating-linear-gradient(45deg, ${t.surfaceAlt}, ${t.surfaceAlt} 13px, ${t.surface} 13px, ${t.surface} 26px)`,
            display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 12 }}>
            {photo ? (
              <img src={photo.previewUrl} alt="assiette" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
            ) : (
              <>
                <div style={{ width: 60, height: 60, borderRadius: 99, background: t.bg, display: 'flex', alignItems: 'center', justifyContent: 'center', boxShadow: t.shadow }}>
                  <Icon name="camera" size={28} color={t.green} />
                </div>
                <div style={{ fontSize: 13, color: t.textMuted, fontWeight: 600 }}>Prendre ou choisir une photo</div>
              </>
            )}
          </button>
          {photo && (
            <button onClick={() => fileRef.current && fileRef.current.click()} style={{
              width: '100%', marginBottom: 18, padding: 10, borderRadius: 12, border: `1px solid ${t.border}`,
              background: t.surface, color: t.textMuted, fontWeight: 600, fontSize: 13, cursor: 'pointer', fontFamily: 'inherit' }}>
              Reprendre la photo
            </button>
          )}

          <div style={{ fontSize: 13, fontWeight: 700, color: t.textMuted, textTransform: 'uppercase', letterSpacing: 0.3, marginBottom: 10 }}>Poids de l’assiette</div>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 20, marginBottom: 22 }}>
            <button onClick={() => setGrams(g => Math.max(50, g - 50))} style={stepBtn(t)}><Icon name="minus" size={22} color={t.text} sw={2.4} /></button>
            <div style={{ display: 'flex', alignItems: 'baseline', gap: 5 }}>
              <span style={{ fontFamily: 'Space Grotesk, sans-serif', fontWeight: 700, fontSize: 44, color: t.text, letterSpacing: -1 }}>{grams}</span>
              <span style={{ fontSize: 18, color: t.textMuted, fontWeight: 600 }}>g</span>
            </div>
            <button onClick={() => setGrams(g => g + 50)} style={stepBtn(t)}><Icon name="plus" size={22} color={t.text} sw={2.4} /></button>
          </div>
          <button onClick={analyze} style={{ ...primaryBtn(t), marginTop: 0,
            display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, opacity: photo ? 1 : 0.55 }}>
            <Icon name={photo ? 'spark' : 'camera'} size={19} color={t.onAccent} fill={!!photo} />
            {photo ? 'Analyser mon assiette' : 'Prends une photo d’abord'}
          </button>
        </div>
      )}

      {step === 'analyzing' && (
        <div style={{ height: 360, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 20 }}>
          <div style={{ width: 64, height: 64, borderRadius: 99, border: `3px solid ${t.ringTrack}`, borderTopColor: t.green, animation: 'spin 0.9s linear infinite' }} />
          <div style={{ fontSize: 16, fontWeight: 700, color: t.text }}>Hermès analyse ton assiette…</div>
          <div style={{ fontSize: 13, color: t.textMuted }}>Estimation des macros et du verdict</div>
        </div>
      )}

      {step === 'error' && (
        <div style={{ height: 360, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 16, textAlign: 'center', padding: '0 10px' }}>
          <div style={{ width: 56, height: 56, borderRadius: 99, background: `color-mix(in srgb, ${t.red} 16%, ${t.surface})`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <Icon name="info" size={26} color={t.red} />
          </div>
          <div style={{ fontSize: 15.5, fontWeight: 700, color: t.text }}>Analyse impossible</div>
          <div style={{ fontSize: 13, color: t.textMuted, lineHeight: 1.5, maxWidth: 260 }}>{errMsg}</div>
          <button onClick={() => setStep('capture')} style={{ ...primaryBtn(t), marginTop: 6, width: 'auto', padding: '12px 24px' }}>Réessayer</button>
        </div>
      )}

      {step === 'result' && res && (
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '14px 16px', borderRadius: 16, marginBottom: 18,
            background: `color-mix(in srgb, ${vc} 14%, ${t.surface})`, border: `1px solid color-mix(in srgb, ${vc} 35%, ${t.surface})` }}>
            <Icon name={ok ? 'check' : 'info'} size={24} color={vc} sw={2.6} fill={!ok} />
            <div>
              <div style={{ fontWeight: 700, fontSize: 15, color: vc }}>{ok ? 'Aligné avec ton objectif' : 'Attention'}</div>
              <div style={{ fontSize: 12.5, color: t.textMuted }}>{ok ? 'Repas compatible avec ta journée.' : (res.containsAddedSugar ? 'Sucre ajouté détecté.' : 'Apport à surveiller pour ton objectif.')}</div>
            </div>
          </div>

          {res.foods.length > 0 && <>
            <div style={{ fontSize: 12.5, fontWeight: 700, color: t.textMuted, textTransform: 'uppercase', letterSpacing: 0.3, marginBottom: 10 }}>Aliments détectés</div>
            <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 20 }}>
              {res.foods.map((f, i) => (
                <span key={i} style={{ padding: '8px 13px', borderRadius: 99, background: t.surface, border: `1px solid ${t.borderSoft}`, fontSize: 13, fontWeight: 600, color: t.text }}>{f}</span>
              ))}
            </div>
          </>}

          <div style={{ display: 'flex', gap: 12, marginBottom: 20 }}>
            <div style={{ flex: 1, padding: 16, borderRadius: 16, background: t.surface, border: `1px solid ${t.borderSoft}` }}>
              <div style={{ fontSize: 12, color: t.textMuted, fontWeight: 600, marginBottom: 4 }}>Calories est.</div>
              <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontWeight: 700, fontSize: 28, color: t.green }}>{res.kcal}<span style={{ fontSize: 14, color: t.textFaint, fontWeight: 500 }}> kcal</span></div>
            </div>
            <div style={{ flex: 1, padding: 16, borderRadius: 16, background: t.surface, border: `1px solid ${t.borderSoft}` }}>
              <div style={{ fontSize: 12, color: t.textMuted, fontWeight: 600, marginBottom: 4 }}>Protéines est.</div>
              <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontWeight: 700, fontSize: 28, color: t.orange }}>{res.prot}<span style={{ fontSize: 14, color: t.textFaint, fontWeight: 500 }}> g</span></div>
            </div>
          </div>

          {res.advice && (
            <div style={{ display: 'flex', gap: 11, padding: '14px 16px', borderRadius: 16, marginBottom: 22, background: t.surfaceAlt }}>
              <Icon name="spark" size={20} color={t.green} fill style={{ flexShrink: 0, marginTop: 1 }} />
              <div style={{ fontSize: 13, color: t.textMuted, lineHeight: 1.5 }}>
                <b style={{ color: t.text }}>Conseil d’Hermès :</b> {res.advice}
              </div>
            </div>
          )}

          <button onClick={() => { onAdd(res); onClose(); }} style={{ ...primaryBtn(t), marginTop: 0,
            display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8 }}>
            <Icon name="plus" size={19} color={t.onAccent} sw={2.4} /> Ajouter à ma journée
          </button>
          <button onClick={() => { setRes(null); setStep('capture'); }} style={{ width: '100%', marginTop: 10, padding: 12, borderRadius: 14, border: 'none',
            background: 'none', color: t.textMuted, fontWeight: 600, fontSize: 14, cursor: 'pointer', fontFamily: 'inherit' }}>Refaire une analyse</button>
        </div>
      )}
    </Sheet>
  );
}

// ── PROFIL / ONBOARDING — calcul auto des cibles ──────────────
function ProfileNumRow({ t, label, value, unit, step = 1, min, max, onChange }) {
  const small = (children, onClick) => (
    <button onClick={onClick} style={{ width: 38, height: 38, borderRadius: 11, border: `1px solid ${t.border}`,
      background: t.surface, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>{children}</button>
  );
  return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '11px 0', borderBottom: `1px solid ${t.borderSoft}` }}>
      <span style={{ fontSize: 14.5, color: t.text, fontWeight: 600 }}>{label}</span>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
        {small(<Icon name="minus" size={18} color={t.text} sw={2.4} />, () => onChange(Math.max(min ?? -Infinity, +(value - step).toFixed(2))))}
        <span style={{ fontFamily: 'Space Grotesk, sans-serif', fontWeight: 700, fontSize: 18, color: t.text, minWidth: 64, textAlign: 'center' }}>
          {String(value).replace('.', ',')}<span style={{ fontSize: 13, color: t.textFaint, fontWeight: 500 }}> {unit}</span>
        </span>
        {small(<Icon name="plus" size={18} color={t.text} sw={2.4} />, () => onChange(Math.min(max ?? Infinity, +(value + step).toFixed(2))))}
      </div>
    </div>
  );
}

function ProfileSheet({ t, profile, onboarding, onClose, onSave, onSignOut }) {
  const [f, setF] = useM(() => ({ ...DEFAULT_PROFILE, ...(profile || {}) }));
  const set = (k, v) => setF(p => ({ ...p, [k]: v }));
  const tg = computeTargets(f);
  const sectionTitle = (s) => <div style={{ fontSize: 12.5, fontWeight: 700, color: t.textMuted, textTransform: 'uppercase', letterSpacing: 0.3, margin: '20px 0 10px' }}>{s}</div>;

  return (
    <Sheet t={t} onClose={onClose} full label={<span style={{ display: 'flex', alignItems: 'center', gap: 8, whiteSpace: 'nowrap' }}><Icon name="user" size={19} color={t.green} /> {onboarding ? 'Bienvenue' : 'Mon profil'}</span>}>
      {onboarding && (
        <p style={{ margin: '0 0 4px', fontSize: 14, color: t.textMuted, lineHeight: 1.5 }}>
          Réponds à quelques questions : Hermès calcule automatiquement tes cibles calories et protéines.
        </p>
      )}

      {sectionTitle('Objectif')}
      <Chips items={OBJECTIFS} active={f.objectif} onPick={v => set('objectif', v)} t={t} />

      {f.objectif !== 'maintien' && <>
        {sectionTitle('Rythme visé')}
        <Chips t={t} active={f.rythme}
          items={[{ id: 0.25, label: '0,25 kg/sem' }, { id: 0.5, label: '0,5 kg/sem' }, { id: 0.75, label: '0,75 kg/sem' }, { id: 1, label: '1 kg/sem' }]}
          onPick={v => set('rythme', v)} />
      </>}

      {sectionTitle('Sexe')}
      <Chips items={[{ id: 'H', label: 'Homme' }, { id: 'F', label: 'Femme' }]} active={f.sexe} onPick={v => set('sexe', v)} t={t} />

      {sectionTitle('Mensurations')}
      <div>
        <ProfileNumRow t={t} label="Âge" value={f.age} unit="ans" step={1} min={14} max={99} onChange={v => set('age', v)} />
        <ProfileNumRow t={t} label="Taille" value={f.taille} unit="cm" step={1} min={130} max={220} onChange={v => set('taille', v)} />
        <ProfileNumRow t={t} label="Poids" value={f.poids} unit="kg" step={0.5} min={40} max={250} onChange={v => set('poids', v)} />
      </div>

      {sectionTitle('Niveau d’activité')}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {ACTIVITY.map(a => {
          const on = f.activite === a.id;
          return (
            <button key={a.id} onClick={() => set('activite', a.id)} style={{
              display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '12px 14px', borderRadius: 14,
              cursor: 'pointer', fontFamily: 'inherit', textAlign: 'left',
              background: on ? `color-mix(in srgb, ${t.green} 14%, ${t.surface})` : t.surface,
              border: `1px solid ${on ? t.green : t.borderSoft}` }}>
              <div>
                <div style={{ fontWeight: 700, fontSize: 14.5, color: t.text }}>{a.label}</div>
                <div style={{ fontSize: 12, color: t.textMuted }}>{a.sub}</div>
              </div>
              <CheckDot on={on} color={t.green} t={t} size={22} />
            </button>
          );
        })}
      </div>

      {/* Aperçu des cibles calculées */}
      <div style={{ marginTop: 22, padding: 18, borderRadius: 18, background: `color-mix(in srgb, ${t.green} 12%, ${t.surface})`, border: `1px solid color-mix(in srgb, ${t.green} 30%, ${t.surface})` }}>
        <div style={{ fontSize: 12.5, fontWeight: 700, color: t.green, textTransform: 'uppercase', letterSpacing: 0.3, marginBottom: 12 }}>Tes cibles quotidiennes</div>
        <div style={{ display: 'flex', gap: 10, marginBottom: 12 }}>
          <div style={{ flex: 1 }}>
            <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontWeight: 700, fontSize: 30, color: t.text, lineHeight: 1 }}>{tg.kcal}</div>
            <div style={{ fontSize: 11.5, color: t.textMuted, fontWeight: 600 }}>kcal</div>
          </div>
          <div style={{ flex: 1 }}>
            <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontWeight: 700, fontSize: 30, color: t.orange, lineHeight: 1 }}>{tg.prot}<span style={{ fontSize: 15, color: t.textFaint }}>g</span></div>
            <div style={{ fontSize: 11.5, color: t.textMuted, fontWeight: 600 }}>protéines</div>
          </div>
          <div style={{ flex: 1 }}>
            <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontWeight: 700, fontSize: 30, color: t.blue, lineHeight: 1 }}>{tg.gluc}<span style={{ fontSize: 15, color: t.textFaint }}>g</span></div>
            <div style={{ fontSize: 11.5, color: t.textMuted, fontWeight: 600 }}>glucides</div>
          </div>
          <div style={{ flex: 1 }}>
            <div style={{ fontFamily: 'Space Grotesk, sans-serif', fontWeight: 700, fontSize: 30, color: t.amber, lineHeight: 1 }}>{tg.lip}<span style={{ fontSize: 15, color: t.textFaint }}>g</span></div>
            <div style={{ fontSize: 11.5, color: t.textMuted, fontWeight: 600 }}>lipides</div>
          </div>
        </div>
        <div style={{ fontSize: 12, color: t.textMuted, lineHeight: 1.45 }}>
          Maintien estimé ≈ <b style={{ color: t.text }}>{tg.tdee} kcal</b>{f.objectif === 'perte' ? ` · déficit de ${tg.tdee - tg.kcal} kcal/j` : f.objectif === 'prise' ? ` · surplus de ${tg.kcal - tg.tdee} kcal/j` : ''}.
        </div>
      </div>

      <button onClick={() => onSave(f)} style={primaryBtn(t)}>{onboarding ? 'C’est parti' : 'Enregistrer'}</button>

      {!onboarding && onSignOut && (
        <button onClick={onSignOut} style={{ width: '100%', marginTop: 12, padding: '13px', borderRadius: 14, border: `1px solid ${t.borderSoft}`,
          cursor: 'pointer', background: 'transparent', color: t.red, fontWeight: 700, fontSize: 14.5, fontFamily: 'inherit' }}>
          Se déconnecter
        </button>
      )}
    </Sheet>
  );
}


// ── CHAT — converser avec Hermès (contexte enrichi + actions) ──
function ChatModal({ t, chatContext, onAction, onClose }) {
  const [messages, setMessages] = useM([
    { role: 'assistant', content: 'Salut Atou ! Je suis Hermès, ton coach. Pose-moi une question : quoi manger ce soir, gérer un écart, optimiser tes protéines… Je connais ta journée.' },
  ]);
  const [input, setInput] = useM('');
  const [loading, setLoading] = useM(false);
  const [pendingImage, setPendingImage] = useM(null); // { base64, mediaType, previewUrl }
  const chatFileRef = React.useRef(null);
  // Historique chargé en async au montage (poids + 7 derniers jours), fusionné au contexte.
  const [history, setHistory] = useM({ weightHistory: [], recentDays: [] });
  const scrollRef = React.useRef(null);

  const onPickChatPhoto = async (e) => {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    const { base64, mediaType } = await window.FuelFitAPI.fileToBase64(file);
    setPendingImage({ base64, mediaType, previewUrl: URL.createObjectURL(file) });
  };

  React.useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [messages, loading]);

  const [userFacts, setUserFacts] = useM([]);

  // Chargement au montage : suivi réel + mémoire (historique conversation + faits).
  useME(() => {
    let cancelled = false;
    (async () => {
      if (!window.FuelFitDB) return;
      try {
        const [weightHistory, recentDays, chatHist, facts] = await Promise.all([
          window.FuelFitDB.getWeightHistory(),
          window.FuelFitDB.getRecentDays(7),
          window.FuelFitDB.getChatHistory(60),
          window.FuelFitDB.getUserFacts(),
        ]);
        if (cancelled) return;
        setHistory({ weightHistory: weightHistory || [], recentDays: recentDays || [] });
        setUserFacts(facts || []);
        // Restaure la conversation passée (ou message d'accueil si vide)
        if (chatHist && chatHist.length) {
          setMessages(chatHist.map(m => ({ role: m.role, content: m.content })));
        }
      } catch (e) { /* mémoire optionnelle */ }
    })();
    return () => { cancelled = true; };
  }, []);

  const send = async () => {
    const text = input.trim();
    if ((!text && !pendingImage) || loading) return;
    const userMsg = { role: 'user', content: text || (pendingImage ? 'Analyse cette photo de mon repas.' : '') };
    if (pendingImage) {
      userMsg.image = { base64: pendingImage.base64, mediaType: pendingImage.mediaType };
      userMsg.previewUrl = pendingImage.previewUrl; // pour l'affichage local seulement
    }
    const next = [...messages, userMsg];
    setMessages(next);
    setInput('');
    setPendingImage(null);
    setLoading(true);
    try {
      const ctx = { ...(chatContext || {}), weightHistory: history.weightHistory, recentDays: history.recentDays, userFacts };
      // on envoie l'historique sans le message d'accueil initial ni les champs d'affichage local
      const convo = next.filter((m, i) => !(i === 0 && m.role === 'assistant'))
        .map(m => ({ role: m.role, content: m.content, ...(m.image ? { image: m.image } : {}) }));
      const { reply, actions, newFacts } = await window.FuelFitAPI.chatHermes(convo, ctx);
      setMessages(m => [...m, { role: 'assistant', content: reply }]);
      // Persiste la conversation en mémoire cloud (message user + réponse).
      try {
        if (window.FuelFitDB) {
          await window.FuelFitDB.saveChatMessage('user', userMsg.content, !!userMsg.image);
          await window.FuelFitDB.saveChatMessage('assistant', reply, false);
        }
      } catch (e) {}
      // Mémorise les nouveaux faits appris sur Atou.
      if (Array.isArray(newFacts) && newFacts.length && window.FuelFitDB) {
        try { await window.FuelFitDB.addUserFacts(newFacts); setUserFacts(f => [...f, ...newFacts]); } catch (e) {}
      }
      // Exécute chaque action décidée par Hermès dans l'app.
      if (Array.isArray(actions) && onAction) {
        for (const action of actions) {
          try { await onAction(action); } catch (e) {}
        }
      }
    } catch (err) {
      setMessages(m => [...m, { role: 'assistant', content: 'Désolé, je n’ai pas pu répondre (' + (err.message || 'erreur') + '). Réessaie.' }]);
    }
    setLoading(false);
  };

  return (
    <Sheet t={t} onClose={onClose} full label={<span style={{ display: 'flex', alignItems: 'center', gap: 8, whiteSpace: 'nowrap' }}><Icon name="spark" size={20} color={t.green} fill /> Hermès · Coach</span>}>
      <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
        <div ref={scrollRef} style={{ flex: 1, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 10, paddingBottom: 12 }}>
          {messages.map((m, i) => (
            <div key={i} style={{ display: 'flex', justifyContent: m.role === 'user' ? 'flex-end' : 'flex-start' }}>
              <div style={{ maxWidth: '82%', display: 'flex', flexDirection: 'column', gap: 6, alignItems: m.role === 'user' ? 'flex-end' : 'flex-start' }}>
                {m.previewUrl && (
                  <img src={m.previewUrl} alt="repas" style={{ maxWidth: 200, maxHeight: 200, borderRadius: 14, objectFit: 'cover' }} />
                )}
                {m.content && (
                  <div style={{ padding: '11px 14px', borderRadius: 16, fontSize: 14, lineHeight: 1.5,
                    background: m.role === 'user' ? t.green : t.surface,
                    color: m.role === 'user' ? t.onAccent : t.text,
                    border: m.role === 'user' ? 'none' : `1px solid ${t.borderSoft}`,
                    borderBottomRightRadius: m.role === 'user' ? 5 : 16,
                    borderBottomLeftRadius: m.role === 'user' ? 16 : 5 }}>{m.content}</div>
                )}
              </div>
            </div>
          ))}
          {loading && (
            <div style={{ display: 'flex', justifyContent: 'flex-start' }}>
              <div style={{ padding: '11px 14px', borderRadius: 16, background: t.surface, border: `1px solid ${t.borderSoft}`, color: t.textMuted, fontSize: 14 }}>Hermès réfléchit…</div>
            </div>
          )}
        </div>
        <input ref={chatFileRef} type="file" accept="image/*" capture="environment" onChange={onPickChatPhoto} style={{ display: 'none' }} />
        {pendingImage && (
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 10px', marginTop: 8, borderRadius: 12, background: t.surfaceAlt }}>
            <img src={pendingImage.previewUrl} alt="aperçu" style={{ width: 44, height: 44, borderRadius: 9, objectFit: 'cover' }} />
            <span style={{ flex: 1, fontSize: 13, color: t.textMuted }}>Photo prête à envoyer</span>
            <button onClick={() => setPendingImage(null)} style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 4 }}>
              <Icon name="close" size={17} color={t.textMuted} sw={2.2} />
            </button>
          </div>
        )}
        <div style={{ display: 'flex', gap: 8, paddingTop: 10, borderTop: `1px solid ${t.borderSoft}` }}>
          <button onClick={() => chatFileRef.current && chatFileRef.current.click()} aria-label="Envoyer une photo" style={{
            width: 46, flexShrink: 0, borderRadius: 14, border: `1px solid ${t.border}`, background: t.surface, cursor: 'pointer',
            display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <Icon name="camera" size={20} color={t.green} />
          </button>
          <input value={input} onChange={e => setInput(e.target.value)}
            onKeyDown={e => { if (e.key === 'Enter') send(); }}
            placeholder={pendingImage ? 'Ajoute un message (optionnel)…' : 'Écris à Hermès…'}
            style={{ flex: 1, padding: '13px 14px', borderRadius: 14, background: t.surface,
              border: `1px solid ${t.border}`, color: t.text, fontFamily: 'inherit', fontSize: 15, outline: 'none', boxSizing: 'border-box' }} />
          <button onClick={send} disabled={loading} style={{ padding: '0 18px', borderRadius: 14, border: 'none',
            background: t.green, color: t.onAccent, fontWeight: 700, fontSize: 14.5, cursor: 'pointer', fontFamily: 'inherit', opacity: loading ? 0.6 : 1 }}>
            <Icon name="chevron" size={20} color={t.onAccent} sw={2.4} />
          </button>
        </div>
      </div>
    </Sheet>
  );
}


// ── BILAN HEBDO + PLAN 7 JOURS ────────────────────────────────
function WeeklyPlanModal({ t, weightLog, onClose }) {
  const [step, setStep] = useM('intro'); // intro | loading | result | error
  const [data, setData] = useM(null);
  const [errMsg, setErrMsg] = useM('');

  const generate = async () => {
    setStep('loading');
    try {
      const hist = (weightLog || []).slice(-8).map((d, i, arr) => ({
        date: new Date(Date.now() - (arr.length - 1 - i) * 7 * 86400000).toISOString().slice(0, 10),
        weight: d.kg,
      }));
      // moyenne approximative consommée = cible (l'app ne stocke pas encore l'historique quotidien complet)
      const bank = MEALS.map(m => ({ id: m.id, name: m.name, type: m.type, kcal: m.kcal, prot: m.prot }));
      const res = await window.FuelFitAPI.weeklyPlan(hist, TARGETS.kcal, TARGETS.prot, bank);
      setData(res);
      setStep('result');
    } catch (err) {
      setErrMsg(err.message || 'Génération impossible.');
      setStep('error');
    }
  };

  return (
    <Sheet t={t} onClose={onClose} full label={<span style={{ display: 'flex', alignItems: 'center', gap: 8, whiteSpace: 'nowrap' }}><Icon name="spark" size={20} color={t.green} fill /> Bilan de la semaine</span>}>
      {step === 'intro' && (
        <div style={{ paddingTop: 8 }}>
          <p style={{ fontSize: 14.5, color: t.textMuted, lineHeight: 1.6, marginTop: 0 }}>
            Hermès analyse ta progression (poids, calories, protéines) et te génère un <b style={{ color: t.text }}>plan de repas sur 7 jours</b> adapté à tes résultats — zéro sucre ajouté, calé sur tes cibles.
          </p>
          <button onClick={generate} style={{ ...primaryBtn(t), display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8 }}>
            <Icon name="spark" size={19} color={t.onAccent} fill /> Générer mon bilan + plan
          </button>
        </div>
      )}

      {step === 'loading' && (
        <div style={{ height: 360, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 18 }}>
          <div style={{ width: 60, height: 60, borderRadius: 99, border: `3px solid ${t.ringTrack}`, borderTopColor: t.green, animation: 'spin 0.9s linear infinite' }} />
          <div style={{ fontSize: 15, fontWeight: 700, color: t.text }}>Hermès prépare ta semaine…</div>
        </div>
      )}

      {step === 'result' && data && (
        <div style={{ paddingBottom: 20 }}>
          <div style={{ display: 'flex', gap: 11, padding: '14px 16px', borderRadius: 16, marginBottom: 18, background: `color-mix(in srgb, ${t.green} 12%, ${t.surface})`, border: `1px solid color-mix(in srgb, ${t.green} 30%, ${t.surface})` }}>
            <Icon name="spark" size={20} color={t.green} fill style={{ flexShrink: 0, marginTop: 1 }} />
            <div style={{ fontSize: 13.5, color: t.text, lineHeight: 1.55 }}><b>Bilan :</b> {data.bilan}</div>
          </div>
          {data.plan.map((day, i) => (
            <div key={i} style={{ marginBottom: 14 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', margin: '0 4px 8px' }}>
                <span style={{ fontSize: 14.5, fontWeight: 700, color: t.text }}>{day.day}</span>
                <span style={{ fontSize: 12, color: t.textMuted, fontFamily: 'Space Grotesk, sans-serif' }}>{day.totalKcal} kcal · {day.totalProt}g prot</span>
              </div>
              <Card t={t} pad={6}>
                {day.meals.map((m, j) => (
                  <div key={j} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 12px', borderTop: j ? `1px solid ${t.borderSoft}` : 'none' }}>
                    <div style={{ width: 70, flexShrink: 0, fontSize: 11.5, fontWeight: 600, color: t.textFaint }}>{m.slot}</div>
                    <div style={{ flex: 1, fontSize: 13.5, color: t.text }}>{m.name}</div>
                    <div style={{ fontSize: 11.5, color: t.textMuted, fontFamily: 'Space Grotesk, sans-serif', whiteSpace: 'nowrap' }}>{m.kcal} · {m.prot}g</div>
                  </div>
                ))}
              </Card>
            </div>
          ))}
          <button onClick={() => setStep('intro')} style={{ ...primaryBtn(t), marginTop: 8, background: t.surfaceAlt, color: t.text }}>Regénérer</button>
        </div>
      )}

      {step === 'error' && (
        <div style={{ height: 300, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 16, textAlign: 'center', padding: '0 10px' }}>
          <Icon name="info" size={28} color={t.red} />
          <div style={{ fontSize: 13.5, color: t.textMuted, lineHeight: 1.5, maxWidth: 270 }}>{errMsg}</div>
          <button onClick={() => setStep('intro')} style={{ ...primaryBtn(t), width: 'auto', padding: '12px 24px' }}>Retour</button>
        </div>
      )}
    </Sheet>
  );
}

Object.assign(window, { Sheet, MealPicker, MealDetail, WeightModal, ScanModal, HermesModal, ProfileSheet, ChatModal, WeeklyPlanModal });
