/*:
 * @target MZ
 * @plugindesc [v1.1] Écran de victoire style Persona / SMT — Plein écran + fondu
 * @author VictoryScreenPersona
 *
 * @param bgColor1
 * @text Couleur de fond 1
 * @type string
 * @default #0a0a1a
 *
 * @param bgColor2
 * @text Couleur de fond 2
 * @type string
 * @default #1a0a2e
 *
 * @param accentColor
 * @text Couleur d'accent
 * @type string
 * @default #ff2d78
 *
 * @param victoryText
 * @text Texte de victoire
 * @type string
 * @default VICTORY
 *
 * @param showEnemiesDefeated
 * @text Afficher ennemis vaincus
 * @type boolean
 * @default true
 *
 * @param levelUpFlash
 * @text Flash au Level Up
 * @type boolean
 * @default true
 *
 * @param fadeDuration
 * @text Durée fondu retour (frames)
 * @type number
 * @min 10
 * @max 120
 * @default 45
 * @desc Nombre de frames pour le fondu au noir vers la carte.
 *
 * @help
 * ============================================================
 * VictoryScreenPersona v1.1
 * ============================================================
 * Remplace COMPLÈTEMENT l'écran de victoire MZ.
 * - Plein écran (suit le canvas PIXI de MZ)
 * - Supprime la bulle de victoire native
 * - Fondu au noir vers la carte
 * ============================================================
 */

