// Generates PS_Launcher-Guide-Utilisateur.pptx
const pptxgen = require("pptxgenjs");

const COL = {
    bg:        "000000",
    card:      "161B23",
    elev:      "1E2632",
    border:    "2A2F3A",
    text:      "F2F2F2",
    muted:     "A0A0A8",
    accent:    "3B82F6",
    accentDk:  "1F3A66",
    green:     "16A34A",
    greenDk:   "0E2A1B",
    amber:     "F59E0B",
    amberDk:   "3A2A0E",
    red:       "EF4444",
    redDk:     "2A1414",
    codeBg:    "0A0E14",
};
const F_TITLE = "Calibri";
const F_BODY  = "Calibri";
const F_CODE  = "Consolas";

const pres = new pptxgen();
pres.layout = "LAYOUT_16x9";
pres.author = "ASTERION VR";
pres.title  = "PROSERVE Launcher — Guide Utilisateur";
pres.company = "ASTERION VR";

const W = 10, H = 5.625;

// ---- helpers (same as internal but kept local to avoid module fuss) ----
function fillBg(slide) { slide.background = { color: COL.bg }; }

function addHeader(slide, title, kicker) {
    slide.addShape(pres.shapes.RECTANGLE, {
        x: 0, y: 0, w: W, h: 0.06, fill: { color: COL.green }, line: { type: "none" }
    });
    if (kicker) {
        slide.addText(kicker.toUpperCase(), {
            x: 0.5, y: 0.25, w: W - 1, h: 0.3,
            fontFace: F_BODY, fontSize: 11, bold: true,
            color: COL.green, charSpacing: 4, margin: 0
        });
    }
    slide.addText(title, {
        x: 0.5, y: kicker ? 0.55 : 0.35, w: W - 1, h: 0.7,
        fontFace: F_TITLE, fontSize: 32, bold: true,
        color: COL.text, margin: 0
    });
    slide.addShape(pres.shapes.LINE, {
        x: 0.5, y: kicker ? 1.3 : 1.15, w: 1.2, h: 0,
        line: { color: COL.green, width: 2 }
    });
}

function addFooter(slide, page) {
    slide.addText("PROSERVE Launcher  •  Guide Utilisateur  •  ASTERION VR", {
        x: 0.5, y: H - 0.35, w: W - 2, h: 0.25,
        fontFace: F_BODY, fontSize: 9, color: COL.muted, margin: 0
    });
    if (page) {
        slide.addText(String(page), {
            x: W - 1, y: H - 0.35, w: 0.5, h: 0.25,
            fontFace: F_BODY, fontSize: 9, color: COL.muted, align: "right", margin: 0
        });
    }
}

function addCard(slide, x, y, w, h, options = {}) {
    slide.addShape(pres.shapes.RECTANGLE, {
        x, y, w, h,
        fill: { color: options.fill || COL.card },
        line: { color: options.border || COL.border, width: 1 },
    });
}

function addAccentCard(slide, x, y, w, h, accentColor) {
    addCard(slide, x, y, w, h);
    slide.addShape(pres.shapes.RECTANGLE, {
        x, y, w: 0.08, h,
        fill: { color: accentColor }, line: { type: "none" }
    });
}

function addCodeBlock(slide, x, y, w, h, lines) {
    slide.addShape(pres.shapes.RECTANGLE, {
        x, y, w, h, fill: { color: COL.codeBg }, line: { color: COL.border, width: 1 }
    });
    const text = (Array.isArray(lines) ? lines : [lines]).map((line, i, arr) => ({
        text: line,
        options: { breakLine: i < arr.length - 1 }
    }));
    slide.addText(text, {
        x: x + 0.15, y: y + 0.1, w: w - 0.3, h: h - 0.2,
        fontFace: F_CODE, fontSize: 11, color: COL.text, margin: 0,
        valign: "top"
    });
}

function addBullets(slide, x, y, w, h, items, opts = {}) {
    const fontSize = opts.fontSize || 14;
    const color = opts.color || COL.text;
    const arr = items.map((it, i) => ({
        text: it,
        options: { bullet: { code: "25A0" }, breakLine: i < items.length - 1, color }
    }));
    slide.addText(arr, {
        x, y, w, h, fontFace: F_BODY, fontSize, color, margin: 0,
        paraSpaceAfter: 6
    });
}

