// pantry-data.jsx — data, i18n, palettes

// ─────────────────────────────────────────────────────────────
// DATE HELPERS — real calendar dates for the meal plan
// Meals are keyed by ISO date string 'YYYY-MM-DD' (local time).
// ─────────────────────────────────────────────────────────────
function isoDate(d) {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  return `${y}-${m}-${day}`;
}
function todayISO() { return isoDate(new Date()); }
function parseISO(s) {
  // local-midnight Date from 'YYYY-MM-DD'
  const [y, m, d] = (s || todayISO()).split('-').map(Number);
  return new Date(y, (m || 1) - 1, d || 1);
}
function addDays(iso, n) {
  const d = parseISO(iso); d.setDate(d.getDate() + n); return isoDate(d);
}
// Monday-based start of the week containing `iso`.
function startOfWeekISO(iso) {
  const d = parseISO(iso);
  const dow = (d.getDay() + 6) % 7; // Mon=0 … Sun=6
  d.setDate(d.getDate() - dow);
  return isoDate(d);
}
// 0=Mon … 6=Sun for an ISO date.
function weekdayIndex(iso) { return (parseISO(iso).getDay() + 6) % 7; }
function dateNumber(iso) { return parseISO(iso).getDate(); }

// ── Freshness (expiry that actually advances with real time) ───
// Inventory historically stored a frozen `daysLeft` number — so after day 1 the
// countdown never moved. We now anchor an absolute `expiresOn` date and DERIVE
// `daysLeft` from today every time the app loads, so freshness is always live.
function daysUntil(iso) {
  if (!iso) return null;
  return Math.round((parseISO(iso).getTime() - parseISO(todayISO()).getTime()) / 86400000);
}
function ensureExpiry(item) {
  if (!item) return item;
  let expiresOn = item.expiresOn;
  if (!expiresOn) {
    const d = (typeof item.daysLeft === 'number') ? item.daysLeft : 7;
    expiresOn = addDays(todayISO(), d);
  }
  const daysLeft = daysUntil(expiresOn);
  return { ...item, expiresOn, daysLeft, addedAt: item.addedAt || Date.now() };
}
function normalizeInventory(list) {
  return Array.isArray(list) ? list.map(ensureExpiry) : list;
}

// Migrate legacy meal entries ({day:0-6}) to real ISO dates (this week's Monday
// + day offset). New entries already have {date}; they pass through untouched.
function migrateMealPlan(meals) {
  if (!Array.isArray(meals)) return meals;
  const wk = startOfWeekISO(todayISO());
  return meals.map(m => {
    if (m && m.date) return m;
    if (m && typeof m.day === 'number') {
      const { day, ...rest } = m;
      return { ...rest, date: addDays(wk, day) };
    }
    return m;
  });
}
function monthYearLabel(iso, lang) {
  const d = parseISO(iso);
  const monthsFr = ['janvier','février','mars','avril','mai','juin','juillet','août','septembre','octobre','novembre','décembre'];
  const monthsEn = ['January','February','March','April','May','June','July','August','September','October','November','December'];
  const m = (lang === 'fr' ? monthsFr : monthsEn)[d.getMonth()];
  return `${m.charAt(0).toUpperCase() + m.slice(1)} ${d.getFullYear()}`;
}

// ─────────────────────────────────────────────────────────────
// PALETTES — sage / terracotta / dark
// ─────────────────────────────────────────────────────────────
const PALETTES = {
  sage: {
    name: 'Sauge',
    bg: '#FAF8F3',
    bgInset: '#F2EFE6',
    card: '#FFFFFF',
    cardSub: '#F7F4ED',
    ink: '#1F2A24',
    ink2: '#4B5650',
    ink3: '#6B7470',
    line: '#E6E2D8',
    line2: '#EFECE3',
    primary: '#4F8267',
    primaryInk: '#FFFFFF',
    primarySoft: '#DCE9DC',
    primarySoftInk: '#2E5C42',
    amber: '#C68A2E',
    amberSoft: '#F6E5C2',
    amberSoftInk: '#7A5316',
    red: '#B85149',
    redSoft: '#F5DAD7',
    redSoftInk: '#823B36',
    blue: '#4A6FA5',
    blueSoft: '#DCE5F1',
    overlay: 'rgba(31,42,36,0.45)',
    isDark: false,
  },
  terracotta: {
    name: 'Terracotta',
    bg: '#F8F1EB',
    bgInset: '#F0E6DC',
    card: '#FFFFFF',
    cardSub: '#F6EBE0',
    ink: '#2A1F1A',
    ink2: '#5A4538',
    ink3: '#8A7468',
    line: '#E8DDD3',
    line2: '#EFE6DC',
    primary: '#B86B47',
    primaryInk: '#FFFFFF',
    primarySoft: '#F1DDD0',
    primarySoftInk: '#7A3F22',
    amber: '#B07A26',
    amberSoft: '#F4E2BD',
    amberSoftInk: '#6E4912',
    red: '#A0413B',
    redSoft: '#EDD0CD',
    redSoftInk: '#6A2926',
    blue: '#5B7A7A',
    blueSoft: '#DEE6E6',
    overlay: 'rgba(42,31,26,0.45)',
    isDark: false,
  },
  dark: {
    name: 'Sombre',
    bg: '#0F1411',
    bgInset: '#161B18',
    card: '#1B221E',
    cardSub: '#222A26',
    ink: '#ECE9DF',
    ink2: '#B5BAB1',
    ink3: '#7E837A',
    line: '#2A312D',
    line2: '#222A26',
    primary: '#7FB59A',
    primaryInk: '#0F1411',
    primarySoft: '#243329',
    primarySoftInk: '#A8D4BD',
    amber: '#E9B85C',
    amberSoft: '#3A2E18',
    amberSoftInk: '#F2D294',
    red: '#D67067',
    redSoft: '#3A1F1D',
    redSoftInk: '#EFA8A2',
    blue: '#7FA0CC',
    blueSoft: '#1F2A38',
    overlay: 'rgba(0,0,0,0.55)',
    isDark: true,
  },
};

// ─────────────────────────────────────────────────────────────
// I18N — fr/en
// ─────────────────────────────────────────────────────────────
const I18N = {
  fr: {
    brand: 'PantryWise',
    greeting: 'Bonjour Alex',
    todayLabel: "Lundi 18 mai",
    soon: 'Expire bientôt',
    urgent: 'Urgent',
    expired: 'Expiré',
    safe: 'En stock',
    expSoon: 'à utiliser bientôt',
    inStock: 'en stock',
    expiredCount: 'expirés',
    totalItems: 'aliments',
    add: 'Ajouter',
    quickAdd: 'Ajouter un aliment',
    chooseMethod: 'Choisis ta méthode',
    manual: 'Manuel',
    manualDesc: 'Recherche et saisie',
    barcode: 'Code-barres',
    barcodeDesc: "Scanner l'emballage",
    photoAI: 'Photo IA',
    photoAIDesc: 'Plusieurs aliments à la fois',
    inventory: 'Inventaire',
    recipes: 'Recettes',
    grocery: 'Liste',
    plan: 'Plan',
    profile: 'Profil',
    home: 'Accueil',
    // Family hub + real invite
    familyHub: 'Famille',
    familySpace: 'Espace famille',
    familyMembers: 'Membres',
    pendingInvites: 'Invitations en attente',
    sharedList: 'Liste partagée',
    sharedPlan: 'Plan de repas',
    inviteLink: "Lien d'invitation",
    copyLink: 'Copier le lien',
    linkCopied: 'Lien copié !',
    shareLink: 'Partager',
    generatingLink: 'Génération…',
    inviteHowto: "Envoie ce lien à la personne. Elle crée son compte avec le même courriel et rejoint ta famille.",
    inviteExpires: 'Expire dans 14 jours',
    noMembersYet: 'Toi seul·e pour l\'instant',
    changePhoto: 'Changer la photo',
    removePhoto: 'Retirer la photo',
    choosePhoto: 'Choisir une photo',
    barcodeManual: 'Entrer le code manuellement',
    barcodeEnter: 'Code-barres (chiffres)',
    barcodeLookup: 'Rechercher',
    barcodeNotFound: 'Produit introuvable — ajoute-le manuellement',
    barcodeUnsupported: 'Scan caméra non supporté ici — entre le code à la main',
    scanning: 'Lecture…',
    // Recipes — extended catalog, diets, allergens, explore
    recExplore: 'Explorer',
    recLocal: 'Catalogue',
    recOnline: 'En ligne',
    recDiet: 'Régime',
    recAllergy: 'Sans (allergies)',
    recNoneFilter: 'Tous',
    recLoadingOnline: 'Chargement des recettes…',
    recOnlineHint: 'Des centaines de recettes avec photos',
    recOfflineMsg: 'Recettes en ligne indisponibles (hors-ligne)',
    dietVegetarian: 'Végétarien', dietVegan: 'Végane', dietPescatarian: 'Pescétarien',
    dietGlutenFree: 'Sans gluten', dietDairyFree: 'Sans lactose', dietLowCarb: 'Faible en glucides', dietHighProtein: 'Riche en protéines',
    algGluten: 'Gluten', algDairy: 'Lactose', algEggs: 'Œufs', algNuts: 'Noix', algPeanuts: 'Arachides',
    algSoy: 'Soja', algShellfish: 'Crustacés', algFish: 'Poisson', algSesame: 'Sésame',
    priceEstimate: 'Coût estimé', priceRegion: 'Région', priceRemaining: 'à acheter',
    priceNote: 'Estimation selon les prix moyens — pas une facture réelle',
    priceRecipe: 'Coût estimé', priceEach: 'unité',
    suggestedToday: "Suggéré pour ce soir",
    usesExpiring: 'utilise tes aliments à risque',
    haveAll: "Tu as tout!",
    available: 'disponibles',
    missing: 'manquant',
    missingPlural: 'manquants',
    addMissing: 'Ajouter à la liste',
    cook: "J'ai cuisiné",
    minutes: 'min',
    portions: 'pers.',
    name: 'Nom',
    searchPh: 'Lait, avocat, poulet…',
    quantity: 'Quantité',
    unit: 'Unité',
    expiry: "Expiration",
    location: 'Emplacement',
    fridge: 'Frigo',
    freezer: 'Congélateur',
    pantry: 'Garde-manger',
    confirm: 'Ajouter',
    cancel: 'Annuler',
    close: 'Fermer',
    detecting: 'Détection IA…',
    detected: 'Détectés',
    saveAll: 'Tout ajouter',
    days: 'j',
    today: "auj.",
    tomorrow: 'demain',
    in: 'dans',
    ago: 'depuis',
    seeAll: 'Voir tout',
    suggestions: 'Suggestions',
    recent: 'Récents',
    pickItem: "Choisis l'aliment",
    setQty: 'Quantité',
    common: 'Aliments fréquents',
    snapShelf: 'Photographie l\'étagère',
    pointCamera: 'Pointe l\'appareil sur ton frigo ouvert',
    tapToScan: 'Tape pour scanner',
    barcodeFound: 'Produit trouvé',
    addAll: 'Tout ajouter',
    almostExpired: 'À utiliser',
    ingredients: 'Ingrédients',
    steps: 'Étapes',
    haveIt: 'Tu as',
    needIt: 'Manque',
    why: 'Pourquoi cette recette',
    whyDesc: 'Utilise 3 ingrédients à risque',
    stepHint: 'Tape pour voir les étapes',
    plannedFor: 'Prévu pour',
    inventoryShort: 'Inventaire',
    filterAll: 'Tout',
    matches: 'matchs',
    of: 'de',
    expiresIn: 'Expire',
    addedJust: 'Ajouté',
    autoFilled: 'Pré-rempli automatiquement',
    moreOptions: 'Plus',
    save: 'Sauvegarder',
    alertTitle: 'Avocat ajouté',
    alertSub: 'Expire demain · 3 recettes trouvées',
    viewRecipes: 'Voir les recettes',
    yes: 'Oui',
    // Inventory page
    invTitle: 'Mon inventaire',
    invSub: 'aliments suivis',
    filterFridge: 'Frigo',
    filterFreezer: 'Congélo',
    filterPantry: 'Garde-manger',
    sortBy: 'Trier par',
    sortUrgency: 'Urgence',
    sortAlpha: 'A → Z',
    sortAdded: 'Récents',
    bulkSelect: 'Sélection',
    selected: 'sélectionnés',
    deleteN: 'Supprimer',
    moveTo: 'Déplacer',
    empty: 'Rien ici pour l\'instant',
    emptyCTA: 'Ajoute ton premier aliment',
    // Recipes page
    recTitle: 'Recettes',
    recSub: 'triées par ce que tu as déjà',
    filterFast: '≤ 15 min',
    filterMid: '≤ 30 min',
    filterBreakfast: 'Petit-déj',
    filterLunch: 'Lunch',
    filterDinner: 'Souper',
    haveAllShort: 'Tu as tout',
    saved: 'Sauvegardée',
    // Grocery page
    grocTitle: 'Liste d\'épicerie',
    grocSub: 'items à acheter',
    addToList: 'Ajouter un item',
    grocPh: 'Ex : Lait, pommes…',
    aisleFresh: 'Frais',
    aisleDry: 'Sec',
    aisleFrozen: 'Surgelés',
    aisleOther: 'Autres',
    clearChecked: 'Vider cochés',
    checkedCount: 'cochés',
    smartHint: 'Bientôt à racheter',
    smartHintSub: 'D\'après ce qui expire',
    // Profile page
    profTitle: 'Profil',
    profStats: 'Tes statistiques',
    statsSaved: 'Économisé',
    statsAvoid: 'Aliments sauvés',
    statsCooked: 'Recettes cuisinées',
    sectionAccount: 'Compte',
    sectionPrefs: 'Préférences',
    sectionFood: 'Alimentation',
    sectionAbout: 'À propos',
    email: 'Courriel',
    language: 'Langue',
    units: 'Unités',
    unitsMetric: 'Métrique',
    unitsImperial: 'Impérial',
    notifs: 'Notifications',
    notifsOn: 'Activées',
    notifsOff: 'Désactivées',
    diet: 'Régime',
    dietNone: 'Aucun',
    dietVeg: 'Végétarien',
    allergies: 'Allergies',
    family: 'Partage famille',
    familySoon: 'Bientôt',
    help: 'Aide',
    version: 'Version',
    logout: 'Se déconnecter',
    edit: 'Modifier',
    // Onboarding
    onboardSkip: 'Passer',
    onboardNext: 'Suivant',
    onboardStart: 'Commencer',
    onboardTitle1: 'Cuisine ce que tu as déjà.',
    onboardDesc1: 'PantryWise te dit ce qui est dans ton frigo et te suggère quoi cuisiner ce soir.',
    onboardTitle2: 'Plus de gaspillage.',
    onboardDesc2: 'Reçois une alerte avant que ce que tu as acheté n\'expire — et trouve une recette qui l\'utilise.',
    onboardTitle3: 'Liste d\'épicerie automatique.',
    onboardDesc3: 'D\'un tap, ajoute les ingrédients manquants à ta liste. Plus jamais de doublons.',
    onboardSetupTitle: 'Ajoute tes premiers aliments',
    onboardSetupSub: 'Coche ce que tu as déjà — ou passe pour le faire plus tard.',
    onboardSetupCTA: 'C\'est parti',
    selectedN: 'sélectionnés',
    // Plan & lunch
    planTitle: 'Plan de la semaine',
    planSub: 'Repas, lunchs et qui cuisine',
    planThisWeek: 'Cette semaine',
    planAdd: 'Ajouter un repas',
    planSuggest: 'Suggestion',
    planVote: 'En vote',
    planAssign: 'Qui cuisine',
    planTime: 'Heure',
    planEmpty: 'Aucun repas prévu',
    planLunch: 'Lunch',
    planBreakfast: 'Déj',
    planDinner: 'Souper',
    planMon: 'L', planTue: 'M', planWed: 'M', planThu: 'J', planFri: 'V', planSat: 'S', planSun: 'D',
    planMonL: 'Lundi', planTueL: 'Mardi', planWedL: 'Mercredi', planThuL: 'Jeudi', planFriL: 'Vendredi', planSatL: 'Samedi', planSunL: 'Dimanche',
    leftovers: 'Restants',
    leftoversSub: 'Lunch demain ?',
    portionsLeft: 'portion(s) restante(s)',
    addToInv: 'Ajouter au frigo',
    members: 'Membres',
    inviteFamily: 'Inviter quelqu\'un',
    shared: 'Partagé',
    // Recipe extra
    prepTime: 'Préparation',
    cookTime: 'Cuisson',
    nutrition: 'Nutrition (par portion)',
    calories: 'kcal',
    protein: 'Protéines',
    carbs: 'Glucides',
    fat: 'Lipides',
    autoAdd: 'Ajouter les manquants à ma liste',
    autoAddOn: 'Sera ajouté',
    leftoverQ: 'Combien de portions restent ?',
    saveAsLeftover: 'Garder pour lunch',
    // Item action menu
    edit: 'Modifier',
    move: 'Changer d\'emplacement',
    delete: 'Supprimer',
    usedSome: 'J\'en ai utilisé',
    seeRecipes: 'Voir recettes',
    nRecipesUse: 'recettes utilisent',
    // Quick log
    quickLog: 'J\'ai mangé ça',
    quickLogSub: 'Ajuste ton inventaire en 5 secondes',
    snack: 'Collation',
    breakfast: 'Petit-déj',
    lunch: 'Lunch',
    dinner: 'Souper',
    // Saved explainer
    savedHow: 'Comment c\'est calculé ?',
    savedExpl: 'On suit les aliments que tu as cuisinés à temps (sauvés du gaspillage) et on estime leur valeur d\'après les prix moyens d\'épicerie. Bientôt : prix réels depuis les circulaires.',
    // Profile preferences
    notifPref: 'Choisir mes alertes',
    notifExpiry: 'Aliments qui expirent',
    notifLow: 'Stock faible',
    notifSpecials: 'Spéciaux sur tes items',
    notifNoMeal: 'Pas de repas planifié',
    notifReady: 'Recette prête à cuisiner',
    dietsHeading: 'Régimes',
    dietVegan: 'Vegan',
    dietGF: 'Sans gluten',
    dietLactose: 'Sans lactose',
    dietKeto: 'Keto',
    dietPescetarian: 'Pescétarien',
    addCustom: 'Ajouter…',
    allergyTypeholder: 'Ex : arachides, kiwi…',
    avoid: 'À éviter',
    prefer: 'Préférés',
    // Buy → inventory
    boughtIt: 'Je l\'ai acheté',
    boughtItSub: 'Combien tu as pris ? On l\'ajoute au frigo.',
    nUnits: 'unité(s)',
    // Variants
    sort: 'Sorte',
    pickSort: 'Choisis la sorte',
    // Hero CTA
    seeAllRecipes: 'Voir les recettes',
    nMatching: 'recettes possibles',
    // Lunch suggestion
    lunchSuggest: 'Idée de lunch',
    lunchSuggestSub: 'Reste de souper',
  },
  en: {
    brand: 'PantryWise',
    greeting: 'Hi Alex',
    todayLabel: "Monday, May 18",
    soon: 'Expiring soon',
    urgent: 'Urgent',
    expired: 'Expired',
    safe: 'In stock',
    expSoon: 'to use soon',
    inStock: 'in stock',
    expiredCount: 'expired',
    totalItems: 'items',
    add: 'Add',
    quickAdd: 'Add an item',
    chooseMethod: 'Pick a method',
    manual: 'Manual',
    manualDesc: 'Search and enter',
    barcode: 'Barcode',
    barcodeDesc: 'Scan the package',
    photoAI: 'AI Photo',
    photoAIDesc: 'Several items at once',
    inventory: 'Inventory',
    recipes: 'Recipes',
    grocery: 'List',
    plan: 'Plan',
    profile: 'Profile',
    home: 'Home',
    // Family hub + real invite
    familyHub: 'Family',
    familySpace: 'Family space',
    familyMembers: 'Members',
    pendingInvites: 'Pending invites',
    sharedList: 'Shared list',
    sharedPlan: 'Meal plan',
    inviteLink: 'Invite link',
    copyLink: 'Copy link',
    linkCopied: 'Link copied!',
    shareLink: 'Share',
    generatingLink: 'Generating…',
    inviteHowto: 'Send this link to the person. They create their account with the same email and join your household.',
    inviteExpires: 'Expires in 14 days',
    noMembersYet: 'Just you for now',
    changePhoto: 'Change photo',
    removePhoto: 'Remove photo',
    choosePhoto: 'Choose a photo',
    barcodeManual: 'Enter code manually',
    barcodeEnter: 'Barcode (digits)',
    barcodeLookup: 'Look up',
    barcodeNotFound: 'Product not found — add it manually',
    barcodeUnsupported: 'Camera scan not supported here — type the code',
    scanning: 'Reading…',
    // Recipes — extended catalog, diets, allergens, explore
    recExplore: 'Explore',
    recLocal: 'Catalog',
    recOnline: 'Online',
    recDiet: 'Diet',
    recAllergy: 'Free from',
    recNoneFilter: 'All',
    recLoadingOnline: 'Loading recipes…',
    recOnlineHint: 'Hundreds of recipes with photos',
    recOfflineMsg: 'Online recipes unavailable (offline)',
    dietVegetarian: 'Vegetarian', dietVegan: 'Vegan', dietPescatarian: 'Pescatarian',
    dietGlutenFree: 'Gluten-free', dietDairyFree: 'Dairy-free', dietLowCarb: 'Low-carb', dietHighProtein: 'High-protein',
    algGluten: 'Gluten', algDairy: 'Dairy', algEggs: 'Eggs', algNuts: 'Nuts', algPeanuts: 'Peanuts',
    algSoy: 'Soy', algShellfish: 'Shellfish', algFish: 'Fish', algSesame: 'Sesame',
    priceEstimate: 'Estimated cost', priceRegion: 'Region', priceRemaining: 'to buy',
    priceNote: 'Estimate based on average prices — not a real receipt',
    priceRecipe: 'Estimated cost', priceEach: 'each',
    suggestedToday: 'Suggested for tonight',
    usesExpiring: 'uses your at-risk items',
    haveAll: 'You have everything!',
    available: 'on hand',
    missing: 'missing',
    missingPlural: 'missing',
    addMissing: 'Add to list',
    cook: 'I cooked this',
    minutes: 'min',
    portions: 'serv.',
    name: 'Name',
    searchPh: 'Milk, avocado, chicken…',
    quantity: 'Qty',
    unit: 'Unit',
    expiry: 'Expires',
    location: 'Location',
    fridge: 'Fridge',
    freezer: 'Freezer',
    pantry: 'Pantry',
    confirm: 'Add',
    cancel: 'Cancel',
    close: 'Close',
    detecting: 'AI detecting…',
    detected: 'Detected',
    saveAll: 'Add all',
    days: 'd',
    today: 'today',
    tomorrow: 'tomorrow',
    in: 'in',
    ago: 'ago',
    seeAll: 'See all',
    suggestions: 'Suggestions',
    recent: 'Recent',
    pickItem: 'Pick the item',
    setQty: 'Quantity',
    common: 'Common items',
    snapShelf: 'Photograph the shelf',
    pointCamera: 'Point the camera at your open fridge',
    tapToScan: 'Tap to scan',
    barcodeFound: 'Product found',
    addAll: 'Add all',
    almostExpired: 'Use up',
    ingredients: 'Ingredients',
    steps: 'Steps',
    haveIt: 'You have',
    needIt: 'Need',
    why: 'Why this recipe',
    whyDesc: 'Uses 3 at-risk ingredients',
    stepHint: 'Tap to view steps',
    plannedFor: 'Planned for',
    inventoryShort: 'Inventory',
    filterAll: 'All',
    matches: 'matches',
    of: 'of',
    expiresIn: 'Expires',
    addedJust: 'Added',
    autoFilled: 'Auto-filled',
    moreOptions: 'More',
    save: 'Save',
    alertTitle: 'Avocado added',
    alertSub: 'Expires tomorrow · 3 recipes found',
    viewRecipes: 'View recipes',
    yes: 'Yes',
    // Inventory page
    invTitle: 'My inventory',
    invSub: 'items tracked',
    filterFridge: 'Fridge',
    filterFreezer: 'Freezer',
    filterPantry: 'Pantry',
    sortBy: 'Sort by',
    sortUrgency: 'Urgency',
    sortAlpha: 'A → Z',
    sortAdded: 'Recent',
    bulkSelect: 'Select',
    selected: 'selected',
    deleteN: 'Delete',
    moveTo: 'Move',
    empty: 'Nothing here yet',
    emptyCTA: 'Add your first item',
    // Recipes page
    recTitle: 'Recipes',
    recSub: 'sorted by what you have',
    filterFast: '≤ 15 min',
    filterMid: '≤ 30 min',
    filterBreakfast: 'Breakfast',
    filterLunch: 'Lunch',
    filterDinner: 'Dinner',
    haveAllShort: 'You have all',
    saved: 'Saved',
    // Grocery page
    grocTitle: 'Grocery list',
    grocSub: 'items to buy',
    addToList: 'Add an item',
    grocPh: 'e.g. Milk, apples…',
    aisleFresh: 'Fresh',
    aisleDry: 'Dry goods',
    aisleFrozen: 'Frozen',
    aisleOther: 'Other',
    clearChecked: 'Clear checked',
    checkedCount: 'checked',
    smartHint: 'Coming up to rebuy',
    smartHintSub: 'Based on what\'s expiring',
    // Profile page
    profTitle: 'Profile',
    profStats: 'Your stats',
    statsSaved: 'Saved',
    statsAvoid: 'Items rescued',
    statsCooked: 'Recipes cooked',
    sectionAccount: 'Account',
    sectionPrefs: 'Preferences',
    sectionFood: 'Food',
    sectionAbout: 'About',
    email: 'Email',
    language: 'Language',
    units: 'Units',
    unitsMetric: 'Metric',
    unitsImperial: 'Imperial',
    notifs: 'Notifications',
    notifsOn: 'On',
    notifsOff: 'Off',
    diet: 'Diet',
    dietNone: 'None',
    dietVeg: 'Vegetarian',
    allergies: 'Allergies',
    family: 'Family sharing',
    familySoon: 'Soon',
    help: 'Help',
    version: 'Version',
    logout: 'Sign out',
    edit: 'Edit',
    // Onboarding
    onboardSkip: 'Skip',
    onboardNext: 'Next',
    onboardStart: 'Get started',
    onboardTitle1: 'Cook what you already have.',
    onboardDesc1: 'PantryWise shows what\'s in your fridge and tells you what to cook tonight.',
    onboardTitle2: 'No more waste.',
    onboardDesc2: 'Get alerted before food expires — and find a recipe that uses it.',
    onboardTitle3: 'Auto grocery list.',
    onboardDesc3: 'One tap to add missing ingredients. No more buying duplicates.',
    onboardSetupTitle: 'Add your first items',
    onboardSetupSub: 'Tap what you already have — or skip to do it later.',
    onboardSetupCTA: 'Let\'s go',
    selectedN: 'selected',
    planTitle: 'Weekly plan',
    planSub: 'Meals, lunches and who cooks',
    planThisWeek: 'This week',
    planAdd: 'Add a meal',
    planSuggest: 'Suggestion',
    planVote: 'Voting',
    planAssign: 'Who cooks',
    planTime: 'Time',
    planEmpty: 'No meal planned',
    planLunch: 'Lunch',
    planBreakfast: 'Breakfast',
    planDinner: 'Dinner',
    planMon: 'M', planTue: 'T', planWed: 'W', planThu: 'T', planFri: 'F', planSat: 'S', planSun: 'S',
    planMonL: 'Monday', planTueL: 'Tuesday', planWedL: 'Wednesday', planThuL: 'Thursday', planFriL: 'Friday', planSatL: 'Saturday', planSunL: 'Sunday',
    leftovers: 'Leftovers',
    leftoversSub: 'Lunch tomorrow?',
    portionsLeft: 'portion(s) left',
    addToInv: 'Add to fridge',
    members: 'Members',
    inviteFamily: 'Invite someone',
    shared: 'Shared',
    prepTime: 'Prep',
    cookTime: 'Cook',
    nutrition: 'Nutrition (per serving)',
    calories: 'kcal',
    protein: 'Protein',
    carbs: 'Carbs',
    fat: 'Fat',
    autoAdd: 'Add missing to my list',
    autoAddOn: 'Will be added',
    leftoverQ: 'How many portions left?',
    saveAsLeftover: 'Save for lunch',
    edit: 'Edit',
    move: 'Move',
    delete: 'Delete',
    usedSome: 'I used some',
    seeRecipes: 'See recipes',
    nRecipesUse: 'recipes use',
    quickLog: 'I ate this',
    quickLogSub: 'Adjust your inventory in 5 seconds',
    snack: 'Snack',
    breakfast: 'Breakfast',
    lunch: 'Lunch',
    dinner: 'Dinner',
    savedHow: 'How is this calculated?',
    savedExpl: 'We track items you cooked in time (rescued from waste) and estimate value from average grocery prices. Soon: real prices from local flyers.',
    notifPref: 'Choose my alerts',
    notifExpiry: 'Items expiring',
    notifLow: 'Low stock',
    notifSpecials: 'Sales on your items',
    notifNoMeal: 'No meal planned',
    notifReady: 'Recipe ready to cook',
    dietsHeading: 'Diets',
    dietVegan: 'Vegan',
    dietGF: 'Gluten-free',
    dietLactose: 'Lactose-free',
    dietKeto: 'Keto',
    dietPescetarian: 'Pescetarian',
    addCustom: 'Add…',
    allergyTypeholder: 'e.g. peanuts, kiwi…',
    avoid: 'Avoid',
    prefer: 'Preferred',
    boughtIt: 'I bought it',
    boughtItSub: 'How many did you get? We\'ll add it to the fridge.',
    nUnits: 'unit(s)',
    sort: 'Variant',
    pickSort: 'Pick variant',
    seeAllRecipes: 'See recipes',
    nMatching: 'recipes possible',
    lunchSuggest: 'Lunch idea',
    lunchSuggestSub: 'Last night\'s dinner',
  },
};

// ─────────────────────────────────────────────────────────────
// Default inventory
// emoji is the food glyph; mono is the monogram letter for line/filled icon styles
// daysLeft: -N expired, 0 today, 1 tomorrow, etc.
// ─────────────────────────────────────────────────────────────
const DEFAULT_INVENTORY = [
  { id: 'i1', name: { fr: 'Épinards', en: 'Spinach' }, emoji: '🥬', mono: 'E', tone: '#7FB575', qty: '1', unit: { fr: 'sac', en: 'bag' }, location: 'fridge', daysLeft: 0 },
  { id: 'i2', name: { fr: 'Lait 2%', en: 'Milk 2%' }, emoji: '🥛', mono: 'L', tone: '#D8DAE0', qty: '1', unit: 'L', location: 'fridge', daysLeft: 2 },
  { id: 'i3', name: { fr: 'Pain', en: 'Bread' }, emoji: '🍞', mono: 'P', tone: '#D9A75A', qty: '1', unit: { fr: 'pain', en: 'loaf' }, location: 'pantry', daysLeft: 3 },
  { id: 'i4', name: { fr: 'Yogourt grec', en: 'Greek yogurt' }, emoji: '🥣', mono: 'Y', tone: '#E8E0C8', qty: '500', unit: 'g', location: 'fridge', daysLeft: 5 },
  { id: 'i5', name: { fr: 'Poulet', en: 'Chicken' }, emoji: '🍗', mono: 'C', tone: '#E2B485', qty: '600', unit: 'g', location: 'freezer', daysLeft: 45 },
  { id: 'i6', name: { fr: 'Pâtes', en: 'Pasta' }, emoji: '🍝', mono: 'P', tone: '#E8C982', qty: '500', unit: 'g', location: 'pantry', daysLeft: 240 },
  { id: 'i7', name: { fr: 'Tomates cerises', en: 'Cherry tomatoes' }, emoji: '🍅', mono: 'T', tone: '#D86A55', qty: '250', unit: 'g', location: 'fridge', daysLeft: 4 },
  { id: 'i8', name: { fr: 'Œufs', en: 'Eggs' }, emoji: '🥚', mono: 'O', tone: '#E8DCB6', qty: '6', unit: { fr: 'pcs', en: 'pcs' }, location: 'fridge', daysLeft: 12 },
  { id: 'i9', name: { fr: 'Cheddar', en: 'Cheddar' }, emoji: '🧀', mono: 'F', tone: '#E8B65F', qty: '200', unit: 'g', location: 'fridge', daysLeft: 9 },
];

// Suggestions shown in the search list (manual add)
// `variants` (optional): array of "sortes" — selectable subtypes (e.g. Penne / Spaghetti for pasta)
const ITEM_SUGGESTIONS = [
  { id: 's1', name: { fr: 'Avocat', en: 'Avocado' }, emoji: '🥑', mono: 'A', tone: '#7FA86A', defaultDays: 3, defaultLoc: 'fridge', defaultQty: '2', defaultUnit: { fr: 'pcs', en: 'pcs' } },
  { id: 's2', name: { fr: 'Banane', en: 'Banana' }, emoji: '🍌', mono: 'B', tone: '#E8C95C', defaultDays: 5, defaultLoc: 'pantry', defaultQty: '4', defaultUnit: { fr: 'pcs', en: 'pcs' } },
  { id: 's3', name: { fr: 'Beurre', en: 'Butter' }, emoji: '🧈', mono: 'B', tone: '#E8D885', defaultDays: 30, defaultLoc: 'fridge', defaultQty: '250', defaultUnit: 'g' },
  { id: 's4', name: { fr: 'Saumon', en: 'Salmon' }, emoji: '🐟', mono: 'S', tone: '#E08A77', defaultDays: 2, defaultLoc: 'fridge', defaultQty: '400', defaultUnit: 'g' },
  { id: 's5', name: { fr: 'Champignons', en: 'Mushrooms' }, emoji: '🍄', mono: 'C', tone: '#C2A085', defaultDays: 4, defaultLoc: 'fridge', defaultQty: '227', defaultUnit: 'g' },
  { id: 's6', name: { fr: 'Carottes', en: 'Carrots' }, emoji: '🥕', mono: 'C', tone: '#E08A4A', defaultDays: 14, defaultLoc: 'fridge', defaultQty: '6', defaultUnit: { fr: 'pcs', en: 'pcs' } },
  // — Pantry staples / common quick-add —
  { id: 's10', name: { fr: 'Ail', en: 'Garlic' }, emoji: '🧄', mono: 'A', tone: '#E8DAB6', defaultDays: 60, defaultLoc: 'pantry', defaultQty: '1', defaultUnit: { fr: 'tête', en: 'head' } },
  { id: 's11', name: { fr: 'Oignon', en: 'Onion' }, emoji: '🧅', mono: 'O', tone: '#D8C28B', defaultDays: 45, defaultLoc: 'pantry', defaultQty: '3', defaultUnit: { fr: 'pcs', en: 'pcs' } },
  { id: 's12', name: { fr: 'Lait', en: 'Milk' }, emoji: '🥛', mono: 'L', tone: '#D8DAE0', defaultDays: 7, defaultLoc: 'fridge', defaultQty: '1', defaultUnit: 'L',
    variants: [
      { id: 'milk-2', name: { fr: '2% — 1 L', en: '2% — 1 L' } },
      { id: 'milk-3', name: { fr: '3.25% — 1 L', en: '3.25% — 1 L' } },
      { id: 'milk-1', name: { fr: '1% — 2 L', en: '1% — 2 L' } },
      { id: 'milk-sk', name: { fr: 'Écrémé — 1 L', en: 'Skim — 1 L' } },
      { id: 'milk-amande', name: { fr: 'Amande non sucré', en: 'Almond unsweetened' } },
    ] },
  { id: 's13', name: { fr: 'Poulet', en: 'Chicken' }, emoji: '🍗', mono: 'C', tone: '#E2B485', defaultDays: 3, defaultLoc: 'fridge', defaultQty: '500', defaultUnit: 'g',
    variants: [
      { id: 'pou-poit', name: { fr: 'Poitrine désossée', en: 'Boneless breast' } },
      { id: 'pou-haut', name: { fr: 'Hauts de cuisse', en: 'Thighs' } },
      { id: 'pou-pilon', name: { fr: 'Pilons', en: 'Drumsticks' } },
      { id: 'pou-ent', name: { fr: 'Entier', en: 'Whole' } },
    ] },
  { id: 's14', name: { fr: 'Pâtes', en: 'Pasta' }, emoji: '🍝', mono: 'P', tone: '#E8C982', defaultDays: 240, defaultLoc: 'pantry', defaultQty: '500', defaultUnit: 'g',
    variants: [
      { id: 'pa-pen', name: { fr: 'Penne', en: 'Penne' } },
      { id: 'pa-spa', name: { fr: 'Spaghetti', en: 'Spaghetti' } },
      { id: 'pa-fus', name: { fr: 'Fusilli', en: 'Fusilli' } },
      { id: 'pa-rig', name: { fr: 'Rigatoni', en: 'Rigatoni' } },
      { id: 'pa-laz', name: { fr: 'Lasagne', en: 'Lasagna' } },
    ] },
  { id: 's15', name: { fr: 'Fromage', en: 'Cheese' }, emoji: '🧀', mono: 'F', tone: '#E8B65F', defaultDays: 14, defaultLoc: 'fridge', defaultQty: '200', defaultUnit: 'g',
    variants: [
      { id: 'fr-ched', name: { fr: 'Cheddar fort', en: 'Sharp cheddar' } },
      { id: 'fr-moz', name: { fr: 'Mozzarella', en: 'Mozzarella' } },
      { id: 'fr-par', name: { fr: 'Parmesan', en: 'Parmesan' } },
      { id: 'fr-fet', name: { fr: 'Feta', en: 'Feta' } },
      { id: 'fr-bri', name: { fr: 'Brie', en: 'Brie' } },
    ] },
  { id: 's16', name: { fr: 'Pain', en: 'Bread' }, emoji: '🍞', mono: 'P', tone: '#D9A75A', defaultDays: 5, defaultLoc: 'pantry', defaultQty: '1', defaultUnit: { fr: 'pain', en: 'loaf' },
    variants: [
      { id: 'pn-bla', name: { fr: 'Blanc tranché', en: 'White sliced' } },
      { id: 'pn-com', name: { fr: 'Blé entier', en: 'Whole wheat' } },
      { id: 'pn-mul', name: { fr: 'Multigrain', en: 'Multigrain' } },
      { id: 'pn-bag', name: { fr: 'Baguette', en: 'Baguette' } },
      { id: 'pn-pit', name: { fr: 'Pitas', en: 'Pitas' } },
    ] },
  { id: 's17', name: { fr: 'Œufs', en: 'Eggs' }, emoji: '🥚', mono: 'O', tone: '#E8DCB6', defaultDays: 21, defaultLoc: 'fridge', defaultQty: '12', defaultUnit: { fr: 'pcs', en: 'pcs' } },
  { id: 's18', name: { fr: 'Yogourt', en: 'Yogurt' }, emoji: '🥣', mono: 'Y', tone: '#E8E0C8', defaultDays: 14, defaultLoc: 'fridge', defaultQty: '500', defaultUnit: 'g' },
  { id: 's19', name: { fr: 'Tomate', en: 'Tomato' }, emoji: '🍅', mono: 'T', tone: '#D86A55', defaultDays: 6, defaultLoc: 'fridge', defaultQty: '4', defaultUnit: { fr: 'pcs', en: 'pcs' } },
  { id: 's20', name: { fr: 'Pomme', en: 'Apple' }, emoji: '🍎', mono: 'P', tone: '#D85556', defaultDays: 14, defaultLoc: 'fridge', defaultQty: '5', defaultUnit: { fr: 'pcs', en: 'pcs' } },
  { id: 's21', name: { fr: 'Riz', en: 'Rice' }, emoji: '🌾', mono: 'R', tone: '#E2D7A6', defaultDays: 365, defaultLoc: 'pantry', defaultQty: '1', defaultUnit: 'kg',
    variants: [
      { id: 'ri-bas', name: { fr: 'Basmati', en: 'Basmati' } },
      { id: 'ri-jas', name: { fr: 'Jasmin', en: 'Jasmine' } },
      { id: 'ri-arb', name: { fr: 'Arborio', en: 'Arborio' } },
      { id: 'ri-bru', name: { fr: 'Brun', en: 'Brown' } },
    ] },
  { id: 's22', name: { fr: 'Pommes de terre', en: 'Potatoes' }, emoji: '🥔', mono: 'P', tone: '#D8B485', defaultDays: 21, defaultLoc: 'pantry', defaultQty: '1', defaultUnit: 'kg' },
  { id: 's23', name: { fr: 'Concombre', en: 'Cucumber' }, emoji: '🥒', mono: 'C', tone: '#7BB07A', defaultDays: 7, defaultLoc: 'fridge', defaultQty: '2', defaultUnit: { fr: 'pcs', en: 'pcs' } },
  { id: 's24', name: { fr: 'Poivron', en: 'Pepper' }, emoji: '🫑', mono: 'P', tone: '#D86655', defaultDays: 8, defaultLoc: 'fridge', defaultQty: '2', defaultUnit: { fr: 'pcs', en: 'pcs' } },
  { id: 's25', name: { fr: 'Épinards', en: 'Spinach' }, emoji: '🥬', mono: 'E', tone: '#7FB575', defaultDays: 5, defaultLoc: 'fridge', defaultQty: '1', defaultUnit: { fr: 'sac', en: 'bag' } },
  { id: 's26', name: { fr: 'Citron', en: 'Lemon' }, emoji: '🍋', mono: 'C', tone: '#E8D14A', defaultDays: 14, defaultLoc: 'fridge', defaultQty: '3', defaultUnit: { fr: 'pcs', en: 'pcs' } },
  { id: 's27', name: { fr: 'Bœuf haché', en: 'Ground beef' }, emoji: '🥩', mono: 'B', tone: '#B85149', defaultDays: 2, defaultLoc: 'fridge', defaultQty: '500', defaultUnit: 'g' },
  { id: 's28', name: { fr: 'Huile d\'olive', en: 'Olive oil' }, emoji: '🫒', mono: 'H', tone: '#9CB070', defaultDays: 365, defaultLoc: 'pantry', defaultQty: '1', defaultUnit: 'L' },
  { id: 's29', name: { fr: 'Brocoli', en: 'Broccoli' }, emoji: '🥦', mono: 'B', tone: '#5C9A5E', defaultDays: 6, defaultLoc: 'fridge', defaultQty: '1', defaultUnit: { fr: 'pcs', en: 'pcs' } },
  { id: 's30', name: { fr: 'Gingembre', en: 'Ginger' }, emoji: '🌿', mono: 'G', tone: '#C29A60', defaultDays: 21, defaultLoc: 'fridge', defaultQty: '50', defaultUnit: 'g' },
];

// ── FOODS — broad pantry/fridge/freezer database for search + bulk add ──
// Covers produce, proteins, dairy, grains, pantry staples, spices, condiments,
// baking, frozen, herbs, etc. — at minimum every ingredient used by the recipe
// catalog. `staple` items can be bulk-added as a typical kitchen starter.
function _food(id, fr, en, emoji, days, loc, unit, staple) {
  return {
    id: 'f_' + id, name: { fr, en }, emoji, mono: (fr[0] || '?').toUpperCase(), tone: '#9CA98C',
    defaultDays: days, defaultLoc: loc, defaultQty: '1',
    defaultUnit: typeof unit === 'string' ? unit : { fr: 'pcs', en: 'pcs' },
    cat: undefined, staple: !!staple,
  };
}
const FOODS = [
  // Vegetables
  _food('spinach', 'Épinards', 'Spinach', '🥬', 5, 'fridge', { fr: 'sac', en: 'bag' }),
  _food('lettuce', 'Laitue', 'Lettuce', '🥬', 7, 'fridge', { fr: 'pcs', en: 'head' }),
  _food('kale', 'Chou kale', 'Kale', '🥬', 6, 'fridge', { fr: 'botte', en: 'bunch' }),
  _food('tomato', 'Tomates', 'Tomatoes', '🍅', 7, 'fridge', 'pcs', true),
  _food('cherrytomato', 'Tomates cerises', 'Cherry tomatoes', '🍅', 7, 'fridge', 'g'),
  _food('onion', 'Oignon', 'Onion', '🧅', 30, 'pantry', 'pcs', true),
  _food('redonion', 'Oignon rouge', 'Red onion', '🧅', 30, 'pantry', 'pcs'),
  _food('greenonion', 'Oignon vert', 'Green onion', '🌿', 10, 'fridge', { fr: 'botte', en: 'bunch' }),
  _food('garlic', 'Ail', 'Garlic', '🧄', 60, 'pantry', { fr: 'tête', en: 'head' }, true),
  _food('pepper', 'Poivron', 'Bell pepper', '🫑', 10, 'fridge', 'pcs', true),
  _food('carrot', 'Carottes', 'Carrots', '🥕', 21, 'fridge', 'pcs', true),
  _food('celery', 'Céleri', 'Celery', '🥬', 14, 'fridge', { fr: 'branche', en: 'stalk' }),
  _food('cucumber', 'Concombre', 'Cucumber', '🥒', 10, 'fridge', 'pcs'),
  _food('broccoli', 'Brocoli', 'Broccoli', '🥦', 7, 'fridge', 'pcs', true),
  _food('cauliflower', 'Chou-fleur', 'Cauliflower', '🥦', 7, 'fridge', 'pcs'),
  _food('mushroom', 'Champignons', 'Mushrooms', '🍄', 7, 'fridge', 'g'),
  _food('potato', 'Pommes de terre', 'Potatoes', '🥔', 30, 'pantry', 'pcs', true),
  _food('sweetpotato', 'Patate douce', 'Sweet potato', '🍠', 21, 'pantry', 'pcs'),
  _food('zucchini', 'Courgette', 'Zucchini', '🥒', 10, 'fridge', 'pcs'),
  _food('eggplant', 'Aubergine', 'Eggplant', '🍆', 7, 'fridge', 'pcs'),
  _food('corn', 'Maïs', 'Corn', '🌽', 5, 'fridge', 'pcs'),
  _food('peas', 'Petits pois', 'Peas', '🟢', 240, 'freezer', 'g'),
  _food('greenbean', 'Haricots verts', 'Green beans', '🫛', 7, 'fridge', 'g'),
  _food('bokchoy', 'Bok choy', 'Bok choy', '🥬', 7, 'fridge', 'pcs'),
  _food('avocado', 'Avocat', 'Avocado', '🥑', 4, 'fridge', 'pcs', true),
  _food('squash', 'Courge', 'Squash', '🎃', 30, 'pantry', 'pcs'),
  _food('beet', 'Betterave', 'Beet', '🟣', 21, 'fridge', 'pcs'),
  _food('cabbage', 'Chou', 'Cabbage', '🥬', 21, 'fridge', 'pcs'),
  // Fruit
  _food('banana', 'Banane', 'Banana', '🍌', 5, 'pantry', 'pcs', true),
  _food('apple', 'Pomme', 'Apple', '🍎', 21, 'fridge', 'pcs', true),
  _food('lemon', 'Citron', 'Lemon', '🍋', 21, 'fridge', 'pcs', true),
  _food('lime', 'Lime', 'Lime', '🍈', 21, 'fridge', 'pcs'),
  _food('orange', 'Orange', 'Orange', '🍊', 21, 'fridge', 'pcs'),
  _food('berries', 'Petits fruits', 'Mixed berries', '🫐', 5, 'fridge', 'g'),
  _food('strawberry', 'Fraises', 'Strawberries', '🍓', 5, 'fridge', 'g'),
  _food('blueberry', 'Bleuets', 'Blueberries', '🫐', 7, 'fridge', 'g'),
  _food('grape', 'Raisins', 'Grapes', '🍇', 10, 'fridge', 'g'),
  _food('pear', 'Poire', 'Pear', '🍐', 10, 'fridge', 'pcs'),
  _food('mango', 'Mangue', 'Mango', '🥭', 7, 'fridge', 'pcs'),
  _food('pineapple', 'Ananas', 'Pineapple', '🍍', 7, 'fridge', 'pcs'),
  _food('date', 'Dattes', 'Dates', '🟤', 180, 'pantry', 'g'),
  // Proteins
  _food('chicken', 'Poulet', 'Chicken', '🍗', 2, 'fridge', 'g', true),
  _food('chickenbreast', 'Poitrines de poulet', 'Chicken breasts', '🍗', 2, 'fridge', 'pcs'),
  _food('beef', 'Bœuf haché', 'Ground beef', '🥩', 2, 'fridge', 'g', true),
  _food('beefcube', 'Cubes de bœuf', 'Beef cubes', '🥩', 2, 'fridge', 'g'),
  _food('steak', 'Bifteck', 'Steak', '🥩', 3, 'fridge', 'pcs'),
  _food('pork', 'Porc', 'Pork', '🐖', 3, 'fridge', 'g'),
  _food('groundpork', 'Porc haché', 'Ground pork', '🥩', 2, 'fridge', 'g'),
  _food('porkchop', 'Côtelettes de porc', 'Pork chops', '🍖', 3, 'fridge', 'pcs'),
  _food('ham', 'Jambon', 'Ham', '🍖', 7, 'fridge', 'g'),
  _food('bacon', 'Bacon', 'Bacon', '🥓', 14, 'fridge', { fr: 'paquet', en: 'pack' }),
  _food('salmon', 'Saumon', 'Salmon', '🐟', 2, 'fridge', { fr: 'filet', en: 'fillet' }, true),
  _food('tuna', 'Thon', 'Tuna', '🐟', 2, 'fridge', 'g'),
  _food('cannedtuna', 'Thon en conserve', 'Canned tuna', '🥫', 730, 'pantry', { fr: 'boîte', en: 'can' }),
  _food('cannedsalmon', 'Saumon en conserve', 'Canned salmon', '🥫', 730, 'pantry', { fr: 'boîte', en: 'can' }),
  _food('shrimp', 'Crevettes', 'Shrimp', '🦐', 2, 'fridge', 'g'),
  _food('cod', 'Morue', 'Cod', '🐟', 2, 'fridge', { fr: 'filet', en: 'fillet' }),
  _food('walleye', 'Doré', 'Walleye', '🐟', 2, 'fridge', { fr: 'filet', en: 'fillet' }),
  _food('tofu', 'Tofu', 'Tofu', '🧈', 14, 'fridge', { fr: 'bloc', en: 'block' }, true),
  _food('egg', 'Œufs', 'Eggs', '🥚', 28, 'fridge', { fr: 'douzaine', en: 'dozen' }, true),
  // Dairy
  _food('milk', 'Lait', 'Milk', '🥛', 7, 'fridge', 'L', true),
  _food('butter', 'Beurre', 'Butter', '🧈', 60, 'fridge', { fr: 'bloc', en: 'block' }, true),
  _food('cream', 'Crème', 'Cream', '🥛', 14, 'fridge', 'ml'),
  _food('yogurt', 'Yogourt', 'Yogurt', '🥛', 21, 'fridge', { fr: 'pot', en: 'tub' }),
  _food('greekyogurt', 'Yogourt grec', 'Greek yogurt', '🥛', 21, 'fridge', { fr: 'pot', en: 'tub' }),
  _food('cheddar', 'Cheddar', 'Cheddar', '🧀', 30, 'fridge', 'g', true),
  _food('mozzarella', 'Mozzarella', 'Mozzarella', '🧀', 21, 'fridge', 'g'),
  _food('parmesan', 'Parmesan', 'Parmesan', '🧀', 60, 'fridge', 'g'),
  _food('feta', 'Féta', 'Feta', '🧀', 30, 'fridge', 'g'),
  _food('curds', 'Fromage en grains', 'Cheese curds', '🧀', 14, 'fridge', 'g'),
  _food('creamcheese', 'Fromage à la crème', 'Cream cheese', '🧀', 30, 'fridge', { fr: 'paquet', en: 'pack' }),
  _food('swiss', 'Fromage suisse', 'Swiss cheese', '🧀', 30, 'fridge', 'g'),
  _food('ricotta', 'Ricotta', 'Ricotta', '🧀', 14, 'fridge', { fr: 'pot', en: 'tub' }),
  _food('mascarpone', 'Mascarpone', 'Mascarpone', '🧀', 14, 'fridge', { fr: 'pot', en: 'tub' }),
  // Grains / dry
  _food('rice', 'Riz', 'Rice', '🍚', 365, 'pantry', 'g', true),
  _food('arborio', 'Riz arborio', 'Arborio rice', '🍚', 365, 'pantry', 'g'),
  _food('pasta', 'Pâtes', 'Pasta', '🍝', 365, 'pantry', 'g', true),
  _food('spaghetti', 'Spaghetti', 'Spaghetti', '🍝', 365, 'pantry', 'g'),
  _food('macaroni', 'Macaroni', 'Macaroni', '🍝', 365, 'pantry', 'g'),
  _food('lasagna', 'Pâtes à lasagne', 'Lasagna noodles', '🍝', 365, 'pantry', { fr: 'boîte', en: 'box' }),
  _food('noodles', 'Nouilles', 'Noodles', '🍜', 365, 'pantry', 'g'),
  _food('ricenoodle', 'Nouilles de riz', 'Rice noodles', '🍜', 365, 'pantry', 'g'),
  _food('quinoa', 'Quinoa', 'Quinoa', '🌾', 365, 'pantry', 'g'),
  _food('oats', 'Flocons d\'avoine', 'Rolled oats', '🌾', 365, 'pantry', 'g', true),
  _food('flour', 'Farine', 'Flour', '🌾', 365, 'pantry', 'g', true),
  _food('bread', 'Pain', 'Bread', '🍞', 7, 'pantry', { fr: 'pain', en: 'loaf' }, true),
  _food('bagel', 'Bagel', 'Bagel', '🥯', 7, 'pantry', { fr: 'paquet', en: 'pack' }),
  _food('tortilla', 'Tortillas', 'Tortillas', '🫓', 30, 'pantry', { fr: 'paquet', en: 'pack' }),
  _food('pita', 'Pita', 'Pita', '🫓', 14, 'pantry', { fr: 'paquet', en: 'pack' }),
  _food('couscous', 'Couscous', 'Couscous', '🌾', 365, 'pantry', 'g'),
  _food('breadcrumb', 'Chapelure', 'Breadcrumbs', '🍞', 180, 'pantry', 'g'),
  _food('piecrust', 'Pâte à tarte', 'Pie crust', '🥧', 60, 'freezer', 'pcs'),
  _food('pizzadough', 'Pâte à pizza', 'Pizza dough', '🍕', 7, 'fridge', { fr: 'boule', en: 'ball' }),
  // Legumes / cans
  _food('chickpea', 'Pois chiches', 'Chickpeas', '🫛', 730, 'pantry', { fr: 'boîte', en: 'can' }, true),
  _food('blackbean', 'Haricots noirs', 'Black beans', '🫘', 730, 'pantry', { fr: 'boîte', en: 'can' }),
  _food('kidneybean', 'Haricots rouges', 'Red kidney beans', '🫘', 730, 'pantry', { fr: 'boîte', en: 'can' }),
  _food('navybean', 'Haricots blancs', 'Navy beans', '🫘', 730, 'pantry', 'g'),
  _food('lentil', 'Lentilles', 'Lentils', '🟤', 365, 'pantry', 'g'),
  _food('redlentil', 'Lentilles corail', 'Red lentils', '🟠', 365, 'pantry', 'g'),
  _food('splitpea', 'Pois jaunes secs', 'Dried yellow peas', '🟡', 365, 'pantry', 'g'),
  _food('dicedtomato', 'Tomates en dés', 'Diced tomatoes', '🥫', 730, 'pantry', { fr: 'boîte', en: 'can' }, true),
  _food('tomatosauce', 'Sauce tomate', 'Tomato sauce', '🥫', 365, 'pantry', { fr: 'pot', en: 'jar' }, true),
  _food('cannedcorn', 'Maïs en conserve', 'Canned corn', '🥫', 730, 'pantry', { fr: 'boîte', en: 'can' }),
  _food('creamedcorn', 'Maïs en crème', 'Creamed corn', '🥫', 730, 'pantry', { fr: 'boîte', en: 'can' }),
  _food('coconutmilk', 'Lait de coco', 'Coconut milk', '🥥', 730, 'pantry', { fr: 'boîte', en: 'can' }),
  _food('broth', 'Bouillon', 'Broth', '🍲', 365, 'pantry', 'ml', true),
  _food('edamame', 'Edamame', 'Edamame', '🫛', 240, 'freezer', 'g'),
  // Pantry / condiments
  _food('oliveoil', 'Huile d\'olive', 'Olive oil', '🫒', 365, 'pantry', 'L', true),
  _food('oil', 'Huile végétale', 'Vegetable oil', '🛢️', 365, 'pantry', 'L', true),
  _food('vinegar', 'Vinaigre', 'Vinegar', '🍶', 730, 'pantry', 'ml', true),
  _food('balsamic', 'Vinaigre balsamique', 'Balsamic vinegar', '🍶', 730, 'pantry', 'ml'),
  _food('soysauce', 'Sauce soya', 'Soy sauce', '🍶', 730, 'pantry', 'ml', true),
  _food('ketchup', 'Ketchup', 'Ketchup', '🍅', 365, 'pantry', { fr: 'bouteille', en: 'bottle' }, true),
  _food('mustard', 'Moutarde', 'Mustard', '🟡', 365, 'pantry', { fr: 'pot', en: 'jar' }, true),
  _food('dijon', 'Moutarde de Dijon', 'Dijon mustard', '🟡', 365, 'pantry', { fr: 'pot', en: 'jar' }),
  _food('mayo', 'Mayonnaise', 'Mayonnaise', '🥚', 90, 'fridge', { fr: 'pot', en: 'jar' }, true),
  _food('salsa', 'Salsa', 'Salsa', '🍅', 60, 'fridge', { fr: 'pot', en: 'jar' }),
  _food('honey', 'Miel', 'Honey', '🍯', 730, 'pantry', { fr: 'pot', en: 'jar' }, true),
  _food('maple', 'Sirop d\'érable', 'Maple syrup', '🍁', 365, 'pantry', { fr: 'bouteille', en: 'bottle' }, true),
  _food('molasses', 'Mélasse', 'Molasses', '🟤', 730, 'pantry', { fr: 'bouteille', en: 'bottle' }),
  _food('peanutbutter', 'Beurre d\'arachide', 'Peanut butter', '🥜', 180, 'pantry', { fr: 'pot', en: 'jar' }, true),
  _food('tahini', 'Tahini', 'Tahini', '🥣', 180, 'pantry', { fr: 'pot', en: 'jar' }),
  _food('miso', 'Miso', 'Miso', '🍲', 180, 'fridge', { fr: 'pot', en: 'tub' }),
  _food('currypaste', 'Pâte de cari', 'Curry paste', '🟠', 180, 'fridge', { fr: 'pot', en: 'jar' }),
  _food('teriyaki', 'Sauce teriyaki', 'Teriyaki sauce', '🍶', 365, 'pantry', { fr: 'bouteille', en: 'bottle' }),
  _food('hotsauce', 'Sauce piquante', 'Hot sauce', '🌶️', 365, 'pantry', { fr: 'bouteille', en: 'bottle' }),
  // Baking / sweet
  _food('sugar', 'Sucre', 'Sugar', '🍬', 730, 'pantry', 'g', true),
  _food('brownsugar', 'Cassonade', 'Brown sugar', '🟤', 730, 'pantry', 'g', true),
  _food('bakingpowder', 'Poudre à pâte', 'Baking powder', '🥄', 365, 'pantry', { fr: 'pot', en: 'tin' }),
  _food('bakingsoda', 'Bicarbonate', 'Baking soda', '🥄', 730, 'pantry', { fr: 'boîte', en: 'box' }),
  _food('yeast', 'Levure', 'Yeast', '🥖', 365, 'pantry', { fr: 'sachet', en: 'packet' }),
  _food('vanilla', 'Vanille', 'Vanilla', '🟫', 730, 'pantry', { fr: 'bouteille', en: 'bottle' }),
  _food('chocolate', 'Chocolat', 'Chocolate', '🍫', 365, 'pantry', { fr: 'tablette', en: 'bar' }),
  _food('chocchips', 'Brisures de chocolat', 'Chocolate chips', '🍫', 365, 'pantry', { fr: 'sac', en: 'bag' }),
  _food('cocoa', 'Cacao', 'Cocoa', '🟫', 730, 'pantry', { fr: 'boîte', en: 'tin' }),
  _food('granola', 'Granola', 'Granola', '🥣', 120, 'pantry', { fr: 'sac', en: 'bag' }),
  // Spices / herbs
  _food('salt', 'Sel', 'Salt', '🧂', 1825, 'pantry', { fr: 'pot', en: 'tin' }, true),
  _food('blackpepper', 'Poivre', 'Pepper', '🧂', 1825, 'pantry', { fr: 'moulin', en: 'mill' }, true),
  _food('cinnamon', 'Cannelle', 'Cinnamon', '🟤', 730, 'pantry', { fr: 'pot', en: 'jar' }),
  _food('cumin', 'Cumin', 'Cumin', '🟤', 730, 'pantry', { fr: 'pot', en: 'jar' }),
  _food('paprika', 'Paprika', 'Paprika', '🔴', 730, 'pantry', { fr: 'pot', en: 'jar' }),
  _food('turmeric', 'Curcuma', 'Turmeric', '🟡', 730, 'pantry', { fr: 'pot', en: 'jar' }),
  _food('chilipowder', 'Poudre de chili', 'Chili powder', '🌶️', 730, 'pantry', { fr: 'pot', en: 'jar' }),
  _food('garammasala', 'Garam masala', 'Garam masala', '🟤', 730, 'pantry', { fr: 'pot', en: 'jar' }),
  _food('oregano', 'Origan', 'Oregano', '🌿', 730, 'pantry', { fr: 'pot', en: 'jar' }),
  _food('basil', 'Basilic', 'Basil', '🌿', 7, 'fridge', { fr: 'botte', en: 'bunch' }),
  _food('parsley', 'Persil', 'Parsley', '🌿', 7, 'fridge', { fr: 'botte', en: 'bunch' }),
  _food('cilantro', 'Coriandre', 'Cilantro', '🌿', 7, 'fridge', { fr: 'botte', en: 'bunch' }),
  _food('thyme', 'Thym', 'Thyme', '🌿', 14, 'fridge', { fr: 'botte', en: 'bunch' }),
  _food('rosemary', 'Romarin', 'Rosemary', '🌿', 14, 'fridge', { fr: 'botte', en: 'bunch' }),
  _food('ginger', 'Gingembre', 'Ginger', '🌿', 21, 'fridge', 'g'),
  _food('clove', 'Clou de girofle', 'Clove', '🟤', 730, 'pantry', { fr: 'pot', en: 'jar' }),
  _food('nutmeg', 'Muscade', 'Nutmeg', '🟤', 730, 'pantry', { fr: 'pot', en: 'jar' }),
  _food('cardamom', 'Cardamome', 'Cardamom', '🟢', 730, 'pantry', { fr: 'pot', en: 'jar' }),
  // Nuts / misc
  _food('almond', 'Amandes', 'Almonds', '🌰', 180, 'pantry', 'g'),
  _food('walnut', 'Noix', 'Walnuts', '🌰', 180, 'pantry', 'g'),
  _food('peanut', 'Arachides', 'Peanuts', '🥜', 180, 'pantry', 'g'),
  _food('cashew', 'Noix de cajou', 'Cashews', '🌰', 180, 'pantry', 'g'),
  _food('sesame', 'Graines de sésame', 'Sesame seeds', '🌰', 365, 'pantry', 'g'),
  _food('coffee', 'Café', 'Coffee', '☕', 180, 'pantry', { fr: 'sac', en: 'bag' }, true),
  _food('tea', 'Thé', 'Tea', '🍵', 365, 'pantry', { fr: 'boîte', en: 'box' }),
  _food('olives', 'Olives', 'Olives', '🫒', 180, 'pantry', { fr: 'pot', en: 'jar' }),
  _food('capers', 'Câpres', 'Capers', '🫛', 365, 'pantry', { fr: 'pot', en: 'jar' }),
  _food('seaweed', 'Algues', 'Seaweed', '🌿', 365, 'pantry', { fr: 'paquet', en: 'pack' }),
  _food('redwine', 'Vin rouge', 'Red wine', '🍷', 365, 'pantry', { fr: 'bouteille', en: 'bottle' }),
  _food('whitewine', 'Vin blanc', 'Vin blanc', '🍷', 365, 'pantry', { fr: 'bouteille', en: 'bottle' }),
];

// Master id → {name, emoji} map: resolves recipe ingredient ids to a NAME even
// when the item isn't in the user's current inventory (fixes "qty with no name").
const FOOD_BY_ID = {};
[].concat(DEFAULT_INVENTORY, ITEM_SUGGESTIONS, FOODS).forEach(it => {
  if (it && it.id && !FOOD_BY_ID[it.id]) FOOD_BY_ID[it.id] = { name: it.name, emoji: it.emoji };
});
// Resolve an ingredient's display name + emoji from its inline data or the DB.
function resolveIngredient(ing) {
  if (!ing) return { name: { fr: '', en: '' }, emoji: '🍽' };
  const f = FOOD_BY_ID[ing.id];
  return {
    name: ing.name || (f && f.name) || { fr: 'Ingrédient', en: 'Ingredient' },
    emoji: ing.emoji || (f && f.emoji) || '🍽',
  };
}
// Combined searchable add-catalog (suggestions first, then the broad DB).
const ADD_CATALOG = ITEM_SUGGESTIONS.concat(FOODS);

// Approximate average price per default unit, for "saved $" estimate + grocery total.
// Real version: pulled from regional flyers (Reebee/IGA/Metro APIs).
const PRICE_DB = {
  's1': 1.49, 's2': 0.45, 's3': 5.99, 's4': 11.99, 's5': 3.49, 's6': 2.99,
  's10': 0.99, 's11': 0.69, 's12': 5.49, 's13': 9.99, 's14': 2.49, 's15': 7.49,
  's16': 3.49, 's17': 4.99, 's18': 4.49, 's19': 0.79, 's20': 0.89, 's21': 4.99,
  's22': 3.99, 's23': 1.49, 's24': 1.99, 's25': 4.49, 's26': 0.69, 's27': 8.99,
  's28': 12.99, 's29': 2.99, 's30': 0.59,
};

// Mock current flyer specials (price + retailer + km)
const FLYER_SPECIALS = [
  { id: 's1', price: 1.00, was: 1.49, retailer: 'IGA', km: 0.8, ends: 3 },
  { id: 's13', price: 6.99, was: 9.99, retailer: 'Metro', km: 1.4, ends: 2 },
  { id: 's3', price: 4.49, was: 5.99, retailer: 'Maxi', km: 2.1, ends: 5 },
];