(() => {
  "use strict";

  const PLUGIN_NAME  = "VictoryScreenPersona";
  const params       = PluginManager.parameters(PLUGIN_NAME);
  const BG_COLOR1    = String(params.bgColor1    || "#0a0a1a");
  const BG_COLOR2    = String(params.bgColor2    || "#1a0a2e");
  const ACCENT_COLOR = String(params.accentColor || "#ff2d78");
  const VICTORY_TEXT = String(params.victoryText || "VICTORY");
  const SHOW_ENEMIES = String(params.showEnemiesDefeated) !== "false";
  const LEVELUP_FLASH= String(params.levelUpFlash) !== "false";
  const FADE_DUR     = Number(params.fadeDuration || 45);

  // ─────────────────────────────────────────────
  //  Utilitaires
  // ─────────────────────────────────────────────
  function hexToRgb(hex) {
    return {
      r: parseInt(hex.slice(1,3),16),
      g: parseInt(hex.slice(3,5),16),
      b: parseInt(hex.slice(5,7),16)
    };
  }
  function rgb(r,g,b,a=1){ return `rgba(${r},${g},${b},${a})`; }
  function acc(a=1){ const c=hexToRgb(ACCENT_COLOR); return rgb(c.r,c.g,c.b,a); }

  // ─────────────────────────────────────────────
  //  Supprime la bulle native de victoire
  //  BattleManager.processVictory affiche le
  //  message via $gameMessage — on l'écrase.
  // ─────────────────────────────────────────────
  BattleManager.processVictory = function() {
    // Gain de récompenses SANS afficher la fenêtre de message native
    this.gainRewards();
    this.endBattle(0);
  };

  // ─────────────────────────────────────────────
  //  Capture des récompenses juste AVANT gainRewards
  //  (les rewards existent encore ici)
  // ─────────────────────────────────────────────
  const _gainRewards = BattleManager.gainRewards;
  BattleManager.gainRewards = function() {
    // Snapshot AVANT que gainRewards efface/distribue
    if (!BattleManager._personaSnapshot) {
      BattleManager._personaSnapshot = {
        exp:     this._rewards ? this._rewards.exp  : 0,
        gold:    this._rewards ? this._rewards.gold : 0,
        enemies: $gameTroop.members().map(e => e.originalName()),
        actors:  $gameParty.battleMembers().map(a => ({
          actorId:   a.actorId(),
          name:      a.name(),
          prevLevel: a.level,
          prevExp:   a.currentExp(),
          faceName:  a.faceName(),
          faceIndex: a.faceIndex()
        }))
      };
      // Sauvegarde niveaux avant gain
      $gameParty.battleMembers().forEach(a => { a._snapshotLevel = a.level; });
    }
    _gainRewards.call(this);
  };

  // ─────────────────────────────────────────────
  //  Après endBattle(0) → on démarre notre scène
  // ─────────────────────────────────────────────
  const _endBattle = BattleManager.endBattle;
  BattleManager.endBattle = function(result) {
    if (result === 0 && BattleManager._personaSnapshot) {
      const snap = BattleManager._personaSnapshot;
      BattleManager._personaSnapshot = null;
      // Calcule delta EXP APRÈS gainRewards
      snap.actors = snap.actors.map(s => {
        const actor = $gameActors.actor(s.actorId);
        return Object.assign(s, {
          newLevel: actor ? actor.level : s.prevLevel,
          newExp:   actor ? actor.currentExp() : s.prevExp
        });
      });
      _endBattle.call(this, result);
      // Remplace Scene_Map par notre scène
      SceneManager.goto(Scene_VictoryPersona);
      SceneManager._nextScene._snap = snap;
      return;
    }
    _endBattle.call(this, result);
  };

  // ─────────────────────────────────────────────
  //  SCÈNE PRINCIPALE
  // ─────────────────────────────────────────────
  class Scene_VictoryPersona extends Scene_Base {
    constructor() {
      super();
      this._snap       = null;
      this._phase      = "flash";
      this._timer      = 0;
      this._locked     = true;
      this._particles  = [];
      this._diagLines  = [];
      this._letters    = [];
      this._actorRows  = [];
      this._lvQueue    = [];
      this._curLv      = null;
      this._lvTimer    = 0;
      this._resultAlpha= 0;
      this._flashAlpha = 1;
      this._fadeAlpha  = 0;   // fondu sortie
      this._canvas     = null;
      this._ctx        = null;
    }

    // ── Création ──────────────────────────────
    create() {
      super.create();
      this._buildCanvas();
      this._initParticles(90);
      this._initDiagLines(14);
      this._initLetters();
      this._buildActorRows();
    }

    _buildCanvas() {
      // Récupère le vrai canvas PIXI pour coller dessus proprement
      const pixiCanvas = document.querySelector("canvas");
      this._canvas = document.createElement("canvas");
      this._canvas.id = "persona-victory-canvas";

      const resize = () => {
        const ref = document.querySelector("canvas#persona-victory-canvas ~ canvas, canvas:not(#persona-victory-canvas)") || pixiCanvas;
        const rect = (pixiCanvas || document.body).getBoundingClientRect();
        this._canvas.width  = pixiCanvas ? pixiCanvas.width  : Graphics.width;
        this._canvas.height = pixiCanvas ? pixiCanvas.height : Graphics.height;
        this._canvas.style.position = "fixed";
        this._canvas.style.left   = pixiCanvas ? pixiCanvas.style.left   || rect.left+"px" : "0";
        this._canvas.style.top    = pixiCanvas ? pixiCanvas.style.top    || rect.top+"px"  : "0";
        this._canvas.style.width  = pixiCanvas ? pixiCanvas.style.width  || rect.width+"px"  : "100%";
        this._canvas.style.height = pixiCanvas ? pixiCanvas.style.height || rect.height+"px" : "100%";
        this._canvas.style.zIndex = "9999";
        this._canvas.style.imageRendering = "pixelated";
      };
      resize();
      document.body.appendChild(this._canvas);
      this._ctx = this._canvas.getContext("2d");
      this._W = this._canvas.width;
      this._H = this._canvas.height;
    }

    _buildActorRows() {
      if (!this._snap) return;
      this._actorRows = this._snap.actors.map(s => {
        const actor    = $gameActors.actor(s.actorId);
        const gained   = (s.newExp || s.prevExp) - s.prevExp;
        const leveled  = (s.newLevel || s.prevLevel) > s.prevLevel;
        const curExp   = actor ? (actor.currentExp() - actor.currentLevelExp()) : 0;
        const maxExp   = actor ? Math.max(1, actor.nextLevelExp() - actor.currentLevelExp()) : 1;
        return {
          name:      s.name,
          prevLevel: s.prevLevel,
          newLevel:  s.newLevel || s.prevLevel,
          gained,
          leveled,
          bar: { cur: 0, target: Math.min(1, curExp / maxExp) },
          done: false
        };
      });
      this._lvQueue = this._actorRows.filter(r => r.leveled);
    }

    _initParticles(n) {
      const c = hexToRgb(ACCENT_COLOR);
      for (let i=0;i<n;i++) {
        this._particles.push({
          x: Math.random()*this._W,
          y: Math.random()*this._H,
          vx:(Math.random()-0.5)*0.5,
          vy:-(Math.random()*0.9+0.2),
          r: Math.random()*2.5+0.5,
          a: Math.random()*0.5+0.2,
          col: Math.random()<0.65 ? rgb(c.r,c.g,c.b,0.75) : "rgba(255,255,255,0.45)"
        });
      }
    }

    _initDiagLines(n) {
      for (let i=0;i<n;i++) {
        this._diagLines.push({
          x: Math.random()*this._W*1.5 - this._W*0.25,
          spd: Math.random()*1.2+0.4,
          a: Math.random()*0.12+0.04,
          w: Math.random()*1.8+0.3
        });
      }
    }

    _initLetters() {
      this._letters = VICTORY_TEXT.split("").map((ch,i)=>({
        ch, i,
        oy: -(80 + i*20),
        a: 0,
        delay: i*5,
        done: false
      }));
    }

    // ── Update ────────────────────────────────
    update() {
      super.update();
      this._timer++;
      this._tick();
      this._tickParticles();
      this._tickDiagLines();
      this._draw();
    }

    _tick() {
      switch(this._phase) {

        case "flash":
          this._flashAlpha = Math.max(0, 1 - this._timer/20);
          if (this._timer >= 20) this._phase = "title", this._timer = 0;
          break;

        case "title":
          this._tickLetters();
          if (this._timer > 70) this._phase = "results", this._timer = 0;
          break;

        case "results":
          this._resultAlpha = Math.min(1, this._resultAlpha+0.05);
          this._tickBars();
          if (this._timer > 50) this._locked = false;
          if (!this._locked && this._allBarsDone() && this._triggered()) {
            if (this._lvQueue.length) {
              this._phase = "levelup"; this._timer = 0;
              this._locked = true;
            } else {
              this._phase = "fadeout"; this._timer = 0;
            }
          }
          break;

        case "levelup":
          if (!this._curLv) { this._curLv = this._lvQueue.shift(); this._lvTimer = 0; }
          this._lvTimer++;
          if (this._lvTimer > 95) {
            this._curLv = null;
            if (!this._lvQueue.length) { this._locked = false; this._phase = "lvwait"; }
          }
          break;

        case "lvwait":
          if (this._triggered()) { this._phase = "fadeout"; this._timer = 0; }
          break;

        case "fadeout":
          this._fadeAlpha = Math.min(1, this._timer / FADE_DUR);
          if (this._fadeAlpha >= 1) this._phase = "done";
          break;

        case "done":
          this._end();
          break;
      }
    }

    _tickLetters() {
      this._letters.forEach(l => {
        if (this._timer < l.delay) return;
        const t = this._timer - l.delay;
        l.oy  = Math.max(0, l.oy + 9);
        l.a   = Math.min(1, t/8);
        if (l.oy >= 0) l.done = true;
      });
    }

    _tickBars() {
      this._actorRows.forEach(r => {
        if (!r.done) {
          r.bar.cur = Math.min(r.bar.target, r.bar.cur + 0.009);
          if (Math.abs(r.bar.cur - r.bar.target) < 0.004) {
            r.bar.cur = r.bar.target; r.done = true;
          }
        }
      });
    }

    _allBarsDone() { return this._actorRows.every(r => r.done); }

    _triggered() {
      return Input.isTriggered("ok") || Input.isTriggered("cancel") || TouchInput.isTriggered();
    }

    _tickParticles() {
      this._particles.forEach(p => {
        p.x += p.vx; p.y += p.vy;
        if (p.y < -5) { p.y = this._H+5; p.x = Math.random()*this._W; }
      });
    }

    _tickDiagLines() {
      this._diagLines.forEach(l => {
        l.x += l.spd;
        if (l.x > this._W*1.3) l.x = -this._W*0.3;
      });
    }

    // ── Dessin ────────────────────────────────
    _draw() {
      const ctx = this._ctx;
      const W = this._W, H = this._H;
      ctx.clearRect(0,0,W,H);

      this._dBg(ctx,W,H);
      this._dDiag(ctx,W,H);
      this._dParticles(ctx);
      this._dCorners(ctx,W,H);

      if (this._phase !== "flash") this._dTitle(ctx,W,H);

      if (["results","levelup","lvwait","fadeout"].includes(this._phase))
        this._dResults(ctx,W,H);

      if (this._phase === "levelup" && this._curLv)
        this._dLevelUp(ctx,W,H);

      // Fondu sortie
      if (this._fadeAlpha > 0) {
        ctx.fillStyle = `rgba(0,0,0,${this._fadeAlpha})`;
        ctx.fillRect(0,0,W,H);
      }

      // Flash d'entrée
      if (this._flashAlpha > 0) {
        ctx.fillStyle = `rgba(255,255,255,${this._flashAlpha})`;
        ctx.fillRect(0,0,W,H);
      }

      if (!this._locked && !["fadeout","done"].includes(this._phase))
        this._dPrompt(ctx,W,H);
    }

    _dBg(ctx,W,H) {
      const g = ctx.createLinearGradient(0,0,W,H);
      g.addColorStop(0, BG_COLOR1);
      g.addColorStop(1, BG_COLOR2);
      ctx.fillStyle = g;
      ctx.fillRect(0,0,W,H);
      // Bande accent en bas
      const c = hexToRgb(ACCENT_COLOR);
      const bg = ctx.createLinearGradient(0,H-10,0,H);
      bg.addColorStop(0, rgb(c.r,c.g,c.b,0));
      bg.addColorStop(1, rgb(c.r,c.g,c.b,0.9));
      ctx.fillStyle = bg;
      ctx.fillRect(0,H-10,W,10);
    }

    _dDiag(ctx,W,H) {
      const c = hexToRgb(ACCENT_COLOR);
      ctx.save();
      this._diagLines.forEach(l=>{
        ctx.strokeStyle = rgb(c.r,c.g,c.b,l.a);
        ctx.lineWidth   = l.w;
        ctx.beginPath();
        ctx.moveTo(l.x,0);
        ctx.lineTo(l.x - H*0.65, H);
        ctx.stroke();
      });
      ctx.restore();
    }

    _dParticles(ctx) {
      this._particles.forEach(p=>{
        ctx.beginPath();
        ctx.arc(p.x,p.y,p.r,0,Math.PI*2);
        ctx.fillStyle = p.col;
        ctx.fill();
      });
    }

    _dCorners(ctx,W,H) {
      const c = hexToRgb(ACCENT_COLOR);
      ctx.save();
      ctx.strokeStyle = rgb(c.r,c.g,c.b,0.65);
      ctx.lineWidth = 2;
      const S = 44;
      // coin haut-gauche
      ctx.beginPath(); ctx.moveTo(18,18+S); ctx.lineTo(18,18); ctx.lineTo(18+S,18); ctx.stroke();
      // coin haut-droit
      ctx.beginPath(); ctx.moveTo(W-18-S,18); ctx.lineTo(W-18,18); ctx.lineTo(W-18,18+S); ctx.stroke();
      // coin bas-gauche
      ctx.beginPath(); ctx.moveTo(18,H-18-S); ctx.lineTo(18,H-18); ctx.lineTo(18+S,H-18); ctx.stroke();
      // coin bas-droit
      ctx.beginPath(); ctx.moveTo(W-18-S,H-18); ctx.lineTo(W-18,H-18); ctx.lineTo(W-18,H-18-S); ctx.stroke();
      ctx.restore();
      // Losange centré haut
      this._diamond(ctx, W/2, 22, 7, acc(0.9));
    }

    _diamond(ctx,x,y,r,color) {
      ctx.save(); ctx.fillStyle = color;
      ctx.beginPath();
      ctx.moveTo(x,y-r); ctx.lineTo(x+r,y);
      ctx.lineTo(x,y+r); ctx.lineTo(x-r,y);
      ctx.closePath(); ctx.fill(); ctx.restore();
    }

    _dTitle(ctx,W,H) {
      const baseY  = 82;
      const fsize  = Math.round(H * 0.12); // adaptatif
      ctx.save();
      ctx.font = `900 ${fsize}px 'Segoe UI Black','Arial Black',Arial,sans-serif`;
      ctx.textAlign    = "left";
      ctx.textBaseline = "middle";
      const totalW = ctx.measureText(VICTORY_TEXT).width;
      const startX = (W - totalW) / 2;
      const charW  = totalW / VICTORY_TEXT.length;

      this._letters.forEach((l,i) => {
        ctx.globalAlpha = l.a;
        const lx = startX + i * charW;
        const ly = baseY + l.oy;
        // Glow
        ctx.shadowColor = acc(0.8);
        ctx.shadowBlur  = 28;
        // Ombre décalée rosée
        ctx.fillStyle = "rgba(255,180,180,0.25)";
        ctx.fillText(l.ch, lx+3, ly+3);
        // Texte blanc
        ctx.fillStyle = "#ffffff";
        ctx.fillText(l.ch, lx, ly);
        // Underscore coloré
        if (l.done) {
          ctx.shadowBlur = 0;
          ctx.fillStyle  = acc(0.9);
          const cw = ctx.measureText(l.ch).width;
          ctx.fillRect(lx, ly + fsize*0.52, cw, 3);
        }
      });
      ctx.globalAlpha = 1;
      ctx.shadowBlur  = 0;
      ctx.restore();
    }

    _dResults(ctx,W,H) {
      ctx.save();
      ctx.globalAlpha = this._resultAlpha;
      const c  = hexToRgb(ACCENT_COLOR);
      const px = 36, pw = W - 72;
      const headerY = Math.round(H * 0.27);

      // Séparateur
      ctx.strokeStyle = acc(0.4);
      ctx.lineWidth   = 1;
      ctx.beginPath(); ctx.moveTo(px,headerY); ctx.lineTo(px+pw,headerY); ctx.stroke();

      // EXP
      ctx.font = `bold ${Math.round(H*0.034)}px 'Segoe UI',Arial,sans-serif`;
      ctx.textAlign    = "left";
      ctx.textBaseline = "top";
      ctx.fillStyle    = "#ffffff";
      const exp  = this._snap ? this._snap.exp  : 0;
      const gold = this._snap ? this._snap.gold : 0;
      ctx.fillText(`EXP  +${exp}`, px+8, headerY+10);

      // OR
      ctx.textAlign = "right";
      ctx.fillStyle = "#ffd700";
      ctx.fillText(`OR  +${gold}`, px+pw-8, headerY+10);

      // Ennemis
      if (SHOW_ENEMIES && this._snap && this._snap.enemies.length) {
        ctx.textAlign = "center";
        ctx.font = `${Math.round(H*0.026)}px 'Segoe UI',Arial,sans-serif`;
        ctx.fillStyle = "rgba(255,255,255,0.45)";
        const en = [...new Set(this._snap.enemies)].join("  ·  ");
        ctx.fillText(en, W/2, headerY + Math.round(H*0.065));
      }

      // Acteurs
      const rowStart = headerY + Math.round(H*0.12);
      const rowH     = Math.round(H*0.13);
      this._actorRows.forEach((r,i) => {
        this._dActorRow(ctx, r, px, rowStart + i*rowH, pw, rowH-6, c);
      });

      ctx.restore();
    }

    _dActorRow(ctx, data, x, y, w, h, c) {
      // Fond
      ctx.fillStyle = "rgba(255,255,255,0.04)";
      this._rrect(ctx,x,y,w,h,5); ctx.fill();

      const fs   = Math.round(h*0.85);
      const fpad = Math.round((h - fs)/2);
      const faceX= x+8, faceY=y+fpad;

      // Case face
      ctx.fillStyle = "rgba(255,255,255,0.07)";
      this._rrect(ctx,faceX,faceY,fs,fs,4); ctx.fill();
      ctx.strokeStyle = acc(0.35); ctx.lineWidth=1;
      this._rrect(ctx,faceX,faceY,fs,fs,4); ctx.stroke();

      // Initiale
      ctx.font = `900 ${Math.round(fs*0.55)}px 'Segoe UI Black','Arial Black',Arial,sans-serif`;
      ctx.textAlign    = "center";
      ctx.textBaseline = "middle";
      ctx.fillStyle    = "#ffffff";
      ctx.fillText(data.name[0].toUpperCase(), faceX+fs/2, faceY+fs/2);

      const inX = faceX+fs+12;
      const fnS = Math.round(h*0.22);

      // Nom
      ctx.font = `bold ${fnS}px 'Segoe UI',Arial,sans-serif`;
      ctx.textAlign    = "left";
      ctx.textBaseline = "top";
      ctx.fillStyle    = "#ffffff";
      ctx.fillText(data.name, inX, y+Math.round(h*0.1));

      // Niveau
      ctx.font      = `${Math.round(fnS*0.85)}px 'Segoe UI',Arial,sans-serif`;
      ctx.fillStyle = data.leveled ? acc(1) : "rgba(255,255,255,0.55)";
      const lvTxt   = data.leveled ? `Lv ${data.prevLevel} → ${data.newLevel}` : `Lv ${data.newLevel}`;
      ctx.fillText(lvTxt, inX, y+Math.round(h*0.42));

      // Gain EXP (droite)
      ctx.textAlign = "right";
      ctx.font      = `${Math.round(fnS*0.85)}px 'Segoe UI',Arial,sans-serif`;
      ctx.fillStyle = "#aaffcc";
      ctx.fillText(`+${data.gained} EXP`, x+w-10, y+Math.round(h*0.1));

      // Barre EXP
      const bX = inX, bY = y+Math.round(h*0.72);
      const bW = x+w-inX-10, bH = Math.max(4, Math.round(h*0.1));

      ctx.fillStyle = "rgba(255,255,255,0.1)";
      this._rrect(ctx,bX,bY,bW,bH,bH/2); ctx.fill();

      const fw = bW * data.bar.cur;
      if (fw > 1) {
        const bg = ctx.createLinearGradient(bX,0,bX+bW,0);
        bg.addColorStop(0, acc(0.9));
        bg.addColorStop(1,"rgba(255,255,255,0.95)");
        ctx.fillStyle    = bg;
        ctx.shadowColor  = acc(0.9);
        ctx.shadowBlur   = 7;
        this._rrect(ctx,bX,bY,fw,bH,bH/2); ctx.fill();
        ctx.shadowBlur = 0;
      }
    }

    _dLevelUp(ctx,W,H) {
      const t = this._lvTimer;
      const c = hexToRgb(ACCENT_COLOR);
      const cx= W/2, cy=H/2;

      if (t<12 && LEVELUP_FLASH) {
        ctx.fillStyle=`rgba(255,255,255,${0.85-t*0.07})`;
        ctx.fillRect(0,0,W,H);
      }

      const ov = Math.min(0.78, t/14*0.78);
      ctx.fillStyle=`rgba(0,0,8,${ov})`; ctx.fillRect(0,0,W,H);

      if (t>6) {
        const ra = Math.min(0.28,(t-6)/18*0.28);
        ctx.save(); ctx.translate(cx,cy); ctx.rotate(t*0.004);
        for(let i=0;i<12;i++){
          const ang=(i/12)*Math.PI*2;
          ctx.beginPath(); ctx.moveTo(0,0);
          ctx.lineTo(Math.cos(ang)*H*0.55,Math.sin(ang)*H*0.55);
          ctx.strokeStyle=`rgba(255,200,50,${ra})`;
          ctx.lineWidth=20; ctx.stroke();
        }
        ctx.restore();

        const cr=H*0.22+Math.sin(t*0.1)*8;
        const rg=ctx.createRadialGradient(cx,cy,0,cx,cy,cr);
        rg.addColorStop(0,`rgba(255,210,90,${Math.min(0.45,(t-6)/18*0.45)})`);
        rg.addColorStop(1,"rgba(255,210,90,0)");
        ctx.fillStyle=rg; ctx.beginPath(); ctx.arc(cx,cy,cr,0,Math.PI*2); ctx.fill();
      }

      const ta = t<15?t/15 : t>78?Math.max(0,1-(t-78)/17) : 1;
      const ts = t<15?0.55+0.45*(t/15):1;
      ctx.save();
      ctx.globalAlpha=ta; ctx.translate(cx,cy); ctx.scale(ts,ts);

      const fS1=Math.round(H*0.04);
      ctx.font=`bold ${fS1}px 'Segoe UI',Arial,sans-serif`;
      ctx.textAlign="center"; ctx.textBaseline="middle";
      ctx.fillStyle="rgba(255,255,255,0.9)";
      ctx.fillText(this._curLv.name,0,-H*0.1);

      const fS2=Math.round(H*0.115);
      ctx.shadowColor="#ffd700"; ctx.shadowBlur=28;
      ctx.font=`900 ${fS2}px 'Segoe UI Black','Arial Black',Arial,sans-serif`;
      ctx.fillStyle="#ffffff";
      ctx.fillText("LEVEL UP!",0,0);

      ctx.shadowBlur=14; ctx.shadowColor="#ffd700";
      ctx.font=`bold ${Math.round(fS2*0.55)}px 'Segoe UI',Arial,sans-serif`;
      ctx.fillStyle="#ffd700";
      ctx.fillText(`Lv.${this._curLv.newLevel}`,0,H*0.1);

      ctx.shadowBlur=0;
      const dOff=H*0.18;
      this._diamond(ctx,-dOff,0,11,acc(0.9));
      this._diamond(ctx, dOff,0,11,acc(0.9));
      this._diamond(ctx,0,-H*0.16,7,"rgba(255,220,100,0.9)");
      this._diamond(ctx,0, H*0.16,7,"rgba(255,220,100,0.9)");
      ctx.restore();
    }

    _dPrompt(ctx,W,H) {
      const a = 0.35+0.35*Math.sin(Date.now()/420);
      ctx.save();
      ctx.globalAlpha=a;
      ctx.font=`${Math.round(H*0.027)}px 'Segoe UI',Arial,sans-serif`;
      ctx.textAlign="center"; ctx.textBaseline="bottom";
      ctx.fillStyle="rgba(255,255,255,0.85)";
      ctx.fillText("Appuyer pour continuer",W/2,H-18);
      ctx.restore();
    }

    _rrect(ctx,x,y,w,h,r) {
      ctx.beginPath();
      ctx.moveTo(x+r,y);
      ctx.lineTo(x+w-r,y); ctx.quadraticCurveTo(x+w,y,x+w,y+r);
      ctx.lineTo(x+w,y+h-r); ctx.quadraticCurveTo(x+w,y+h,x+w-r,y+h);
      ctx.lineTo(x+r,y+h); ctx.quadraticCurveTo(x,y+h,x,y+h-r);
      ctx.lineTo(x,y+r); ctx.quadraticCurveTo(x,y,x+r,y);
      ctx.closePath();
    }

    // ── Fin ───────────────────────────────────
    _end() {
      if (this._canvas) { this._canvas.remove(); this._canvas=null; }
      SceneManager.goto(Scene_Map);
    }

    terminate() {
      super.terminate();
      if (this._canvas && this._canvas.parentNode) { this._canvas.remove(); this._canvas=null; }
    }
  }

  // Expose globalement pour que SceneManager puisse instancier
  window.Scene_VictoryPersona = Scene_VictoryPersona;

})();

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: