/* GUIDKO App — Connexion par identité + hub d'applications dynamique.
   - Chaque compte possède SES accès (apps souscrites) → le hub n'affiche que ça.
   - Inscription dynamique pilotée par Lia : questions → composition des accès.
   - Règles : un élève n'accède jamais aux vues pro ; un pro peut tout cumuler.
   - Activation vivante : on peut ajouter un service depuis le hub à tout moment. */

// ---------- Catalogue d'applications ----------
const APP_CATALOG = [
  { k: "pro",       fr: "Espace Pro",   en: "Pro app",      g: "♛", dark: true,  desc: { fr: "Gérant · Accueil · Moniteur — gérer l'auto-école.", en: "Manager · Front desk · Instructor — run the school." }, requires: "pro" },
  { k: "eleve",     fr: "Espace Élève", en: "Student app",  g: "▲", flame: true, desc: { fr: "Progression, réservations, code de la route.", en: "Progress, bookings, road code." }, requires: "eleve" },
  { k: "auto",      fr: "Marché Mobilité",  en: "Mobility Market",  g: "⇄", cream: true, desc: { fr: "Acheter · louer · vendre — autos, motos, vélos, bateaux, pièces. Ouvert à tous.", en: "Buy · rent · sell — cars, bikes, boats, parts. Open to all." }, requires: null },
  { k: "covoit",    fr: "Covoiturage",  en: "Carpool",      g: "⇅", desc: { fr: "Trajets partagés, Passager ou Conducteur.", en: "Shared rides, Passenger or Driver." }, requires: null },
  { k: "livraison", fr: "Livraison",    en: "Delivery",     g: "📦", desc: { fr: "Commander ou livrer — repas, colis, B2B.", en: "Order or deliver — food, parcels, B2B." }, requires: null },
  { k: "gps",       fr: "GUIDAROUTE",      en: "GUIDAROUTE",      g: "🛰", ink: true,  desc: { fr: "Le code de la route vivant en conduite.", en: "The road code alive while driving." }, requires: null },
];

// Route d'entrée par app
const APP_ROUTES = { pro: null /* choix de rôle */, eleve: "/eleve/overview", auto: "/auto/market", covoit: "/covoit/overview", livraison: "/livraison/overview", gps: "/gps/drive" };

// Promo + thème par application (page d'accueil : chaque app séparée)
const APP_PROMO = {
  pro:       { color: "#0B0F1F", accent: "#FF5A1F", tagline: { fr: "Pilote ton auto-école", en: "Run your driving school" }, pitch: { fr: "Planning, élèves, rentabilité, flotte. Gérant, accueil et moniteurs — chacun son espace.", en: "Schedule, students, profit, fleet. Manager, front desk and instructors — each their space." }, stat: { fr: "48 auto-écoles", en: "48 schools" } },
  eleve:     { color: "#FF5A1F", accent: "#fff",    tagline: { fr: "Décroche ton permis", en: "Get your licence" }, pitch: { fr: "Code en continu personnalisé par l'IA, réservation de leçons, suivi de progression jusqu'à l'examen.", en: "AI-personalized continuous code, lesson booking, progress tracking to the exam." }, stat: { fr: "Tous permis", en: "All licences" } },
  auto:      { color: "#A78BFA", accent: "#1a1030", tagline: { fr: "Achète, vends, loue", en: "Buy, sell, rent" }, pitch: { fr: "Toute la mobilité : autos, motos, vélos, trottinettes, bateaux, engins, pièces. Entre particuliers et pros, paiement sécurisé escrow.", en: "All mobility: cars, bikes, scooters, boats, machinery, parts. Private & pro, escrow-secured." }, stat: { fr: "2 481 annonces", en: "2,481 listings" } },
  covoit:    { color: "#0FB76B", accent: "#fff",    tagline: { fr: "Partage la route", en: "Share the road" }, pitch: { fr: "Passager ou conducteur. Trajets partagés, ponctuels ou récurrents, dans tout le pays.", en: "Passenger or driver. Shared rides, one-off or recurring, nationwide." }, stat: { fr: "Passager · Conducteur", en: "Passenger · Driver" } },
  livraison: { color: "#3B6FF8", accent: "#fff",    tagline: { fr: "Commande ou livre", en: "Order or deliver" }, pitch: { fr: "Repas, colis, médical, logistique B2B. Tous véhicules, du vélo au poids lourd.", en: "Food, parcels, medical, B2B logistics. Every vehicle, bike to truck." }, stat: { fr: "Client · Livreur", en: "Client · Courier" } },
  gps:       { color: "#0B0F1F", accent: "#FF5A1F", tagline: { fr: "Le code, vivant", en: "The code, alive" }, pitch: { fr: "GPS nouvelle génération : sécurité routière temps réel + carte des ressources de l'écosystème.", en: "Next-gen GPS: real-time road safety + ecosystem resource map." }, stat: { fr: "Création Schneider", en: "By Schneider" } },
};

// ---------- Comptes de démonstration (identité → accès) ----------
// proRoles = rôles INTERNES auto-école autorisés. Le gérant les détient tous
// (il accède à l'espace moniteur car c'est lui qui donne les accès) ; un moniteur
// indépendant n'a que ["moniteur"] et entre directement. Jamais d'espace élève côté pro.
const DEMO_ACCOUNTS = {
  "kevin@lubasa.fr":   { name: "Kevin Lubasa",  tone: 0, profile: "pro",   apps: ["pro", "auto", "covoit"],            proRoles: ["gerant", "accueil", "moniteur"], school: "Auto-École Lubasa", label: { fr: "Gérant d'auto-école", en: "School manager" } },
  "marc@lubasa.fr":    { name: "Marc Lefèvre",  tone: 2, profile: "pro",   apps: ["pro", "covoit", "gps"],             proRoles: ["moniteur"], school: "Auto-École Lubasa", label: { fr: "Moniteur (salarié)", en: "Instructor (staff)" } },
  "sofia@indep.fr":    { name: "Sofia Nkamba",  tone: 1, profile: "pro",   apps: ["pro", "gps"],                       proRoles: ["moniteur"], school: null, label: { fr: "Monitrice indépendante", en: "Independent instructor" } },
  "lea@gmail.com":     { name: "Léa Mercier",   tone: 3, profile: "eleve", apps: ["eleve", "covoit"],                  label: { fr: "Élève conduite B", en: "Student" } },
  "yanis@gmail.com":   { name: "Yanis Traoré",  tone: 4, profile: "libre", apps: ["covoit", "livraison", "auto", "gps"], label: { fr: "Conducteur indépendant", en: "Independent driver" } },
};

// Rôles internes auto-école qu'un compte est autorisé à ouvrir
function proRolesFor(acc) {
  if (acc && Array.isArray(acc.proRoles) && acc.proRoles.length) return acc.proRoles;
  return ["moniteur"];
}

function loadAccount(email) {
  let saved = {};
  try { saved = JSON.parse(localStorage.getItem("guidko_accounts") || "{}"); } catch (e) {}
  const demo = DEMO_ACCOUNTS[email];
  if (demo) {
    // Le code fait foi pour les comptes démo : on fusionne le sauvegardé MAIS
    // proRoles/profile viennent toujours de DEMO_ACCOUNTS (évite les données périmées).
    return { ...demo, ...(saved[email] || {}), proRoles: demo.proRoles, profile: demo.profile, school: demo.school };
  }
  return saved[email] || null;
}
function saveAccount(email, acc) {
  try {
    const saved = JSON.parse(localStorage.getItem("guidko_accounts") || "{}");
    saved[email] = acc;
    localStorage.setItem("guidko_accounts", JSON.stringify(saved));
  } catch (e) {}
}
// Règles d'éligibilité : ce qu'un profil PEUT activer
function eligibleApps(profile) {
  if (profile === "eleve") return ["eleve", "auto", "covoit", "livraison", "gps"];   // jamais "pro"
  if (profile === "pro")   return ["pro", "auto", "covoit", "livraison", "gps"];     // pas la vue élève
  return ["auto", "covoit", "livraison", "gps"];                                       // profil libre
}

// ---------- Questions Lia pour l'inscription dynamique ----------
const LIA_QUESTIONS = [
  { id: "who", fr: "Qui es-tu sur la route ?", en: "Who are you on the road?", multi: false, options: [
    { k: "pro",   fr: "Je travaille dans une auto-école", en: "I work in a driving school", apps: ["pro"], profile: "pro" },
    { k: "eleve", fr: "Je veux apprendre à conduire",     en: "I want to learn to drive",   apps: ["eleve"], profile: "eleve" },
    { k: "libre", fr: "Ni l'un ni l'autre — je roule déjà", en: "Neither — I already drive", apps: [], profile: "libre" },
  ]},
  { id: "wants", fr: "Que veux-tu faire sur GUIDKO ? (plusieurs choix possibles)", en: "What do you want to do on GUIDKO? (pick several)", multi: true, options: [
    { k: "market", fr: "Acheter, vendre ou louer un moyen de mobilité", en: "Buy, sell or rent any mobility", apps: ["auto"] },
    { k: "covoit", fr: "Covoiturer — comme passager ou conducteur", en: "Carpool — as passenger or driver", apps: ["covoit"] },
    { k: "livrer", fr: "Livrer ou me faire livrer", en: "Deliver or get delivered", apps: ["livraison"] },
    { k: "gps",    fr: "Conduire avec le GUIDAROUTE (code vivant)", en: "Drive with GUIDAROUTE (live code)", apps: ["gps"] },
    { k: "rien",   fr: "Juste l'essentiel pour l'instant", en: "Just the essentials for now", apps: [] },
  ]},
];