// ===================== SLIDE 1: COVER =====================
{
    const s = pres.addSlide();
    fillBg(s);

    // Big band on left
    s.addShape(pres.shapes.RECTANGLE, {
        x: 0, y: 0, w: 3.5, h: H, fill: { color: COL.greenDk }, line: { type: "none" }
    });
    s.addShape(pres.shapes.RECTANGLE, {
        x: 3.45, y: 0, w: 0.05, h: H, fill: { color: COL.green }, line: { type: "none" }
    });

    // Brand
    s.addText("ASTERION VR", {
        x: 0.4, y: 0.5, w: 3, h: 0.4,
        fontFace: F_BODY, fontSize: 13, bold: true,
        color: COL.green, charSpacing: 8, margin: 0
    });

    // Big right title
    s.addText("PROSERVE", {
        x: 3.9, y: 1.3, w: 6, h: 1,
        fontFace: F_TITLE, fontSize: 60, bold: true,
        color: COL.text, margin: 0
    });
    s.addText("Launcher", {
        x: 3.9, y: 2.1, w: 6, h: 0.7,
        fontFace: F_TITLE, fontSize: 40, bold: true,
        color: COL.muted, margin: 0
    });

    s.addText("Guide utilisateur", {
        x: 3.9, y: 3.0, w: 6, h: 0.5,
        fontFace: F_TITLE, fontSize: 22,
        color: COL.green, margin: 0
    });
    s.addText("Installation, activation et utilisation", {
        x: 3.9, y: 3.5, w: 6, h: 0.4,
        fontFace: F_BODY, fontSize: 14, italic: true,
        color: COL.muted, margin: 0
    });

    // Left band content
    s.addText("v0.8", {
        x: 0.4, y: 2, w: 3, h: 1,
        fontFace: F_TITLE, fontSize: 56, bold: true,
        color: COL.text, align: "center", margin: 0
    });
    s.addText("Mai 2026", {
        x: 0.4, y: 2.95, w: 3, h: 0.3,
        fontFace: F_BODY, fontSize: 13,
        color: COL.muted, align: "center", margin: 0
    });

    // Bottom strip
    s.addShape(pres.shapes.RECTANGLE, {
        x: 0, y: H - 0.5, w: W, h: 0.5, fill: { color: COL.card }, line: { type: "none" }
    });
    s.addText("© 2026 ASTERION VR — Tous droits réservés", {
        x: 0.5, y: H - 0.45, w: W - 1, h: 0.4,
        fontFace: F_BODY, fontSize: 11, color: COL.muted, margin: 0
    });
}

// ===================== SLIDE 2: WHAT IS IT =====================
{
    const s = pres.addSlide();
    fillBg(s);
    addHeader(s, "Qu'est-ce que PROSERVE Launcher ?", "introduction");
    addFooter(s, 2);

    s.addText("Une application Windows qui te permet de :", {
        x: 0.5, y: 1.4, w: W - 1, h: 0.4,
        fontFace: F_BODY, fontSize: 16, color: COL.text, margin: 0
    });

    const features = [
        ["📦", "Installer", "Télécharge et déploie chaque nouvelle version de Proserve sur ta machine en quelques clics."],
        ["▶", "Lancer",     "Démarre la version de ton choix. Plusieurs versions peuvent cohabiter sur le même PC."],
        ["🔄", "Mettre à jour", "Détecte automatiquement les nouvelles versions disponibles côté serveur ASTERION et propose la mise à jour."],
        ["🔑", "License",    "Vérifie ta license en ligne (ou via cache local 7 jours en cas de coupure réseau)."],
    ];

    let y = 2.0;
    features.forEach(([icon, title, desc]) => {
        addCard(s, 0.5, y, W - 1, 0.7);
        s.addText(icon, {
            x: 0.7, y: y + 0.13, w: 0.6, h: 0.45,
            fontFace: F_TITLE, fontSize: 20, color: COL.green, align: "center", margin: 0
        });
        s.addText(title, {
            x: 1.4, y: y + 0.07, w: 2, h: 0.3,
            fontFace: F_TITLE, fontSize: 14, bold: true, color: COL.text, margin: 0
        });
        s.addText(desc, {
            x: 1.4, y: y + 0.34, w: W - 1.9, h: 0.35,
            fontFace: F_BODY, fontSize: 11, color: COL.muted, margin: 0
        });
        y += 0.78;
    });
}

// ===================== SLIDE 3: PREREQUISITES =====================
{
    const s = pres.addSlide();
    fillBg(s);
    addHeader(s, "Pré-requis", "avant de commencer");
    addFooter(s, 3);

    const prereqs = [
        ["💻", "Windows 10 ou 11", "Édition 64-bit. Pas de version macOS / Linux pour l'instant."],
        ["🌐", "Connexion internet", "Requise pour activer la license et télécharger les versions. Le launcher fonctionne hors-ligne pendant 7 jours après la dernière validation."],
        ["💾", "Espace disque", "Prévoir ~14 Go par version installée + ~14 Go de cache temporaire pendant le téléchargement."],
        ["🔑", "Une clé license", "Format PRSRV-XXXX-XXXX-XXXX-XXXX, fournie par ASTERION VR."],
    ];

    let y = 1.5;
    prereqs.forEach(([icon, title, desc]) => {
        addAccentCard(s, 0.5, y, W - 1, 0.85, COL.green);
        s.addText(icon, {
            x: 0.75, y: y + 0.18, w: 0.7, h: 0.5,
            fontFace: F_TITLE, fontSize: 22, color: COL.green, align: "center", margin: 0
        });
        s.addText(title, {
            x: 1.5, y: y + 0.12, w: 6, h: 0.3,
            fontFace: F_TITLE, fontSize: 14, bold: true, color: COL.text, margin: 0
        });
        s.addText(desc, {
            x: 1.5, y: y + 0.42, w: W - 2, h: 0.4,
            fontFace: F_BODY, fontSize: 11, color: COL.muted, margin: 0
        });
        y += 0.95;
    });
}

