/* GUIDKO App — brand mark + app shell (sidebar + topbar), role-aware nav, routing. */

const BRAND = "GUIDKO";

function GuidkoMark({ size = 32 }) {
  return (
    <img src="/assets/gk-logo.jpg" alt="GUIDKO"
      style={{ width: size, height: size, objectFit: "contain", display: "block", flexShrink: 0, borderRadius: 6 }} />
  );
}

function GuidkoLogo({ color = "#0B0F1F", scale = 1 }) {
  return (
    <div style={{ display: "inline-flex", alignItems: "center", gap: 8 * scale, lineHeight: 1 }}>
      <GuidkoMark size={34 * scale} />
      <span style={{ fontFamily: "'Geist', sans-serif", fontWeight: 800, letterSpacing: "0.04em", fontSize: 20 * scale, color }}>{BRAND}</span>
    </div>
  );
}

// ---------- Role configuration ----------
// Each role: label, the person identity, and nav items. Véhicules present for ALL school roles.
const ROLES = {
  gerant: {
    fr: "Gérant", en: "Manager", place: "Auto-École Lubasa",
    person: { name: "Kevin Lubasa", email: "kevin@lubasa.fr", tone: 0 },
    nav: [
      { k: "discover",  fr: "Discover",      en: "Discover",    g: "◍" },
      { k: "overview",  fr: "Vue d'ensemble", en: "Overview",    g: "◎" },
      { k: "planning",  fr: "Planning",       en: "Schedule",    g: "▤" },
      { k: "students",  fr: "Élèves",         en: "Students",    g: "★" },
      { k: "instructors", fr: "Moniteurs",    en: "Instructors", g: "♛" },
      { k: "vehicles",  fr: "Véhicules",      en: "Vehicles",    g: "⇄", market: true },
      { k: "analytics", fr: "Analytics",      en: "Analytics",   g: "▲" },
      { k: "finance",   fr: "Finances",       en: "Finance",     g: "€" },
      { k: "wallet",    fr: "Wallet",         en: "Wallet",      g: "▣" },
      { k: "messages",  fr: "Messages",       en: "Messages",    g: "✉" },
      { k: "trust",     fr: "Confiance",      en: "Trust",       g: "🛡" },
      { k: "assurance", fr: "Assurance",      en: "Insurance",   g: "🛡" },
      { k: "pricing",   fr: "Abonnements",    en: "Plans",       g: "€" },
      { k: "security",  fr: "Sécurité",       en: "Security",    g: "🔒" },
      { k: "contracts", fr: "Contrats",       en: "Contracts",   g: "🔏" },
      { k: "referral",  fr: "Parrainage",     en: "Referral",    g: "🎁" },
      { k: "region",    fr: "Région",         en: "Region",      g: "🌍" },
      { k: "settings",  fr: "Paramètres",     en: "Settings",    g: "◆" },
    ],
  },
  accueil: {
    fr: "Accueil", en: "Front desk", place: "Auto-École Lubasa",
    person: { name: "Nadia Fontaine", email: "accueil@lubasa.fr", tone: 4 },
    nav: [
      { k: "discover",  fr: "Discover",      en: "Discover",     g: "◍" },
      { k: "overview",  fr: "Hall d'accueil", en: "Reception",     g: "◎" },
      { k: "enroll",    fr: "Inscriptions",   en: "Enrollments",   g: "✎" },
      { k: "students",  fr: "Élèves",         en: "Students",      g: "★" },
      { k: "planning",  fr: "Planning",       en: "Schedule",      g: "▤" },
      { k: "vehicles",  fr: "Véhicules",      en: "Vehicles",      g: "⇄", market: true },
      { k: "messages",  fr: "Messages",       en: "Messages",      g: "✉" },
      { k: "security",  fr: "Sécurité",       en: "Security",      g: "🔒" },
      { k: "settings",  fr: "Paramètres",     en: "Settings",      g: "◆" },
    ],
  },
  moniteur: {
    fr: "Moniteur", en: "Instructor", place: "Auto-École Lubasa",
    person: { name: "Marc Lefèvre", email: "marc@lubasa.fr", tone: 0 },
    nav: [
      { k: "discover",  fr: "Discover",   en: "Discover",    g: "◍" },
      { k: "overview",  fr: "Ma journée",  en: "My day",      g: "◎" },
      { k: "planning",  fr: "Planning",    en: "Schedule",    g: "▤" },
      { k: "students",  fr: "Mes élèves",  en: "My students", g: "★" },
      { k: "vehicles",  fr: "Véhicules",   en: "Vehicles",    g: "⇄", market: true },
      { k: "earnings",  fr: "Mes gains",   en: "Earnings",    g: "€" },
      { k: "wallet",    fr: "Wallet",      en: "Wallet",      g: "▣" },
      { k: "messages",  fr: "Messages",   en: "Messages",    g: "✉" },
      { k: "trust",     fr: "Confiance",  en: "Trust",       g: "🛡" },
      { k: "assurance", fr: "Assurance",  en: "Insurance",   g: "🛡" },
      { k: "security",  fr: "Sécurité",  en: "Security",    g: "🔒" },
      { k: "contracts", fr: "Contrats",  en: "Contracts",   g: "🔏" },
      { k: "referral",  fr: "Parrainage",en: "Referral",    g: "🎁" },
      { k: "profile",   fr: "Profil",      en: "Profile",     g: "◆" },
    ],
  },
  eleve: {
    fr: "Élève", en: "Student", place: "Auto-École Lubasa",
    person: { name: "Léa Mercier", email: "lea.mercier@gmail.com", tone: 1, studentId: "s1" },
    nav: [
      { k: "discover",  fr: "Discover",      en: "Discover",    g: "◍" },
      { k: "overview",  fr: "Ma progression", en: "My progress", g: "▲" },
      { k: "book",      fr: "Réserver",       en: "Book",        g: "▤" },
      { k: "code",      fr: "Code",           en: "Code test",   g: "★" },
      { k: "vehicles",  fr: "Véhicules",      en: "Vehicles",    g: "⇄", market: true },
      { k: "messages",  fr: "Messages",       en: "Messages",    g: "✉" },
      { k: "wallet",    fr: "Wallet",         en: "Wallet",      g: "▣" },
      { k: "trust",     fr: "Confiance",      en: "Trust",       g: "🛡" },
      { k: "assurance", fr: "Assurance",      en: "Insurance",   g: "🛡" },
      { k: "pricing",   fr: "Abonnements",    en: "Plans",       g: "€" },
      { k: "security",  fr: "Sécurité",       en: "Security",    g: "🔒" },
      { k: "contracts", fr: "Contrats",       en: "Contracts",   g: "🔏" },
      { k: "referral",  fr: "Parrainage",     en: "Referral",    g: "🎁" },
      { k: "profile",   fr: "Profil",         en: "Profile",     g: "◆" },
    ],
  },
  covoit: {
    fr: "Covoiturage", en: "Carpool", place: "GUIDKO Mobility",
    person: { name: "Yanis Traoré", email: "yanis@guidko.com", tone: 2 },
    nav: [
      { k: "overview",  fr: "Accueil",      en: "Home",       g: "⇅" },
      { k: "search",    fr: "Passager",     en: "Passenger",  g: "🔍" },
      { k: "driver",    fr: "Conducteur",   en: "Driver",     g: "🚗" },
      { k: "publish",   fr: "Publier",      en: "Offer",      g: "✎" },
      { k: "drive",     fr: "GUIDAROUTE",      en: "GUIDAROUTE",    g: "🛰", lia: true },
      { k: "vehicles",  fr: "Véhicules",    en: "Vehicles",   g: "⇄", market: true },
      { k: "wallet",    fr: "Wallet",       en: "Wallet",     g: "▣" },
      { k: "messages",  fr: "Messages",     en: "Messages",   g: "✉" },
      { k: "trust",     fr: "Confiance",    en: "Trust",      g: "🛡" },
    ],
  },
  livraison: {
    fr: "Livraison", en: "Delivery", place: "GUIDKO Livraison",
    person: { name: "Yanis Livreur", email: "yanis.livr@guidko.com", tone: 4 },
    nav: [
      { k: "overview",  fr: "Accueil",      en: "Home",         g: "📦" },
      { k: "client",    fr: "Commander",    en: "Order",         g: "🛒" },
      { k: "livreur",   fr: "Livrer",       en: "Deliver",       g: "🚴" },
      { k: "drive",     fr: "GPS Livraison",en: "Delivery GPS",  g: "🛰", lia: true },
      { k: "vehicles",  fr: "Véhicules",    en: "Vehicles",     g: "⇄", market: true },
      { k: "wallet",    fr: "Wallet",       en: "Wallet",       g: "▣" },
      { k: "messages",  fr: "Messages",     en: "Messages",     g: "✉" },
      { k: "trust",     fr: "Confiance",    en: "Trust",        g: "🛡" },
    ],
  },
};

// Branches-services autonomes : leur propre espace (sidebar dédiée).
const SERVICE_ROLES = {
  assurance: { fr: "Assurance", en: "Insurance", place: "GUIDKO Assurance", g: "🛡", person: { name: "Invité", email: "", tone: 3 } },
  energie:   { fr: "Énergie",   en: "Energy",    place: "GUIDKO Énergie",   g: "⚡", person: { name: "Invité", email: "", tone: 3 } },
  parking:   { fr: "Stationnement", en: "Parking", place: "GUIDKO Parking", g: "🅿", person: { name: "Invité", email: "", tone: 3 } },
  entretien: { fr: "Entretien", en: "Service",   place: "GUIDKO Entretien", g: "🔧", person: { name: "Invité", email: "", tone: 3 } },
  flotte:    { fr: "Flotte B2B", en: "B2B Fleet", place: "GUIDKO Flotte",   g: "🚐", person: { name: "Invité", email: "", tone: 3 } },
  depannage: { fr: "Dépannage", en: "Roadside", place: "GUIDKO Dépannage", g: "🛟", person: { name: "Invité", email: "", tone: 3 } },
  controle:  { fr: "Contrôle technique", en: "Inspection", place: "GUIDKO Contrôle", g: "✓", person: { name: "Invité", email: "", tone: 3 } },
  lavage:    { fr: "Lavage", en: "Wash", place: "GUIDKO Lavage", g: "✦", person: { name: "Invité", email: "", tone: 3 } },
  financement:{ fr: "Financement", en: "Financing", place: "GUIDKO Financement", g: "€", person: { name: "Invité", email: "", tone: 3 } },
  recyclage: { fr: "Recyclage", en: "Recycling", place: "GUIDKO Recyclage", g: "♺", person: { name: "Invité", email: "", tone: 3 } },
  tourisme:  { fr: "Tourisme & LLD", en: "Tourism", place: "GUIDKO Tourisme", g: "🌍", person: { name: "Invité", email: "", tone: 3 } },
  recharge:  { fr: "Recharge solidaire", en: "Solidarity charge", place: "GUIDKO Recharge", g: "⚡", person: { name: "Invité", email: "", tone: 3 } },
  emploi:    { fr: "Emploi", en: "Jobs", place: "GUIDKO Emploi", g: "✦", person: { name: "Invité", email: "", tone: 3 } },
  formation: { fr: "Formation Pro", en: "Pro training", place: "GUIDKO Formation", g: "▲", person: { name: "Invité", email: "", tone: 3 } },
  pass:      { fr: "Pass Mobilité", en: "Mobility Pass", place: "GUIDKO Pass", g: "🌍", person: { name: "Invité", email: "", tone: 3 } },
  carrosserie: { fr: "Carrosserie", en: "Bodywork", place: "GUIDKO Carrosserie", g: "🛡", person: { name: "Invité", email: "", tone: 3 } },
  mobilitedouce: { fr: "Mobilité douce", en: "Soft mobility", place: "GUIDKO Mobilité", g: "⇅", person: { name: "Invité", email: "", tone: 3 } },
  convoyage: { fr: "Convoyage", en: "Vehicle transport", place: "GUIDKO Convoyage", g: "▢", person: { name: "Invité", email: "", tone: 3 } },
  vtc:       { fr: "Taxi & VTC", en: "Taxi & Ride", place: "GUIDKO VTC", g: "◈", person: { name: "Invité", email: "", tone: 3 } },
  adapte:    { fr: "Transport adapté", en: "Accessible transport", place: "GUIDKO Adapté", g: "♿", person: { name: "Invité", email: "", tone: 3 } },
  autopartage: { fr: "Auto-partage", en: "Car-sharing", place: "GUIDKO Auto-partage", g: "⇄", person: { name: "Invité", email: "", tone: 3 } },
  demarches: { fr: "Démarches auto", en: "Admin & papers", place: "GUIDKO Démarches", g: "▤", person: { name: "Invité", email: "", tone: 3 } },
  train:     { fr: "Train & Ferroviaire", en: "Rail", place: "GUIDKO Train", g: "▦", person: { name: "Invité", email: "", tone: 3 } },
  bus:       { fr: "Bus & Car", en: "Bus & Coach", place: "GUIDKO Bus", g: "▥", person: { name: "Invité", email: "", tone: 3 } },
  bateau:    { fr: "Maritime & Fluvial", en: "Sea & River", place: "GUIDKO Maritime", g: "⚓", person: { name: "Invité", email: "", tone: 3 } },
  aerien:    { fr: "Aérien & Drone", en: "Air & Drone", place: "GUIDKO Aérien", g: "✈", person: { name: "Invité", email: "", tone: 3 } },
  peage:     { fr: "Péage & Autoroute", en: "Tolls & Highway", place: "GUIDKO Péage", g: "▦", person: { name: "Invité", email: "", tone: 3 } },
  fret:      { fr: "Fret & Transport lourd", en: "Freight", place: "GUIDKO Fret", g: "▣", person: { name: "Invité", email: "", tone: 3 } },
  sanitaire: { fr: "Transport sanitaire", en: "Medical transport", place: "GUIDKO Sanitaire", g: "✚", person: { name: "Invité", email: "", tone: 3 } },
  loisirs:   { fr: "Loisirs & Camping-car", en: "Leisure & Camper", place: "GUIDKO Loisirs", g: "◳", person: { name: "Invité", email: "", tone: 3 } },
  engins:    { fr: "Engins & BTP", en: "Machinery", place: "GUIDKO Engins", g: "◮", person: { name: "Invité", email: "", tone: 3 } },
  prevention:{ fr: "Prévention & Stages", en: "Safety & Courses", place: "GUIDKO Prévention", g: "🛡", person: { name: "Invité", email: "", tone: 3 } },
  evenement: { fr: "Événementiel", en: "Events", place: "GUIDKO Événementiel", g: "◈", person: { name: "Invité", email: "", tone: 3 } },
  voiturier: { fr: "Voiturier & Gardiennage", en: "Valet & Storage", place: "GUIDKO Voiturier", g: "◳", person: { name: "Invité", email: "", tone: 3 } },
  connect:   { fr: "Connectivité & Objets", en: "Connectivity", place: "GUIDKO Connect", g: "◉", person: { name: "Invité", email: "", tone: 3 } },
  equipement:{ fr: "Équipement & Accessoires", en: "Gear", place: "GUIDKO Équipement", g: "◮", person: { name: "Invité", email: "", tone: 3 } },
  transit:   { fr: "Transit urbain", en: "Urban transit", place: "GUIDKO Transit", g: "▦", person: { name: "Invité", email: "", tone: 3 } },
  verte:     { fr: "Mobilité verte", en: "Green mobility", place: "GUIDKO Verte", g: "✦", person: { name: "Invité", email: "", tone: 3 } },
  data:      { fr: "Data & Infrastructure", en: "Data & Infra", place: "GUIDKO Data", g: "◍", person: { name: "Invité", email: "", tone: 3 } },
};
Object.entries(SERVICE_ROLES).forEach(([k, v]) => {
  ROLES[k] = {
    fr: v.fr, en: v.en, place: v.place, person: { ...v.person, role: k },
    nav: [
      { k: "overview",  fr: "Accueil",   en: "Home",      g: v.g },
      { k: "wallet",    fr: "Wallet",    en: "Wallet",    g: "▣" },
      { k: "messages",  fr: "Messages",  en: "Messages",  g: "✉" },
      { k: "trust",     fr: "Confiance", en: "Trust",     g: "🛡" },
      { k: "assurance", fr: "Assurance", en: "Insurance", g: "🛡" },
    ],
  };
});
// Chaque espace est distinct : on ne voit que SES sections + le tronc commun.
const SIDE_NAV = {
  covoit: {
    passager: { label: { fr: "Espace Passager", en: "Passenger space" }, other: "conducteur", otherLabel: { fr: "Passer conducteur", en: "Switch to driver" }, items: [
      { k: "overview", fr: "Accueil", en: "Home", g: "⇅" },
      { k: "search",   fr: "Mes trajets", en: "My rides", g: "🔍" },
    ]},
    conducteur: { label: { fr: "Espace Conducteur", en: "Driver space" }, other: "passager", otherLabel: { fr: "Passer passager", en: "Switch to passenger" }, items: [
      { k: "overview", fr: "Accueil", en: "Home", g: "⇅" },
      { k: "driver",   fr: "Mes trajets", en: "My rides", g: "🚗" },
      { k: "publish",  fr: "Publier", en: "Offer", g: "✎" },
      { k: "drive",    fr: "GUIDAROUTE", en: "GUIDAROUTE", g: "🛰", lia: true },
    ]},
  },
  livraison: {
    client: { label: { fr: "Espace Client", en: "Client space" }, other: "livreur", otherLabel: { fr: "Devenir livreur", en: "Become courier" }, items: [
      { k: "overview", fr: "Accueil", en: "Home", g: "📦" },
      { k: "client",   fr: "Commander", en: "Order", g: "🛒" },
    ]},
    livreur: { label: { fr: "Espace Livreur", en: "Courier space" }, other: "client", otherLabel: { fr: "Passer client", en: "Switch to client" }, items: [
      { k: "overview", fr: "Accueil", en: "Home", g: "📦" },
      { k: "livreur",  fr: "Mes missions", en: "My missions", g: "🚴" },
      { k: "b2b",      fr: "Logistique B2B", en: "B2B Logistics", g: "🏭" },
      { k: "drive",    fr: "GPS Livraison", en: "Delivery GPS", g: "🛰", lia: true },
    ]},
  },
};
const SIDE_COMMON = [
  { k: "vehicles",  fr: "Véhicules", en: "Vehicles", g: "⇄", market: true },
  { k: "wallet",    fr: "Wallet",    en: "Wallet",   g: "▣" },
  { k: "messages",  fr: "Messages",  en: "Messages", g: "✉" },
  { k: "trust",     fr: "Confiance", en: "Trust",    g: "🛡" },
  { k: "assurance", fr: "Assurance", en: "Insurance", g: "🛡" },
];
// Renvoie {nav, space} selon le côté connecté, sinon null (nav par défaut).
function sideNavFor(role, user) {
  const map = SIDE_NAV[role];
  if (!map) return null;
  const side = role === "covoit" ? (user && user.covoitSide) : (user && user.livrSide);
  const conf = side && map[side];
  if (!conf) return null;
  return { nav: [...conf.items, ...SIDE_COMMON], space: conf, side };
}
// Responsive viewport hook: 'mobile' (<760) | 'tablet' (760-1100) | 'desktop'
function useViewport() {
  const get = () => {
    if (window.GK_FORCE_VIEWPORT) return window.GK_FORCE_VIEWPORT; // 'mobile' | 'tablet' | 'desktop' — forcé par la surface (ex: GUIDKO Mobile V1)
    const w = window.innerWidth;
    return w < 760 ? "mobile" : w < 1100 ? "tablet" : "desktop";
  };
  const [vp, setVp] = React.useState(get());
  React.useEffect(() => {
    const on = () => setVp(get());
    window.addEventListener("resize", on);
    return () => window.removeEventListener("resize", on);
  }, []);
  return vp;
}
window.useViewport = useViewport;

// Mappe une clé de section vers une icône premium (fallback emoji si absente)
const NAV_ICON = {
  overview: "overview", schedule: "schedule", students: "students", instructors: "instructor",
  vehicles: "vehicles", analytics: "analytics", finance: "finance", wallet: "wallet",
  messages: "messages", trust: "trust", pricing: "pricing", security: "security",
  contracts: "contracts", referral: "referral", region: "region", settings: "settings",
  profile: "profil", earnings: "finance", planning: "schedule", enrollments: "students",
  search: "search", driver: "covoit", publish: "publish", drive: "drive",
  client: "livraison", livreur: "livraison", b2b: "b2b", code: "eleve", book: "schedule",
  assurance: "shield",
  energie: "bolt", parking: "location", entretien: "auto", flotte: "b2b",
};
function NavGlyph({ item, size = 18 }) {
  const nm = NAV_ICON[item.k];
  if (nm && window.hasGKIcon && window.hasGKIcon(nm)) return <GKIcon name={nm} size={size}/>;
  return <span style={{ fontSize: size - 2 }}>{item.g}</span>;
}

function AppShell({ role, section, navigate, children }) {
  const C = GK.colors;
  const { lang, t, setLang } = useI18n();
  const store = useStore();
  const cfg = ROLES[role];
  const person = store.state.user || cfg.person;
  const sideInfo = sideNavFor(role, store.state.user);
  const gkHiddenNav = (window.GK_LAUNCH && window.GK_LAUNCH.hidden) || [];
  const navItems = (sideInfo ? sideInfo.nav : cfg.nav).filter(it => !gkHiddenNav.includes(it.k));
  const [menuOpen, setMenuOpen] = React.useState(false);
  const vp = useViewport();

  // Bascule d'espace (client ↔ pro) : retour à l'accueil de l'app pour re-choisir l'entrée
  function switchSpace() { navigate(`/${role}/overview`); }

  // ===== MOBILE / TABLET PORTRAIT: bottom tab bar =====
  if (vp === "mobile") {
    const tabs = navItems.slice(0, 4);
    const more = navItems.slice(4);
    const [moreOpen, setMoreOpen] = [menuOpen, setMenuOpen];
    return (
      <div style={{ display: "flex", flexDirection: "column", height: "100vh", background: C.paper, color: C.ink, fontFamily: "'Geist', sans-serif", overflow: "hidden" }}>
        {/* Mobile header */}
        <header style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "12px 16px", background: C.ink, color: "#fff", flexShrink: 0 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 9 }} onClick={() => navigate(`/${role}/overview`)}>
            <GuidkoMark size={22} color="#fff" accent={C.flame}/>
            <div>
              <div style={{ fontWeight: 800, fontSize: 14, letterSpacing: "0.04em" }}>GUIDKO</div>
              <div style={{ fontFamily: "'Geist Mono', monospace", fontSize: 8, color: C.flame, letterSpacing: "0.12em" }}>{(cfg[lang] || cfg.fr || "").toUpperCase()}</div>
            </div>
          </div>
          <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
            <button onClick={() => window.dispatchEvent(new CustomEvent("gk-cmdk"))} style={{ width: 36, height: 36, borderRadius: 9, background: "#1F2542", color: "#fff", border: "none", fontSize: 15 }}>⌕</button>
            <LangSelector dark compact/>
          </div>
        </header>

        {/* Page body */}
        <div style={{ flex: 1, overflow: "hidden", display: "flex", flexDirection: "column" }}>{store.state.user && store.state.user.guest && <GuestBanner navigate={navigate}/>}{children}</div>

        {/* More sheet */}
        {moreOpen && (
          <div onClick={() => setMoreOpen(false)} style={{ position: "fixed", inset: 0, background: "rgba(8,11,24,0.5)", zIndex: 700, display: "flex", alignItems: "flex-end" }}>
            <div onClick={e => e.stopPropagation()} style={{ background: "#fff", width: "100%", borderRadius: "18px 18px 0 0", padding: "10px 14px 26px", maxHeight: "70vh", overflowY: "auto" }}>
              <div style={{ width: 38, height: 4, borderRadius: 2, background: "#D9D2C0", margin: "6px auto 14px" }}/>
              <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 8 }}>
                {more.map(item => (
                  <button key={item.k} onClick={() => { navigate(`/${role}/${item.k}`); setMoreOpen(false); }} style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 7, padding: "14px 6px", borderRadius: 12, border: `1px solid ${C.softLine}`, background: section === item.k ? C.cream : "#fff", fontSize: 11.5, color: C.ink }}>
                    <span style={{ display: "grid", placeItems: "center", height: 20 }}><NavGlyph item={item} size={19}/></span>{navLabel(item, lang)}
                  </button>
                ))}
              </div>
              <div style={{ borderTop: `1px solid ${C.softLine}`, marginTop: 14, paddingTop: 12, display: "flex", gap: 8 }}>
                <button onClick={() => { navigate("/login"); }} style={{ flex: 1, padding: "12px", borderRadius: 10, border: `1px solid ${C.softLine}`, background: "#fff", fontSize: 13, fontWeight: 600 }}>⇄ {t("Changer", "Switch")}</button>
                <button onClick={() => { store.logout(); navigate("/login"); }} style={{ flex: 1, padding: "12px", borderRadius: 10, border: "none", background: "#FFF1EB", color: C.flame, fontSize: 13, fontWeight: 600 }}>⏻ {t("Quitter", "Sign out")}</button>
              </div>
            </div>
          </div>
        )}

        {/* Bottom tab bar */}
        <nav style={{ display: "flex", background: "#fff", borderTop: `1px solid ${C.softLine}`, flexShrink: 0, paddingBottom: "env(safe-area-inset-bottom, 0)" }}>
          {tabs.map(item => {
            const on = item.k === section;
            return (
              <button key={item.k} onClick={() => navigate(`/${role}/${item.k}`)} style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center", gap: 3, padding: "9px 2px", background: "none", border: "none", color: on ? C.flame : "#9098B5", minHeight: 54 }}>
                <span style={{ display: "grid", placeItems: "center", height: 20 }}><NavGlyph item={item} size={19}/></span>
                <span style={{ fontSize: 9.5, fontWeight: on ? 700 : 500 }}>{navLabel(item, lang)}</span>
              </button>
            );
          })}
          {more.length > 0 && (
            <button onClick={() => setMoreOpen(true)} style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center", gap: 3, padding: "9px 2px", background: "none", border: "none", color: moreOpen ? C.flame : "#9098B5", minHeight: 54 }}>
              <span style={{ fontSize: 18 }}>⋯</span><span style={{ fontSize: 9.5 }}>{t("Plus", "More")}</span>
            </button>
          )}
        </nav>
        <LiaAssistant role={role} navigate={navigate}/>
      </div>
    );
  }

  // ===== TABLET: icon rail (72px) =====
  const railWidth = vp === "tablet" ? 72 : 240;
  const compact = vp === "tablet";

  return (
    <div style={{ display: "grid", gridTemplateColumns: `${railWidth}px 1fr`, height: "100vh", background: C.paper, color: C.ink, fontFamily: "'Geist', sans-serif", overflow: "hidden" }}>
      {/* Sidebar */}
      <aside style={{ background: C.ink, color: "#fff", padding: compact ? "18px 10px" : "20px 16px", display: "flex", flexDirection: "column", overflow: "hidden", alignItems: compact ? "center" : "stretch" }}>
        <div style={{ marginBottom: 22, cursor: "pointer" }} onClick={() => navigate(`/${role}/overview`)}>
          {compact ? <GuidkoMark size={26} color="#fff" accent={C.flame}/> : <GuidkoLogo color="#fff"/>}
        </div>

        {!compact && (
          <div style={{ border: "1px solid #1F2542", padding: "11px 13px", borderRadius: 9, marginBottom: 22 }}>
            <Label color="#7A82A8" style={{ fontSize: 9 }}>{sideInfo ? t("Espace actif", "Active space") : t("Espace", "Workspace")}</Label>
            <div style={{ fontSize: 14, fontWeight: 600, marginTop: 4 }}>{sideInfo ? (sideInfo.space.label[lang] || sideInfo.space.label.fr) : cfg[lang]}</div>
            {sideInfo ? (
              <button onClick={switchSpace} style={{ marginTop: 8, width: "100%", padding: "7px 10px", borderRadius: 7, border: `1px solid ${C.flame}55`, background: "#1F2542", color: C.flame, fontSize: 11.5, fontWeight: 600, cursor: "pointer", fontFamily: "inherit", display: "flex", alignItems: "center", justifyContent: "center", gap: 6 }}>
                ⇄ {sideInfo.space.otherLabel[lang] || sideInfo.space.otherLabel.fr}
              </button>
            ) : (
              <div style={{ fontFamily: "'Geist Mono', monospace", fontSize: 10, color: C.flame, marginTop: 5 }}>{cfg.place}</div>
            )}
          </div>
        )}

        <nav style={{ display: "flex", flexDirection: "column", gap: compact ? 6 : 2, flex: 1, overflowY: "auto", width: "100%", alignItems: compact ? "center" : "stretch" }} className="gk-scroll">
          {navItems.map(item => {
            const on = item.k === section;
            if (compact) {
              return (
                <div key={item.k} onClick={() => navigate(`/${role}/${item.k}`)} title={navLabel(item, lang)} style={{
                  width: 46, height: 46, borderRadius: 11, display: "grid", placeItems: "center", cursor: "pointer",
                  background: on ? "#1F2542" : "transparent", color: on ? C.flame : "#8A91B0", fontSize: 17,
                  borderLeft: on ? `2px solid ${C.flame}` : "2px solid transparent",
                }}><NavGlyph item={item} size={20}/></div>
              );
            }
            return (
              <div key={item.k} onClick={() => navigate(`/${role}/${item.k}`)} style={{
                display: "flex", alignItems: "center", gap: 12, padding: "10px 12px", borderRadius: 8,
                fontSize: 14, cursor: "pointer", background: on ? "#1F2542" : "transparent",
                color: on ? "#fff" : "#C9CEE3", borderLeft: on ? `2px solid ${C.flame}` : "2px solid transparent",
                transition: "background .12s",
              }}
              onMouseEnter={e => { if (!on) e.currentTarget.style.background = "#141A30"; }}
              onMouseLeave={e => { if (!on) e.currentTarget.style.background = "transparent"; }}>
                <span style={{ color: on ? C.flame : "#6B7390", width: 18, display: "grid", placeItems: "center" }}><NavGlyph item={item} size={18}/></span>
                <span style={{ flex: 1 }}>{navLabel(item, lang)}</span>
                {item.market && <span style={{ fontFamily: "'Geist Mono', monospace", fontSize: 8, letterSpacing: "0.1em", color: on ? C.flame : "#5B6388", padding: "2px 5px", border: `1px solid ${on ? C.flame + "55" : "#2A3250"}`, borderRadius: 4 }}>B2B</span>}
              </div>
            );
          })}
        </nav>

        <div style={{ borderTop: "1px solid #1F2542", paddingTop: 14, marginTop: 14, position: "relative", width: "100%" }}>
          {compact ? (
            <div onClick={() => setMenuOpen(o => !o)} style={{ display: "grid", placeItems: "center", cursor: "pointer" }}>
              <Avatar name={person.name} size={34} tone={person.tone}/>
            </div>
          ) : (
          <div onClick={() => setMenuOpen(o => !o)} style={{ display: "flex", alignItems: "center", gap: 10, cursor: "pointer" }}>
            <Avatar name={person.name} size={34} tone={person.tone}/>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 13, fontWeight: 600, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{person.name}</div>
              <div style={{ fontSize: 11, color: "#9098B5", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{person.email}</div>
            </div>
            <span style={{ color: "#9098B5", fontSize: 12 }}>{menuOpen ? "▾" : "▴"}</span>
          </div>
          )}
          {menuOpen && (
            <div style={{ position: "absolute", bottom: 56, left: 0, right: compact ? -120 : 0, width: compact ? 180 : "auto", background: "#141A30", border: "1px solid #1F2542", borderRadius: 9, overflow: "hidden", boxShadow: "0 -8px 30px rgba(0,0,0,0.4)", zIndex: 50 }}>
              <div onClick={() => { navigate("/login"); }} style={{ padding: "11px 14px", fontSize: 13, cursor: "pointer", display: "flex", gap: 8 }}
                onMouseEnter={e => e.currentTarget.style.background = "#1F2542"} onMouseLeave={e => e.currentTarget.style.background = "transparent"}>
                ⇄ {t("Changer de rôle", "Switch role")}
              </div>
              <div onClick={() => { store.logout(); navigate("/login"); }} style={{ padding: "11px 14px", fontSize: 13, cursor: "pointer", display: "flex", gap: 8, color: "#FF8854", borderTop: "1px solid #1F2542" }}
                onMouseEnter={e => e.currentTarget.style.background = "#1F2542"} onMouseLeave={e => e.currentTarget.style.background = "transparent"}>
                ⏻ {t("Déconnexion", "Sign out")}
              </div>
            </div>
          )}
        </div>
      </aside>

      {/* Main column */}
      <div style={{ display: "flex", flexDirection: "column", overflow: "hidden" }}>
        {store.state.user && store.state.user.guest && <GuestBanner navigate={navigate}/>}
        {children}
      </div>

      {/* Lang toggle floats */}
      <TransversalToolbar role={role} navigate={navigate}/>
      <LiaAssistant role={role} navigate={navigate}/>
      {/* Universal language selector floats */}
      <div style={{ position: "fixed", top: 14, right: 18, zIndex: 600 }}>
        <LangSelector/>
      </div>
    </div>
  );
}

// Bannière invité : présente partout en mode visiteur, invite à créer un compte.
function GuestBanner({ navigate }) {
  const C = GK.colors;
  const { t } = useI18n();
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 12, padding: "9px 18px", background: C.ink, color: "#fff", flexShrink: 0, flexWrap: "wrap" }}>
      <span style={{ display: "inline-flex", alignItems: "center", gap: 7, fontFamily: "'Geist Mono', monospace", fontSize: 9, letterSpacing: "0.14em", color: C.flame }}>👁 {t("MODE VISITEUR","GUEST MODE")}</span>
      <span style={{ fontSize: 12.5, color: "#C9CEE3", flex: 1, minWidth: 180 }}>{t("Tu explores en invité. Crée ton compte pour réserver, gagner et tout débloquer.","You're exploring as a guest. Create your account to book, earn and unlock everything.")}</span>
      <button onClick={() => navigate("/login")} style={{ padding: "6px 14px", borderRadius: 999, border: "none", background: C.flame, color: "#fff", fontSize: 12.5, fontWeight: 600, cursor: "pointer", fontFamily: "inherit", whiteSpace: "nowrap", flexShrink: 0 }}>{t("Créer mon compte","Create account")} →</button>
      <button onClick={() => navigate("/login")} style={{ padding: "6px 12px", borderRadius: 999, border: "1px solid #2A3250", background: "transparent", color: "#C9CEE3", fontSize: 12.5, fontWeight: 600, cursor: "pointer", fontFamily: "inherit", whiteSpace: "nowrap", flexShrink: 0 }}>{t("Se connecter","Sign in")}</button>
    </div>
  );
}

// ---------- Topbar (inside main column) ----------
function Topbar({ subtitle, title, actions, search = true }) {
  const C = GK.colors;
  const { t } = useI18n();
  const vp = (window.useViewport ? window.useViewport() : "desktop");
  const mobile = vp === "mobile";
  return (
    <header style={{ padding: mobile ? "13px 16px" : "18px 28px", borderBottom: `1px solid ${C.softLine}`, display: "flex", justifyContent: "space-between", alignItems: "center", flexShrink: 0, background: C.paper, gap: 10 }}>
      <div style={{ minWidth: 0, flex: 1 }}>
        {subtitle && <Label style={{ fontSize: 10 }}>{subtitle}</Label>}
        <h1 style={{ fontFamily: "'Instrument Serif', serif", fontSize: mobile ? 24 : 34, fontWeight: 400, margin: "3px 0 0", letterSpacing: "-0.02em", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{title}</h1>
      </div>
      <div style={{ display: "flex", alignItems: "center", gap: 10, flexShrink: 0, marginRight: mobile ? 0 : 104 }}>
        {search && !mobile && (
          <div onClick={() => window.dispatchEvent(new CustomEvent("gk-cmdk"))} style={{ display: "flex", alignItems: "center", gap: 8, padding: "9px 12px", background: "#fff", border: `1px solid ${C.softLine}`, borderRadius: 9, fontSize: 13, color: C.slate, minWidth: 160, cursor: "pointer" }}>
            <span>⌕</span> {t("Rechercher…", "Search…")}
            <span style={{ marginLeft: "auto", fontFamily: "'Geist Mono', monospace", fontSize: 10, padding: "2px 6px", background: C.paper, borderRadius: 4 }}>⌘K</span>
          </div>
        )}
        {actions}
      </div>
    </header>
  );
}

// Scroll container for page bodies
function PageBody({ children, style = {} }) {
  return <div className="gk-scroll gk-page" style={{ padding: 26, overflowY: "auto", flex: 1, background: GK.colors.paper, ...style }}>{children}</div>;
}

// KPI card
// Mappe les symboles KPI usuels vers des icônes premium
const KPI_ICON = {
  "€": "finance", "$": "finance", "★": "star", "◎": "target", "⇄": "auto",
  "▲": "trendup", "▼": "trenddown", "!": "alert", "🔥": "flame", "📋": "clipboard",
  "✎": "edit", "✆": "phone", "⇅": "covoit", "♥": "heart", "♡": "heart",
};
function KPI({ label, value, delta, deltaTone = "signal", sub, icon }) {
  const C = GK.colors;
  const iconName = icon && KPI_ICON[icon];
  return (
    <Card style={{ padding: 20 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
        <Label style={{ marginBottom: 10 }}>{label}</Label>
        {icon && <div style={{ width: 32, height: 32, borderRadius: 8, background: "#F6F2E6", display: "grid", placeItems: "center", fontSize: 15, color: C.ink }}>{iconName && window.hasGKIcon && window.hasGKIcon(iconName) ? <GKIcon name={iconName} size={17}/> : icon}</div>}
      </div>
      <div style={{ fontFamily: "'Instrument Serif', serif", fontSize: 42, lineHeight: 1, letterSpacing: "-0.02em" }}>{value}</div>
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginTop: 10 }}>
        {delta && <Pill tone={deltaTone}>{delta}</Pill>}
        {sub && <span style={{ fontSize: 12, color: C.slate }}>{sub}</span>}
      </div>
    </Card>
  );
}

Object.assign(window, { BRAND, GuidkoMark, GuidkoLogo, ROLES, AppShell, Topbar, PageBody, KPI });