// AI Photo "detected" items — used for the AI flow
const AI_DETECTED = [
  { id: 's1', name: { fr: 'Avocat', en: 'Avocado' }, emoji: '🥑', mono: 'A', tone: '#7FA86A', defaultDays: 3, defaultLoc: 'fridge', defaultQty: '2', defaultUnit: { fr: 'pcs', en: 'pcs' }, conf: 96 },
  { id: 'd2', name: { fr: 'Citron', en: 'Lemon' }, emoji: '🍋', mono: 'L', tone: '#E8D14A', defaultDays: 10, defaultLoc: 'fridge', defaultQty: '3', defaultUnit: { fr: 'pcs', en: 'pcs' }, conf: 91 },
  { id: 'd3', name: { fr: 'Poivron rouge', en: 'Red pepper' }, emoji: '🫑', mono: 'P', tone: '#D86655', defaultDays: 7, defaultLoc: 'fridge', defaultQty: '2', defaultUnit: { fr: 'pcs', en: 'pcs' }, conf: 88 },
];

// Recipes — manually curated, matched against inventory ids
const RECIPES = [
  {
    id: 'r1',
    name: { fr: 'Avocado toast aux épinards', en: 'Avocado toast with spinach' },
    accent: '#7FA86A',
    accentSoft: '#E2EBD9',
    bg1: '#A8C895', bg2: '#7FA86A',
    minutes: 12, prepTime: 5, cookTime: 7,
    portions: 2,
    difficulty: { fr: 'Facile', en: 'Easy' },
    nutrition: { cal: 340, p: 14, c: 32, f: 18 },
    hero: '🥑',
    tagline: { fr: 'Brunch rapide, anti-gaspillage', en: 'Quick brunch, anti-waste' },
    uses: ['s1', 'i1', 'i3'],
    ingredients: [
      { id: 's1', qty: { fr: '1 mûr', en: '1 ripe' } },
      { id: 'i1', qty: { fr: '1 poignée', en: '1 handful' } },
      { id: 'i3', qty: { fr: '2 tranches', en: '2 slices' } },
      { id: 'i8', qty: { fr: '2', en: '2' } },
      { id: 'extra1', name: { fr: 'Citron', en: 'Lemon' }, emoji: '🍋', qty: { fr: '½', en: '½' }, missing: true },
      { id: 'extra2', name: { fr: 'Sel · Poivre', en: 'Salt · Pepper' }, emoji: '🧂', qty: { fr: '—', en: '—' }, missing: false, pantry: true },
    ],
    steps: [
      { fr: 'Toaste le pain doré.', en: 'Toast the bread until golden.' },
      { fr: "Écrase l'avocat avec citron, sel, poivre.", en: 'Mash the avocado with lemon, salt, pepper.' },
      { fr: 'Étale sur le pain, ajoute les épinards.', en: 'Spread on the bread, top with spinach.' },
      { fr: 'Dépose un œuf poché sur le dessus.', en: 'Add a poached egg on top.' },
    ],
  },
  {
    id: 'r2',
    name: { fr: 'Pâtes crémeuses aux tomates', en: 'Creamy tomato pasta' },
    accent: '#D86A55',
    accentSoft: '#F5DDD6',
    bg1: '#E89478', bg2: '#D86A55',
    minutes: 22, prepTime: 8, cookTime: 14,
    portions: 4,
    difficulty: { fr: 'Facile', en: 'Easy' },
    nutrition: { cal: 520, p: 18, c: 78, f: 14 },
    hero: '🍝',
    tagline: { fr: 'Réconfortant en 22 min', en: 'Comfort in 22 min' },
    uses: ['i6', 'i7', 'i2'],
    ingredients: [
      { id: 'i6', qty: { fr: '300 g', en: '300 g' } },
      { id: 'i7', qty: { fr: '250 g', en: '250 g' } },
      { id: 'i2', qty: { fr: '200 ml', en: '200 ml' } },
      { id: 'i9', qty: { fr: '50 g râpé', en: '50 g grated' } },
      { id: 'extra3', name: { fr: 'Ail', en: 'Garlic' }, emoji: '🧄', qty: { fr: '2 gousses', en: '2 cloves' }, missing: true },
      { id: 'extra4', name: { fr: 'Basilic', en: 'Basil' }, emoji: '🌿', qty: { fr: '6 feuilles', en: '6 leaves' }, missing: true },
    ],
    steps: [
      { fr: 'Fais bouillir une grande casserole d\'eau salée. Ajoute les pâtes, cuis al dente (8–10 min).', en: 'Bring a large pot of salted water to a boil. Cook pasta al dente (8–10 min).' },
      { fr: 'Fais revenir l\'ail écrasé dans l\'huile d\'olive 1 min.', en: 'Sauté crushed garlic in olive oil for 1 min.' },
      { fr: 'Ajoute les tomates coupées, laisse éclater 5 min.', en: 'Add halved tomatoes, let them burst for 5 min.' },
      { fr: 'Verse la crème, ajoute le fromage râpé, mijote 3 min.', en: 'Pour in cream, add grated cheese, simmer 3 min.' },
      { fr: 'Mélange les pâtes égouttées, garnis de basilic.', en: 'Toss in drained pasta, top with basil.' },
    ],
  },
  {
    id: 'r3',
    name: { fr: 'Omelette grecque', en: 'Greek omelette' },
    accent: '#E8B65F',
    accentSoft: '#F8E8C7',
    bg1: '#F2C97A', bg2: '#E8B65F',
    minutes: 8, prepTime: 3, cookTime: 5,
    portions: 2,
    difficulty: { fr: 'Facile', en: 'Easy' },
    nutrition: { cal: 280, p: 19, c: 3, f: 21 },
    hero: '🍳',
    tagline: { fr: 'Petit-déj express', en: 'Quick breakfast' },
    uses: ['i8', 'i9', 'i1'],
    ingredients: [
      { id: 'i8', qty: { fr: '4', en: '4' } },
      { id: 'i9', qty: { fr: '60 g', en: '60 g' } },
      { id: 'i1', qty: { fr: '1 poignée', en: '1 handful' } },
    ],
    steps: [
      { fr: 'Bats les œufs avec sel et poivre.', en: 'Whisk eggs with salt and pepper.' },
      { fr: 'Fais fondre du beurre dans une poêle chaude.', en: 'Melt butter in a hot pan.' },
      { fr: 'Verse les œufs, ajoute le fromage et les épinards.', en: 'Pour in eggs, add cheese and spinach.' },
      { fr: 'Plie en deux, sers chaud.', en: 'Fold in half, serve hot.' },
    ],
  },
];

// More recipes (used in the Recipes feed)
RECIPES.push(
  {
    id: 'r4',
    name: { fr: 'Bol poulet & légumes rôtis', en: 'Chicken & roasted veg bowl' },
    accent: '#C68A2E', accentSoft: '#F6E5C2',
    bg1: '#E0B05E', bg2: '#C68A2E',
    minutes: 32, portions: 3, difficulty: { fr: 'Moyen', en: 'Medium' },
    prepTime: 10, cookTime: 22,
    nutrition: { cal: 480, p: 34, c: 38, f: 18 },
    hero: '🍗', tagline: { fr: 'Souper réconfortant', en: 'Comforting dinner' },
    mealType: 'dinner',
    uses: ['i5', 'i7', 'i1'],
    ingredients: [
      { id: 'i5', qty: { fr: '500 g', en: '500 g' } },
      { id: 'i7', qty: { fr: '150 g', en: '150 g' } },
      { id: 'i1', qty: { fr: '1 sac', en: '1 bag' } },
      { id: 'ex5', name: { fr: 'Huile d\'olive', en: 'Olive oil' }, emoji: '🫒', qty: { fr: '2 c.s.', en: '2 tbsp' }, pantry: true },
      { id: 'ex6', name: { fr: 'Pommes de terre', en: 'Potatoes' }, emoji: '🥔', qty: { fr: '4', en: '4' }, missing: true },
    ],
    steps: [
      { fr: 'Préchauffe le four à 200°C.', en: 'Preheat oven to 400°F (200°C).' },
      { fr: 'Coupe les pommes de terre en cubes, mélange-les avec l\'huile, sel et poivre.', en: 'Cube potatoes, toss with oil, salt and pepper.' },
      { fr: 'Place le poulet et les pommes de terre sur une plaque, rôtis 25 min.', en: 'Place chicken and potatoes on a sheet pan, roast 25 min.' },
      { fr: 'Ajoute les tomates les 5 dernières minutes.', en: 'Add tomatoes for the last 5 min.' },
      { fr: 'Sers sur lit d\'épinards frais.', en: 'Serve on a bed of fresh spinach.' },
    ],
  },
  {
    id: 'r5',
    name: { fr: 'Yogourt aux fruits', en: 'Yogurt parfait' },
    accent: '#7FA86A', accentSoft: '#E2EBD9',
    bg1: '#BFD6A8', bg2: '#A2C28C',
    minutes: 5, portions: 1, difficulty: { fr: 'Facile', en: 'Easy' },
    prepTime: 5, cookTime: 0,
    nutrition: { cal: 290, p: 18, c: 38, f: 6 },
    hero: '🥣', tagline: { fr: 'Petit-déj en 5 min', en: '5-min breakfast' },
    mealType: 'breakfast',
    uses: ['i4'],
    ingredients: [
      { id: 'i4', qty: { fr: '200 g', en: '200 g' } },
      { id: 'ex7', name: { fr: 'Bleuets', en: 'Blueberries' }, emoji: '🫐', qty: { fr: '½ tasse', en: '½ cup' }, missing: true },
      { id: 'ex8', name: { fr: 'Granola', en: 'Granola' }, emoji: '🌾', qty: { fr: '30 g', en: '30 g' }, missing: true },
      { id: 'ex9', name: { fr: 'Miel', en: 'Honey' }, emoji: '🍯', qty: { fr: '1 c.t.', en: '1 tsp' }, pantry: true },
    ],
    steps: [
      { fr: 'Verse la moitié du yogourt dans un grand verre.', en: 'Spoon half the yogurt into a tall glass.' },
      { fr: 'Ajoute une couche de bleuets et de granola.', en: 'Add a layer of blueberries and granola.' },
      { fr: 'Répète, finis avec un filet de miel.', en: 'Repeat, finish with a drizzle of honey.' },
    ],
  },
  {
    id: 'r6',
    name: { fr: 'Sandwich grillé au fromage', en: 'Grilled cheese' },
    accent: '#D9A75A', accentSoft: '#F5E5C8',
    bg1: '#EBC983', bg2: '#D9A75A',
    minutes: 10, portions: 2, difficulty: { fr: 'Facile', en: 'Easy' },
    prepTime: 3, cookTime: 7,
    nutrition: { cal: 420, p: 18, c: 32, f: 24 },
    hero: '🥪', tagline: { fr: 'Classique réconfortant', en: 'Comfort classic' },
    mealType: 'lunch',
    uses: ['i3', 'i9'],
    ingredients: [
      { id: 'i3', qty: { fr: '4 tranches', en: '4 slices' } },
      { id: 'i9', qty: { fr: '120 g', en: '120 g' } },
      { id: 's3', qty: { fr: '20 g', en: '20 g' }, missing: true, name: { fr: 'Beurre', en: 'Butter' }, emoji: '🧈' },
    ],
    steps: [
      { fr: 'Beurre légèrement le pain des deux côtés.', en: 'Lightly butter the bread on both sides.' },
      { fr: 'Garnis avec le fromage, ferme les sandwichs.', en: 'Fill with cheese, close the sandwiches.' },
      { fr: 'Grille à feu moyen-doux 3–4 min par côté.', en: 'Toast on medium-low 3–4 min per side.' },
    ],
  },
  {
    id: 'r7',
    name: { fr: 'Smoothie verde aux épinards', en: 'Green spinach smoothie' },
    accent: '#7FB575', accentSoft: '#D7E8CE',
    bg1: '#A8D29E', bg2: '#7FB575',
    minutes: 4, portions: 1, difficulty: { fr: 'Facile', en: 'Easy' },
    prepTime: 4, cookTime: 0,
    nutrition: { cal: 220, p: 9, c: 36, f: 4 },
    hero: '🥤', tagline: { fr: 'Boost énergie matinal', en: 'Morning energy boost' },
    mealType: 'breakfast',
    uses: ['i1', 'i2'],
    ingredients: [
      { id: 'i1', qty: { fr: '1 poignée', en: '1 handful' } },
      { id: 'i2', qty: { fr: '250 ml', en: '250 ml' } },
      { id: 'exB1', name: { fr: 'Banane', en: 'Banana' }, emoji: '🍌', qty: { fr: '1', en: '1' }, missing: true },
    ],
    steps: [
      { fr: 'Mets tout dans le blender.', en: 'Drop everything into the blender.' },
      { fr: 'Mixe 30 secondes jusqu\'à lisse.', en: 'Blend 30 seconds until smooth.' },
    ],
  },
);