// ===================== SLIDE 4: INSTALLATION =====================
{
    const s = pres.addSlide();
    fillBg(s);
    addHeader(s, "Installation", "première fois");
    addFooter(s, 4);

    const steps = [
        ["1", "Télécharge le setup", "Tu reçois un fichier nommé PSLauncher-Setup-X.Y.Z.exe (~80 Mo) — par email, lien WeTransfer, ou via le site ASTERION."],
        ["2", "Double-clique pour lancer", "Windows peut afficher un avertissement SmartScreen « Éditeur inconnu ».\nClique « Informations complémentaires » → « Exécuter quand même »."],
        ["3", "Suis l'assistant", "Choisis la langue, valide les chemins par défaut. Le launcher s'installe dans ton profil utilisateur — pas besoin de droits administrateur."],
        ["4", "Lance PROSERVE Launcher", "Un raccourci apparaît sur le bureau et dans le menu Démarrer."],
    ];

    let y = 1.5;
    steps.forEach(([num, title, desc]) => {
        addCard(s, 0.5, y, W - 1, 0.85);
        s.addShape(pres.shapes.OVAL, {
            x: 0.7, y: y + 0.2, w: 0.45, h: 0.45,
            fill: { color: COL.green }, line: { type: "none" }
        });
        s.addText(num, {
            x: 0.7, y: y + 0.2, w: 0.45, h: 0.45,
            fontFace: F_TITLE, fontSize: 16, bold: true,
            color: "FFFFFF", align: "center", valign: "middle", margin: 0
        });
        s.addText(title, {
            x: 1.4, y: y + 0.1, w: W - 2, h: 0.3,
            fontFace: F_TITLE, fontSize: 14, bold: true, color: COL.text, margin: 0
        });
        s.addText(desc, {
            x: 1.4, y: y + 0.4, w: W - 2, h: 0.4,
            fontFace: F_BODY, fontSize: 11, color: COL.muted, margin: 0
        });
        y += 0.95;
    });
}

// ===================== SLIDE 5: ACTIVATE LICENSE =====================
{
    const s = pres.addSlide();
    fillBg(s);
    addHeader(s, "Activer ta license", "premier démarrage");
    addFooter(s, 5);

    s.addText("Au premier lancement, le badge en haut au centre de la fenêtre indique « 🔒 Aucune license » en rouge.", {
        x: 0.5, y: 1.4, w: W - 1, h: 0.45,
        fontFace: F_BODY, fontSize: 13, color: COL.text, margin: 0
    });

    // Badge mockup
    addAccentCard(s, 0.5, 1.95, 4.5, 1.6, COL.red);
    s.addText("🔒  Aucune license", {
        x: 0.7, y: 2.05, w: 4, h: 0.4,
        fontFace: F_TITLE, fontSize: 16, bold: true, color: COL.red, margin: 0
    });
    s.addText("Visible dans la barre du haut au centre", {
        x: 0.7, y: 2.4, w: 4, h: 0.3,
        fontFace: F_BODY, fontSize: 11, italic: true, color: COL.muted, margin: 0
    });
    s.addText("👉  Clique dessus !", {
        x: 0.7, y: 2.85, w: 4, h: 0.5,
        fontFace: F_TITLE, fontSize: 16, bold: true, color: COL.green, margin: 0
    });

    // Then
    addAccentCard(s, 5.2, 1.95, 4.3, 1.6, COL.green);
    s.addText("Dialog d'activation", {
        x: 5.4, y: 2.05, w: 4, h: 0.3,
        fontFace: F_TITLE, fontSize: 14, bold: true, color: COL.text, margin: 0
    });
    addBullets(s, 5.4, 2.4, 4, 1.1, [
        "Colle ta clé PRSRV-…",
        "Clique « Activer »",
        "Le badge passe en vert ✓",
    ], { fontSize: 11 });

    // Result
    addCard(s, 0.5, 3.85, W - 1, 1.0);
    s.addText("Une fois activée :", {
        x: 0.7, y: 3.95, w: 4, h: 0.3,
        fontFace: F_TITLE, fontSize: 13, bold: true, color: COL.green, margin: 0
    });
    s.addText("La barre indique le nom du client + la date de validité. Tu peux maintenant télécharger les versions de Proserve auxquelles ta license te donne accès.", {
        x: 0.7, y: 4.25, w: W - 1.4, h: 0.6,
        fontFace: F_BODY, fontSize: 11, color: COL.muted, margin: 0
    });
}

