diff --git a/build/icon.png b/build/icon.png
new file mode 100644
index 0000000..cbf1ea5
Binary files /dev/null and b/build/icon.png differ
diff --git a/build/icon.svg b/build/icon.svg
new file mode 100644
index 0000000..6fc8876
--- /dev/null
+++ b/build/icon.svg
@@ -0,0 +1,12 @@
+
diff --git a/scripts/gen-logo.mjs b/scripts/gen-logo.mjs
new file mode 100644
index 0000000..6e12363
--- /dev/null
+++ b/scripts/gen-logo.mjs
@@ -0,0 +1,105 @@
+#!/usr/bin/env node
+/**
+ * Génère le logo/icône du launcher : monogramme "OF" en style voxel (blocs
+ * biseautés façon Minecraft) sur un badge sombre arrondi, accent vert du thème.
+ *
+ * node scripts/gen-logo.mjs -> build/icon.svg
+ * node scripts/gen-logo.mjs --png -> + build/icon.png (1024px) via @resvg/resvg-js
+ *
+ * electron-builder dérive ensuite l'ICO Windows et les PNG Linux depuis
+ * build/icon.png (directories.buildResources = build).
+ */
+import { writeFile } from 'node:fs/promises'
+import { join } from 'node:path'
+
+const SIZE = 512
+const OUT = join(process.cwd(), 'build')
+
+// Palette (cohérente avec src/renderer/src/index.css).
+const C = {
+ bgTop: '#1b2330',
+ bgBottom: '#0d1014',
+ border: '#2b3444',
+ base: '#3fb950', // vert accent
+ light: '#74e08a', // arête haut/gauche (lumière)
+ dark: '#218a3b' // arête bas/droite (ombre)
+}
+
+// Matrices pixel des lettres (1 = bloc plein).
+const O = ['01110', '10001', '10001', '10001', '10001', '10001', '01110']
+const F = ['1111', '1000', '1000', '1110', '1000', '1000', '1000']
+
+const ROWS = 7
+const GAP_COLS = 1
+const COLS = O[0].length + GAP_COLS + F[0].length // 5 + 1 + 4 = 10
+
+const cell = 40 // pas de la grille
+const blockGap = 6 // espace entre blocs (effet grille pixel)
+const bs = cell - blockGap // taille d'un bloc
+const bevel = Math.round(bs * 0.18) // épaisseur du biseau
+
+const gridW = COLS * cell
+const gridH = ROWS * cell
+const x0 = (SIZE - gridW) / 2
+const y0 = (SIZE - gridH) / 2
+
+/** Un bloc voxel : base + arêtes claires (haut/gauche) et sombres (bas/droite). */
+function block(col, row) {
+ const x = x0 + col * cell + blockGap / 2
+ const y = y0 + row * cell + blockGap / 2
+ const t = bevel
+ return [
+ ``,
+ ``,
+ ``,
+ ``,
+ ``
+ ].join('')
+}
+
+/** Rend une matrice à un décalage de colonnes donné. */
+function letter(matrix, colOffset) {
+ const out = []
+ matrix.forEach((line, r) => {
+ ;[...line].forEach((px, c) => {
+ if (px === '1') out.push(block(colOffset + c, r))
+ })
+ })
+ return out.join('')
+}
+
+const blocks = letter(O, 0) + letter(F, O[0].length + GAP_COLS)
+
+const radius = 112
+const svg = `
+`
+
+async function main() {
+ await writeFile(join(OUT, 'icon.svg'), svg)
+ console.log('✓ build/icon.svg')
+
+ if (process.argv.includes('--png')) {
+ const { Resvg } = await import('@resvg/resvg-js')
+ const png = new Resvg(svg, { fitTo: { mode: 'width', value: 1024 } })
+ .render()
+ .asPng()
+ await writeFile(join(OUT, 'icon.png'), png)
+ console.log('✓ build/icon.png (1024px)')
+ }
+}
+
+main().catch((e) => {
+ console.error(e.message)
+ process.exit(1)
+})