diff --git a/README.md b/README.md
deleted file mode 100644
index de545f3..0000000
--- a/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# ogame_notepad
-
-Estensione per browser derivati da Chrome che mette un piccolo blocco note a sinistra della pagina web ogame
\ No newline at end of file
diff --git a/content.css b/content.css
new file mode 100644
index 0000000..cb4499d
--- /dev/null
+++ b/content.css
@@ -0,0 +1,144 @@
+/* ===== OGame Notepad - finestra flottante ===== */
+#ogame-notepad {
+ position: fixed;
+ left: 20px;
+ top: 20px;
+ width: 280px;
+ height: 360px;
+ z-index: 999999;
+ display: flex;
+ flex-direction: column;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ background: #0b1220;
+ border: 1px solid #2a4a6b;
+ border-radius: 6px;
+ box-shadow: 0 6px 24px rgba(0, 0, 0, 0.65), inset 0 0 0 1px rgba(255, 255, 255, 0.03);
+ overflow: hidden;
+}
+
+/* Barra del titolo (trascinabile) */
+#ogame-notepad .onp-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ background: linear-gradient(180deg, #1b2f4d, #14243c);
+ color: #d9b45a;
+ padding: 8px 10px;
+ border-bottom: 1px solid #2a4a6b;
+ font-size: 13px;
+ font-weight: bold;
+ letter-spacing: 1px;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+ user-select: none;
+ cursor: move;
+}
+
+#ogame-notepad .onp-title {
+ display: flex;
+ align-items: center;
+ gap: 7px;
+}
+
+#ogame-notepad .onp-title .onp-dot {
+ width: 10px;
+ height: 10px;
+ background: radial-gradient(circle at 35% 35%, #7fd0ff, #2a6bb0);
+ border-radius: 50%;
+ box-shadow: 0 0 8px #2a6bb0;
+}
+
+#ogame-notepad .onp-actions {
+ display: flex;
+ gap: 4px;
+}
+
+#ogame-notepad .onp-btn {
+ background: transparent;
+ border: 1px solid transparent;
+ color: #9db8d6;
+ font-size: 14px;
+ cursor: pointer;
+ padding: 1px 6px;
+ line-height: 1;
+ border-radius: 3px;
+}
+#ogame-notepad .onp-btn:hover {
+ background: #2a4a6b;
+ color: #ffffff;
+ border-color: #3a6a9b;
+}
+
+#ogame-notepad textarea {
+ flex: 1;
+ resize: none;
+ border: none;
+ background: #0b1220;
+ color: #dce6f2;
+ padding: 10px;
+ font-size: 13px;
+ line-height: 1.55;
+ font-family: inherit;
+ outline: none;
+}
+#ogame-notepad textarea::placeholder {
+ color: #4a5f7a;
+}
+
+#ogame-notepad .onp-footer {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ background: #101a2c;
+ color: #6f87a3;
+ padding: 5px 10px;
+ border-top: 1px solid #2a4a6b;
+ font-size: 11px;
+}
+
+#ogame-notepad .onp-footer .onp-status {
+ color: #6fbf6f;
+}
+
+/* Impugnatura per il ridimensionamento (angolo in basso a destra) */
+#ogame-notepad .onp-resizer {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ width: 18px;
+ height: 18px;
+ cursor: nwse-resize;
+ z-index: 3;
+}
+#ogame-notepad .onp-resizer::after {
+ content: '';
+ position: absolute;
+ right: 3px;
+ bottom: 3px;
+ width: 8px;
+ height: 8px;
+ border-right: 2px solid #3a6a9b;
+ border-bottom: 2px solid #3a6a9b;
+ border-radius: 0 0 3px 0;
+}
+#ogame-notepad .onp-resizer:hover::after {
+ border-color: #d9b45a;
+}
+
+/* Pulsante per riaprire il notepad quando è chiuso */
+#ogame-notepad-toggle {
+ position: fixed;
+ left: 10px;
+ top: 20px;
+ z-index: 999999;
+ background: linear-gradient(180deg, #1b2f4d, #14243c);
+ color: #d9b45a;
+ border: 1px solid #2a4a6b;
+ border-radius: 6px;
+ padding: 10px 8px;
+ cursor: pointer;
+ font-size: 15px;
+ box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);
+}
+#ogame-notepad-toggle:hover {
+ background: linear-gradient(180deg, #2a4a6b, #1b2f4d);
+}
diff --git a/content.js b/content.js
new file mode 100644
index 0000000..cc01fc8
--- /dev/null
+++ b/content.js
@@ -0,0 +1,263 @@
+(() => {
+ 'use strict';
+
+ // Doppia sicurezza: attivo solo sul dominio richiesto
+ if (window.location.hostname !== 's170-ar.ogame.gameforge.com') {
+ return;
+ }
+
+ const STORAGE_KEY = 'ogame_notepad_text';
+ const COLLAPSED_KEY = 'ogame_notepad_collapsed';
+ const POS_KEY = 'ogame_notepad_pos';
+ const SIZE_KEY = 'ogame_notepad_size';
+
+ // ---- Creazione elementi ----
+ const container = document.createElement('div');
+ container.id = 'ogame-notepad';
+
+ const header = document.createElement('div');
+ header.className = 'onp-header';
+ header.innerHTML =
+ 'Notepad' +
+ '' +
+ '' +
+ '';
+
+ const textarea = document.createElement('textarea');
+ textarea.placeholder = 'Scrivi le tue note qui...';
+ textarea.spellcheck = false;
+
+ const footer = document.createElement('div');
+ footer.className = 'onp-footer';
+ footer.innerHTML =
+ '0 caratteri' +
+ '● Salvato';
+
+ const resizer = document.createElement('div');
+ resizer.className = 'onp-resizer';
+ resizer.title = 'Trascina per ridimensionare';
+
+ container.appendChild(header);
+ container.appendChild(textarea);
+ container.appendChild(footer);
+ container.appendChild(resizer);
+ document.body.appendChild(container);
+
+ // Pulsante per riaprire quando chiuso
+ const toggleBtn = document.createElement('button');
+ toggleBtn.id = 'ogame-notepad-toggle';
+ toggleBtn.innerHTML = '▶';
+ toggleBtn.title = 'Apri notepad';
+ document.body.appendChild(toggleBtn);
+
+ const countEl = footer.querySelector('#onp-count');
+ const statusEl = footer.querySelector('.onp-status');
+
+ // ---- Persistenza ----
+ let saveTimer = null;
+ let dirty = false; // true se ci sono modifiche non ancora salvate
+ let syncing = false; // evita loop quando aggiorniamo da un'altra tab
+
+ function loadNote() {
+ try {
+ const saved = localStorage.getItem(STORAGE_KEY);
+ if (saved !== null) {
+ textarea.value = saved;
+ }
+ } catch (e) {
+ /* storage non disponibile */
+ }
+ updateCount();
+ }
+
+ function saveNote() {
+ dirty = false;
+ try {
+ localStorage.setItem(STORAGE_KEY, textarea.value);
+ statusEl.textContent = '\u25CF Salvato';
+ statusEl.style.color = '#6fbf6f';
+ } catch (e) {
+ statusEl.textContent = '\u26A0 Errore salvataggio';
+ statusEl.style.color = '#e0a050';
+ }
+ }
+
+ function updateCount() {
+ const n = textarea.value.length;
+ countEl.textContent = n + (n === 1 ? ' carattere' : ' caratteri');
+ }
+
+ // Salvataggio automatico con debounce
+ textarea.addEventListener('input', () => {
+ dirty = true;
+ updateCount();
+ statusEl.textContent = '\u25CF Salvataggio...';
+ statusEl.style.color = '#d8d8a0';
+ clearTimeout(saveTimer);
+ saveTimer = setTimeout(saveNote, 400);
+ });
+
+ // Sincronizzazione in tempo reale tra le tab dello stesso dominio.
+ // Quando un'altra tab salva, questa riceve l'evento 'storage' e aggiorna
+ // la textarea, così premendo F5 qui trovi sempre i dati più recenti.
+ window.addEventListener('storage', (e) => {
+ if (e.key !== STORAGE_KEY) return;
+ // Non sovrascrivere mentre l'utente sta digitando in questa tab
+ if (document.activeElement === textarea && dirty) return;
+ syncing = true;
+ textarea.value = e.newValue !== null ? e.newValue : '';
+ updateCount();
+ statusEl.textContent = '\u25CF Salvato';
+ statusEl.style.color = '#6fbf6f';
+ syncing = false;
+ });
+
+ // ---- Trascinamento finestra ----
+ function restorePosition() {
+ try {
+ const saved = localStorage.getItem(POS_KEY);
+ if (saved) {
+ const pos = JSON.parse(saved);
+ if (typeof pos.left === 'number' && typeof pos.top === 'number') {
+ container.style.left = pos.left + 'px';
+ container.style.top = pos.top + 'px';
+ }
+ }
+ } catch (e) {}
+ }
+
+ function restoreSize() {
+ try {
+ const saved = localStorage.getItem(SIZE_KEY);
+ if (saved) {
+ const size = JSON.parse(saved);
+ if (typeof size.w === 'number') container.style.width = size.w + 'px';
+ if (typeof size.h === 'number') container.style.height = size.h + 'px';
+ }
+ } catch (e) {}
+ }
+
+ function makeResizable() {
+ let startX = 0, startY = 0, startW = 0, startH = 0, resizing = false;
+
+ resizer.addEventListener('mousedown', (e) => {
+ resizing = true;
+ startX = e.clientX;
+ startY = e.clientY;
+ startW = container.offsetWidth;
+ startH = container.offsetHeight;
+ e.preventDefault();
+ e.stopPropagation();
+ });
+
+ window.addEventListener('mousemove', (e) => {
+ if (!resizing) return;
+ const newW = Math.max(200, startW + (e.clientX - startX));
+ const newH = Math.max(160, startH + (e.clientY - startY));
+ container.style.width = newW + 'px';
+ container.style.height = newH + 'px';
+ });
+
+ window.addEventListener('mouseup', () => {
+ if (!resizing) return;
+ resizing = false;
+ try {
+ localStorage.setItem(SIZE_KEY, JSON.stringify({
+ w: container.offsetWidth,
+ h: container.offsetHeight
+ }));
+ } catch (e) {}
+ });
+ }
+
+ function makeDraggable() {
+ let dragStartX = 0, dragStartY = 0, origLeft = 0, origTop = 0, dragging = false;
+
+ header.addEventListener('mousedown', (e) => {
+ if (e.target.closest('.onp-btn')) return; // non trascinare quando clicchi i bottoni
+ dragging = true;
+ dragStartX = e.clientX;
+ dragStartY = e.clientY;
+ const rect = container.getBoundingClientRect();
+ origLeft = rect.left;
+ origTop = rect.top;
+ e.preventDefault();
+ });
+
+ window.addEventListener('mousemove', (e) => {
+ if (!dragging) return;
+ const dx = e.clientX - dragStartX;
+ const dy = e.clientY - dragStartY;
+ container.style.left = (origLeft + dx) + 'px';
+ container.style.top = (origTop + dy) + 'px';
+ });
+
+ window.addEventListener('mouseup', () => {
+ if (!dragging) return;
+ dragging = false;
+ try {
+ localStorage.setItem(POS_KEY, JSON.stringify({
+ left: container.getBoundingClientRect().left,
+ top: container.getBoundingClientRect().top
+ }));
+ } catch (e) {}
+ });
+ }
+
+ // ---- Collapse / expand ----
+ function setCollapsed(collapsed) {
+ container.classList.toggle('collapsed', collapsed);
+ toggleBtn.style.display = collapsed ? 'block' : 'none';
+ try {
+ localStorage.setItem(COLLAPSED_KEY, collapsed ? '1' : '0');
+ } catch (e) {}
+ }
+
+ header.querySelector('#onp-collapse').addEventListener('click', () => {
+ setCollapsed(true);
+ });
+
+ toggleBtn.addEventListener('click', () => {
+ setCollapsed(false);
+ textarea.focus();
+ });
+
+ // ---- Blocca le scorciatoie di OGame quando il focus è sul notepad ----
+ // Intercetta in fase di cattura così gli handler globali di OGame
+ // (frecce, spazio, invio, ecc.) non reagiscono mentre scrivi.
+ function blockKeysWhileTyping(e) {
+ if (document.activeElement === textarea) {
+ // Blocca SOLO la propagazione verso gli handler globali di OGame,
+ // ma NON chiama preventDefault: così la textarea continua a inserire
+ // caratteri, spostare il cursore, creare nuove righe, ecc.
+ e.stopImmediatePropagation();
+ return false;
+ }
+ }
+ window.addEventListener('keydown', blockKeysWhileTyping, true);
+ window.addEventListener('keyup', blockKeysWhileTyping, true);
+ window.addEventListener('keypress', blockKeysWhileTyping, true);
+
+ // ---- Init ----
+ restorePosition();
+ restoreSize();
+ makeDraggable();
+ makeResizable();
+ loadNote();
+
+ let collapsed = false;
+ try {
+ collapsed = localStorage.getItem(COLLAPSED_KEY) === '1';
+ } catch (e) {}
+ setCollapsed(collapsed);
+
+ // Salva al cambio pagina SOLO se ci sono modifiche non ancora salvate.
+ // In questo modo una tab "stantia" non sovrascrive i dati più recenti
+ // scritti da un'altra tab quando premi F5.
+ window.addEventListener('beforeunload', () => {
+ if (dirty) {
+ clearTimeout(saveTimer);
+ saveNote();
+ }
+ });
+})();
diff --git a/icons/icon128.png b/icons/icon128.png
new file mode 100644
index 0000000..6ea8fb5
Binary files /dev/null and b/icons/icon128.png differ
diff --git a/icons/icon16.png b/icons/icon16.png
new file mode 100644
index 0000000..7a5bb6d
Binary files /dev/null and b/icons/icon16.png differ
diff --git a/icons/icon32.png b/icons/icon32.png
new file mode 100644
index 0000000..02a86d7
Binary files /dev/null and b/icons/icon32.png differ
diff --git a/icons/icon48.png b/icons/icon48.png
new file mode 100644
index 0000000..5882fd2
Binary files /dev/null and b/icons/icon48.png differ
diff --git a/make_icon.py b/make_icon.py
new file mode 100644
index 0000000..bb62da7
--- /dev/null
+++ b/make_icon.py
@@ -0,0 +1,38 @@
+from PIL import Image, ImageDraw
+
+def make_icon(size):
+ img = Image.new("RGBA", (size, size), (0,0,0,0))
+ d = ImageDraw.Draw(img)
+ s = size / 128.0 # scala
+
+ def P(x, y):
+ return (int(x*s), int(y*s))
+
+ # Sfondo circolare blu-navy con bordo
+ d.ellipse([P(4,4), P(124,124)], fill=(20,36,60,255), outline=(42,74,107,255), width=int(3*s))
+
+ # Corpo del notepad (rettangolo arrotondato, carta chiara)
+ pad = [P(30,20), P(98,112)]
+ d.rounded_rectangle(pad, radius=int(8*s), fill=(224,232,244,255))
+
+ # Spirale in alto
+ for i in range(3):
+ x = 44 + i*18
+ d.ellipse([P(x,16), P(x+6,24)], fill=(42,74,107,255))
+
+ # Righe di testo
+ line_color = (150,168,196,255)
+ for i in range(5):
+ y = 38 + i*14
+ d.line([P(38,y), P(90,y)], fill=line_color, width=int(3*s))
+
+ # Penna (diagonale, oro)
+ pen = [(92,30),(112,92),(104,96),(82,34)]
+ d.polygon(pen, fill=(217,180,90,255))
+ d.polygon([(112,92),(116,86),(108,94)], fill=(217,180,90,255))
+
+ return img
+
+for sz in [16, 32, 48, 128]:
+ make_icon(sz).save(f"icons/icon{sz}.png")
+ print("creato", sz)
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..77fcede
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,22 @@
+{
+ "manifest_version": 3,
+ "name": "OGame Notepad",
+ "version": "1.0.0",
+ "description": "Notepad laterale per OGame s170-ar. Le note vengono salvate in modo persistente.",
+ "icons": {
+ "16": "icons/icon16.png",
+ "32": "icons/icon32.png",
+ "48": "icons/icon48.png",
+ "128": "icons/icon128.png"
+ },
+ "content_scripts": [
+ {
+ "matches": [
+ "https://s170-ar.ogame.gameforge.com/*"
+ ],
+ "js": ["content.js"],
+ "css": ["content.css"],
+ "run_at": "document_idle"
+ }
+ ]
+}