// ===================== SLIDE 6: LIBRARY OVERVIEW =====================
{
    const s = pres.addSlide();
    fillBg(s);
    addHeader(s, "La fenêtre principale", "ta bibliothèque");
    addFooter(s, 6);

    // Hero card simulated
    addAccentCard(s, 0.5, 1.4, W - 1, 1.2, COL.green);
    s.addText("VERSION COURANTE", {
        x: 0.75, y: 1.5, w: 4, h: 0.3,
        fontFace: F_BODY, fontSize: 10, bold: true, color: COL.muted, charSpacing: 4, margin: 0
    });
    s.addText("Proserve v1.4.7", {
        x: 0.75, y: 1.78, w: 5, h: 0.5,
        fontFace: F_TITLE, fontSize: 24, bold: true, color: COL.text, margin: 0
    });
    s.addText("● Installée  •  Sortie le 29/04/2026  •  14 Go", {
        x: 0.75, y: 2.25, w: 5, h: 0.3,
        fontFace: F_BODY, fontSize: 11, color: COL.muted, margin: 0
    });
    // Big launcher button mockup
    s.addShape(pres.shapes.ROUNDED_RECTANGLE, {
        x: 7.4, y: 1.7, w: 1.8, h: 0.6,
        fill: { color: COL.green }, line: { type: "none" }, rectRadius: 0.05
    });
    s.addText("▶  LANCER", {
        x: 7.4, y: 1.7, w: 1.8, h: 0.6,
        fontFace: F_TITLE, fontSize: 16, bold: true,
        color: "FFFFFF", align: "center", valign: "middle", margin: 0
    });

    // Section header
    s.addText("AUTRES VERSIONS", {
        x: 0.5, y: 2.85, w: 3, h: 0.3,
        fontFace: F_BODY, fontSize: 10, bold: true, color: COL.muted, charSpacing: 4, margin: 0
    });

    // Other rows
    const rowY1 = 3.2, rowY2 = 4.0;
    addAccentCard(s, 0.5, rowY1, W - 1, 0.7, COL.green);
    s.addText("v1.4.6  ● Installée", {
        x: 0.75, y: rowY1 + 0.1, w: 5, h: 0.3,
        fontFace: F_TITLE, fontSize: 13, bold: true, color: COL.text, margin: 0
    });
    s.addText("14 Go  •  15/04/2026", {
        x: 0.75, y: rowY1 + 0.4, w: 5, h: 0.3,
        fontFace: F_BODY, fontSize: 10, color: COL.muted, margin: 0
    });
    s.addShape(pres.shapes.ROUNDED_RECTANGLE, {
        x: 8.3, y: rowY1 + 0.18, w: 1.05, h: 0.4,
        fill: { color: COL.green }, line: { type: "none" }, rectRadius: 0.05
    });
    s.addText("▶ Lancer", {
        x: 8.3, y: rowY1 + 0.18, w: 1.05, h: 0.4,
        fontFace: F_BODY, fontSize: 11, bold: true, color: "FFFFFF", align: "center", valign: "middle", margin: 0
    });

    addAccentCard(s, 0.5, rowY2, W - 1, 0.7, COL.accent);
    s.addText("v1.4.5  ○ Disponible", {
        x: 0.75, y: rowY2 + 0.1, w: 5, h: 0.3,
        fontFace: F_TITLE, fontSize: 13, bold: true, color: COL.text, margin: 0
    });
    s.addText("448 Mo  •  15/04/2026", {
        x: 0.75, y: rowY2 + 0.4, w: 5, h: 0.3,
        fontFace: F_BODY, fontSize: 10, color: COL.muted, margin: 0
    });
    s.addShape(pres.shapes.ROUNDED_RECTANGLE, {
        x: 8.1, y: rowY2 + 0.18, w: 1.25, h: 0.4,
        fill: { color: COL.accent }, line: { type: "none" }, rectRadius: 0.05
    });
    s.addText("⬇ Installer", {
        x: 8.1, y: rowY2 + 0.18, w: 1.25, h: 0.4,
        fontFace: F_BODY, fontSize: 11, bold: true, color: "FFFFFF", align: "center", valign: "middle", margin: 0
    });
}