// Grocery seed items
const DEFAULT_GROCERY = [
  { id: 'g1', name: { fr: 'Avocats', en: 'Avocados' }, emoji: '🥑', aisle: 'fresh', qty: '3', checked: false, source: 'recipe' },
  { id: 'g2', name: { fr: 'Citron', en: 'Lemon' }, emoji: '🍋', aisle: 'fresh', qty: '2', checked: false, source: 'recipe' },
  { id: 'g3', name: { fr: 'Ail', en: 'Garlic' }, emoji: '🧄', aisle: 'fresh', qty: '1 tête', checked: false, source: 'recipe' },
  { id: 'g4', name: { fr: 'Pâtes penne', en: 'Penne pasta' }, emoji: '🍝', aisle: 'dry', qty: '500 g', checked: false, source: 'manual' },
  { id: 'g5', name: { fr: 'Huile d\'olive', en: 'Olive oil' }, emoji: '🫒', aisle: 'dry', qty: '1 L', checked: true, source: 'manual' },
  { id: 'g6', name: { fr: 'Petits pois congelés', en: 'Frozen peas' }, emoji: '🫛', aisle: 'frozen', qty: '500 g', checked: false, source: 'manual' },
  { id: 'g7', name: { fr: 'Pain complet', en: 'Whole wheat bread' }, emoji: '🍞', aisle: 'dry', qty: '1', checked: true, source: 'manual' },
];

// Onboarding quick-pick items (more variety for the 5-tap setup)
const ONBOARD_PICKS = [
  { id: 'ob1', name: { fr: 'Lait', en: 'Milk' }, emoji: '🥛', defaultDays: 7, defaultLoc: 'fridge', defaultQty: '1', defaultUnit: 'L' },
  { id: 'ob2', name: { fr: 'Œufs', en: 'Eggs' }, emoji: '🥚', defaultDays: 14, defaultLoc: 'fridge', defaultQty: '12', defaultUnit: { fr: 'pcs', en: 'pcs' } },
  { id: 'ob3', name: { fr: 'Pain', en: 'Bread' }, emoji: '🍞', defaultDays: 4, defaultLoc: 'pantry', defaultQty: '1', defaultUnit: { fr: 'pain', en: 'loaf' } },
  { id: 'ob4', name: { fr: 'Beurre', en: 'Butter' }, emoji: '🧈', defaultDays: 30, defaultLoc: 'fridge', defaultQty: '250', defaultUnit: 'g' },
  { id: 'ob5', name: { fr: 'Poulet', en: 'Chicken' }, emoji: '🍗', defaultDays: 3, defaultLoc: 'fridge', defaultQty: '500', defaultUnit: 'g' },
  { id: 'ob6', name: { fr: 'Pâtes', en: 'Pasta' }, emoji: '🍝', defaultDays: 365, defaultLoc: 'pantry', defaultQty: '500', defaultUnit: 'g' },
  { id: 'ob7', name: { fr: 'Tomates', en: 'Tomatoes' }, emoji: '🍅', defaultDays: 5, defaultLoc: 'fridge', defaultQty: '4', defaultUnit: { fr: 'pcs', en: 'pcs' } },
  { id: 'ob8', name: { fr: 'Avocat', en: 'Avocado' }, emoji: '🥑', defaultDays: 3, defaultLoc: 'fridge', defaultQty: '2', defaultUnit: { fr: 'pcs', en: 'pcs' } },
  { id: 'ob9', name: { fr: 'Fromage', en: 'Cheese' }, emoji: '🧀', defaultDays: 14, defaultLoc: 'fridge', defaultQty: '200', defaultUnit: 'g' },
  { id: 'ob10', name: { fr: 'Yogourt', en: 'Yogurt' }, emoji: '🥣', defaultDays: 10, defaultLoc: 'fridge', defaultQty: '500', defaultUnit: 'g' },
  { id: 'ob11', name: { fr: 'Pommes', en: 'Apples' }, emoji: '🍎', defaultDays: 14, defaultLoc: 'fridge', defaultQty: '5', defaultUnit: { fr: 'pcs', en: 'pcs' } },
  { id: 'ob12', name: { fr: 'Banane', en: 'Banana' }, emoji: '🍌', defaultDays: 5, defaultLoc: 'pantry', defaultQty: '4', defaultUnit: { fr: 'pcs', en: 'pcs' } },
];

// Helper to figure out the meal type (used by recipes filter)
RECIPES.forEach(r => { if (!r.mealType) r.mealType = r.minutes <= 12 ? 'breakfast' : (r.minutes <= 20 ? 'lunch' : 'dinner'); });

// ─────────────────────────────────────────────────────────────
// MEAL PLAN — week schedule, with shared assignees + votes
// daysAhead 0 = today; meal slots: breakfast/lunch/dinner
// ─────────────────────────────────────────────────────────────
const HOUSEHOLD = [
  { id: 'u1', name: 'Alex',   tone: '#4F8267', initial: 'A' },
  { id: 'u2', name: 'Camille', tone: '#C68A2E', initial: 'C' },
  { id: 'u3', name: 'Sam',    tone: '#4A6FA5', initial: 'S' },
];

// recipeId references RECIPES; status: 'confirmed' | 'voting' | null
// Meals are keyed by real ISO date ('YYYY-MM-DD'). Seed data is anchored to
// the current week's Monday so the demo always looks "this week".
const _WK = startOfWeekISO(todayISO());
const MEAL_PLAN = [
  { date: addDays(_WK, 0), slot: 'dinner',    recipeId: 'r4', cook: 'u1', status: 'confirmed', time: '18:30' },
  { date: addDays(_WK, 0), slot: 'lunch',     recipeId: 'r6', cook: 'u2', status: 'confirmed', time: '12:30' },
  { date: addDays(_WK, 1), slot: 'breakfast', recipeId: 'r5', cook: 'u1', status: 'confirmed', time: '08:00' },
  { date: addDays(_WK, 1), slot: 'dinner',    recipeId: 'r2', cook: 'u2', status: 'voting', votes: { u1: true, u2: true, u3: false }, time: '19:00' },
  { date: addDays(_WK, 2), slot: 'dinner',    recipeId: 'r3', cook: 'u3', status: 'confirmed', time: '18:00' },
  { date: addDays(_WK, 3), slot: 'dinner',    recipeId: 'r1', cook: 'u1', status: 'voting', votes: { u1: true, u2: null, u3: null }, time: '18:30' },
  { date: addDays(_WK, 5), slot: 'dinner',    recipeId: 'r7', cook: 'u2', status: 'confirmed', time: '19:30' },
];

// Leftovers from things you've cooked (set by handleCooked → addLeftover)
const DEFAULT_LEFTOVERS = [
  { id: 'lf1', recipeId: 'r2', portions: 2, cookedDaysAgo: 0, name: { fr: 'Pâtes crémeuses aux tomates', en: 'Creamy tomato pasta' }, emoji: '🍝' },
];

const NOTIF_PREFS_DEFAULT = {
  expiry: true,
  low: true,
  specials: true,
  noMeal: false,
  ready: true,
};

const DIETS_LIST = ['none', 'vegan', 'vegetarian', 'gf', 'lactose', 'keto', 'pescetarian'];
const dietLabel = (lang, k) => ({
  none: t(lang, 'dietNone'),
  vegan: t(lang, 'dietVegan'),
  vegetarian: t(lang, 'dietVeg'),
  gf: t(lang, 'dietGF'),
  lactose: t(lang, 'dietLactose'),
  keto: t(lang, 'dietKeto'),
  pescetarian: t(lang, 'dietPescetarian'),
})[k] || k;

// helpers
const t = (lang, k) => (I18N[lang] || I18N.fr)[k] || k;
const localized = (lang, v) => (typeof v === 'string' ? v : v ? v[lang] || v.fr || v.en : '');
const itemById = (inv, id) => inv.find(i => i.id === id);

function statusOf(item) {
  if (item.daysLeft < 0) return 'expired';
  if (item.daysLeft <= 1) return 'urgent';
  if (item.daysLeft <= 3) return 'soon';
  return 'safe';
}

function expiryLabel(lang, daysLeft) {
  if (daysLeft < 0) return lang === 'fr' ? `Expiré il y a ${-daysLeft}j` : `Expired ${-daysLeft}d ago`;
  if (daysLeft === 0) return lang === 'fr' ? 'Expire aujourd\'hui' : 'Expires today';
  if (daysLeft === 1) return lang === 'fr' ? 'Expire demain' : 'Expires tomorrow';
  if (daysLeft < 30) return lang === 'fr' ? `Expire dans ${daysLeft}j` : `Expires in ${daysLeft}d`;
  if (daysLeft < 365) return lang === 'fr' ? `Expire dans ${Math.round(daysLeft/30)}m` : `Expires in ${Math.round(daysLeft/30)}mo`;
  return lang === 'fr' ? `Expire dans 1 an+` : `Expires 1y+`;
}

Object.assign(window, {
  PALETTES, I18N, DEFAULT_INVENTORY, ITEM_SUGGESTIONS, AI_DETECTED, RECIPES,
  DEFAULT_GROCERY, ONBOARD_PICKS,
  PRICE_DB, FLYER_SPECIALS,
  HOUSEHOLD, MEAL_PLAN, DEFAULT_LEFTOVERS,
  NOTIF_PREFS_DEFAULT, DIETS_LIST, dietLabel,
  t, localized, itemById, statusOf, expiryLabel,
  isoDate, todayISO, parseISO, addDays, startOfWeekISO, weekdayIndex, dateNumber, monthYearLabel,
  migrateMealPlan,
  FOODS, FOOD_BY_ID, resolveIngredient, ADD_CATALOG,
  daysUntil, ensureExpiry, normalizeInventory,
});