// ============================================================
function LoginScreen({ navigate }) {
  const C = GK.colors;
  const { lang, t, setLang } = useI18n();
  const store = useStore();
  // Lit l'intention laissée par le Discover (ou la galerie) pour ouvrir directement le bon service
  const getIntent = () => {
    try { const v = localStorage.getItem("guidko_intent"); if (v) { localStorage.removeItem("guidko_intent"); return v; } } catch (e) {}
    return null;
  };
  const _intent = React.useRef(getIntent());
  const [step, setStep] = React.useState(_intent.current ? "signin" : "gallery");
  const [appCtx, setAppCtx] = React.useState(_intent.current || null);

  // Deep-link depuis le Discover : une intention pré-sélectionne la porte de connexion.
  React.useEffect(() => {
    let intent = null;
    try { intent = localStorage.getItem("guidko_intent"); localStorage.removeItem("guidko_intent"); } catch (e) {}
    if (!intent) return;
    const appKeys = ["pro", "eleve", "auto", "covoit", "livraison", "gps"];
    if (appKeys.includes(intent)) { setAppCtx(intent); setStep("signin"); }
    else if (typeof enterService === "function") { enterService(intent); }
  }, []);
  const [email, setEmail] = React.useState("kevin@lubasa.fr");
  const [pwd, setPwd] = React.useState("guidko2026");
  const [account, setAccount] = React.useState(null);
  const [err, setErr] = React.useState("");
  const [authBusy, setAuthBusy] = React.useState(false);

  // — Lia signup state
  const [liaStep, setLiaStep] = React.useState(0);
  const [liaName, setLiaName] = React.useState("");
  const [liaAnswers, setLiaAnswers] = React.useState({}); // qid -> [option keys]
  // — Sécurité : 2FA + reset mot de passe
  const [vMethod, setVMethod] = React.useState("email");
  const [vCode, setVCode] = React.useState("");
  const [faceScan, setFaceScan] = React.useState(0); // 0 idle, 1 scanning, 2 ok
  const [fStep, setFStep] = React.useState(0);       // reset: 0 email, 1 code, 2 new pwd, 3 done
  const [fCode, setFCode] = React.useState("");
  const [fPwd, setFPwd] = React.useState("");
  const VERIFY_METHODS = [
    { k: "email", g: "✉", fr: "Code par email", en: "Email code", hint: { fr: "Envoyé à ton adresse", en: "Sent to your address" } },
    { k: "sms",   g: "📱", fr: "Code par SMS", en: "SMS code", hint: { fr: "Sur ton numéro ···45", en: "To your number ···45" } },
    { k: "face",  g: "🙂", fr: "Reconnaissance faciale", en: "Face recognition", hint: { fr: "Caméra du téléphone", en: "Phone camera" } },
    { k: "auth",  g: "🔑", fr: "Application authenticator", en: "Authenticator app", hint: { fr: "Code à 6 chiffres", en: "6-digit code" } },
  ];
  const [team, setTeam] = React.useState([
    { name: "Marc Lefèvre",  role: t("Moniteur · permis B","Instructor · B"),       tone: 2, on: true },
    { name: "Sofia Nkamba",  role: t("Accueil · inscriptions","Front desk"),         tone: 1, on: true },
    { name: "Karim Belaïd",  role: t("Moniteur · permis A/A2","Instructor · A/A2"),  tone: 4, on: false },
  ]);

  const proRoles = [
    { role: "gerant",   fr: "Gérant",   en: "Manager",     desc: t("Pilote l'auto-école : CA, planning, rentabilité.", "Run the school: revenue, schedule, profit."), g: "◎" },
    { role: "accueil",  fr: "Accueil",  en: "Front desk",  desc: t("Reçoit les élèves, gère les inscriptions.", "Welcomes students, manages enrollments."), g: "✎" },
    { role: "moniteur", fr: "Moniteur", en: "Instructor",  desc: t("Sa journée, ses élèves, ses gains.", "Their day, students, earnings."), g: "♛" },
  ];

  function normalizeBackendAccount(user, fallback) {
    const roleRaw = String((user && user.role) || "").toLowerCase();
    const isPro = ["pro", "manager", "gerant", "accueil", "frontdesk", "moniteur", "instructor", "school"].includes(roleRaw);
    const isStudent = ["eleve", "student", "learner"].includes(roleRaw);
    const profile = isPro ? "pro" : (isStudent ? "eleve" : ((fallback && fallback.profile) || "libre"));
    const defaultApps = profile === "pro"
      ? ["pro", "auto", "covoit", "livraison", "gps"]
      : profile === "eleve"
        ? ["eleve", "auto", "covoit", "livraison", "gps"]
        : ["auto", "covoit", "livraison", "gps"];
    const apps = (fallback && Array.isArray(fallback.apps) && fallback.apps.length) ? fallback.apps : defaultApps;
    const firstName = (user && user.firstName) || "";
    const lastName = (user && user.lastName) || "";
    const fullName = `${firstName} ${lastName}`.trim();
    return {
      name: fullName || (fallback && fallback.name) || "Membre GUIDKO",
      tone: (fallback && typeof fallback.tone === "number") ? fallback.tone : 2,
      profile,
      apps,
      proRoles: profile === "pro"
        ? ((fallback && Array.isArray(fallback.proRoles) && fallback.proRoles.length) ? fallback.proRoles : ["gerant", "accueil", "moniteur"])
        : undefined,
      school: (fallback && fallback.school) || null,
      label: (fallback && fallback.label) || (
        profile === "pro"
          ? { fr: "Professionnel", en: "Professional" }
          : profile === "eleve"
            ? { fr: "Élève", en: "Student" }
            : { fr: "Conducteur", en: "Driver" }
      ),
    };
  }

  async function signIn() {
    if (authBusy) return;
    const normalizedEmail = email.trim().toLowerCase();
    if (!normalizedEmail || !pwd) {
      setErr(t("Email et mot de passe requis.", "Email and password are required."));
      return;
    }

    const localAcc = loadAccount(normalizedEmail);
    const hasApi = !!(window.GuidkoAPI && window.GuidkoAPI.auth && typeof window.GuidkoAPI.auth.login === "function");
    setAuthBusy(true);
    setErr("");

    try {
      let nextAcc = null;

      if (hasApi) {
        try {
          const response = await window.GuidkoAPI.auth.login({ email: normalizedEmail, password: pwd });
          if (response && response.token && typeof window.GuidkoAPI.setToken === "function") {
            window.GuidkoAPI.setToken(response.token);
          }
          if (response && response.user) {
            nextAcc = normalizeBackendAccount(response.user, localAcc);
            saveAccount(normalizedEmail, nextAcc);
          }
        } catch (apiError) {
          const msg = (apiError && apiError.message) || "";
          const isConnectivityIssue = /failed to fetch|network|econnrefused|load failed|cors/i.test(msg.toLowerCase());
          if (!(isConnectivityIssue && localAcc)) throw apiError;
        }
      }

      if (!nextAcc) {
        if (!localAcc) {
          throw new Error(t("Compte inconnu. Essaie un compte démo ci-dessous, ou crée un compte avec Lia.", "Unknown account. Try a demo account below, or sign up with Lia."));
        }
        nextAcc = localAcc;
      }

      setAccount({ ...nextAcc, email: normalizedEmail });
      setVCode(""); setFaceScan(0); setVMethod("email");
      setStep("verify");   // passerelle 2FA avant le hub
    } catch (e) {
      setErr((e && e.message) || t("Connexion impossible.", "Unable to sign in."));
    } finally {
      setAuthBusy(false);
    }
  }

  // Mode invité : entrer dans une app sans compte (on est invité à s'inscrire ensuite)
  function guestEnter(appKey) {
    const k = appKey || "eleve";
    const role = k === "pro" ? "moniteur" : k;
    const extra = k === "covoit" ? { covoitSide: "passager" } : k === "livraison" ? { livrSide: "client" } : {};
    store.login({ name: t("Invité","Guest"), email: "", tone: 3, role, guest: true, ...extra });
    navigate(role === "pro" || k === "pro" ? "/moniteur/overview" : (APP_ROUTES[k] || `/${role}/overview`));
  }

  // Porte d'entrée vers une branche-service autonome : son propre espace.
  function enterService(section) {
    store.login({ name: t("Invité","Guest"), email: "", tone: 3, role: section, guest: true });
    navigate(`/${section}/overview`);
  }
  const SERVICE_DOORS = [
    { k: "assurance", ic: "shield",   color: "#0FB76B", fr: "Assurance",  en: "Insurance", d: { fr: "Trajets, véhicules, pro", en: "Trips, vehicles, pro" } },
    { k: "energie",   ic: "bolt",     color: "#0FB76B", fr: "Énergie",    en: "Energy",    d: { fr: "Carburant & recharge", en: "Fuel & charging" } },
    { k: "parking",   ic: "location", color: "#3B6FF8", fr: "Stationnement", en: "Parking", d: { fr: "Réserver une place", en: "Book a spot" } },
    { k: "entretien", ic: "auto",     color: "#A78BFA", fr: "Entretien",  en: "Service",   d: { fr: "Garages & pièces", en: "Garages & parts" } },
    { k: "flotte",    ic: "b2b",      color: "#6B7280", fr: "Flotte B2B", en: "B2B Fleet", d: { fr: "Gérer son parc", en: "Manage fleet" } },
    { k: "depannage", ic: "shield",   color: "#E11D48", fr: "Dépannage",  en: "Roadside",  d: { fr: "Assistance & remorquage", en: "Assist & tow" } },
    { k: "controle",  ic: "check",    color: "#0FB76B", fr: "Contrôle technique", en: "Inspection", d: { fr: "Réserver un créneau", en: "Book a slot" } },
    { k: "lavage",    ic: "bolt",     color: "#3B6FF8", fr: "Lavage",     en: "Wash",      d: { fr: "À domicile ou station", en: "Home or station" } },
    { k: "financement",ic: "finance", color: "#A78BFA", fr: "Financement",en: "Financing", d: { fr: "Crédit & leasing", en: "Loan & lease" } },
    { k: "recyclage", ic: "auto",     color: "#0FB76B", fr: "Recyclage",  en: "Recycling", d: { fr: "Fin de vie & pièces", en: "Scrap & parts" } },
    { k: "tourisme",  ic: "region",   color: "#FF5A1F", fr: "Tourisme & LLD", en: "Tourism", d: { fr: "Voyage & longue durée", en: "Travel & long-term" } },
    { k: "recharge",  ic: "bolt",     color: "#0FB76B", fr: "Recharge solidaire", en: "Solidarity charge", d: { fr: "Bornes partagées", en: "Shared chargers" } },
    { k: "emploi",    ic: "b2b",      color: "#3B6FF8", fr: "Emploi mobilité", en: "Mobility jobs", d: { fr: "Recrutement vérifié", en: "Verified hiring" } },
    { k: "formation", ic: "eleve",    color: "#A78BFA", fr: "Formation Pro", en: "Pro training", d: { fr: "Permis pro, CACES, VTC", en: "Pro licences, VTC" } },
    { k: "pass",      ic: "region",   color: "#FF5A1F", fr: "Pass Mobilité", en: "Mobility Pass", d: { fr: "Tout-en-un abonnement", en: "All-in-one plan" } },
    { k: "carrosserie", ic: "shield", color: "#E11D48", fr: "Carrosserie & Sinistre", en: "Bodywork & Claims", d: { fr: "Réparation, assurance", en: "Repair, insurance" } },
    { k: "mobilitedouce", ic: "covoit", color: "#0FB76B", fr: "Mobilité douce", en: "Soft mobility", d: { fr: "Vélos, trottinettes", en: "Bikes, scooters" } },
    { k: "convoyage", ic: "b2b",      color: "#6B7280", fr: "Convoyage", en: "Vehicle transport", d: { fr: "Transport de véhicules", en: "Vehicle ferrying" } },
    { k: "vtc",       ic: "covoit",   color: "#FF5A1F", fr: "Taxi & VTC", en: "Taxi & Ride", d: { fr: "Course à la demande", en: "Ride on demand" } },
    { k: "adapte",    ic: "shield",   color: "#3B6FF8", fr: "Transport adapté", en: "Accessible transport", d: { fr: "PMR, seniors", en: "PRM, seniors" } },
    { k: "autopartage", ic: "auto",   color: "#0FB76B", fr: "Auto-partage", en: "Car-sharing", d: { fr: "Voiture en libre-service", en: "Self-service car" } },
    { k: "demarches", ic: "contracts",color: "#A78BFA", fr: "Démarches auto", en: "Admin & papers", d: { fr: "Carte grise, plaques", en: "Registration, plates" } },
    { k: "train",     ic: "region",   color: "#3B6FF8", fr: "Train & Ferroviaire", en: "Rail", d: { fr: "Billets, porte-à-porte", en: "Tickets, door-to-door" } },
    { k: "bus",       ic: "b2b",      color: "#0FB76B", fr: "Bus & Car", en: "Bus & Coach", d: { fr: "Lignes, longue distance", en: "Lines, long distance" } },
    { k: "bateau",    ic: "region",   color: "#3B6FF8", fr: "Maritime & Fluvial", en: "Sea & River", d: { fr: "Ferry, permis bateau", en: "Ferry, boat licence" } },
    { k: "aerien",    ic: "region",   color: "#A78BFA", fr: "Aérien & Drone", en: "Air & Drone", d: { fr: "Navettes, drone", en: "Shuttles, drone" } },
    { k: "peage",     ic: "region",   color: "#6B7280", fr: "Péage & Autoroute", en: "Tolls & Highway", d: { fr: "Télépéage, vignettes", en: "E-toll, stickers" } },
    { k: "fret",      ic: "b2b",      color: "#6B7280", fr: "Fret & Transport lourd", en: "Freight", d: { fr: "Bourse de fret, PL", en: "Freight exchange" } },
    { k: "sanitaire", ic: "shield",   color: "#E11D48", fr: "Transport sanitaire", en: "Medical transport", d: { fr: "Ambulance, VSL", en: "Ambulance, medical" } },
    { k: "loisirs",   ic: "region",   color: "#0FB76B", fr: "Loisirs & Camping-car", en: "Leisure & Camper", d: { fr: "Van, caravane", en: "Van, caravan" } },
    { k: "engins",    ic: "b2b",      color: "#FF5A1F", fr: "Engins & BTP", en: "Machinery", d: { fr: "Chantier, agricole", en: "Site, farm" } },
    { k: "prevention",ic: "shield",   color: "#0FB76B", fr: "Prévention & Stages", en: "Safety & Courses", d: { fr: "Récup. points, stages", en: "Points, courses" } },
    { k: "evenement", ic: "covoit",   color: "#A78BFA", fr: "Événementiel", en: "Events", d: { fr: "Navettes, mariages", en: "Shuttles, weddings" } },
    { k: "voiturier", ic: "location", color: "#6B7280", fr: "Voiturier & Gardiennage", en: "Valet & Storage", d: { fr: "Voiturier, hivernage", en: "Valet, storage" } },
    { k: "connect",   ic: "bolt",     color: "#3B6FF8", fr: "Connectivité & Objets", en: "Connectivity", d: { fr: "Traceur, assurance km", en: "Tracker, pay-per-km" } },
    { k: "equipement",ic: "auto",     color: "#A78BFA", fr: "Équipement & Accessoires", en: "Gear", d: { fr: "Pneus, casques, sièges", en: "Tyres, helmets, seats" } },
    { k: "transit",   ic: "region",   color: "#0FB76B", fr: "Transit urbain", en: "Urban transit", d: { fr: "Métro, tram, multimodal", en: "Metro, tram" } },
    { k: "verte",     ic: "bolt",     color: "#0FB76B", fr: "Mobilité verte & Carbone", en: "Green & Carbon", d: { fr: "CO2, bonus écolo", en: "CO2, eco-bonus" } },
    { k: "data",      ic: "b2b",      color: "#6B7280", fr: "Data & Infrastructure", en: "Data & Infra", d: { fr: "API, bornes, smart-city", en: "API, chargers, city" } },
  ].filter(s => !window.GK_LAUNCH || window.GK_LAUNCH.branches.includes(s.k));

  // Familles du Discover — regroupent TOUTES les branches (apps + services) harmonieusement.
  const SERVICE_FAMILIES = [
    { fr: "Apprendre & Travailler", en: "Learn & Work", keys: ["emploi", "formation", "prevention", "demarches"] },
    { fr: "Acheter, Vendre & Entretenir", en: "Buy, Sell & Maintain", keys: ["entretien", "carrosserie", "equipement", "recyclage", "financement", "voiturier"] },
    { fr: "Se déplacer", en: "Get around", keys: ["vtc", "autopartage", "mobilitedouce", "adapte", "transit", "train", "bus", "bateau", "aerien"] },
    { fr: "Transporter & Livrer", en: "Transport & Deliver", keys: ["fret", "convoyage", "sanitaire", "flotte"] },
    { fr: "Énergie, Route & Loisirs", en: "Energy, Road & Leisure", keys: ["energie", "recharge", "parking", "peage", "lavage", "depannage", "controle", "loisirs", "engins", "evenement", "tourisme"] },
    { fr: "Socle, Confiance & Données", en: "Core, Trust & Data", keys: ["assurance", "pass", "connect", "verte", "data"] },
  ];
  const doorIndex = {}; SERVICE_DOORS.forEach(s => { doorIndex[s.k] = s; });
  function doorMeta(k) {
    const s = doorIndex[k];
    if (s) return { ic: s.ic, color: s.color, label: s[lang] || s.fr, desc: s.d[lang] || s.d.fr };
    const bd = window.BRANCH_DATA && window.BRANCH_DATA[k];
    return { ic: (bd && bd.icon) || "region", color: (bd && bd.accent) || "#6B7280", label: bd ? (bd[lang] || bd.fr) : k, desc: "" };
  }
  // Les apps principales mènent à leur page de connexion distincte ; les branches à leur espace.
  function doorEnter(k) {
    if (APP_PROMO[k]) { setAppCtx(k); setErr(""); setStep("signin"); return; }
    enterService(k);
  }

  function openApp(appKey) {
    if (appKey === "pro") {
      const roles = proRolesFor(account);
      if (roles.length === 1) { pickRole(roles[0]); return; }  // moniteur indépendant → direct
      setStep("pro"); return;
    }
    const role = appKey === "eleve" ? "eleve" : appKey === "auto" ? "auto" : appKey === "covoit" ? "covoit" : appKey === "livraison" ? "livraison" : "gps";
    store.login({ name: account.name, email: account.email, tone: account.tone, role });
    navigate(APP_ROUTES[appKey]);
  }

  // Après vérification 2FA : ouvre directement l'app choisie dans la galerie si l'identité y a accès
  function afterVerify() {
    if (appCtx && account && account.apps && account.apps.includes(appCtx)) { openApp(appCtx); return; }
    setStep("hub");
  }

  function activate(appKey) {
    const next = { ...account, apps: [...account.apps, appKey] };
    setAccount(next);
    saveAccount(account.email, next);
  }

  function pickRole(role) {
    // Garde RBAC : on n'entre que dans un rôle auquel le compte est autorisé
    if (account && !proRolesFor(account).includes(role)) return;
    store.login({ name: account ? account.name : ROLES[role].person.name, email: account ? account.email : "", tone: account ? account.tone : ROLES[role].person.tone, role });
    navigate(`/${role}/overview`);
  }

  // — Lia signup logic
  function liaToggle(q, optKey) {
    setLiaAnswers(a => {
      const cur = a[q.id] || [];
      if (!q.multi) return { ...a, [q.id]: [optKey] };
      return { ...a, [q.id]: cur.includes(optKey) ? cur.filter(k => k !== optKey) : [...cur, optKey] };
    });
  }
  async function liaFinish() {
    setErr("");
    const whoOpt = LIA_QUESTIONS[0].options.find(o => (liaAnswers.who || []).includes(o.k));
    const profile = whoOpt ? whoOpt.profile : "libre";
    const elig = eligibleApps(profile);
    let apps = [...(whoOpt ? whoOpt.apps : [])];
    (liaAnswers.wants || []).forEach(k => {
      const opt = LIA_QUESTIONS[1].options.find(o => o.k === k);
      if (opt) opt.apps.forEach(a => { if (elig.includes(a) && !apps.includes(a)) apps.push(a); });
    });
    if (apps.length === 0) apps = [elig[0]];
    const fullName = liaName.trim() || "Nouveau membre";
    const newEmail = (liaName.trim().toLowerCase().replace(/\s+/g, ".") || "nouveau") + "@guidko.com";
    const acc = {
      name: fullName,
      tone: Math.floor(Math.random() * 5),
      profile,
      apps,
      label: {
        fr: profile === "pro" ? "Professionnel" : profile === "eleve" ? "Élève" : "Conducteur",
        en: profile === "pro" ? "Professional" : profile === "eleve" ? "Student" : "Driver",
      },
    };

    if (window.GuidkoAPI && window.GuidkoAPI.auth && typeof window.GuidkoAPI.auth.register === "function") {
      try {
        const [firstName, ...rest] = fullName.split(/\s+/);
        const lastName = rest.join(" ") || "Membre";
        const signupPassword = (pwd && pwd.length >= 8) ? pwd : "guidko2026";
        const response = await window.GuidkoAPI.auth.register({
          email: newEmail,
          password: signupPassword,
          firstName: firstName || "Nouveau",
          lastName,
          role: profile === "pro" ? "pro" : profile === "eleve" ? "student" : "member",
        });
        if (response && response.token && typeof window.GuidkoAPI.setToken === "function") {
          window.GuidkoAPI.setToken(response.token);
        }
        if (response && response.user) {
          const backendAcc = normalizeBackendAccount(response.user, acc);
          saveAccount(newEmail, backendAcc);
          setAccount({ ...backendAcc, email: newEmail });
          setStep("hub");
          return;
        }
      } catch (e) {
        const msg = (e && e.message) || "";
        if (!/already|existe|registered|409/i.test(msg.toLowerCase())) {
          setErr(msg || t("Inscription impossible.", "Unable to register."));
          return;
        }
      }
    }

    saveAccount(newEmail, acc);
    setAccount({ ...acc, email: newEmail });
    setStep("hub");
  }

  const liaQ = LIA_QUESTIONS[Math.min(liaStep, LIA_QUESTIONS.length - 1)];
  const liaCanNext = liaStep === 0 ? (liaAnswers.who || []).length > 0 : true;

  // ---------- RENDER ----------
  // ===== GALERIE D'ACCUEIL : chaque app séparée, promo directe → page privée =====
  if (step === "gallery") {
    return (
      <div className="gk-scroll" style={{ height: "100vh", overflowY: "auto", background: C.ink, color: "#fff", fontFamily: "'Geist', sans-serif" }}>
        {/* topbar */}
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "22px 5vw", position: "sticky", top: 0, background: "rgba(11,15,31,0.86)", backdropFilter: "blur(10px)", zIndex: 20, borderBottom: "1px solid #161C36" }}>
          <GuidkoLogo color="#fff"/>
          <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
            <LangSelector dark compact/>
            <Button kind="flame" size="sm" onClick={() => { setAppCtx(null); setStep("signin"); }}>{t("Se connecter", "Sign in")}</Button>
          </div>
        </div>

        {/* hero */}
        <div style={{ padding: "60px 5vw 34px", maxWidth: 1240, margin: "0 auto", position: "relative" }}>
          <svg style={{ position: "absolute", right: "3vw", top: 30, opacity: 0.07, pointerEvents: "none" }} width="360" height="360" viewBox="0 0 48 48" fill="none">
            <path d="M4 38 L4 22 A12 12 0 0 1 16 10 L24 10" stroke="#fff" strokeWidth="0.5" fill="none"/>
            <path d="M44 38 L44 22 A12 12 0 0 0 32 10 L24 10" stroke="#fff" strokeWidth="0.5" fill="none"/>
            <rect x="4" y="37" width="40" height="0.5" fill="#fff"/>
          </svg>
          <Label color={C.flame} style={{ fontSize: 11 }}>{t("DISCOVER · L'ÉCOSYSTÈME DE LA MOBILITÉ", "DISCOVER · THE MOBILITY ECOSYSTEM")}</Label>
          <h1 style={{ fontFamily: "'Instrument Serif', serif", fontSize: "clamp(52px, 7.5vw, 96px)", fontWeight: 400, lineHeight: 0.92, letterSpacing: "-0.025em", margin: "14px 0 20px" }}>
            {t("Toute la mobilité,", "All mobility,")} <span style={{ fontStyle: "italic", color: C.flame }}>{t("un seul pont.", "one bridge.")}</span>
          </h1>
          <p style={{ fontSize: 18, lineHeight: 1.55, color: "#C9CEE3", maxWidth: 580 }}>
            {t("Apprendre, acheter, se déplacer, livrer, entretenir, voyager — sur route, rail, eau et ciel. Découvre chaque service ci-dessous et entre par la porte qui te ressemble. Ou ouvre la connexion unifiée.", "Learn, buy, move, deliver, maintain, travel — by road, rail, sea and air. Explore each service below and enter through the door that fits you. Or open the unified login.")}
          </p>
          <div style={{ display: "flex", gap: 30, marginTop: 32, flexWrap: "wrap" }}>
            {[["48", t("AUTO-ÉCOLES","SCHOOLS")], ["1 284", t("UTILISATEURS","USERS")], ["2 481", t("VÉHICULES","VEHICLES")], ["14", t("LANGUES","LANGUAGES")]].map(([v, l]) => (
              <div key={l}><div style={{ fontFamily: "'Instrument Serif', serif", fontSize: 36, lineHeight: 1, whiteSpace: "nowrap" }}>{v}</div><Label color="#7A82A8" style={{ fontSize: 9, marginTop: 4 }}>{l}</Label></div>
            ))}
          </div>
        </div>

        {/* manifesto — ce qui fait comprendre la plateforme (cœur éditorial du Discover) */}
        <div style={{ padding: "10px 5vw 0", maxWidth: 1240, margin: "0 auto" }}>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(260px, 1fr))", gap: 14 }}>
            {[
              { ic: "covoit", t: { fr: "Un noyau, pas une appli", en: "A core, not an app" }, d: { fr: "Une seule identité, un Wallet, une confiance, une intelligence. Tout le reste rayonne autour.", en: "One identity, one Wallet, one trust, one intelligence. Everything else radiates from it." } },
              { ic: "auto", t: { fr: "Tout se parle", en: "Everything connects" }, d: { fr: "Ton véhicule d'école devient covoiturage le soir, livraison en creux, location le week-end. Rien ne dort.", en: "Your school car becomes carpool at night, delivery in gaps, rental on weekends. Nothing idles." } },
              { ic: "bolt", t: { fr: "Lia t'accompagne", en: "Lia is with you" }, d: { fr: "Un co-pilote qui agit par rôle, traduit, guide sur la route — au service de l'humain, jamais à sa place.", en: "A copilot that acts per role, translates, guides on the road — serving you, never replacing you." } },
            ].map((m, i) => (
              <div key={i} style={{ background: "#10172E", border: "1px solid #1F2542", borderRadius: 14, padding: 20 }}>
                <div style={{ width: 38, height: 38, borderRadius: 10, background: C.flame + "22", color: C.flame, display: "grid", placeItems: "center", marginBottom: 12 }}>{window.GKIcon && window.hasGKIcon && window.hasGKIcon(m.ic) ? <GKIcon name={m.ic} size={19}/> : "◆"}</div>
                <div style={{ fontSize: 16, fontWeight: 600, marginBottom: 6 }}>{m.t[lang] || m.t.fr}</div>
                <div style={{ fontSize: 13, color: "#9098B5", lineHeight: 1.55 }}>{m.d[lang] || m.d.fr}</div>
              </div>
            ))}
          </div>
        </div>

        {/* actualités de l'écosystème */}
        <div style={{ padding: "26px 5vw 0", maxWidth: 1240, margin: "0 auto" }}>
          <div style={{ fontFamily: "'Geist Mono', monospace", fontSize: 9, letterSpacing: "0.16em", color: "#5B6388", margin: "4px 0 14px" }}>{t("À LA UNE DE L'ÉCOSYSTÈME", "ECOSYSTEM HEADLINES")}</div>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))", gap: 12 }}>
            {[
              { tag: { fr: "NOUVEAU", en: "NEW" }, k: "train", ti: { fr: "Le rail rejoint le pont", en: "Rail joins the bridge" }, b: { fr: "Train + dernier km en covoiturage, un seul trajet porte-à-porte.", en: "Train + last-mile carpool, one door-to-door journey." } },
              { tag: { fr: "ÉCOSYSTÈME", en: "ECOSYSTEM" }, k: "autopartage", ti: { fr: "Ton véhicule ne dort plus", en: "Your vehicle never idles" }, b: { fr: "Lia propose tes véhicules libres en location, covoit ou auto-partage.", en: "Lia lists your idle vehicles for rental, carpool or sharing." } },
              { tag: { fr: "VERT", en: "GREEN" }, k: "verte", ti: { fr: "Roule, compense, gagne", en: "Drive, offset, earn" }, b: { fr: "Suis ton empreinte CO2 et gagne des récompenses fidélité.", en: "Track your CO2 footprint and earn loyalty rewards." } },
            ].map((n, i) => (
              <div key={i} onClick={() => doorEnter(n.k)} style={{ background: "#10172E", border: "1px solid #1F2542", borderRadius: 14, padding: 18, cursor: "pointer", transition: "border-color .14s" }}
                onMouseEnter={e => e.currentTarget.style.borderColor = C.flame} onMouseLeave={e => e.currentTarget.style.borderColor = "#1F2542"}>
                <span style={{ display: "inline-flex", padding: "4px 10px", borderRadius: 999, background: C.flame + "22", color: C.flame, fontSize: 10, fontWeight: 600, fontFamily: "'Geist Mono', monospace", letterSpacing: "0.12em" }}>{n.tag[lang] || n.tag.fr}</span>
                <div style={{ fontSize: 16, fontWeight: 600, margin: "12px 0 6px" }}>{n.ti[lang] || n.ti.fr}</div>
                <div style={{ fontSize: 13, color: "#9098B5", lineHeight: 1.5 }}>{n.b[lang] || n.b.fr}</div>
                <div style={{ marginTop: 12, fontSize: 12.5, fontWeight: 600, color: C.flame }}>{t("Découvrir", "Discover")} →</div>
              </div>
            ))}
          </div>
        </div>

        {/* core apps */}
        <div style={{ padding: "20px 5vw 8px", maxWidth: 1240, margin: "0 auto" }}>
          <div style={{ fontFamily: "'Geist Mono', monospace", fontSize: 9, letterSpacing: "0.16em", color: "#5B6388", margin: "4px 0 14px" }}>{t("LES ESPACES PRINCIPAUX", "CORE SPACES")}</div>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(330px, 1fr))", gap: 16 }}>
            {APP_CATALOG.map(app => {
              const p = APP_PROMO[app.k];
              const dark = p.color === "#0B0F1F";
              return (
                <div key={app.k} onClick={() => { setAppCtx(app.k); setErr(""); setStep("signin"); }}
                  style={{ background: p.color, color: dark ? "#fff" : (p.accent === "#fff" ? "#fff" : "#fff"), borderRadius: 18, padding: 26, cursor: "pointer", border: dark ? "1px solid #1F2542" : "none", position: "relative", overflow: "hidden", minHeight: 220, display: "flex", flexDirection: "column", transition: "transform .14s, box-shadow .14s" }}
                  onMouseEnter={e => { e.currentTarget.style.transform = "translateY(-4px)"; e.currentTarget.style.boxShadow = "0 22px 50px rgba(0,0,0,0.34)"; }}
                  onMouseLeave={e => { e.currentTarget.style.transform = "none"; e.currentTarget.style.boxShadow = "none"; }}>
                  <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 16 }}>
                    <div style={{ width: 48, height: 48, borderRadius: 13, background: dark ? C.flame : "rgba(255,255,255,0.18)", display: "grid", placeItems: "center", fontSize: 23 }}>{app.g}</div>
                    <div>
                      <div style={{ fontSize: 19, fontWeight: 700 }}>{app[lang] || app.fr}</div>
                      <div style={{ fontFamily: "'Geist Mono', monospace", fontSize: 10, opacity: 0.8, letterSpacing: "0.08em" }}>{(p.tagline[lang] || p.tagline.fr).toUpperCase()}</div>
                    </div>
                  </div>
                  <p style={{ fontSize: 13.5, lineHeight: 1.5, opacity: 0.92, flex: 1 }}>{p.pitch[lang] || p.pitch.fr}</p>
                  <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginTop: 18, paddingTop: 14, borderTop: "1px solid rgba(255,255,255,0.16)" }}>
                    <button onClick={(e) => { e.stopPropagation(); guestEnter(app.k); }} style={{ background: "rgba(255,255,255,0.14)", border: "none", color: "#fff", fontSize: 11.5, fontWeight: 600, padding: "6px 11px", borderRadius: 999, cursor: "pointer", fontFamily: "inherit" }}>👁 {t("Visiter", "Visit")}</button>
                    <span style={{ display: "inline-flex", alignItems: "center", gap: 7, fontSize: 13, fontWeight: 600 }}>{t("S'inscrire · Se connecter", "Sign up · Sign in")} →</span>
                  </div>
                </div>
              );
            })}
          </div>
        </div>

        {/* all branches grouped by family — le cœur du Discover */}
        <div style={{ padding: "22px 5vw 0", maxWidth: 1240, margin: "0 auto" }}>
          {SERVICE_FAMILIES.map((fam, fi) => (
            <div key={fi} style={{ marginBottom: 22 }}>
              <div style={{ display: "flex", alignItems: "center", gap: 10, margin: "4px 0 12px" }}>
                <span style={{ fontFamily: "'Geist Mono', monospace", fontSize: 9, letterSpacing: "0.16em", color: C.flame }}>{(fam[lang] || fam.fr).toUpperCase()}</span>
                <div style={{ flex: 1, height: 1, background: "#1A2142" }}/>
                <span style={{ fontFamily: "'Geist Mono', monospace", fontSize: 9, color: "#5B6388" }}>{fam.keys.length}</span>
              </div>
              <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(190px, 1fr))", gap: 10 }}>
                {fam.keys.map(k => {
                  const m = doorMeta(k);
                  return (
                    <div key={k} onClick={() => doorEnter(k)} style={{ background: "#10172E", border: "1px solid #1F2542", borderRadius: 13, padding: 15, cursor: "pointer", transition: "transform .14s, border-color .14s", display: "flex", alignItems: "center", gap: 12 }}
                      onMouseEnter={e => { e.currentTarget.style.transform = "translateY(-3px)"; e.currentTarget.style.borderColor = m.color; }}
                      onMouseLeave={e => { e.currentTarget.style.transform = "none"; e.currentTarget.style.borderColor = "#1F2542"; }}>
                      <div style={{ width: 36, height: 36, borderRadius: 10, background: m.color + "26", color: m.color, display: "grid", placeItems: "center", flexShrink: 0 }}>{window.GKIcon && window.hasGKIcon && window.hasGKIcon(m.ic) ? <GKIcon name={m.ic} size={18}/> : "◆"}</div>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ fontSize: 13.5, fontWeight: 600, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{m.label}</div>
                        <div style={{ fontSize: 10.5, color: "#7A82A8", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{m.desc}</div>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          ))}
        </div>

        {/* central unified connection */}
        <div style={{ padding: "26px 5vw 60px", maxWidth: 1240, margin: "0 auto" }}>
          <div onClick={() => { setAppCtx(null); setStep("signin"); }} style={{ background: "#10172E", border: `1px solid #1F2542`, borderRadius: 18, padding: "26px 30px", display: "flex", alignItems: "center", gap: 22, cursor: "pointer", flexWrap: "wrap" }}>
            <div style={{ width: 54, height: 54, borderRadius: 15, background: C.flame, display: "grid", placeItems: "center", fontSize: 24, flexShrink: 0 }}>⌘</div>
            <div style={{ flex: 1, minWidth: 240 }}>
              <div style={{ fontSize: 20, fontWeight: 700 }}>{t("Connexion unifiée GUIDKO", "Unified GUIDKO login")}</div>
              <div style={{ fontSize: 13.5, color: "#9098B5", marginTop: 4, lineHeight: 1.5 }}>{t("Un seul compte, latéralement relié à tous tes services. Ton identité ouvre exactement les applications qui te servent.", "One account, laterally linked to all your services. Your identity opens exactly the apps you need.")}</div>
            </div>
            <Button kind="flame" onClick={(e) => { e.stopPropagation(); setAppCtx(null); setStep("signin"); }}>{t("Entrer", "Enter")} →</Button>
          </div>
          <div style={{ textAlign: "center", marginTop: 26, fontFamily: "'Geist Mono', monospace", fontSize: 10, letterSpacing: "0.18em", color: "#5B6388" }}>INNOVER · CONNECTER · RÉVÉLER · CONSTRUIRE</div>
        </div>
      </div>
    );
  }

  const ctx = appCtx ? APP_PROMO[appCtx] : null;
  const ctxApp = appCtx ? APP_CATALOG.find(a => a.k === appCtx) : null;

  return (
    <div style={{ display: "grid", gridTemplateColumns: "1.05fr 0.95fr", height: "100vh", background: C.paper, color: C.ink, fontFamily: "'Geist', sans-serif", overflow: "hidden" }}>
      {/* Left visual */}
      <div style={{ background: ctx ? ctx.color : C.ink, color: "#fff", padding: 52, display: "flex", flexDirection: "column", justifyContent: "space-between", position: "relative", overflow: "hidden" }}>
        <GuidkoLogo color="#fff"/>
        <svg style={{ position: "absolute", right: -140, top: 160, opacity: 0.06 }} width="520" height="520" viewBox="0 0 48 48" fill="none">
          <path d="M4 38 L4 22 A12 12 0 0 1 16 10 L24 10" stroke="#fff" strokeWidth="0.6" fill="none"/>
          <path d="M44 38 L44 22 A12 12 0 0 0 32 10 L24 10" stroke="#fff" strokeWidth="0.6" fill="none"/>
          <rect x="4" y="36" width="40" height="0.6" fill="#fff"/>
        </svg>
        <div>
          <Label color={C.flame} style={{ fontSize: 11 }}>{step === "lia" ? "LIA · ONBOARDING" : t("BIENVENUE", "WELCOME")}</Label>
          {step === "lia" ? (
            <>
              <h1 style={{ fontFamily: "'Instrument Serif', serif", fontSize: 76, fontWeight: 400, lineHeight: 0.95, letterSpacing: "-0.025em", margin: "12px 0 22px" }}>
                {t("Dis-moi qui", "Tell me who")}<br/><span style={{ fontStyle: "italic", color: C.flame }}>{t("tu es.", "you are.")}</span>
              </h1>
              <p style={{ fontSize: 16, lineHeight: 1.55, color: "#C9CEE3", maxWidth: 420 }}>
                {t("Je compose ton GUIDKO sur mesure : tu n'auras que les applications qui te servent — et tu pourras en activer d'autres à tout moment.", "I tailor your GUIDKO: only the apps you need — and you can activate more anytime.")}
              </p>
            </>
          ) : step === "hub" && account ? (
            <>
              <h1 style={{ fontFamily: "'Instrument Serif', serif", fontSize: 76, fontWeight: 400, lineHeight: 0.95, letterSpacing: "-0.025em", margin: "12px 0 22px" }}>
                {t("Salut", "Hi")} <span style={{ fontStyle: "italic", color: C.flame }}>{account.name.split(" ")[0]}.</span>
              </h1>
              <p style={{ fontSize: 16, lineHeight: 1.55, color: "#C9CEE3", maxWidth: 420 }}>
                {t("Ton GUIDKO, composé pour toi. Chaque service activé enrichit les autres — c'est ça, le pont.", "Your GUIDKO, made for you. Each activated service enriches the others — that's the bridge.")}
              </p>
              <div style={{ display: "flex", gap: 10, marginTop: 26, flexWrap: "wrap" }}>
                <span style={{ padding: "6px 14px", borderRadius: 999, background: "#1F2542", fontSize: 12, fontFamily: "'Geist Mono', monospace", letterSpacing: "0.08em" }}>{(account.label && (account.label[lang] || account.label.fr)) || ""}</span>
                <span style={{ padding: "6px 14px", borderRadius: 999, background: C.flame + "22", color: C.flame, fontSize: 12, fontFamily: "'Geist Mono', monospace", letterSpacing: "0.08em" }}>{account.apps.length} {t("APPS ACTIVES", "ACTIVE APPS")}</span>
              </div>
            </>
          ) : ctx ? (
            <>
              <div style={{ display: "inline-flex", alignItems: "center", gap: 11, marginBottom: 20 }}>
                <div style={{ width: 52, height: 52, borderRadius: 14, background: "rgba(255,255,255,0.16)", display: "grid", placeItems: "center", fontSize: 25 }}>{ctxApp.g}</div>
                <Label color="#fff" style={{ fontSize: 11, opacity: 0.85 }}>{(ctx.tagline[lang] || ctx.tagline.fr).toUpperCase()}</Label>
              </div>
              <h1 style={{ fontFamily: "'Instrument Serif', serif", fontSize: 70, fontWeight: 400, lineHeight: 0.95, letterSpacing: "-0.025em", margin: "0 0 20px" }}>
                {ctxApp[lang] || ctxApp.fr}
              </h1>
              <p style={{ fontSize: 17, lineHeight: 1.55, color: "rgba(255,255,255,0.86)", maxWidth: 440 }}>
                {ctx.pitch[lang] || ctx.pitch.fr}
              </p>
              <div style={{ marginTop: 26 }}>
                <span style={{ padding: "7px 14px", borderRadius: 999, background: "rgba(255,255,255,0.14)", fontSize: 12, fontFamily: "'Geist Mono', monospace", letterSpacing: "0.06em" }}>{ctx.stat[lang] || ctx.stat.fr}</span>
              </div>
            </>
          ) : (
            <>
              <h1 style={{ fontFamily: "'Instrument Serif', serif", fontSize: 88, fontWeight: 400, lineHeight: 0.95, letterSpacing: "-0.025em", margin: "12px 0 22px" }}>
                {t("Le pont est", "The bridge is")}<br/><span style={{ fontStyle: "italic", color: C.flame }}>{t("ouvert.", "open.")}</span>
              </h1>
              <p style={{ fontSize: 17, lineHeight: 1.5, color: "#C9CEE3", maxWidth: 440 }}>
                {t("Former, gérer, accueillir, vendre, acheter. Une seule plateforme.", "Train, manage, welcome, sell, buy. One platform.")}
              </p>
              <div style={{ display: "flex", gap: 30, marginTop: 36 }}>
                {[["48", t("AUTO-ÉCOLES","SCHOOLS")], ["1 284", t("UTILISATEURS","USERS")], ["2 481", t("VÉHICULES","VEHICLES")]].map(([v, l]) => (
                  <div key={l}><div style={{ fontFamily: "'Instrument Serif', serif", fontSize: 40, lineHeight: 1 }}>{v}</div><Label color="#7A82A8" style={{ fontSize: 9, marginTop: 5 }}>{l}</Label></div>
                ))}
              </div>
            </>
          )}
        </div>
        <Label color="#7A82A8" style={{ fontSize: 10 }}>INNOVER · CONNECTER · RÉVÉLER · CONSTRUIRE</Label>
      </div>

      {/* Right panel */}
      <div className="gk-scroll" style={{ padding: 52, display: "flex", flexDirection: "column", justifyContent: "center", overflowY: "auto", position: "relative" }}>
        <div style={{ position: "absolute", top: 20, right: 24 }}>
          <LangSelector/>
        </div>

        <div style={{ maxWidth: 470, width: "100%", margin: "0 auto" }}>
          {/* ============ SIGNIN ============ */}
          {step === "signin" && (
            <>
              <button onClick={() => { setAppCtx(null); setErr(""); setStep("gallery"); }} style={{ background: "none", border: "none", color: C.slate, fontSize: 13, cursor: "pointer", marginBottom: 16, padding: 0 }}>← {t("Toutes les applications", "All applications")}</button>
              {ctx ? (
                <>
                  <h2 style={{ fontFamily: "'Instrument Serif', serif", fontSize: 42, fontWeight: 400, letterSpacing: "-0.02em", margin: "0 0 6px" }}>{t("Rejoins", "Join")} {ctxApp[lang] || ctxApp.fr}</h2>
                  <p style={{ fontSize: 14, color: C.slate, marginBottom: 24 }}>{t("Inscris-toi ou connecte-toi — un seul compte GUIDKO te suit partout.", "Sign up or sign in — one GUIDKO account follows you everywhere.")}</p>
                </>
              ) : (
                <>
                  <h2 style={{ fontFamily: "'Instrument Serif', serif", fontSize: 46, fontWeight: 400, letterSpacing: "-0.02em", margin: "0 0 6px" }}>{t("Ravi de te revoir.", "Glad you're back.")}</h2>
                  <p style={{ fontSize: 14, color: C.slate, marginBottom: 24 }}>{t("Ta connexion ouvre TES applications.", "Your sign-in opens YOUR apps.")}</p>
                </>
              )}
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginBottom: 16 }}>
                <Button kind="light" icon="G" full>Google</Button>
                <Button kind="light" icon="✦" full>Microsoft</Button>
              </div>
              <div style={{ display: "flex", alignItems: "center", gap: 12, color: C.slate, fontSize: 11, fontFamily: "'Geist Mono', monospace", letterSpacing: "0.14em", margin: "6px 0 16px" }}>
                <div style={{ flex: 1, height: 1, background: C.softLine }}/>{t("OU","OR")}<div style={{ flex: 1, height: 1, background: C.softLine }}/>
              </div>
              <Input label="Email" value={email} onChange={setEmail}/>
              <Input label={t("Mot de passe","Password")} value={pwd} onChange={setPwd} type="password"/>
              {err && <div style={{ padding: "10px 14px", background: "#FEE2E2", color: "#B91C1C", borderRadius: 8, fontSize: 13, marginTop: 10 }}>{err}</div>}
              <Button kind="primary" size="lg" full style={{ marginTop: 16 }} onClick={signIn} disabled={authBusy}>
                {authBusy ? t("Connexion…", "Signing in…") : `${t("Se connecter","Sign in")} →`}
              </Button>
              <p style={{ textAlign: "center", marginTop: 12 }}>
                <span onClick={() => { setStep("forgot"); setFStep(0); setFCode(""); setFPwd(""); }} style={{ fontSize: 12.5, color: C.slate, cursor: "pointer", textDecoration: "underline", textUnderlineOffset: 3 }}>{t("Mot de passe oublié ?","Forgot password?")}</span>
              </p>
              <div style={{ display: "flex", alignItems: "center", gap: 8, justifyContent: "center", marginTop: 10, fontSize: 11.5, color: C.signal }}>
                🔒 {t("Connexion sécurisée · vérification en 2 étapes","Secure sign-in · 2-step verification")}
              </div>

              {/* Accès invité : entrer sans compte, on est invité à s'inscrire */}
              <div style={{ marginTop: 18, padding: 14, background: ctx ? "#fff" : C.cream, border: `1px dashed ${C.softLine}`, borderRadius: 12, textAlign: "center" }}>
                <div style={{ fontSize: 12.5, color: C.slate, marginBottom: 10, lineHeight: 1.45 }}>{t("Juste curieux ? Entre en visiteur — tu pourras créer ton compte à tout moment.","Just curious? Enter as a guest — you can create your account anytime.")}</div>
                <Button kind="light" full onClick={() => guestEnter(appCtx || "eleve")}>👁 {appCtx ? t("Visiter ","Visit ") + (ctxApp[lang] || ctxApp.fr) : t("Explorer en invité","Explore as guest")} →</Button>
              </div>

              {/* Demo accounts */}
              <div style={{ marginTop: 22, padding: 14, background: "#fff", border: `1px solid ${C.softLine}`, borderRadius: 12 }}>
                <Label style={{ marginBottom: 10 }}>{t("COMPTES DÉMO — chaque identité a SES accès", "DEMO ACCOUNTS — each identity has ITS access")}</Label>
                <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 6 }}>
                  {Object.entries(DEMO_ACCOUNTS).map(([em, a]) => (
                    <div key={em} onClick={() => { setEmail(em); setErr(""); }} style={{ padding: "8px 10px", borderRadius: 8, cursor: "pointer", background: email === em ? C.cream : "transparent", border: `1px solid ${email === em ? C.softLine : "transparent"}` }}>
                      <div style={{ fontSize: 12.5, fontWeight: 600 }}>{a.name}</div>
                      <div style={{ fontSize: 11, color: C.slate }}>{a.label[lang] || a.label.fr} · {a.apps.length} apps</div>
                    </div>
                  ))}
                </div>
              </div>

              <p style={{ fontSize: 12.5, color: C.slate, textAlign: "center", marginTop: 18, lineHeight: 1.5 }}>
                {t("Pas encore de compte ?","No account yet?")} <span onClick={() => { setStep("lia"); setLiaStep(0); setLiaAnswers({}); }} style={{ color: C.flame, fontWeight: 600, cursor: "pointer" }}>✦ {t("S'inscrire avec Lia","Sign up with Lia")}</span>
              </p>
            </>
          )}

          {/* ============ 2FA VERIFICATION ============ */}
          {step === "verify" && account && (
            <>
              <button onClick={() => setStep("signin")} style={{ background: "none", border: "none", color: C.slate, fontSize: 13, cursor: "pointer", marginBottom: 14, padding: 0 }}>← {t("Retour","Back")}</button>
              <div style={{ display: "inline-flex", alignItems: "center", gap: 7, padding: "5px 11px", borderRadius: 999, background: "#EAF7F0", color: "#0a7d4a", fontSize: 11.5, fontWeight: 600, marginBottom: 14 }}>🔒 {t("Vérification en 2 étapes","2-step verification")}</div>
              <h2 style={{ fontFamily: "'Instrument Serif', serif", fontSize: 40, fontWeight: 400, letterSpacing: "-0.02em", margin: "0 0 6px" }}>{t("C'est bien toi ?","Is it really you?")}</h2>
              <p style={{ fontSize: 14, color: C.slate, marginBottom: 20 }}>{t("Choisis comment confirmer ton identité.","Choose how to confirm your identity.")}</p>

              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginBottom: 18 }}>
                {VERIFY_METHODS.map(m => {
                  const on = vMethod === m.k;
                  return (
                    <div key={m.k} onClick={() => { setVMethod(m.k); setFaceScan(0); setVCode(""); }} style={{ padding: "13px 14px", borderRadius: 11, cursor: "pointer", border: `1.5px solid ${on ? C.flame : C.softLine}`, background: on ? "#FFF1EB" : "#fff" }}>
                      <div style={{ fontSize: 20, marginBottom: 6 }}>{m.g}</div>
                      <div style={{ fontSize: 13, fontWeight: 600 }}>{t(m.fr, m.en)}</div>
                      <div style={{ fontSize: 11, color: C.slate, marginTop: 2 }}>{m.hint[lang] || m.hint.fr}</div>
                    </div>
                  );
                })}
              </div>

              {vMethod === "face" ? (
                <div style={{ textAlign: "center", padding: "10px 0 4px" }}>
                  <div onClick={() => { if (faceScan === 0) { setFaceScan(1); setTimeout(() => setFaceScan(2), 1500); } }}
                    style={{ width: 132, height: 132, margin: "0 auto 14px", borderRadius: "50%", border: `3px solid ${faceScan === 2 ? C.signal : faceScan === 1 ? C.flame : C.softLine}`, display: "grid", placeItems: "center", fontSize: 54, cursor: faceScan === 0 ? "pointer" : "default", background: "#fff", transition: "border-color .3s", position: "relative", overflow: "hidden" }}>
                    {faceScan === 2 ? "✓" : "🙂"}
                    {faceScan === 1 && <div style={{ position: "absolute", left: 0, right: 0, height: 3, background: C.flame, animation: "gkScan 1.5s linear", boxShadow: `0 0 10px ${C.flame}` }}/>}
                  </div>
                  <div style={{ fontSize: 13, color: C.slate, marginBottom: 16 }}>{faceScan === 0 ? t("Touche pour scanner ton visage","Tap to scan your face") : faceScan === 1 ? t("Analyse en cours…","Scanning…") : t("Visage reconnu ✓","Face recognized ✓")}</div>
                  <Button kind="primary" size="lg" full disabled={faceScan !== 2} style={{ opacity: faceScan === 2 ? 1 : 0.45 }} onClick={afterVerify}>{t("Confirmer","Confirm")} →</Button>
                  <style>{`@keyframes gkScan{0%{top:8%}100%{top:88%}}`}</style>
                </div>
              ) : (
                <>
                  <div style={{ padding: 13, background: "#fff", border: `1px solid ${C.softLine}`, borderRadius: 10, fontSize: 12.5, color: C.slate, marginBottom: 14, display: "flex", alignItems: "center", gap: 8 }}>
                    <span>{VERIFY_METHODS.find(m => m.k === vMethod).g}</span>
                    {vMethod === "email" ? t("Code envoyé à ","Code sent to ") + (account.email) : vMethod === "sms" ? t("Code envoyé par SMS au ···45","Code sent by SMS to ···45") : t("Ouvre ton app authenticator","Open your authenticator app")}
                    <span style={{ marginLeft: "auto", fontFamily: "'Geist Mono', monospace", color: C.flame, fontWeight: 600 }}>{vMethod === "auth" ? "" : "204 815"}</span>
                  </div>
                  <Input label={t("Code à 6 chiffres","6-digit code")} value={vCode} onChange={setVCode} placeholder="204815"/>
                  <Button kind="primary" size="lg" full style={{ marginTop: 12 }} onClick={afterVerify}>{t("Vérifier","Verify")} →</Button>
                  <p style={{ textAlign: "center", marginTop: 12, fontSize: 12.5, color: C.slate }}>{t("Pas reçu ?","Didn't get it?")} <span style={{ color: C.flame, cursor: "pointer", fontWeight: 600 }}>{t("Renvoyer","Resend")}</span></p>
                </>
              )}
            </>
          )}

          {/* ============ RESET MOT DE PASSE ============ */}
          {step === "forgot" && (
            <>
              <button onClick={() => setStep("signin")} style={{ background: "none", border: "none", color: C.slate, fontSize: 13, cursor: "pointer", marginBottom: 14, padding: 0 }}>← {t("Connexion","Sign in")}</button>
              <h2 style={{ fontFamily: "'Instrument Serif', serif", fontSize: 40, fontWeight: 400, letterSpacing: "-0.02em", margin: "0 0 6px" }}>{t("Réinitialiser","Reset password")}</h2>
              <div style={{ display: "flex", gap: 5, margin: "14px 0 20px" }}>{[0,1,2,3].map(i => <span key={i} style={{ flex: 1, height: 4, borderRadius: 2, background: i <= fStep ? C.flame : C.softLine }}/>)}</div>

              {fStep === 0 && (<>
                <p style={{ fontSize: 14, color: C.slate, marginBottom: 18 }}>{t("Entre ton email : on t'envoie un code de récupération.","Enter your email: we'll send a recovery code.")}</p>
                <Input label="Email" value={email} onChange={setEmail}/>
                <Button kind="primary" size="lg" full style={{ marginTop: 12 }} onClick={() => setFStep(1)}>{t("Envoyer le code","Send code")} →</Button>
              </>)}
              {fStep === 1 && (<>
                <p style={{ fontSize: 14, color: C.slate, marginBottom: 18 }}>{t("Code envoyé à ","Code sent to ")}<strong>{email}</strong>.</p>
                <div style={{ padding: 13, background: "#fff", border: `1px solid ${C.softLine}`, borderRadius: 10, fontSize: 12.5, color: C.slate, marginBottom: 14 }}>📨 {t("Ton code : ","Your code: ")}<span style={{ fontFamily: "'Geist Mono', monospace", color: C.flame, fontWeight: 600 }}>730 912</span></div>
                <Input label={t("Code reçu","Received code")} value={fCode} onChange={setFCode} placeholder="730912"/>
                <Button kind="primary" size="lg" full style={{ marginTop: 12 }} onClick={() => setFStep(2)}>{t("Valider","Validate")} →</Button>
              </>)}
              {fStep === 2 && (<>
                <p style={{ fontSize: 14, color: C.slate, marginBottom: 18 }}>{t("Choisis un nouveau mot de passe.","Choose a new password.")}</p>
                <Input label={t("Nouveau mot de passe","New password")} value={fPwd} onChange={setFPwd} type="password"/>
                <Button kind="primary" size="lg" full style={{ marginTop: 12 }} onClick={() => setFStep(3)}>{t("Mettre à jour","Update")} →</Button>
              </>)}
              {fStep === 3 && (<>
                <div style={{ textAlign: "center", padding: "20px 0" }}>
                  <div style={{ width: 64, height: 64, borderRadius: 18, background: C.signal, color: "#fff", display: "grid", placeItems: "center", fontSize: 30, margin: "0 auto 16px" }}>✓</div>
                  <div style={{ fontFamily: "'Instrument Serif', serif", fontSize: 28 }}>{t("Mot de passe mis à jour","Password updated")}</div>
                  <p style={{ fontSize: 13.5, color: C.slate, marginTop: 8 }}>{t("Tu peux te reconnecter en toute sécurité.","You can sign in securely.")}</p>
                </div>
                <Button kind="primary" size="lg" full onClick={() => { setStep("signin"); setPwd(fPwd || pwd); }}>{t("Retour à la connexion","Back to sign in")} →</Button>
              </>)}
            </>
          )}

          {/* ============ HUB (apps de l'identité) ============ */}
          {step === "hub" && account && (
            <>
              <button onClick={() => { setStep("signin"); setAccount(null); }} style={{ background: "none", border: "none", color: C.slate, fontSize: 13, cursor: "pointer", marginBottom: 12, padding: 0 }}>← {t("Changer de compte","Switch account")}</button>
              <h2 style={{ fontFamily: "'Instrument Serif', serif", fontSize: 40, fontWeight: 400, letterSpacing: "-0.02em", margin: "0 0 4px" }}>{t("Mes applications","My apps")}</h2>
              <p style={{ fontSize: 13.5, color: C.slate, marginBottom: 20 }}>{t("Composées selon ton profil. Active-en d'autres quand tu veux.","Based on your profile. Activate more anytime.")}</p>

              <div style={{ display: "flex", flexDirection: "column", gap: 9 }}>
                {APP_CATALOG.filter(a => account.apps.includes(a.k)).map(a => (
                  <Card key={a.k} hover onClick={() => openApp(a.k)} style={{ padding: 16, display: "flex", alignItems: "center", gap: 14, ...(a.ink ? { background: C.ink, borderColor: C.ink } : a.cream ? { background: C.cream } : {}) }}>
                    <div style={{ width: 46, height: 46, borderRadius: 11, background: a.dark ? C.ink : a.flame ? C.flame : a.ink ? C.flame : "#fff", color: a.dark ? C.flame : "#fff", display: "grid", placeItems: "center", fontSize: 20, flexShrink: 0, border: (!a.dark && !a.flame && !a.ink) ? `1px solid ${C.softLine}` : "none" }}>{a.g}</div>
                    <div style={{ flex: 1 }}>
                      <div style={{ fontSize: 16.5, fontWeight: 600, color: a.ink ? "#fff" : C.ink }}>{a[lang] || a.fr}</div>
                      <div style={{ fontSize: 12, color: a.ink ? "#9098B5" : C.slate, marginTop: 2 }}>{a.desc[lang] || a.desc.fr}</div>
                    </div>
                    <span style={{ color: a.ink ? "#9098B5" : C.slate, fontSize: 17 }}>→</span>
                  </Card>
                ))}
              </div>

              {/* Activable services */}
              {(() => {
                const elig = eligibleApps(account.profile).filter(k => !account.apps.includes(k));
                if (elig.length === 0) return null;
                return (
                  <>
                    <div style={{ display: "flex", alignItems: "center", gap: 10, margin: "24px 0 12px" }}>
                      <Label>{t("À ACTIVER — ton GUIDKO grandit avec toi","TO ACTIVATE — your GUIDKO grows with you")}</Label>
                      <div style={{ flex: 1, height: 1, background: C.softLine }}/>
                    </div>
                    <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
                      {APP_CATALOG.filter(a => elig.includes(a.k)).map(a => (
                        <div key={a.k} style={{ padding: "13px 16px", display: "flex", alignItems: "center", gap: 13, background: "#fff", border: `1px dashed ${C.softLine}`, borderRadius: 12 }}>
                          <div style={{ width: 38, height: 38, borderRadius: 10, background: "#F0EBDC", color: C.slate, display: "grid", placeItems: "center", fontSize: 17, flexShrink: 0 }}>{a.g}</div>
                          <div style={{ flex: 1 }}>
                            <div style={{ fontSize: 14.5, fontWeight: 600 }}>{a[lang] || a.fr}</div>
                            <div style={{ fontSize: 11.5, color: C.slate, marginTop: 1 }}>{a.desc[lang] || a.desc.fr}</div>
                          </div>
                          <Button size="sm" kind="ghost" onClick={() => activate(a.k)}>+ {t("Activer","Activate")}</Button>
                        </div>
                      ))}
                    </div>
                  </>
                );
              })()}

              {/* Cross-promo vivante */}
              {account.profile === "pro" && !account.apps.includes("covoit") && (
                <div style={{ marginTop: 14, padding: 14, background: "#FFF1EB", borderRadius: 10, borderLeft: `3px solid ${C.flame}`, fontSize: 12.5, lineHeight: 1.5 }}>
                  ✦ {t("Offre vivante : tes élèves cherchent des trajets retour. Active Covoiturage et transforme tes trajets en revenus.","Live offer: your students need rides home. Activate Carpool and turn your commute into income.")}
                </div>
              )}
              {account.profile === "eleve" && !account.apps.includes("auto") && (
                <div style={{ marginTop: 14, padding: 14, background: "#FFF1EB", borderRadius: 10, borderLeft: `3px solid ${C.flame}`, fontSize: 12.5, lineHeight: 1.5 }}>
                  ✦ {t("Bientôt le permis ? Active le Marché Mobilité et trouve ton premier véhicule au bon prix.","License coming soon? Activate the Mobility Market and find your first vehicle at the right price.")}
                </div>
              )}
            </>
          )}

          {/* ============ PRO role choice ============ */}
          {step === "pro" && (() => {
            const entitled = proRolesFor(account);
            const myRoles = proRoles.filter(r => entitled.includes(r.role));
            const isManager = entitled.includes("gerant");
            return (
            <>
              <button onClick={() => setStep("hub")} style={{ background: "none", border: "none", color: C.slate, fontSize: 13, cursor: "pointer", marginBottom: 14, padding: 0 }}>← {t("Mes applications","My apps")}</button>
              <h2 style={{ fontFamily: "'Instrument Serif', serif", fontSize: 42, fontWeight: 400, letterSpacing: "-0.02em", margin: "0 0 6px" }}>{account && account.school ? account.school : t("Espace Pro","Pro app")}</h2>
              <p style={{ fontSize: 14, color: C.slate, marginBottom: 8 }}>{isManager ? t("Tu gères l'auto-école. Choisis ta vue — tu as accès à toutes.","You run the school. Pick your view — you have access to all.") : t("Ton espace de travail.","Your workspace.")}</p>
              {isManager && <div style={{ display: "inline-flex", alignItems: "center", gap: 7, padding: "5px 11px", borderRadius: 999, background: "#FFF1EB", color: C.flame, fontSize: 11.5, fontWeight: 600, marginBottom: 18 }}>♛ {t("Gérant — donne les accès à son équipe","Manager — grants team access")}</div>}
              <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
                {myRoles.map(r => (
                  <Card key={r.role} hover onClick={() => pickRole(r.role)} style={{ padding: 16, display: "flex", alignItems: "center", gap: 16 }}>
                    <div style={{ width: 46, height: 46, borderRadius: 11, background: C.ink, color: C.flame, display: "grid", placeItems: "center", fontSize: 20, flexShrink: 0 }}>{r.g}</div>
                    <div style={{ flex: 1 }}>
                      <div style={{ fontSize: 17, fontWeight: 600 }}>{r[lang]}</div>
                      <div style={{ fontSize: 12.5, color: C.slate, marginTop: 2 }}>{r.desc}</div>
                    </div>
                    <span style={{ color: C.slate, fontSize: 18 }}>→</span>
                  </Card>
                ))}
              </div>

              {/* Gestion interne des accès équipe — réservée au gérant */}
              {isManager && (
                <div style={{ marginTop: 22, padding: 16, background: "#fff", border: `1px solid ${C.softLine}`, borderRadius: 12 }}>
                  <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 4 }}>
                    <Label style={{ flex: 1 }}>{t("GESTION DES ACCÈS — MON ÉQUIPE","ACCESS MANAGEMENT — MY TEAM")}</Label>
                    <span style={{ fontFamily: "'Geist Mono', monospace", fontSize: 10, color: C.slate }}>{team.filter(m => m.on).length}/{team.length}</span>
                  </div>
                  <p style={{ fontSize: 12, color: C.slate, margin: "0 0 12px", lineHeight: 1.45 }}>{t("Active ou coupe l'accès de chaque membre à son espace. Les moniteurs n'ont jamais accès à l'espace gérant.","Toggle each member's access to their space. Instructors never reach the manager space.")}</p>
                  <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
                    {team.map((m, i) => (
                      <div key={i} style={{ display: "flex", alignItems: "center", gap: 11, padding: "9px 11px", borderRadius: 9, background: C.paper }}>
                        <Avatar name={m.name} size={30} tone={m.tone}/>
                        <div style={{ flex: 1, minWidth: 0 }}>
                          <div style={{ fontSize: 13.5, fontWeight: 600 }}>{m.name}</div>
                          <div style={{ fontSize: 11, color: C.slate }}>{m.role}</div>
                        </div>
                        <button onClick={() => setTeam(ts => ts.map((x, j) => j === i ? { ...x, on: !x.on } : x))} style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: "5px 11px", borderRadius: 999, border: `1px solid ${m.on ? C.signal : C.softLine}`, background: m.on ? "#EAF7F0" : "#fff", color: m.on ? "#0a7d4a" : C.slate, fontSize: 11.5, fontWeight: 600, cursor: "pointer", fontFamily: "inherit" }}>
                          {m.on ? `✓ ${t("Accès actif","Access on")}` : t("Accès coupé","Access off")}
                        </button>
                      </div>
                    ))}
                  </div>
                  <button onClick={() => setTeam(ts => [...ts, { name: t("Nouveau moniteur","New instructor"), role: t("Moniteur · invitation envoyée","Instructor · invite sent"), tone: (ts.length + 2) % 5, on: false }])} style={{ marginTop: 12, width: "100%", padding: "10px", borderRadius: 9, border: `1px dashed ${C.softLine}`, background: "transparent", color: C.slate, fontSize: 13, fontWeight: 600, cursor: "pointer", fontFamily: "inherit" }}>+ {t("Inviter un membre","Invite a member")}</button>
                </div>
              )}
            </>
            );
          })()}

          {/* ============ LIA — inscription dynamique ============ */}
          {step === "lia" && (
            <>
              <button onClick={() => liaStep === 0 ? setStep("signin") : setLiaStep(s => s - 1)} style={{ background: "none", border: "none", color: C.slate, fontSize: 13, cursor: "pointer", marginBottom: 14, padding: 0 }}>← {t("Retour","Back")}</button>
              <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 18 }}>
                <span style={{ width: 34, height: 34, borderRadius: 10, background: C.ink, color: C.flame, display: "grid", placeItems: "center", fontSize: 15 }}>✦</span>
                <div>
                  <div style={{ fontWeight: 700, fontSize: 15 }}>Lia</div>
                  <div style={{ fontFamily: "'Geist Mono', monospace", fontSize: 9, color: C.signal, letterSpacing: "0.14em" }}>● {t("INSCRIPTION DYNAMIQUE","DYNAMIC SIGNUP")}</div>
                </div>
                <div style={{ marginLeft: "auto", display: "flex", gap: 4 }}>
                  {[0, 1, 2].map(i => <span key={i} style={{ width: 22, height: 4, borderRadius: 2, background: i <= liaStep ? C.flame : C.softLine }}/>)}
                </div>
              </div>

              {liaStep < 2 ? (
                <>
                  <div style={{ padding: "16px 18px", background: "#fff", border: `1px solid ${C.softLine}`, borderRadius: "14px 14px 14px 4px", fontSize: 16, fontWeight: 500, lineHeight: 1.45, marginBottom: 16 }}>
                    {liaQ[lang] || liaQ.fr}
                  </div>
                  <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
                    {liaQ.options.map(o => {
                      const on = (liaAnswers[liaQ.id] || []).includes(o.k);
                      return (
                        <div key={o.k} onClick={() => liaToggle(liaQ, o.k)} style={{ padding: "13px 16px", borderRadius: 11, cursor: "pointer", border: `1.5px solid ${on ? C.flame : C.softLine}`, background: on ? "#FFF1EB" : "#fff", display: "flex", alignItems: "center", gap: 12, transition: "all .12s" }}>
                          <span style={{ width: 20, height: 20, borderRadius: liaQ.multi ? 6 : 999, border: `2px solid ${on ? C.flame : C.softLine}`, background: on ? C.flame : "transparent", display: "grid", placeItems: "center", color: "#fff", fontSize: 11, flexShrink: 0 }}>{on ? "✓" : ""}</span>
                          <span style={{ fontSize: 14.5, fontWeight: on ? 600 : 500 }}>{o[lang] || o.fr}</span>
                        </div>
                      );
                    })}
                  </div>
                  <Button kind="primary" size="lg" full style={{ marginTop: 18, opacity: liaCanNext ? 1 : 0.45 }} onClick={() => liaCanNext && setLiaStep(s => s + 1)}>{t("Continuer","Continue")} →</Button>
                </>
              ) : (
                <>
                  <div style={{ padding: "16px 18px", background: "#fff", border: `1px solid ${C.softLine}`, borderRadius: "14px 14px 14px 4px", fontSize: 16, fontWeight: 500, lineHeight: 1.45, marginBottom: 16 }}>
                    {t("Parfait. Comment tu t'appelles ?","Perfect. What's your name?")}
                  </div>
                  <Input label={t("Prénom & Nom","Full name")} value={liaName} onChange={setLiaName} placeholder="Sami Benali"/>
                  {/* Preview of composed access */}
                  {(() => {
                    const whoOpt = LIA_QUESTIONS[0].options.find(o => (liaAnswers.who || []).includes(o.k));
                    const profile = whoOpt ? whoOpt.profile : "libre";
                    const elig = eligibleApps(profile);
                    let apps = [...(whoOpt ? whoOpt.apps : [])];
                    (liaAnswers.wants || []).forEach(k => { const opt = LIA_QUESTIONS[1].options.find(o => o.k === k); if (opt) opt.apps.forEach(x => { if (elig.includes(x) && !apps.includes(x)) apps.push(x); }); });
                    if (apps.length === 0) apps = [elig[0]];
                    return (
                      <div style={{ marginTop: 12, padding: 14, background: "#fff", border: `1px solid ${C.softLine}`, borderRadius: 12 }}>
                        <Label style={{ marginBottom: 10 }}>{t("LIA A COMPOSÉ TON GUIDKO :","LIA COMPOSED YOUR GUIDKO:")}</Label>
                        <div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
                          {apps.map(k => { const a = APP_CATALOG.find(x => x.k === k); return a ? <span key={k} style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: "6px 12px", borderRadius: 999, background: C.cream, border: `1px solid ${C.softLine}`, fontSize: 12.5, fontWeight: 600 }}>{a.g} {a[lang] || a.fr}</span> : null; })}
                        </div>
                        {profile === "eleve" && <div style={{ fontSize: 11.5, color: C.slate, marginTop: 10 }}>🔒 {t("Les vues professionnelles ne sont pas accessibles au profil élève.","Pro views are not accessible to student profiles.")}</div>}
                      </div>
                    );
                  })()}
                  <Button kind="flame" size="lg" full style={{ marginTop: 16 }} onClick={liaFinish}>✦ {t("Créer mon GUIDKO","Create my GUIDKO")}</Button>
                </>
              )}
            </>
          )}
        </div>
      </div>
    </div>
  );
}

window.LoginScreen = LoginScreen;