// ===================== SLIDE 7: LAUNCH A VERSION =====================
{
    const s = pres.addSlide();
    fillBg(s);
    addHeader(s, "Lancer une version", "▶  jouer");
    addFooter(s, 7);

    s.addText("Deux possibilités :", {
        x: 0.5, y: 1.4, w: W - 1, h: 0.3,
        fontFace: F_BODY, fontSize: 14, color: COL.text, margin: 0
    });

    addAccentCard(s, 0.5, 1.85, 4.5, 2.5, COL.green);
    s.addText("LA PLUS RÉCENTE", {
        x: 0.7, y: 1.95, w: 4, h: 0.3,
        fontFace: F_BODY, fontSize: 11, bold: true, color: COL.green, charSpacing: 3, margin: 0
    });
    s.addText("Le gros bouton vert dans la carte « Version courante » lance la version la plus récente que tu as installée.", {
        x: 0.7, y: 2.3, w: 4, h: 1.2,
        fontFace: F_BODY, fontSize: 12, color: COL.text, margin: 0
    });
    s.addShape(pres.shapes.ROUNDED_RECTANGLE, {
        x: 0.7, y: 3.55, w: 4, h: 0.6,
        fill: { color: COL.green }, line: { type: "none" }, rectRadius: 0.05
    });
    s.addText("▶  LANCER", {
        x: 0.7, y: 3.55, w: 4, h: 0.6,
        fontFace: F_TITLE, fontSize: 16, bold: true,
        color: "FFFFFF", align: "center", valign: "middle", margin: 0
    });

    addAccentCard(s, 5.2, 1.85, 4.3, 2.5, COL.green);
    s.addText("UNE VERSION ANCIENNE", {
        x: 5.4, y: 1.95, w: 4, h: 0.3,
        fontFace: F_BODY, fontSize: 11, bold: true, color: COL.green, charSpacing: 3, margin: 0
    });
    s.addText("Dans la section « Autres versions », chaque ligne installée a son propre bouton ▶ Lancer pour démarrer cette version précisément.", {
        x: 5.4, y: 2.3, w: 4, h: 1.5,
        fontFace: F_BODY, fontSize: 12, color: COL.text, margin: 0
    });

    // Behavior
    addCard(s, 0.5, 4.55, W - 1, 0.7);
    s.addText("ℹ", {
        x: 0.7, y: 4.65, w: 0.5, h: 0.5,
        fontFace: F_TITLE, fontSize: 18, bold: true, color: COL.accent, align: "center", margin: 0
    });
    s.addText("La fenêtre du launcher se réduit automatiquement dans la barre des tâches pour laisser la place à Proserve.", {
        x: 1.2, y: 4.7, w: W - 1.7, h: 0.5,
        fontFace: F_BODY, fontSize: 11, color: COL.muted, margin: 0
    });
}

// ===================== SLIDE 8: INSTALL NEW VERSION =====================
{
    const s = pres.addSlide();
    fillBg(s);
    addHeader(s, "Installer une nouvelle version", "📦  télécharger");
    addFooter(s, 8);

    const steps = [
        ["1", "Vérifie les MAJ", "Bouton « 🔄 Vérifier les MAJ » en bas à gauche.\nLe launcher contacte le serveur et liste les nouvelles versions."],
        ["2", "Repère la ligne bleue", "Une ligne « ○ Disponible » apparaît avec un bouton bleu « ⬇ Installer X.Y.Z »."],
        ["3", "Clique « ⬇ Installer »", "Une fenêtre s'ouvre avec les notes de version (Markdown). Lis et clique « Télécharger » pour confirmer."],
        ["4", "Patience pendant le DL", "La barre de progression en bas montre la vitesse, l'avancement, l'ETA. Tu peux mettre en pause ou annuler."],
        ["5", "Installation auto", "Une fois le ZIP vérifié (SHA-256), il est extrait dans le dossier d'install à côté des autres versions."],
    ];

    let y = 1.45;
    steps.forEach(([num, title, desc]) => {
        addCard(s, 0.5, y, W - 1, 0.7);
        s.addShape(pres.shapes.OVAL, {
            x: 0.7, y: y + 0.13, w: 0.4, h: 0.4,
            fill: { color: COL.accent }, line: { type: "none" }
        });
        s.addText(num, {
            x: 0.7, y: y + 0.13, w: 0.4, h: 0.4,
            fontFace: F_TITLE, fontSize: 14, bold: true,
            color: "FFFFFF", align: "center", valign: "middle", margin: 0
        });
        s.addText(title, {
            x: 1.3, y: y + 0.07, w: 8, h: 0.27,
            fontFace: F_TITLE, fontSize: 12, bold: true, color: COL.text, margin: 0
        });
        s.addText(desc, {
            x: 1.3, y: y + 0.32, w: 8, h: 0.4,
            fontFace: F_BODY, fontSize: 10, color: COL.muted, margin: 0
        });
        y += 0.78;
    });
}

// ===================== SLIDE 9: PROGRESS / RESUME =====================
{
    const s = pres.addSlide();
    fillBg(s);
    addHeader(s, "Suivre un téléchargement", "barre du bas");
    addFooter(s, 9);

    // Mock footer
    addCard(s, 0.5, 1.5, W - 1, 0.7);
    s.addText("⬇ v1.4.7 : 4,2 / 14,0 Go  •  38 Mo/s  •  ETA 4 min", {
        x: 0.75, y: 1.6, w: 7.5, h: 0.3,
        fontFace: F_CODE, fontSize: 12, color: COL.muted, margin: 0
    });
    // Progress bar
    s.addShape(pres.shapes.RECTANGLE, {
        x: 0.75, y: 1.95, w: 7.5, h: 0.1, fill: { color: "2A2A30" }, line: { type: "none" }
    });
    s.addShape(pres.shapes.RECTANGLE, {
        x: 0.75, y: 1.95, w: 2.25, h: 0.1, fill: { color: COL.accent }, line: { type: "none" }
    });
    // Cancel button
    s.addShape(pres.shapes.ROUNDED_RECTANGLE, {
        x: 8.5, y: 1.62, w: 0.85, h: 0.4,
        fill: { color: "3A3A40" }, line: { type: "none" }, rectRadius: 0.05
    });
    s.addText("Annuler", {
        x: 8.5, y: 1.62, w: 0.85, h: 0.4,
        fontFace: F_BODY, fontSize: 11, color: COL.text, align: "center", valign: "middle", margin: 0
    });

    // Features
    s.addText("Ce que tu peux faire pendant le DL", {
        x: 0.5, y: 2.5, w: W - 1, h: 0.3,
        fontFace: F_TITLE, fontSize: 14, bold: true, color: COL.text, margin: 0
    });
    addBullets(s, 0.5, 2.85, W - 1, 1.1, [
        "Annuler à tout moment (le ZIP partiel est conservé pour reprendre plus tard)",
        "Fermer le launcher : la prochaine ouverture proposera de reprendre",
        "Couper le réseau : le launcher attend (retry exponentiel) puis reprend automatiquement",
    ], { fontSize: 12 });

    // Resume callout
    addAccentCard(s, 0.5, 4.15, W - 1, 0.95, COL.amber);
    s.addText("↻  Reprendre", {
        x: 0.75, y: 4.25, w: 2, h: 0.35,
        fontFace: F_TITLE, fontSize: 14, bold: true, color: COL.amber, margin: 0
    });
    s.addText("Un DL interrompu apparaît avec un bouton « ↻ Reprendre (X%) » à la place de « Installer ». Le téléchargement reprend là où il s'était arrêté — pas besoin de tout recommencer.", {
        x: 0.75, y: 4.55, w: W - 1.5, h: 0.6,
        fontFace: F_BODY, fontSize: 11, color: COL.muted, margin: 0
    });
}

// ===================== SLIDE 10: VERSION MENU =====================
{
    const s = pres.addSlide();
    fillBg(s);
    addHeader(s, "Menu d'une version", "bouton ⋯");
    addFooter(s, 10);

    s.addText("Le bouton « ⋯ » à droite de chaque ligne ouvre un menu contextuel.", {
        x: 0.5, y: 1.4, w: W - 1, h: 0.4,
        fontFace: F_BODY, fontSize: 13, color: COL.muted, italic: true, margin: 0
    });

    // Menu mockup
    addCard(s, 0.5, 1.95, 4.5, 2.4);
    s.addText("📜  Voir les release notes", {
        x: 0.75, y: 2.1, w: 4, h: 0.4,
        fontFace: F_BODY, fontSize: 13, color: COL.text, margin: 0
    });
    s.addShape(pres.shapes.LINE, {
        x: 0.75, y: 2.5, w: 4, h: 0,
        line: { color: COL.border, width: 0.5 }
    });
    s.addText("📁  Ouvrir le dossier", {
        x: 0.75, y: 2.6, w: 4, h: 0.4,
        fontFace: F_BODY, fontSize: 13, color: COL.text, margin: 0
    });
    s.addShape(pres.shapes.LINE, {
        x: 0.75, y: 3.0, w: 4, h: 0,
        line: { color: COL.border, width: 0.5 }
    });
    s.addText("🗑  Supprimer cette version…", {
        x: 0.75, y: 3.1, w: 4, h: 0.4,
        fontFace: F_BODY, fontSize: 13, color: COL.text, margin: 0
    });

    // Description
    addBullets(s, 5.3, 2.1, 4.2, 2.4, [
        "Release notes : disponibles aussi sur les versions non installées",
        "Ouvrir le dossier : utile pour vérifier l'installation",
        "Supprimer : libère l'espace disque (≈ 14 Go) avec confirmation. Garde tes anciennes versions tant que tu veux pouvoir y revenir.",
    ], { fontSize: 11 });

    // Tip
    addAccentCard(s, 0.5, 4.55, W - 1, 0.65, COL.green);
    s.addText("✓  Aucune suppression automatique : c'est toujours toi qui décides quand effacer une vieille version.", {
        x: 0.75, y: 4.65, w: W - 1.5, h: 0.5,
        fontFace: F_BODY, fontSize: 11, color: COL.text, margin: 0
    });
}

// ===================== SLIDE 11: SETTINGS =====================
{
    const s = pres.addSlide();
    fillBg(s);
    addHeader(s, "Paramètres ⚙", "bouton en haut à droite");
    addFooter(s, 11);

    const sections = [
        ["🔑", "License", "Statut, propriétaire, date d'expiration. Identifiant machine anonyme (à communiquer à ASTERION en cas de souci de slot machine)."],
        ["🌐", "Serveur", "URL de l'API ASTERION. À ne changer que si tu y es invité par le support."],
        ["📁", "Installation", "Dossier où sont posées les versions de Proserve. Par défaut C:\\ASTERION_VR. Bouton « Parcourir » pour changer."],
        ["💾", "Cache", "Taille du cache de téléchargements. Bouton « Vider » pour libérer de l'espace si besoin."],
        ["📋", "Logs", "Dossier des logs (.log) — utile en cas de souci, à transmettre au support."],
    ];

    let y = 1.4;
    sections.forEach(([icon, title, desc]) => {
        addCard(s, 0.5, y, W - 1, 0.7);
        s.addText(icon, {
            x: 0.7, y: y + 0.12, w: 0.5, h: 0.45,
            fontFace: F_TITLE, fontSize: 18, color: COL.green, align: "center", margin: 0
        });
        s.addText(title, {
            x: 1.25, y: y + 0.07, w: 2, h: 0.3,
            fontFace: F_TITLE, fontSize: 13, bold: true, color: COL.text, margin: 0
        });
        s.addText(desc, {
            x: 1.25, y: y + 0.33, w: W - 1.7, h: 0.4,
            fontFace: F_BODY, fontSize: 10, color: COL.muted, margin: 0
        });
        y += 0.78;
    });
}

// ===================== SLIDE 12: AUTO-UPDATE =====================
{
    const s = pres.addSlide();
    fillBg(s);
    addHeader(s, "Mises à jour du launcher", "🔄  automatiques");
    addFooter(s, 12);

    s.addText("Le launcher se met à jour tout seul quand ASTERION pousse une nouvelle version.", {
        x: 0.5, y: 1.4, w: W - 1, h: 0.4,
        fontFace: F_BODY, fontSize: 13, color: COL.text, margin: 0
    });

    const flow = [
        ["1", "Détection", "Au démarrage et à chaque clic « Vérifier les MAJ », le launcher contacte le serveur."],
        ["2", "Notification", "Si une nouvelle version du launcher existe, une popup t'informe et propose de mettre à jour."],
        ["3", "Téléchargement", "Quelques secondes (le launcher fait ~80 Mo)."],
        ["4", "Redémarrage automatique", "L'application se ferme, est remplacée, puis se relance avec la nouvelle version."],
    ];

    let y = 1.95;
    flow.forEach(([num, title, desc]) => {
        addCard(s, 0.5, y, W - 1, 0.65);
        s.addShape(pres.shapes.OVAL, {
            x: 0.7, y: y + 0.12, w: 0.4, h: 0.4,
            fill: { color: COL.green }, line: { type: "none" }
        });
        s.addText(num, {
            x: 0.7, y: y + 0.12, w: 0.4, h: 0.4,
            fontFace: F_TITLE, fontSize: 14, bold: true,
            color: "FFFFFF", align: "center", valign: "middle", margin: 0
        });
        s.addText(title, {
            x: 1.3, y: y + 0.07, w: 8, h: 0.27,
            fontFace: F_TITLE, fontSize: 12, bold: true, color: COL.text, margin: 0
        });
        s.addText(desc, {
            x: 1.3, y: y + 0.32, w: 8, h: 0.32,
            fontFace: F_BODY, fontSize: 10, color: COL.muted, margin: 0
        });
        y += 0.73;
    });

    addAccentCard(s, 0.5, 4.95, W - 1, 0.5, COL.green);
    s.addText("✓  Tu peux toujours refuser et reporter — clique « Plus tard ».", {
        x: 0.75, y: 5.0, w: W - 1.5, h: 0.4,
        fontFace: F_BODY, fontSize: 11, color: COL.text, margin: 0
    });
}

// ===================== SLIDE 13: FAQ =====================
{
    const s = pres.addSlide();
    fillBg(s);
    addHeader(s, "FAQ", "questions fréquentes");
    addFooter(s, 13);

    const qs = [
        ["❓", "Ma license est expirée. Que se passe-t-il ?",
              "Tu peux toujours utiliser les versions déjà installées. Seul le téléchargement de nouvelles versions est bloqué jusqu'à renouvellement.",
              COL.amber],
        ["❓", "Pas de connexion internet — le launcher marche-t-il ?",
              "Oui, pendant 7 jours après la dernière validation en ligne. Au-delà, la license est considérée comme à revérifier.",
              COL.accent],
        ["❓", "Comment changer de PC ?",
              "Désactive ta license sur l'ancien (Settings → bouton Désactiver), puis active-la sur le nouveau avec la même clé.",
              COL.green],
        ["❓", "Le téléchargement échoue avec « SHA-256 invalide » ?",
              "Réseau bruité ou ZIP modifié côté serveur entre-temps. Le partial est jeté ; le DL recommence proprement au prochain clic.",
              COL.red],
    ];

    let y = 1.5;
    qs.forEach(([icon, q, a, color]) => {
        addAccentCard(s, 0.5, y, W - 1, 0.85, color);
        s.addText(icon, {
            x: 0.7, y: y + 0.18, w: 0.4, h: 0.45,
            fontFace: F_TITLE, fontSize: 16, color, align: "center", margin: 0
        });
        s.addText(q, {
            x: 1.2, y: y + 0.1, w: W - 1.7, h: 0.3,
            fontFace: F_TITLE, fontSize: 12, bold: true, color: COL.text, margin: 0
        });
        s.addText(a, {
            x: 1.2, y: y + 0.4, w: W - 1.7, h: 0.45,
            fontFace: F_BODY, fontSize: 10, color: COL.muted, margin: 0
        });
        y += 0.95;
    });
}

// ===================== SLIDE 14: SUPPORT =====================
{
    const s = pres.addSlide();
    fillBg(s);

    // Big band
    s.addShape(pres.shapes.RECTANGLE, {
        x: 0, y: 1.3, w: W, h: 1.3, fill: { color: COL.greenDk }, line: { type: "none" }
    });
    s.addShape(pres.shapes.RECTANGLE, {
        x: 0, y: 1.3, w: W, h: 0.05, fill: { color: COL.green }, line: { type: "none" }
    });

    s.addText("Besoin d'aide ?", {
        x: 0.5, y: 1.55, w: W - 1, h: 0.6,
        fontFace: F_TITLE, fontSize: 32, bold: true, color: COL.text, margin: 0
    });
    s.addText("Contacte ASTERION VR avec ces infos pour un support efficace :", {
        x: 0.5, y: 2.1, w: W - 1, h: 0.4,
        fontFace: F_BODY, fontSize: 14, italic: true, color: COL.muted, margin: 0
    });

    // Three cards
    const ix = 0.5, iy = 3.05, iw = 3.0, gap = 0.15;
    const refs = [
        ["🔑", "Ta clé license",   "PRSRV-XXXX-XXXX-XXXX-XXXX",   COL.green],
        ["💻", "Ton ID machine", "Settings → License\nbouton 📋 Copier", COL.accent],
        ["📋", "Tes logs",         "Settings → Logs\nbouton 📁 Ouvrir",     COL.amber],
    ];
    refs.forEach(([icon, title, body, color], i) => {
        const x = ix + i * (iw + gap);
        addAccentCard(s, x, iy, iw, 1.7, color);
        s.addText(icon, {
            x: x + 0.2, y: iy + 0.15, w: iw - 0.4, h: 0.45,
            fontFace: F_TITLE, fontSize: 22, color, margin: 0
        });
        s.addText(title, {
            x: x + 0.2, y: iy + 0.65, w: iw - 0.4, h: 0.3,
            fontFace: F_TITLE, fontSize: 13, bold: true, color: COL.text, margin: 0
        });
        s.addText(body, {
            x: x + 0.2, y: iy + 0.95, w: iw - 0.4, h: 0.7,
            fontFace: F_CODE, fontSize: 10, color: COL.muted, margin: 0
        });
    });

    // Footer brand
    s.addShape(pres.shapes.RECTANGLE, {
        x: 0, y: H - 0.5, w: W, h: 0.5, fill: { color: COL.card }, line: { type: "none" }
    });
    s.addText("© 2026 ASTERION VR — Tous droits réservés", {
        x: 0.5, y: H - 0.45, w: W - 1, h: 0.4,
        fontFace: F_BODY, fontSize: 11, color: COL.muted, align: "center", margin: 0
    });
}

pres.writeFile({ fileName: "C:\\ASTERION\\GIT\\PS_Launcher\\docs\\PS_Launcher-Guide-Utilisateur.pptx" })
    .then(f => console.log("Generated:", f));
