vergen-dev commited on
Commit
36f2119
·
verified ·
1 Parent(s): f506717

Upload 28 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ agenzia.jpg filter=lfs diff=lfs merge=lfs -text
37
+ cava.png filter=lfs diff=lfs merge=lfs -text
38
+ oft.pdf filter=lfs diff=lfs merge=lfs -text
39
+ team.jpg filter=lfs diff=lfs merge=lfs -text
.htaccess ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <Files "database.sqlite">
2
+ Order Allow,Deny
3
+ Deny from all
4
+ </Files>
5
+
6
+ <Files "setup_db.php">
7
+ Order Allow,Deny
8
+ Deny from all
9
+ </Files>
10
+
11
+ Options -Indexes
474691146_1999105570500674_8091151825404414418_n.jpg ADDED
LOGO.PNG ADDED
LOGO1.png ADDED
admin/index.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ session_start();
3
+ if (!isset($_SESSION['admin_logged_in'])) {
4
+ header('Location: login.php');
5
+ exit;
6
+ }
7
+ require '../db_connect.php';
8
+ ?>
9
+ <!DOCTYPE html>
10
+ <html lang="it">
11
+ <head>
12
+ <meta charset="UTF-8">
13
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
14
+ <title>Dashboard - OFT MGMT</title>
15
+ <link href="style.css" rel="stylesheet">
16
+ <link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;600;700;800&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
17
+ </head>
18
+ <body>
19
+
20
+ <div class="app-layout">
21
+ <!-- Sidebar -->
22
+ <aside class="sidebar">
23
+ <div class="brand">
24
+ <span>⚡</span> OFT Admin
25
+ </div>
26
+
27
+ <nav>
28
+ <div class="nav-section">Contenuti</div>
29
+ <a href="manage.php?section=config" class="nav-link">⚙️ Configurazione</a>
30
+ <a href="manage.php?section=solutions" class="nav-link">💡 Soluzioni</a>
31
+ <a href="manage.php?section=goals" class="nav-link">🚀 Obiettivi</a>
32
+ <a href="manage.php?section=roadmap" class="nav-link">🗺️ Roadmap</a>
33
+
34
+ <div class="nav-section">Liste</div>
35
+ <a href="manage.php?section=services" class="nav-link">🛠️ Servizi</a>
36
+ <a href="manage.php?section=cases" class="nav-link">📂 Case Studies</a>
37
+ <a href="manage.php?section=founders" class="nav-link">👥 Team</a>
38
+ <a href="manage.php?section=about_gallery" class="nav-link">🖼️ Gallery Chi Siamo</a>
39
+ <a href="manage.php?section=pricing" class="nav-link">💎 Pricing</a>
40
+ <a href="manage.php?section=faq" class="nav-link">❓ FAQ</a>
41
+
42
+ <div class="nav-section">Altro</div>
43
+ <a href="manage.php?section=stats" class="nav-link">📊 Statistiche</a>
44
+ <a href="manage.php?section=bottom_stats" class="nav-link">📈 Big Stats</a>
45
+ </nav>
46
+
47
+ <div style="margin-top:auto">
48
+ <a href="?logout=1" class="nav-link" style="color:var(--danger)">🚪 Logout</a>
49
+ </div>
50
+ </aside>
51
+
52
+ <!-- Main Content -->
53
+ <main class="main-content">
54
+ <div class="page-header">
55
+ <h1>Dashboard</h1>
56
+ <a href="../index.php" target="_blank" class="btn btn-outline">
57
+ Vai al sito ↗
58
+ </a>
59
+ </div>
60
+
61
+ <div class="card-grid">
62
+ <a href="manage.php?section=config" class="dashboard-card">
63
+ <div class="card-icon">⚙️</div>
64
+ <div>
65
+ <strong style="display:block">Configurazione</strong>
66
+ <span class="item-meta">Modifica testi, contatti e foto</span>
67
+ </div>
68
+ </a>
69
+ <a href="manage.php?section=cases" class="dashboard-card">
70
+ <div class="card-icon">📂</div>
71
+ <div>
72
+ <strong style="display:block">Case Studies</strong>
73
+ <span class="item-meta">Gestisci i lavori portfolio</span>
74
+ </div>
75
+ </a>
76
+ <a href="manage.php?section=pricing" class="dashboard-card">
77
+ <div class="card-icon">💎</div>
78
+ <div>
79
+ <strong style="display:block">Pricing</strong>
80
+ <span class="item-meta">Modifica i pacchetti</span>
81
+ </div>
82
+ </a>
83
+ <a href="manage.php?section=about_gallery" class="dashboard-card">
84
+ <div class="card-icon">🖼️</div>
85
+ <div>
86
+ <strong style="display:block">Gallery</strong>
87
+ <span class="item-meta">Foto Chi Siamo</span>
88
+ </div>
89
+ </a>
90
+ </div>
91
+
92
+ <div style="margin-top:40px; color:var(--muted)">
93
+ <p>Seleziona una voce dal menu laterale per iniziare a modificare.</p>
94
+ </div>
95
+ </main>
96
+ </div>
97
+
98
+ </body>
99
+ </html>
admin/login.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ session_start();
3
+ require '../db_connect.php';
4
+
5
+ $error = '';
6
+
7
+ // Handle logout
8
+ if (isset($_GET['logout'])) {
9
+ session_destroy();
10
+ header('Location: login.php');
11
+ exit;
12
+ }
13
+
14
+ // Redirect if already logged in
15
+ if (isset($_SESSION['admin_logged_in'])) {
16
+ header('Location: index.php');
17
+ exit;
18
+ }
19
+
20
+ // Handle login
21
+ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
22
+ $password = $_POST['password'] ?? '';
23
+
24
+ try {
25
+ $stmt = $db->prepare("SELECT value_text FROM config WHERE key_name = 'admin_password'");
26
+ $stmt->execute();
27
+ $stored = $stmt->fetchColumn();
28
+
29
+ if ($stored && password_verify($password, $stored)) {
30
+ $_SESSION['admin_logged_in'] = true;
31
+ header('Location: index.php');
32
+ exit;
33
+ } else {
34
+ $error = 'Password non corretta';
35
+ }
36
+ } catch (Exception $e) {
37
+ $error = 'Errore di sistema';
38
+ }
39
+ }
40
+ ?>
41
+ <!DOCTYPE html>
42
+ <html lang="it">
43
+ <head>
44
+ <meta charset="UTF-8">
45
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
46
+ <title>Login Admin — OFT MGMT</title>
47
+ <link href="style.css" rel="stylesheet">
48
+ <link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;600;700;800&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
49
+ </head>
50
+ <body>
51
+
52
+ <div class="login-page">
53
+ <div class="login-card">
54
+ <div class="brand" style="justify-content:center; margin-bottom:30px; font-size:24px">
55
+ <span>⚡</span> OFT Admin
56
+ </div>
57
+
58
+ <?php if ($error): ?>
59
+ <div style="background:rgba(239,68,68,0.1); color:var(--danger); padding:12px; border-radius:8px; font-size:14px; margin-bottom:20px; text-align:center; border:1px solid var(--danger)">
60
+ <?php echo htmlspecialchars($error); ?>
61
+ </div>
62
+ <?php endif; ?>
63
+
64
+ <form method="POST">
65
+ <div class="form-group">
66
+ <label>Password Amministratore</label>
67
+ <input type="password" name="password" required placeholder="••••••••" style="text-align:center; letter-spacing:2px" autofocus>
68
+ </div>
69
+ <button type="submit" class="btn" style="width:100%; justify-content:center">Accedi</button>
70
+ </form>
71
+
72
+ <div style="text-align:center; margin-top:24px">
73
+ <a href="../index.php" style="font-size:13px; color:var(--muted)">Torna al sito</a>
74
+ </div>
75
+ </div>
76
+ </div>
77
+
78
+ </body>
79
+ </html>
admin/manage.php ADDED
@@ -0,0 +1,314 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ session_start();
3
+ if (!isset($_SESSION['admin_logged_in'])) {
4
+ header('Location: login.php');
5
+ exit;
6
+ }
7
+ require '../db_connect.php';
8
+
9
+ $section = $_GET['section'] ?? 'config';
10
+ $valid_sections = ['config', 'stats', 'services', 'founders', 'cases', 'pricing', 'faq', 'solutions', 'goals', 'roadmap', 'bottom_stats', 'about_gallery'];
11
+
12
+ if (!in_array($section, $valid_sections)) {
13
+ die("Sezione non valida.");
14
+ }
15
+
16
+ // DELETE
17
+ if (isset($_GET['delete']) && $section !== 'config') {
18
+ $id = (int)$_GET['delete'];
19
+ $db->prepare("DELETE FROM $section WHERE id = ?")->execute([$id]);
20
+ header("Location: manage.php?section=$section");
21
+ exit;
22
+ }
23
+
24
+ // SAVE / UPDATE
25
+ $success = false;
26
+ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
27
+ if ($section === 'config') {
28
+ foreach ($_POST as $k => $v) {
29
+ if ($k === 'admin_password' || $k === 'id') continue;
30
+ $stmt = $db->prepare("INSERT OR REPLACE INTO config (key_name, value_text) VALUES (?, ?)");
31
+ $stmt->execute([$k, $v]);
32
+ }
33
+ // Handle Config Images
34
+ foreach ($_FILES as $key => $file) {
35
+ if ($file['error'] === UPLOAD_ERR_OK) {
36
+ $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
37
+ $filename = "uploads/" . $key . "_" . time() . "." . $ext;
38
+ if (move_uploaded_file($file['tmp_name'], "../" . $filename)) {
39
+ $db->prepare("INSERT OR REPLACE INTO config (key_name, value_text) VALUES (?, ?)")->execute([$key, $filename]);
40
+ }
41
+ }
42
+ }
43
+ $success = true;
44
+ } else {
45
+ // Add or Edit Item
46
+ $is_edit = isset($_POST['id']);
47
+ $fields = [];
48
+ $values = [];
49
+
50
+ // Define fields based on section (same logic as before)
51
+ $expected_fields = [];
52
+ if($section=='stats') $expected_fields=['label','value','unit','sort_order'];
53
+ if($section=='services') $expected_fields=['title','icon','description','sort_order'];
54
+ if($section=='founders') $expected_fields=['name','role','image_path','sort_order'];
55
+ if($section=='cases') $expected_fields=['title','stats_text','role_text','tags','image_path','sort_order'];
56
+ if($section=='pricing') $expected_fields=['name','price','features','is_recommended','sort_order'];
57
+ if($section=='faq') $expected_fields=['question','answer','sort_order'];
58
+ if($section=='solutions') $expected_fields=['title','description','sort_order'];
59
+ if($section=='goals') $expected_fields=['title','description','sort_order'];
60
+ if($section=='roadmap') $expected_fields=['phase','detail','sort_order'];
61
+ if($section=='bottom_stats') $expected_fields=['value','label','sort_order'];
62
+ if($section=='about_gallery') $expected_fields=['image_path','sort_order'];
63
+
64
+ foreach ($expected_fields as $f) {
65
+ if (isset($_POST[$f])) {
66
+ $fields[] = $f;
67
+ $values[] = $_POST[$f];
68
+ }
69
+ }
70
+
71
+ // Handle File Upload for Item
72
+ if (in_array('image_path', $expected_fields) && isset($_FILES['image_path']) && $_FILES['image_path']['error'] === UPLOAD_ERR_OK) {
73
+ $ext = pathinfo($_FILES['image_path']['name'], PATHINFO_EXTENSION);
74
+ $filename = "uploads/" . $section . "_" . time() . "." . $ext;
75
+ if (move_uploaded_file($_FILES['image_path']['tmp_name'], "../" . $filename)) {
76
+ if(!in_array('image_path', $fields)) {
77
+ $fields[] = 'image_path';
78
+ $values[] = $filename;
79
+ } else {
80
+ $key = array_search('image_path', $fields);
81
+ $values[$key] = $filename;
82
+ }
83
+ }
84
+ }
85
+
86
+ if ($is_edit) {
87
+ $id = $_POST['id'];
88
+ $set = [];
89
+ foreach ($fields as $index => $field) {
90
+ $set[] = "$field = ?";
91
+ }
92
+ $sql = "UPDATE $section SET " . implode(', ', $set) . " WHERE id = ?";
93
+ $values[] = $id;
94
+ $db->prepare($sql)->execute($values);
95
+ } else {
96
+ $placeholders = array_fill(0, count($fields), '?');
97
+ $sql = "INSERT INTO $section (" . implode(', ', $fields) . ") VALUES (" . implode(', ', $placeholders) . ")";
98
+ $db->prepare($sql)->execute($values);
99
+ }
100
+ }
101
+ if ($section !== 'config') {
102
+ header("Location: manage.php?section=$section");
103
+ exit;
104
+ }
105
+ }
106
+
107
+ // FETCH DATA
108
+ if ($section === 'config') {
109
+ $items = [];
110
+ try {
111
+ $rows = $db->query("SELECT key_name, value_text FROM config")->fetchAll(PDO::FETCH_KEY_PAIR);
112
+ $items = $rows;
113
+ } catch (Exception $e) {
114
+ die("Errore database config: " . $e->getMessage());
115
+ }
116
+ } else {
117
+ try {
118
+ $items = $db->query("SELECT * FROM $section ORDER BY sort_order ASC")->fetchAll();
119
+ } catch (Exception $e) {
120
+ die("Errore database $section: " . $e->getMessage());
121
+ }
122
+ }
123
+ ?>
124
+ <!DOCTYPE html>
125
+ <html lang="it">
126
+ <head>
127
+ <meta charset="UTF-8">
128
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
129
+ <title>Gestisci <?php echo ucfirst($section); ?> — OFT Admin</title>
130
+ <link href="style.css" rel="stylesheet">
131
+ <link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;600;700;800&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
132
+ </head>
133
+ <body>
134
+
135
+ <div class="app-layout">
136
+ <!-- Sidebar -->
137
+ <aside class="sidebar">
138
+ <div class="brand">
139
+ <span>⚡</span> OFT Admin
140
+ </div>
141
+
142
+ <nav>
143
+ <div class="nav-section">Contenuti</div>
144
+ <a href="manage.php?section=config" class="nav-link <?php if($section=='config') echo 'active'; ?>">⚙️ Configurazione</a>
145
+ <a href="manage.php?section=solutions" class="nav-link <?php if($section=='solutions') echo 'active'; ?>">💡 Soluzioni</a>
146
+ <a href="manage.php?section=goals" class="nav-link <?php if($section=='goals') echo 'active'; ?>">🚀 Obiettivi</a>
147
+ <a href="manage.php?section=roadmap" class="nav-link <?php if($section=='roadmap') echo 'active'; ?>">🗺️ Roadmap</a>
148
+
149
+ <div class="nav-section">Liste</div>
150
+ <a href="manage.php?section=services" class="nav-link <?php if($section=='services') echo 'active'; ?>">🛠️ Servizi</a>
151
+ <a href="manage.php?section=cases" class="nav-link <?php if($section=='cases') echo 'active'; ?>">📂 Case Studies</a>
152
+ <a href="manage.php?section=founders" class="nav-link <?php if($section=='founders') echo 'active'; ?>">👥 Team</a>
153
+ <a href="manage.php?section=about_gallery" class="nav-link <?php if($section=='about_gallery') echo 'active'; ?>">🖼️ Gallery Chi Siamo</a>
154
+ <a href="manage.php?section=pricing" class="nav-link <?php if($section=='pricing') echo 'active'; ?>">💎 Pricing</a>
155
+ <a href="manage.php?section=faq" class="nav-link <?php if($section=='faq') echo 'active'; ?>">❓ FAQ</a>
156
+
157
+ <div class="nav-section">Altro</div>
158
+ <a href="manage.php?section=stats" class="nav-link <?php if($section=='stats') echo 'active'; ?>">📊 Statistiche</a>
159
+ <a href="manage.php?section=bottom_stats" class="nav-link <?php if($section=='bottom_stats') echo 'active'; ?>">📈 Big Stats</a>
160
+ </nav>
161
+
162
+ <div style="margin-top:auto">
163
+ <a href="index.php?logout=1" class="nav-link" style="color:var(--danger)">🚪 Logout</a>
164
+ </div>
165
+ </aside>
166
+
167
+ <!-- Main Content -->
168
+ <main class="main-content">
169
+ <div class="page-header">
170
+ <div>
171
+ <a href="index.php" style="color:var(--muted); font-size:12px; font-weight:700; text-transform:uppercase;">← Dashboard</a>
172
+ <h1 style="text-transform:capitalize">Gestisci <?php echo str_replace('_', ' ', $section); ?></h1>
173
+ </div>
174
+ </div>
175
+
176
+ <?php if($section === 'config'): ?>
177
+ <?php if($success): ?>
178
+ <div style="background:rgba(16,185,129,0.1); color:var(--success); padding:16px; border-radius:8px; margin-bottom:24px; border:1px solid var(--success)">
179
+ ✅ Configurazione salvata con successo!
180
+ </div>
181
+ <?php endif; ?>
182
+ <div class="panel" style="padding:32px; max-width:800px">
183
+ <form method="POST" enctype="multipart/form-data">
184
+ <?php foreach($items as $key => $val): if($key=='admin_password' || $key=='id') continue; ?>
185
+ <div class="form-group">
186
+ <label><?php echo str_replace('_', ' ', $key); ?></label>
187
+ <?php if(strpos($key, 'image') !== false): ?>
188
+ <div style="display:flex; align-items:center; gap:12px; margin-bottom:12px; background:var(--bg); padding:10px; border-radius:8px; border:1px solid var(--border)">
189
+ <img src="../<?php echo htmlspecialchars($val); ?>" style="height:60px; width:60px; object-fit:cover; border-radius:6px;">
190
+ <div style="font-size:13px; color:var(--muted); word-break:break-all"><?php echo htmlspecialchars($val); ?></div>
191
+ </div>
192
+ <input type="file" name="<?php echo $key; ?>" accept="image/*">
193
+ <input type="hidden" name="<?php echo $key; ?>" value="<?php echo htmlspecialchars($val); ?>">
194
+ <?php else: ?>
195
+ <input type="text" name="<?php echo $key; ?>" value="<?php echo htmlspecialchars($val); ?>">
196
+ <?php endif; ?>
197
+ </div>
198
+ <?php endforeach; ?>
199
+ <button type="submit" class="btn">Salva Modifiche</button>
200
+ </form>
201
+ </div>
202
+
203
+ <?php else: ?>
204
+ <!-- Add New -->
205
+ <div style="margin-bottom:30px">
206
+ <details>
207
+ <summary class="btn" style="display:inline-flex; list-style:none">
208
+ <span>+ Aggiungi Nuovo</span>
209
+ </summary>
210
+ <div class="panel" style="margin-top:20px; padding:32px; max-width:700px; animation: fadeIn 0.3s ease">
211
+ <h3 style="margin-top:0">Nuovo Elemento</h3>
212
+ <form method="POST" enctype="multipart/form-data">
213
+ <!-- Fields based on section -->
214
+ <?php
215
+ $fields = [];
216
+ if($section=='stats') $fields=['label','value','unit','sort_order'];
217
+ if($section=='services') $fields=['title','icon','description','sort_order'];
218
+ if($section=='founders') $fields=['name','role','image_path','sort_order'];
219
+ if($section=='cases') $fields=['title','stats_text','role_text','tags','image_path','sort_order'];
220
+ if($section=='pricing') $fields=['name','price','features','is_recommended','sort_order'];
221
+ if($section=='faq') $fields=['question','answer','sort_order'];
222
+ if($section=='solutions') $fields=['title','description','sort_order'];
223
+ if($section=='goals') $fields=['title','description','sort_order'];
224
+ if($section=='roadmap') $fields=['phase','detail','sort_order'];
225
+ if($section=='bottom_stats') $fields=['value','label','sort_order'];
226
+ if($section=='about_gallery') $fields=['image_path','sort_order'];
227
+
228
+ foreach($fields as $f): ?>
229
+ <div class="form-group">
230
+ <label><?php echo str_replace('_', ' ', $f); ?></label>
231
+ <?php if($f == 'description' || $f == 'answer' || $f == 'features'): ?>
232
+ <textarea name="<?php echo $f; ?>" rows="4"></textarea>
233
+ <?php elseif($f == 'image_path'): ?>
234
+ <input type="file" name="<?php echo $f; ?>" accept="image/*">
235
+ <?php else: ?>
236
+ <input type="text" name="<?php echo $f; ?>" value="<?php echo ($f=='sort_order')?'0':''; ?>">
237
+ <?php endif; ?>
238
+ </div>
239
+ <?php endforeach; ?>
240
+ <button type="submit" class="btn">Aggiungi Elemento</button>
241
+ </form>
242
+ </div>
243
+ </details>
244
+ </div>
245
+
246
+ <!-- List Panel -->
247
+ <div class="panel">
248
+ <?php foreach($items as $row): ?>
249
+ <div class="list-item">
250
+ <?php if(isset($row['image_path'])): ?>
251
+ <img src="../<?php echo htmlspecialchars($row['image_path']); ?>" class="item-image">
252
+ <?php endif; ?>
253
+
254
+ <div class="item-content">
255
+ <span class="item-title">
256
+ <?php echo htmlspecialchars(reset($row)); // fallback ?>
257
+ <?php echo isset($row['title']) ? $row['title'] : (isset($row['name']) ? $row['name'] : (isset($row['label']) ? $row['label'] : (isset($row['question']) ? $row['question'] : ''))); ?>
258
+ </span>
259
+ <div class="item-meta">
260
+ Ordine: <?php echo $row['sort_order']; ?>
261
+ </div>
262
+ </div>
263
+
264
+ <div style="display:flex; gap:10px; align-items:center">
265
+ <details>
266
+ <summary class="btn btn-outline" style="padding:6px 12px; font-size:12px">Modifica</summary>
267
+ <div style="position:fixed; inset:0; background:rgba(0,0,0,0.8); z-index:999; display:flex; align-items:center; justify-content:center; padding:20px">
268
+ <div class="panel" style="width:100%; max-width:600px; padding:32px; position:relative; max-height:90vh; overflow-y:auto">
269
+ <div style="position:absolute; top:20px; right:20px; cursor:pointer" onclick="this.closest('details').removeAttribute('open')">✕</div>
270
+ <h3 style="margin-top:0">Modifica Elemento</h3>
271
+
272
+ <form method="POST" enctype="multipart/form-data">
273
+ <input type="hidden" name="id" value="<?php echo $row['id']; ?>">
274
+ <?php foreach($fields as $f): ?>
275
+ <div class="form-group">
276
+ <label><?php echo str_replace('_', ' ', $f); ?></label>
277
+
278
+ <?php if($f == 'description' || $f == 'answer' || $f == 'features'): ?>
279
+ <textarea name="<?php echo $f; ?>" rows="4"><?php echo htmlspecialchars($row[$f]); ?></textarea>
280
+
281
+ <?php elseif($f == 'image_path'): ?>
282
+ <div style="display:flex; align-items:center; gap:12px; margin-bottom:10px">
283
+ <img src="../<?php echo htmlspecialchars($row[$f]); ?>" style="height:40px; border-radius:4px">
284
+ </div>
285
+ <input type="file" name="<?php echo $f; ?>" accept="image/*">
286
+
287
+ <?php else: ?>
288
+ <input type="text" name="<?php echo $f; ?>" value="<?php echo htmlspecialchars($row[$f]); ?>">
289
+ <?php endif; ?>
290
+ </div>
291
+ <?php endforeach; ?>
292
+ <button type="submit" class="btn">Salva Modifiche</button>
293
+ </form>
294
+ </div>
295
+ </div>
296
+ </details>
297
+
298
+ <a href="?section=<?php echo $section; ?>&delete=<?php echo $row['id']; ?>" class="btn-danger" style="padding:8px 12px; border-radius:6px; font-size:12px; text-decoration:none" onclick="return confirm('Sicuro di voler eliminare?')">Elimina</a>
299
+ </div>
300
+ </div>
301
+ <?php endforeach; ?>
302
+
303
+ <?php if(empty($items)): ?>
304
+ <div style="padding:40px; text-align:center; color:var(--muted)">
305
+ Nessun elemento presente.
306
+ </div>
307
+ <?php endif; ?>
308
+ </div>
309
+ <?php endif; ?>
310
+ </main>
311
+ </div>
312
+
313
+ </body>
314
+ </html>
admin/style.css ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --bg: #0f172a;
3
+ --sidebar: #1e293b;
4
+ --card: #1e293b;
5
+ --border: #334155;
6
+ --text: #f1f5f9;
7
+ --muted: #94a3b8;
8
+ --primary: #3b82f6;
9
+ --primary-hover: #2563eb;
10
+ --danger: #ef4444;
11
+ --success: #10b981;
12
+ --radius: 12px;
13
+ }
14
+
15
+ body {
16
+ background: var(--bg);
17
+ color: var(--text);
18
+ font-family: 'Inter', system-ui, sans-serif;
19
+ margin: 0;
20
+ line-height: 1.5;
21
+ -webkit-font-smoothing: antialiased;
22
+ }
23
+
24
+ a { text-decoration: none; color: inherit; transition: 0.2s; }
25
+ * { box-sizing: border-box; }
26
+
27
+ /* Layout */
28
+ .app-layout {
29
+ display: flex;
30
+ min-height: 100vh;
31
+ }
32
+
33
+ .sidebar {
34
+ width: 260px;
35
+ background: var(--sidebar);
36
+ border-right: 1px solid var(--border);
37
+ padding: 24px;
38
+ display: flex;
39
+ flex-direction: column;
40
+ position: fixed;
41
+ height: 100vh;
42
+ }
43
+
44
+ .main-content {
45
+ flex: 1;
46
+ margin-left: 260px;
47
+ padding: 40px;
48
+ background: var(--bg);
49
+ }
50
+
51
+ .brand {
52
+ font-size: 20px;
53
+ font-weight: 800;
54
+ margin-bottom: 40px;
55
+ color: var(--text);
56
+ letter-spacing: -0.5px;
57
+ display: flex;
58
+ align-items: center;
59
+ gap: 10px;
60
+ }
61
+ .brand span { color: var(--primary); }
62
+
63
+ /* Navigation */
64
+ .nav-link {
65
+ display: flex;
66
+ align-items: center;
67
+ gap: 12px;
68
+ padding: 12px 16px;
69
+ border-radius: 8px;
70
+ color: var(--muted);
71
+ font-weight: 500;
72
+ margin-bottom: 4px;
73
+ }
74
+ .nav-link:hover, .nav-link.active {
75
+ background: rgba(59, 130, 246, 0.1);
76
+ color: var(--primary);
77
+ }
78
+ .nav-section {
79
+ font-size: 11px;
80
+ text-transform: uppercase;
81
+ color: var(--muted);
82
+ font-weight: 700;
83
+ margin: 24px 0 10px 12px;
84
+ letter-spacing: 0.05em;
85
+ }
86
+
87
+ /* Cards */
88
+ .card-grid {
89
+ display: grid;
90
+ grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
91
+ gap: 20px;
92
+ }
93
+
94
+ .dashboard-card {
95
+ background: var(--card);
96
+ border: 1px solid var(--border);
97
+ border-radius: var(--radius);
98
+ padding: 24px;
99
+ transition: 0.2s;
100
+ display: flex;
101
+ align-items: center;
102
+ gap: 16px;
103
+ }
104
+ .dashboard-card:hover {
105
+ transform: translateY(-2px);
106
+ border-color: var(--primary);
107
+ }
108
+ .card-icon {
109
+ width: 48px;
110
+ height: 48px;
111
+ background: rgba(59, 130, 246, 0.1);
112
+ color: var(--primary);
113
+ border-radius: 12px;
114
+ display: grid;
115
+ place-items: center;
116
+ font-size: 20px;
117
+ }
118
+
119
+ /* Forms & Tables */
120
+ .page-header {
121
+ display: flex;
122
+ justify-content: space-between;
123
+ align-items: center;
124
+ margin-bottom: 32px;
125
+ }
126
+ h1 { margin: 0; font-size: 24px; font-weight: 700; }
127
+
128
+ .panel {
129
+ background: var(--card);
130
+ border: 1px solid var(--border);
131
+ border-radius: var(--radius);
132
+ overflow: hidden;
133
+ }
134
+
135
+ .form-group { margin-bottom: 20px; }
136
+ label { display: block; margin-bottom: 8px; font-size: 13px; font-weight: 600; color: var(--muted); }
137
+ input, textarea, select {
138
+ width: 100%;
139
+ background: var(--bg);
140
+ border: 1px solid var(--border);
141
+ border-radius: 8px;
142
+ padding: 12px;
143
+ color: var(--text);
144
+ font-family: inherit;
145
+ transition: 0.2s;
146
+ }
147
+ input:focus, textarea:focus {
148
+ border-color: var(--primary);
149
+ outline: none;
150
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
151
+ }
152
+
153
+ .btn {
154
+ background: var(--primary);
155
+ color: white;
156
+ padding: 12px 24px;
157
+ border-radius: 8px;
158
+ border: none;
159
+ font-weight: 600;
160
+ cursor: pointer;
161
+ display: inline-flex;
162
+ align-items: center;
163
+ gap: 8px;
164
+ }
165
+ .btn:hover { background: var(--primary-hover); }
166
+ .btn-outline {
167
+ background: transparent;
168
+ border: 1px solid var(--border);
169
+ color: var(--muted);
170
+ }
171
+ .btn-outline:hover {
172
+ border-color: var(--text);
173
+ color: var(--text);
174
+ }
175
+ .btn-danger { color: var(--danger); background: rgba(239, 68, 68, 0.1); }
176
+ .btn-danger:hover { background: rgba(239, 68, 68, 0.2); }
177
+
178
+ /* List Items */
179
+ .list-item {
180
+ display: flex;
181
+ align-items: center;
182
+ padding: 16px 24px;
183
+ border-bottom: 1px solid var(--border);
184
+ gap: 20px;
185
+ }
186
+ .list-item:last-child { border-bottom: none; }
187
+ .item-image {
188
+ width: 48px;
189
+ height: 48px;
190
+ border-radius: 8px;
191
+ object-fit: cover;
192
+ background: var(--bg);
193
+ }
194
+ .item-content { flex: 1; }
195
+ .item-title { font-weight: 600; margin-bottom: 4px; display: block; }
196
+ .item-meta { font-size: 13px; color: var(--muted); }
197
+
198
+ /* Login */
199
+ .login-page {
200
+ display: grid;
201
+ place-items: center;
202
+ height: 100vh;
203
+ background: var(--bg);
204
+ }
205
+ .login-card {
206
+ background: var(--card);
207
+ padding: 40px;
208
+ border-radius: 24px;
209
+ border: 1px solid var(--border);
210
+ width: 100%;
211
+ max-width: 400px;
212
+ }
213
+
214
+ /* Details/Summary Customization */
215
+ details > summary { list-style: none; }
216
+ details > summary::-webkit-details-marker { display: none; }
agenzia.jpg ADDED

Git LFS Details

  • SHA256: 87fbe849dc912eb3ad3950a610b4d50faafebb0ca7f4a32098e131c17a63c23c
  • Pointer size: 131 Bytes
  • Size of remote file: 316 kB
android-chrome-192x192.png ADDED
android-chrome-512x512.png ADDED
apple-touch-icon.png ADDED
cava.png ADDED

Git LFS Details

  • SHA256: ce2642608213b83847a76747d94388ac5279ab4821b8ea1e27d9704a8a39c69a
  • Pointer size: 131 Bytes
  • Size of remote file: 200 kB
database.sqlite ADDED
Binary file (61.4 kB). View file
 
db_connect.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ try {
3
+ // Create (or connect to) the SQLite database in the same directory
4
+ $db = new PDO('sqlite:' . __DIR__ . '/database.sqlite');
5
+ // Set error mode to exceptions
6
+ $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
7
+ // Fetch results as associative arrays by default
8
+ $db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
9
+ } catch (PDOException $e) {
10
+ die("Database connection failed: " . $e->getMessage());
11
+ }
12
+ ?>
elio.jpg ADDED
fav.png ADDED
favicon-16x16.png ADDED
favicon-32x32.png ADDED
favicon.ico ADDED
francesco.jpg ADDED
index.php ADDED
@@ -0,0 +1,937 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // =========================
3
+ // Config OFT MGMT
4
+ // =========================
5
+ require_once 'db_connect.php';
6
+
7
+ // Prevent caching
8
+ header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
9
+ header("Cache-Control: post-check=0, pre-check=0", false);
10
+ header("Pragma: no-cache");
11
+
12
+ function get_config($db, $key, $default = '') {
13
+ try {
14
+ $stmt = $db->prepare("SELECT value_text FROM config WHERE key_name = ?");
15
+ $stmt->execute([$key]);
16
+ $res = $stmt->fetchColumn();
17
+ return $res !== false ? $res : $default;
18
+ } catch(Exception $e) { return $default; }
19
+ }
20
+
21
+ $brand = get_config($db, 'brand', 'OFT MGMT');
22
+ $tagline = get_config($db, 'tagline');
23
+ $email = get_config($db, 'email');
24
+ $phone = get_config($db, 'phone');
25
+ $whatsapp = get_config($db, 'whatsapp_url');
26
+ $instagram = get_config($db, 'instagram_url');
27
+ $instagram_label = get_config($db, 'instagram_label', '@oft_mgmt');
28
+ $tiktok = get_config($db, 'tiktok_url');
29
+ $callUrl = get_config($db, 'booking_url');
30
+ $address = get_config($db, 'address');
31
+ $year = date('Y');
32
+
33
+ // Load Lists
34
+ $stats_list = $db->query("SELECT * FROM stats ORDER BY sort_order ASC")->fetchAll();
35
+ $services_list = $db->query("SELECT * FROM services ORDER BY sort_order ASC")->fetchAll();
36
+ $founders_list = $db->query("SELECT * FROM founders ORDER BY sort_order ASC")->fetchAll();
37
+ $cases_list = $db->query("SELECT * FROM cases ORDER BY sort_order ASC")->fetchAll();
38
+ $pricing_list = $db->query("SELECT * FROM pricing ORDER BY sort_order ASC")->fetchAll();
39
+ $faq_list = $db->query("SELECT * FROM faq ORDER BY sort_order ASC")->fetchAll();
40
+
41
+ // Load New Lists
42
+ $solutions_list = $db->query("SELECT * FROM solutions ORDER BY sort_order ASC")->fetchAll();
43
+ $goals_list = $db->query("SELECT * FROM goals ORDER BY sort_order ASC")->fetchAll();
44
+ $roadmap_list = $db->query("SELECT * FROM roadmap ORDER BY sort_order ASC")->fetchAll();
45
+ $bottom_stats_list = $db->query("SELECT * FROM bottom_stats ORDER BY sort_order ASC")->fetchAll();
46
+ $gallery_list = $db->query("SELECT * FROM about_gallery ORDER BY sort_order ASC")->fetchAll();
47
+
48
+ // Extra Configs
49
+ $hero_h1 = get_config($db, 'hero_h1', 'Creatività, performance e contenuti che portano <span class="accent">risultati reali</span>.');
50
+ $hero_sub = get_config($db, 'hero_sub', $tagline);
51
+ $video_url = get_config($db, 'video_embed_url', 'https://www.youtube.com/embed/dQw4w9WgXcQ?autoplay=1&rel=0');
52
+
53
+ // About Text
54
+ $about_title = get_config($db, 'about_title', 'Chi <span class="accent">siamo</span>');
55
+ $about_intro = get_config($db, 'about_intro');
56
+ $about_txt1 = get_config($db, 'about_text_1');
57
+ $about_txt2 = get_config($db, 'about_text_2');
58
+
59
+ // Contact Text
60
+ $contact_title = get_config($db, 'contact_title', 'Contatti');
61
+ $contact_intro = get_config($db, 'contact_intro');
62
+
63
+ // SEO canonical and OG absolute URLs
64
+ $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
65
+ $host = $_SERVER['HTTP_HOST'] ?? 'localhost';
66
+ $path = strtok($_SERVER['REQUEST_URI'] ?? '/', '?') ?: '/';
67
+ $canonical = $scheme.'://'.$host.$path;
68
+ $ogImage = $scheme.'://'.$host.'/LOGO1.png';
69
+
70
+ function e($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
71
+ ?>
72
+ <!doctype html>
73
+ <html lang="it">
74
+ <head>
75
+ <meta charset="utf-8">
76
+ <title><?php echo e($brand); ?> — Fai Crescere la tua attività</title>
77
+ <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
78
+ <meta name="description" content="<?php echo e($tagline); ?>">
79
+ <link rel="canonical" href="<?php echo e($canonical); ?>">
80
+ <meta property="og:site_name" content="<?php echo e($brand); ?>">
81
+ <meta property="og:title" content="<?php echo e($brand); ?>">
82
+ <meta property="og:description" content="<?php echo e($tagline); ?>">
83
+ <meta property="og:image" content="<?php echo e($ogImage); ?>">
84
+ <meta property="og:url" content="<?php echo e($canonical); ?>">
85
+ <meta property="og:type" content="website">
86
+ <meta name="twitter:card" content="summary">
87
+ <meta name="twitter:title" content="<?php echo e($brand); ?>">
88
+ <meta name="twitter:description" content="<?php echo e($tagline); ?>">
89
+ <meta name="twitter:image" content="<?php echo e($ogImage); ?>">
90
+ <meta name="theme-color" content="#04070d">
91
+ <link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png">
92
+ <link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
93
+ <link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png">
94
+ <link rel="manifest" href="site.webmanifest">
95
+ <link rel="shortcut icon" href="favicon.ico">
96
+
97
+ <!-- Fonts -->
98
+ <link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
99
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
100
+ <link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;600;700;800&family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
101
+
102
+ <style>
103
+ :root{
104
+ /* Premium Dark Palette */
105
+ --bg: #04070d;
106
+ --panel:#0b0f19;
107
+ --panel-hover: #121828;
108
+ --border: #1e293b;
109
+ --text: #ECF2FF;
110
+ --muted: #94A3B8;
111
+
112
+ /* Vibrant Accents */
113
+ --primary: #5B8CFA;
114
+ --cyan: #22D3EE;
115
+ --accent-glow: rgba(91, 140, 250, 0.25);
116
+
117
+ /* Spacing & Radius */
118
+ --radius: 24px;
119
+ --container: 1240px;
120
+
121
+ /* Effects */
122
+ --glass: blur(12px) saturate(160%);
123
+ --shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
124
+ --shadow-glow: 0 0 40px -10px var(--accent-glow);
125
+ }
126
+
127
+ *{ box-sizing: border-box; outline-offset: 4px; }
128
+ html{ scroll-behavior: smooth; }
129
+ body{
130
+ margin: 0; background: var(--bg); color: var(--text);
131
+ font-family: 'Manrope', -apple-system, sans-serif;
132
+ overflow-x: hidden; -webkit-font-smoothing: antialiased;
133
+ line-height: 1.6;
134
+ }
135
+
136
+ /* Backgrounds */
137
+ .scene{ position: fixed; inset: 0; z-index: -2; pointer-events: none; opacity: 1; }
138
+ #aurora { display: block; width: 100%; height: 100%; }
139
+ .grid{
140
+ position: fixed; inset: 0; z-index: -3; pointer-events: none; opacity: 0.15;
141
+ background-image:
142
+ linear-gradient(rgba(255,255,255,0.1) 1px, transparent 1px),
143
+ linear-gradient(90deg, rgba(255,255,255,0.1) 1px, transparent 1px);
144
+ background-size: 40px 40px;
145
+ mask-image: radial-gradient(circle at center, black, transparent 80%);
146
+ }
147
+
148
+ /* Layout */
149
+ .container{ width: min(var(--container), 92vw); margin-inline: auto; }
150
+ img{ max-width: 100%; display: block; border-radius: inherit; }
151
+ a{ color: inherit; text-decoration: none; transition: 0.3s; }
152
+
153
+ /* Typography */
154
+ h1,h2,h3{ margin: 0; font-weight: 800; letter-spacing: -0.02em; line-height: 1.1; color: #fff; }
155
+ h1{ font-size: clamp(48px, 6vw, 82px); margin-bottom: 24px; }
156
+ h2{ font-size: clamp(32px, 5vw, 52px); margin-bottom: 20px; }
157
+ h3{ font-size: 24px; margin-bottom: 12px; }
158
+ p{ margin: 0 0 1em; color: var(--muted); }
159
+
160
+ .eyebrow{
161
+ font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.15em;
162
+ color: var(--cyan); margin-bottom: 16px; display: flex; align-items: center; gap: 12px;
163
+ }
164
+ .eyebrow::before{ content:''; width: 30px; height: 1px; background: var(--cyan); box-shadow: 0 0 10px var(--cyan); }
165
+ .accent{
166
+ background: linear-gradient(135deg, #fff 30%, var(--primary) 100%);
167
+ -webkit-background-clip: text; -webkit-text-fill-color: transparent;
168
+ }
169
+
170
+ /* UI Components */
171
+ .btn{
172
+ display: inline-flex; align-items: center; justify-content: center; gap: 10px;
173
+ height: 54px; padding: 0 28px; border-radius: 999px;
174
+ font-weight: 700; cursor: pointer; border: 1px solid transparent;
175
+ transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1);
176
+ }
177
+ .btn:active{ transform: scale(0.96); }
178
+ .btn.primary{
179
+ background: #F2F4F8; color: #000;
180
+ box-shadow: 0 0 20px -5px rgba(255,255,255,0.4);
181
+ }
182
+ .btn.primary:hover{
183
+ transform: translateY(-3px); box-shadow: 0 10px 40px -5px rgba(255,255,255,0.6);
184
+ }
185
+ .btn.ghost{ border: 1px solid var(--border); background: rgba(255,255,255,0.03); color: #fff; }
186
+ .btn.ghost:hover{ border-color: #fff; background: rgba(255,255,255,0.1); }
187
+
188
+ /* Header */
189
+ header{
190
+ position: sticky; top: 0; z-index: 50;
191
+ border-bottom: 1px solid transparent; transition: 0.4s;
192
+ }
193
+ header.scrolled{
194
+ background: rgba(4, 7, 13, 0.8); backdrop-filter: var(--glass);
195
+ border-bottom-color: var(--border);
196
+ }
197
+ .nav{ height: 80px; display: flex; align-items: center; justify-content: space-between; }
198
+ .logo{ width: 300px; display: flex; align-items: center; } /* Reduced logo size */
199
+ .menu{ display: flex; gap: 32px; font-weight: 600; font-size: 14px; }
200
+ .menu a{ opacity: 0.6; }
201
+ .menu a:hover, .menu a.active{ opacity: 1; text-shadow: 0 0 12px rgba(255,255,255,0.4); }
202
+
203
+ /* Mobile Menu */
204
+ .hamb{ display: none; width: 32px; height: 32px; background: none; border: none; cursor: pointer; padding: 0; position: relative; }
205
+ .hamb span, .hamb span::before, .hamb span::after{ display: block; width: 24px; height: 2px; background: var(--text); transition: 0.3s; }
206
+ .hamb span{ position: relative; }
207
+ .hamb span::before, .hamb span::after{ content: ''; position: absolute; }
208
+ .hamb span::before{ top: -8px; }
209
+ .hamb span::after{ top: 8px; }
210
+ .drawer{ position: fixed; top: 0; right: -100%; width: 100%; max-width: 400px; height: 100vh; background: var(--panel); z-index: 100; transition: 0.4s; padding: 80px 40px; overflow-y: auto; }
211
+ .drawer.open{ right: 0; box-shadow: -10px 0 40px rgba(0,0,0,0.5); }
212
+ .drawer a{ display: block; padding: 16px 0; font-size: 18px; font-weight: 600; border-bottom: 1px solid var(--border); }
213
+ .drawer a:last-child{ border-bottom: none; }
214
+
215
+ /* Layouts */
216
+ section{ padding: 120px 0; position: relative; }
217
+ .hero{ padding: 160px 0 100px; }
218
+ .head{ max-width: 800px; margin: 0 auto 60px; text-align: center; }
219
+ .metrics{
220
+ display: grid; grid-template-columns: repeat(3, 1fr); gap: 32px; margin-top: 80px;
221
+ padding-top: 40px; border-top: 1px solid var(--border);
222
+ }
223
+ .metric{ text-align: center; }
224
+ .metric b{ font-size: 56px; display: block; color: var(--primary); text-shadow: 0 0 40px var(--accent-glow); font-weight: 900; }
225
+ .metric span{ font-size: 13px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.1em; font-weight: 600; }
226
+
227
+ /* Cards */
228
+ .srv, .founder, .plan {
229
+ background: var(--panel); border: 1px solid var(--border);
230
+ border-radius: var(--radius); padding: 36px;
231
+ transition: all 0.4s cubic-bezier(0.25, 1, 0.5, 1);
232
+ position: relative; overflow: hidden;
233
+ }
234
+ .srv::before, .founder::before, .plan::before {
235
+ content: ''; position: absolute; inset: 0;
236
+ background: radial-gradient(circle at top right, rgba(91, 140, 250, 0.08), transparent 60%);
237
+ opacity: 0; transition: 0.4s;
238
+ }
239
+ .srv:hover, .founder:hover, .plan:hover {
240
+ transform: translateY(-8px); border-color: var(--primary);
241
+ box-shadow: 0 20px 60px -10px var(--accent-glow);
242
+ }
243
+ .srv:hover::before, .founder:hover::before, .plan:hover::before { opacity: 1; }
244
+ .srv .icon{ font-size: 40px; margin-bottom: 20px; display: block; }
245
+ .srv h3, .founder h3, .plan h3{ position: relative; z-index: 1; }
246
+
247
+ /* Grids */
248
+ .services{ display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 24px; }
249
+
250
+ /* Case Studies (Fixed) */
251
+ .cases {
252
+ display: grid; grid-template-columns: 1fr 1fr; gap: 40px;
253
+ align-items: center;
254
+ background: var(--panel); border: 1px solid var(--border);
255
+ border-radius: var(--radius); padding: 40px; margin-bottom: 24px;
256
+ transition: 0.3s;
257
+ }
258
+ .cases:hover { border-color: var(--primary); }
259
+ .cases .img { order: 2; border-radius: 12px; overflow: hidden; box-shadow: 0 20px 40px rgba(0,0,0,0.5); }
260
+ .cases h3 { font-size: 32px; margin-bottom: 12px; }
261
+ .tags { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 20px; }
262
+ .tag { padding: 6px 12px; border-radius: 99px; background: rgba(255,255,255,0.05); font-size: 12px; font-weight: 700; border: 1px solid var(--border); }
263
+
264
+ /* Pricing */
265
+ .plan{ position: relative; overflow: hidden; }
266
+ .price{ font-size: 48px; font-weight: 800; margin: 20px 0; color: #fff; }
267
+ .plan ul{ border-top: 1px solid var(--border); padding-top: 24px; margin-top: 24px; list-style: none; padding-left: 0; }
268
+ .plan li { margin-bottom: 10px; display: flex; gap: 10px; }
269
+ .plan li::before { content: '✓'; color: var(--primary); font-weight: bold; }
270
+
271
+ /* Footer */
272
+ footer{
273
+ border-top: 1px solid var(--border); padding: 80px 0 40px;
274
+ background: linear-gradient(to bottom, transparent, #000);
275
+ }
276
+ .foot-grid{ display: grid; grid-template-columns: 1.5fr 1fr 1fr; gap: 40px; padding-top: 40px; }
277
+
278
+ /* Mobile */
279
+ @media(max-width: 900px){
280
+ h1{ font-size: 42px; }
281
+ .metrics{ grid-template-columns: 1fr; gap: 40px; }
282
+ .nav .menu{ display: none; }
283
+ .hamb{ display: block; }
284
+ .cases{ grid-template-columns: 1fr; }
285
+ .cases .img{ order: -1; margin-bottom: 20px; }
286
+ .foot-grid{ grid-template-columns: 1fr; }
287
+ .contact-grid{ grid-template-columns: 1fr; }
288
+ .stack{ grid-template-columns: 1fr; }
289
+ }
290
+
291
+ /* FIXES requested by user */
292
+
293
+ /* 1. Gallery Horizontal Scroll */
294
+ .agency-photos {
295
+ display: flex; overflow-x: auto; gap: 20px; margin-top: 32px;
296
+ padding-bottom: 16px; scroll-snap-type: x mandatory;
297
+ scrollbar-width: thin; scrollbar-color: var(--primary) var(--panel);
298
+ }
299
+ .agency-photos::-webkit-scrollbar { height: 8px; }
300
+ .agency-photos::-webkit-scrollbar-track { background: var(--panel); border-radius: 4px; }
301
+ .agency-photos::-webkit-scrollbar-thumb { background: var(--primary); border-radius: 4px; }
302
+ .agency-photo {
303
+ flex: 0 0 300px; scroll-snap-align: start;
304
+ border-radius: 16px; overflow: hidden; border: 1px solid var(--border);
305
+ transition: 0.3s; cursor: pointer;
306
+ }
307
+ .agency-photo:hover { transform: scale(1.05); border-color: var(--primary); }
308
+ .media img { width: 100%; height: 220px; object-fit: cover; display: block; transition: 0.3s; }
309
+ .agency-photo:hover .media img { transform: scale(1.1); }
310
+
311
+ /* 2. Team Horizontal Grid */
312
+ .founders {
313
+ display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
314
+ gap: 20px; margin-top: 32px;
315
+ }
316
+
317
+ /* 3. Pricing Horizontal Grid */
318
+ .pricing {
319
+ display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
320
+ gap: 24px;
321
+ }
322
+
323
+ /* 4. Roadmap Lines */
324
+ .timeline { position: relative; padding-left: 30px; margin-top: 40px; }
325
+ .tl-line {
326
+ position: absolute; left: 10px; top: 0; bottom: 0; width: 2px;
327
+ background: linear-gradient(to bottom, var(--primary), var(--cyan)); opacity: 0.5;
328
+ }
329
+ .step {
330
+ position: relative; margin-bottom: 30px; padding-left: 20px;
331
+ }
332
+ .step::before {
333
+ content: ''; position: absolute; left: -26px; top: 6px; width: 14px; height: 14px;
334
+ border-radius: 50%; background: var(--bg); border: 2px solid var(--primary);
335
+ box-shadow: 0 0 10px var(--accent-glow);
336
+ }
337
+
338
+ /* 5. FAQ Accordion (Collapsible) */
339
+ .faq { display: flex; flex-direction: column; gap: 12px; }
340
+ .qa {
341
+ background: var(--panel); border: 1px solid var(--border); border-radius: 12px; overflow: hidden;
342
+ }
343
+ .qa summary {
344
+ padding: 20px; cursor: pointer; font-weight: 700; list-style: none; display: flex; justify-content: space-between; align-items: center;
345
+ }
346
+ .qa summary::-webkit-details-marker { display: none; }
347
+ .qa[open] summary { border-bottom: 1px solid var(--border); }
348
+ .qa p { padding: 20px; margin: 0; color: var(--muted); }
349
+ .chev { transition: 0.3s; }
350
+ .qa[open] .chev { transform: rotate(180deg); }
351
+
352
+ /* 6. Contact Grid Horizontal */
353
+ .contact-grid { display: grid; grid-template-columns: 1fr 1.5fr; gap: 32px; margin-top: 40px; }
354
+ .stack { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
355
+ .map-card {
356
+ background: var(--panel); border: 1px solid var(--border); border-radius: 20px; padding: 12px;
357
+ display: flex; flex-direction: column; gap: 12px; height: 100%;
358
+ }
359
+ .map-embed { flex: 1; border-radius: 12px; overflow: hidden; min-height: 250px; }
360
+ .map-embed iframe { width: 100%; height: 100%; border: 0; }
361
+ .map-actions { display: flex; gap: 10px; }
362
+
363
+ /* 7. Sticky FAB */
364
+ .sticky {
365
+ position: fixed; bottom: 30px; right: 30px; z-index: 900;
366
+ display: flex; flex-direction: column; gap: 12px;
367
+ }
368
+ .fab, .totop {
369
+ width: 56px; height: 56px; border-radius: 50%;
370
+ background: #25D366; color: #fff;
371
+ display: flex; align-items: center; justify-content: center;
372
+ box-shadow: 0 10px 20px rgba(0,0,0,0.3);
373
+ border: none; cursor: pointer; transition: 0.3s;
374
+ }
375
+ .fab:hover, .totop:hover { transform: scale(1.1); }
376
+ .fab svg { width: 32px; height: 32px; fill: currentColor; }
377
+ .totop { background: var(--panel); color: var(--text); font-size: 20px; border: 1px solid var(--border); opacity: 0; pointer-events: none; }
378
+ .sticky:hover .totop { opacity: 1; pointer-events: auto; }
379
+ .fab { animation: pulse 2s infinite; }
380
+ @keyframes pulse {
381
+ 0% { box-shadow: 0 0 0 0 rgba(37, 211, 102, 0.7); }
382
+ 70% { box-shadow: 0 0 0 15px rgba(37, 211, 102, 0); }
383
+ 100% { box-shadow: 0 0 0 0 rgba(37, 211, 102, 0); }
384
+ }
385
+
386
+ /* Utilities */
387
+ .reveal{ opacity: 0; transform: translateY(30px); transition: 0.8s ease; }
388
+ .reveal.show{ opacity: 1; transform: translateY(0); }
389
+ .text-center{ text-align: center; }
390
+ </style>
391
+ </head>
392
+ <body>
393
+ <!-- Background scene -->
394
+ <div class="scene" aria-hidden="true">
395
+ <canvas id="aurora"></canvas>
396
+ </div>
397
+ <div class="grid" aria-hidden="true"></div>
398
+ <div class="glow" aria-hidden="true"></div>
399
+ <div class="progressbar" id="progressbar"></div>
400
+ <div class="ring hide" id="ring"></div>
401
+
402
+ <!-- Header -->
403
+ <header>
404
+ <div class="container nav" id="nav">
405
+ <a class="brand" href="#top" aria-label="Home">
406
+ <div class="logo"><img src="LOGO1.png" alt="<?php echo e($brand); ?> logo"></div>
407
+ </a>
408
+ <nav class="menu" aria-label="Primary">
409
+ <a href="#services">Servizi</a>
410
+ <a href="#about">Chi siamo</a>
411
+ <a href="#cases">Casi</a>
412
+ <a href="#roadmap">Roadmap</a>
413
+ <a href="#pricing">Prezzi</a>
414
+ <a href="#faq">FAQ</a>
415
+ <a class="btn primary magnetic" href="<?php echo e($callUrl); ?>">Prenota una call</a>
416
+ </nav>
417
+ <button class="hamb" id="hamb" aria-label="Apri menu" aria-controls="drawer" aria-expanded="false"><span></span></button>
418
+ </div>
419
+
420
+ <div class="drawer" id="drawer" role="dialog" aria-modal="true" aria-label="Menu mobile">
421
+ <div class="container">
422
+ <a href="#services">Servizi</a>
423
+ <a href="#about">Chi siamo</a>
424
+ <a href="#cases">Casi</a>
425
+ <a href="#roadmap">Roadmap</a>
426
+ <a href="#pricing">Prezzi</a>
427
+ <a href="#faq">FAQ</a>
428
+ <div style="display:flex; gap:10px; padding: 6px 0 10px">
429
+ <a class="btn primary magnetic" href="<?php echo e($callUrl); ?>">Prenota call</a>
430
+ <a class="btn whatsapp magnetic" href="<?php echo e($whatsapp); ?>" target="_blank" rel="noopener" aria-label="Apri chat WhatsApp">
431
+ <svg viewBox="0 0 16 16" aria-hidden="true" focusable="false" style="width:16px; height:16px; fill:currentColor">
432
+ <path d="M13.601 2.326a8.269 8.269 0 0 0-11.8 9.94L1 15l2.837-.742a8.269 8.269 0 0 0 4.706 1.39h.003a8.27 8.27 0 0 0 8.27-8.27 8.24 8.24 0 0 0-2.415-5.942zM8.547 13.935a7.1 7.1 0 0 1-3.631-.99l-.261-.155-2.156.563.575-2.102-.17-.273a7.135 7.135 0 1 1 12.559-2.337 7.135 7.135 0 0 1-6.916 5.294z"/>
433
+ </svg>
434
+ WhatsApp
435
+ </a>
436
+ </div>
437
+ </div>
438
+ </div>
439
+ </header>
440
+
441
+ <main id="top">
442
+ <!-- HERO -->
443
+ <section class="container hero">
444
+ <div class="eyebrow"><span class="dash"></span> <?php echo e($brand); ?></div>
445
+ <h1 class="reveal"><?php echo $hero_h1; // Allow HTML in H1 for span.accent ?></h1>
446
+ <p class="sub reveal"><?php echo e($hero_sub); ?></p>
447
+
448
+ <div class="hero-cta reveal">
449
+ <a class="btn primary magnetic" href="<?php echo e($callUrl); ?>">Prenota una call</a>
450
+ <a class="btn ghost" href="#showreel">Guarda lo showreel</a>
451
+ </div>
452
+
453
+ <div class="metrics">
454
+ <?php foreach($stats_list as $s): ?>
455
+ <div class="metric reveal"><b><span data-count="<?php echo e($s['value']); ?>">0</span><span class="unit"><?php echo e($s['unit']); ?></span></b><span><?php echo e($s['label']); ?></span></div>
456
+ <?php endforeach; ?>
457
+ </div>
458
+
459
+ <div id="showreel" class="frame reveal" aria-label="Video presentazione" tabindex="0">
460
+ <div class="box">
461
+ <div class="video-embed" id="heroVideo">
462
+ <div class="cover" id="coverBtn" role="button" aria-label="Riproduci video">
463
+ <div class="play">▶</div>
464
+ </div>
465
+ </div>
466
+ </div>
467
+ </div>
468
+ </section>
469
+
470
+ <!-- SERVICES -->
471
+ <section id="services" class="container">
472
+ <div class="head">
473
+ <h2 class="reveal">Cosa facciamo, in <span class="accent">modo eccellente</span></h2>
474
+ <p class="reveal">Dalla strategia alla produzione, dal social media management alle campagne. Uniamo estetica e performance per impattare sul business.</p>
475
+ </div>
476
+
477
+ <div class="services">
478
+ <?php foreach($services_list as $srv): ?>
479
+ <article class="srv reveal">
480
+ <div class="icon"><?php echo $srv['icon']; ?></div>
481
+ <h3><?php echo e($srv['title']); ?></h3>
482
+ <p><?php echo e($srv['description']); ?></p>
483
+ </article>
484
+ <?php endforeach; ?>
485
+ </div>
486
+ </section>
487
+
488
+ <!-- ABOUT -->
489
+ <section id="about" class="container">
490
+ <div class="head">
491
+ <h2 class="reveal"><?php echo $about_title; ?></h2>
492
+ <p class="reveal"><?php echo e($about_intro); ?></p>
493
+ </div>
494
+
495
+ <div class="about reveal">
496
+ <p style="color:var(--muted); margin:0 0 8px">
497
+ <?php echo e($about_txt1); ?>
498
+ </p>
499
+ <p style="color:var(--muted); margin:0">
500
+ <?php echo e($about_txt2); ?>
501
+ </p>
502
+
503
+ <div class="founders">
504
+ <?php foreach($founders_list as $f): ?>
505
+ <div class="founder">
506
+ <div class="photo"><img src="<?php echo e($f['image_path']); ?>" alt="<?php echo e($f['name']); ?>"></div>
507
+ <div class="role"><?php echo e($f['role']); ?></div>
508
+ <b><?php echo str_replace(' ', '<br>', e($f['name'])); ?></b>
509
+ </div>
510
+ <?php endforeach; ?>
511
+ </div>
512
+ <div class="agency-photos" style="grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));">
513
+ <?php foreach($gallery_list as $img): ?>
514
+ <div class="agency-photo">
515
+ <div class="media"><img src="<?php echo e($img['image_path']); ?>" alt="OFT Gallery"></div>
516
+ </div>
517
+ <?php endforeach; ?>
518
+ </div>
519
+ </div>
520
+ </section>
521
+
522
+ <!-- CASES -->
523
+ <section id="cases" class="container">
524
+ <div class="head">
525
+ <h2 class="reveal"><span class="accent">Storie</span> di Successo</h2>
526
+ <p class="reveal">Strategia, contenuti e distribuzione che hanno generato risultati misurabili.</p>
527
+ </div>
528
+
529
+ <?php foreach($cases_list as $index => $c): ?>
530
+ <article class="cases reveal">
531
+ <div>
532
+ <h3><?php echo e($c['title']); ?></h3>
533
+ <p class="sub" style="font-size:16px"><?php echo e($c['stats_text']); ?></p>
534
+ <p class="sub" style="font-size:16px"><?php echo e($c['role_text']); ?></p>
535
+ <div class="tags">
536
+ <?php foreach(explode(',', $c['tags']) as $tag): ?>
537
+ <span class="tag"><?php echo e(trim($tag)); ?></span>
538
+ <?php endforeach; ?>
539
+ </div>
540
+ </div>
541
+ <div class="img">
542
+ <img src="<?php echo e($c['image_path']); ?>" alt="<?php echo e($c['title']); ?>">
543
+ </div>
544
+ </article>
545
+ <div style="height:14px"></div>
546
+ <?php endforeach; ?>
547
+ <div style="height:2px"></div>
548
+
549
+ <div class="services">
550
+ <?php foreach($bottom_stats_list as $bs): ?>
551
+ <div class="srv reveal" style="text-align:center"><b style="font-size:24px"><?php echo e($bs['value']); ?></b><div class="muted"><?php echo e($bs['label']); ?></div></div>
552
+ <?php endforeach; ?>
553
+ </div>
554
+ </section>
555
+
556
+ <!-- PROBLEM / SOLUTION -->
557
+ <section class="container">
558
+ <div class="head">
559
+ <h2 class="reveal">Da dove <span class="accent">partiamo</span></h2>
560
+ <p class="reveal">Allineiamo identità, contenuti e distribuzione per trasformare visibilità in clienti.</p>
561
+ </div>
562
+
563
+ <div class="services">
564
+ <?php foreach($solutions_list as $sol): ?>
565
+ <div class="srv reveal">
566
+ <div>
567
+ <h3><?php echo e($sol['title']); ?></h3>
568
+ <p class="sub" style="font-size:15px"><?php echo e($sol['description']); ?></p>
569
+ </div>
570
+ </div>
571
+ <?php endforeach; ?>
572
+ </div>
573
+ </section>
574
+
575
+ <!-- GOALS -->
576
+ <section class="container">
577
+ <div class="head">
578
+ <h2 class="reveal"><span class="accent">Obiettivi</span> per i primi 6 mesi</h2>
579
+ <p class="reveal">Awareness, identità e qualità percepita.</p>
580
+ </div>
581
+ <div class="services">
582
+ <?php foreach($goals_list as $g): ?>
583
+ <div class="srv reveal"><h3><?php echo e($g['title']); ?></h3><p class="sub" style="font-size:15px"><?php echo e($g['description']); ?></p></div>
584
+ <?php endforeach; ?>
585
+ </div>
586
+ </section>
587
+
588
+ <!-- ROADMAP -->
589
+ <section id="roadmap" class="container">
590
+ <div class="head">
591
+ <h2 class="reveal">Roadmap & <span class="accent">fasi operative</span></h2>
592
+ <p class="reveal">Dall’onboarding allo scaling: una timeline chiara.</p>
593
+ </div>
594
+
595
+ <div class="timeline reveal" id="timeline">
596
+ <div class="tl-line" id="tlLine"></div>
597
+ <?php foreach($roadmap_list as $step): ?>
598
+ <div class="step"><b><?php echo e($step['phase']); ?></b><br><span class="muted"><?php echo e($step['detail']); ?></span></div>
599
+ <?php endforeach; ?>
600
+ </div>
601
+ </section>
602
+
603
+ <!-- PRICING -->
604
+ <section id="pricing" class="container">
605
+ <div class="head">
606
+ <h2 class="reveal">Pricing & <span class="accent">Packs</span></h2>
607
+ <p class="reveal">Prezzi IVA esclusa. Preventivo valido 7 giorni.</p>
608
+ </div>
609
+
610
+ <div class="pricing">
611
+ <?php foreach($pricing_list as $p): ?>
612
+ <div class="plan reveal">
613
+ <h3><?php echo e($p['name']); ?><?php if($p['is_recommended']): ?> <span class="rec">Consigliato da OFT ✅</span><?php endif; ?></h3>
614
+ <div class="price"><?php echo e($p['price']); ?>€ <small class="muted">/ mese</small></div>
615
+ <ul>
616
+ <?php foreach(explode('|', $p['features']) as $feat): ?>
617
+ <li><?php echo e(trim($feat)); ?></li>
618
+ <?php endforeach; ?>
619
+ </ul>
620
+ </div>
621
+ <?php endforeach; ?>
622
+ </div>
623
+
624
+ <p class="sub" style="text-align:center; margin-top:12px; opacity:.9">Nota: shooting professionale (foto/video) è un costo una tantum.</p>
625
+ </section>
626
+
627
+ <!-- FAQ -->
628
+ <section id="faq" class="container">
629
+ <div class="head" style="display:block; text-align:center">
630
+ <h2 class="reveal">Domande <span class="accent">frequenti</span></h2>
631
+ <p class="reveal">Hai dubbi? Ecco le risposte.</p>
632
+ </div>
633
+
634
+ <div class="faq">
635
+ <?php $i = 1; foreach($faq_list as $f): ?>
636
+ <details class="qa reveal">
637
+ <summary><span><?php echo $i++.'. '.e($f['question']); ?></span><span class="chev">⌄</span></summary>
638
+ <p><?php echo e($f['answer']); ?></p>
639
+ </details>
640
+ <?php endforeach; ?>
641
+ </div>
642
+ </section>
643
+
644
+ <!-- CTA -->
645
+ <section class="container">
646
+ <div class="cta reveal">
647
+ <div class="inner">
648
+ <div class="eyebrow"><span class="dash"></span> Consulenza gratuita</div>
649
+ <h3>Pronti a far crescere il tuo brand con <span class="accent">contenuti che convertono</span>?</h3>
650
+ <p class="sub" style="margin: 0 auto 16px; max-width: 72ch">Parliamo di obiettivi, tono di voce e KPI. Ti inviamo un piano entro 48 ore.</p>
651
+ <a class="btn primary magnetic" href="<?php echo e($callUrl); ?>">Prenota ora la tua call</a>
652
+ </div>
653
+ </div>
654
+ </section>
655
+
656
+ <!-- CONTACT -->
657
+ <section id="contact" class="container">
658
+ <div class="head">
659
+ <h2 class="reveal"><?php echo $contact_title; ?></h2>
660
+ <p class="reveal"><?php echo e($contact_intro); ?></p>
661
+ </div>
662
+ <div class="contact-grid">
663
+ <div class="stack">
664
+ <div class="srv reveal">
665
+ <div><h3>Instagram</h3><p class="sub" style="font-size:15px"><?php echo e($instagram_label); ?></p></div>
666
+ <a class="btn primary magnetic" target="_blank" rel="noopener" href="<?php echo e($instagram); ?>">Apri Instagram</a>
667
+ </div>
668
+ <div class="srv reveal">
669
+ <div><h3>Email</h3><p class="sub" style="font-size:15px"><?php echo e($email); ?></p></div>
670
+ <a class="btn" href="mailto:<?php echo e($email); ?>">Scrivi</a>
671
+ </div>
672
+ <div class="srv reveal">
673
+ <div><h3>Telefono</h3><p class="sub" style="font-size:15px"><?php echo e($phone); ?></p></div>
674
+ <a class="btn" href="tel:<?php echo e(preg_replace('/\s+/', '', $phone)); ?>">Chiama</a>
675
+ </div>
676
+ <div class="srv reveal">
677
+ <div><h3>Indirizzo</h3><p class="sub" style="font-size:15px"><?php echo e($address); ?></p></div>
678
+ </div>
679
+ </div>
680
+ <aside class="map-card reveal">
681
+ <div class="map-embed">
682
+ <iframe src="https://www.google.com/maps?q=<?php echo urlencode($address); ?>&output=embed" loading="lazy" referrerpolicy="no-referrer-when-downgrade" allowfullscreen></iframe>
683
+ </div>
684
+ <div class="map-actions">
685
+ <a class="btn" href="https://maps.google.com/?q=<?php echo urlencode($address); ?>" target="_blank" rel="noopener">Apri Maps</a>
686
+ <a class="btn whatsapp magnetic" href="<?php echo e($whatsapp); ?>" target="_blank" rel="noopener" aria-label="Chat su WhatsApp">
687
+ <svg viewBox="0 0 16 16" aria-hidden="true" focusable="false">
688
+ <path d="M13.601 2.326a8.269 8.269 0 0 0-11.8 9.94L1 15l2.837-.742a8.269 8.269 0 0 0 4.706 1.39h.003a8.27 8.27 0 0 0 8.27-8.27 8.24 8.24 0 0 0-2.415-5.942zM8.547 13.935a7.1 7.1 0 0 1-3.631-.99l-.261-.155-2.156.563.575-2.102-.17-.273a7.135 7.135 0 1 1 12.559-2.337 7.135 7.135 0 0 1-6.916 5.294z"/>
689
+ <path d="M11.245 10.408c-.173-.086-1.02-.504-1.177-.561-.157-.058-.272-.086-.387.086-.115.173-.444.561-.544.676-.101.115-.201.13-.374.043-.173-.086-.732-.27-1.395-.861-.515-.459-.861-1.027-.962-1.2-.101-.173-.011-.267.075-.353.077-.078.173-.202.259-.303.086-.101.115-.173.173-.288.058-.115.029-.216-.014-.302-.043-.086-.387-.934-.53-1.283-.14-.34-.282-.294-.387-.299-.1-.004-.215-.005-.33-.005-.115 0-.302.043-.459.216-.157.173-.602.588-.602 1.433 0 .845.618 1.661.704 1.776.086.115 1.218 1.862 2.952 2.613.413.178.735.284.986.364.414.132.79.113 1.088.068.332-.05 1.02-.416 1.164-.818.144-.401.144-.744.101-.818-.043-.072-.16-.115-.334-.2z"/>
690
+ </svg>
691
+ WhatsApp
692
+ </a>
693
+ </div>
694
+ </aside>
695
+ </div>
696
+ </section>
697
+ </main>
698
+
699
+ <!-- FOOTER -->
700
+ <footer>
701
+ <div class="container">
702
+ <div class="foot-top">
703
+ <div class="logo"><img src="LOGO1.png" alt="<?php echo e($brand); ?> logo"></div>
704
+ <div><?php echo e($brand); ?></div>
705
+ <small style="color:var(--muted)">Marketing italiano, risultati globali.</small>
706
+ <div class="foot-social">
707
+ <a href="<?php echo e($instagram); ?>" target="_blank" rel="noopener">Instagram</a>
708
+ <a href="<?php echo e($tiktok); ?>" target="_blank" rel="noopener">TikTok</a>
709
+ </div>
710
+ </div>
711
+
712
+ <div class="foot-grid">
713
+ <div>
714
+ <b>Azienda</b>
715
+ <div style="height:6px"></div>
716
+ <div><?php echo e($brand); ?></div>
717
+ <div class="muted"><?php echo e($address); ?></div>
718
+ </div>
719
+ <div>
720
+ <b>Pagine Informative</b>
721
+ <div style="height:6px"></div>
722
+ <a href="#">Privacy Policy</a><br>
723
+ <a href="#">Cookie Policy</a><br>
724
+ <a href="#">Termini e Condizioni</a>
725
+ </div>
726
+ <div>
727
+ <b>Contatti</b>
728
+ <div style="height:6px"></div>
729
+ <div>Tel: <a href="tel:<?php echo e(preg_replace('/\s+/', '', $phone)); ?>"><?php echo e($phone); ?></a></div>
730
+ <div>Email: <a href="mailto:<?php echo e($email); ?>"><?php echo e($email); ?></a></div>
731
+ </div>
732
+ </div>
733
+
734
+ <p style="margin-top:14px; color: var(--muted)">© <?php echo e($year); ?> <?php echo e($brand); ?> · Tutti i diritti riservati · <a href="https://www.vergen.it" target="_blank" rel="noopener">Sviluppato da VerGen Developer</a></p>
735
+ </div>
736
+ </footer>
737
+
738
+ <!-- Sticky actions -->
739
+ <div class="sticky">
740
+ <a class="fab" href="<?php echo e($whatsapp); ?>" target="_blank" rel="noopener" aria-label="Chat su WhatsApp">
741
+ <svg viewBox="0 0 16 16" aria-hidden="true" focusable="false">
742
+ <path d="M13.601 2.326a8.269 8.269 0 0 0-11.8 9.94L1 15l2.837-.742a8.269 8.269 0 0 0 4.706 1.39h.003a8.27 8.27 0 0 0 8.27-8.27 8.24 8.24 0 0 0-2.415-5.942zM8.547 13.935a7.1 7.1 0 0 1-3.631-.99l-.261-.155-2.156.563.575-2.102-.17-.273a7.135 7.135 0 1 1 12.559-2.337 7.135 7.135 0 0 1-6.916 5.294z"/>
743
+ <path d="M11.245 10.408c-.173-.086-1.02-.504-1.177-.561-.157-.058-.272-.086-.387.086-.115.173-.444.561-.544.676-.101.115-.201.13-.374.043-.173-.086-.732-.27-1.395-.861-.515-.459-.861-1.027-.962-1.2-.101-.173-.011-.267.075-.353.077-.078.173-.202.259-.303.086-.101.115-.173.173-.288.058-.115.029-.216-.014-.302-.043-.086-.387-.934-.53-1.283-.14-.34-.282-.294-.387-.299-.1-.004-.215-.005-.33-.005-.115 0-.302.043-.459.216-.157.173-.602.588-.602 1.433 0 .845.618 1.661.704 1.776.086.115 1.218 1.862 2.952 2.613.413.178.735.284.986.364.414.132.79.113 1.088.068.332-.05 1.02-.416 1.164-.818.144-.401.144-.744.101-.818-.043-.072-.16-.115-.334-.2z"/>
744
+ </svg>
745
+ </a>
746
+ <button class="totop" id="totop" aria-label="Torna su">↑</button>
747
+ </div>
748
+
749
+ <script>
750
+ const prefersReduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
751
+
752
+ // Canvas Aurora (performante)
753
+ (() => {
754
+ const c = document.getElementById('aurora'); if(!c) return;
755
+ const ctx = c.getContext('2d');
756
+ let dpr = Math.min(window.devicePixelRatio || 1, 2);
757
+ const blobs = [];
758
+ const colors = [
759
+ ['rgba(91,140,250,0.55)','rgba(91,140,250,0.0)'],
760
+ ['rgba(34,211,238,0.45)','rgba(34,211,238,0.0)'],
761
+ ['rgba(55,48,163,0.42)','rgba(55,48,163,0.0)']
762
+ ];
763
+ function resize(){
764
+ const { innerWidth:w, innerHeight:h } = window;
765
+ c.width = w*dpr; c.height = h*dpr; c.style.width = w+'px'; c.style.height = h+'px';
766
+ ctx.setTransform(dpr,0,0,dpr,0,0);
767
+ }
768
+ function makeBlobs(){
769
+ blobs.length = 0;
770
+ const W = c.width/dpr, H = c.height/dpr;
771
+ for (let i=0;i<6;i++){
772
+ const r = Math.max(W,H) * (0.18 + Math.random()*0.18);
773
+ blobs.push({
774
+ x: Math.random()*W, y: Math.random()*H, r,
775
+ dx:(Math.random()-.5)*0.3, dy:(Math.random()-.5)*0.3,
776
+ c: colors[i%colors.length]
777
+ });
778
+ }
779
+ }
780
+ function tick(){
781
+ const W = c.width/dpr, H = c.height/dpr;
782
+ ctx.clearRect(0,0,W,H);
783
+ blobs.forEach(b=>{
784
+ const g = ctx.createRadialGradient(b.x, b.y, 0, b.x, b.y, b.r);
785
+ g.addColorStop(0, b.c[0]); g.addColorStop(1, b.c[1]);
786
+ ctx.globalCompositeOperation = 'lighter';
787
+ ctx.fillStyle = g; ctx.beginPath(); ctx.arc(b.x, b.y, b.r, 0, Math.PI*2); ctx.fill();
788
+ b.x += b.dx; b.y += b.dy;
789
+ if (b.x < -b.r) b.x = W + b.r; if (b.x > W + b.r) b.x = -b.r;
790
+ if (b.y < -b.r) b.y = H + b.r; if (b.y > H + b.r) b.y = -b.r;
791
+ });
792
+ if (!prefersReduce) requestAnimationFrame(tick);
793
+ }
794
+ resize(); makeBlobs(); tick();
795
+ window.addEventListener('resize', () => { dpr = Math.min(window.devicePixelRatio || 1, 2); resize(); makeBlobs(); });
796
+ })();
797
+
798
+ // Sticky header + progress + active section
799
+ const nav = document.getElementById('nav');
800
+ const pb = document.getElementById('progressbar');
801
+ const links= [...document.querySelectorAll('.menu a[href^="#"]')];
802
+ const secs = links.map(a => document.querySelector(a.getAttribute('href'))).filter(Boolean);
803
+
804
+ const onScroll = () => {
805
+ const y = window.scrollY || document.documentElement.scrollTop;
806
+ nav.classList.toggle('scrolled', y > 8);
807
+ const h = document.documentElement;
808
+ const p = (h.scrollTop) / (h.scrollHeight - h.clientHeight) * 100;
809
+ pb.style.width = p + '%';
810
+
811
+ let active = null;
812
+ for (const s of secs){
813
+ const r = s.getBoundingClientRect();
814
+ if (r.top <= 120 && r.bottom >= 120) { active = s; break; }
815
+ }
816
+ links.forEach(a => a.classList.toggle('active', active && a.getAttribute('href') === '#' + active.id));
817
+ };
818
+ document.addEventListener('scroll', onScroll, { passive:true }); onScroll();
819
+
820
+ // Mobile drawer
821
+ const hamb = document.getElementById('hamb');
822
+ const drawer = document.getElementById('drawer');
823
+ hamb.addEventListener('click', () => {
824
+ const open = drawer.classList.toggle('open');
825
+ hamb.setAttribute('aria-expanded', open ? 'true' : 'false');
826
+ });
827
+ drawer.querySelectorAll('a').forEach(a => a.addEventListener('click', () => {
828
+ drawer.classList.remove('open'); hamb.setAttribute('aria-expanded','false');
829
+ }));
830
+
831
+ // Smooth anchor
832
+ document.querySelectorAll('a[href^="#"]').forEach(a => {
833
+ a.addEventListener('click', (e) => {
834
+ const id = a.getAttribute('href').slice(1); if(!id) return;
835
+ const el = document.getElementById(id); if(!el) return;
836
+ e.preventDefault();
837
+ const navEl = document.getElementById('nav');
838
+ const navh = navEl ? navEl.getBoundingClientRect().height : 80;
839
+ const y = el.getBoundingClientRect().top + window.scrollY - (navh + 2);
840
+ window.scrollTo({ top: y, behavior: prefersReduce ? 'auto' : 'smooth' });
841
+ });
842
+ });
843
+
844
+ // Reveal on scroll
845
+ const io = new IntersectionObserver((entries)=>entries.forEach(e=>{ if(e.isIntersecting){ e.target.classList.add('show'); io.unobserve(e.target); }}),{threshold:.15});
846
+ document.querySelectorAll('.reveal').forEach(el=>io.observe(el));
847
+
848
+ // Counters
849
+ const counters = document.querySelectorAll('[data-count]');
850
+ const ioc = new IntersectionObserver((entries)=>{
851
+ entries.forEach(e=>{
852
+ if(!e.isIntersecting) return;
853
+ const el = e.target; const target = +el.dataset.count;
854
+ let n=0; const step = Math.max(1, Math.round(target/40));
855
+ (function tick(){ n+=step; if(n>target) n=target; el.textContent=n; if(n<target) requestAnimationFrame(tick); })();
856
+ ioc.unobserve(el);
857
+ });
858
+ },{threshold:.6});
859
+ counters.forEach(el=>ioc.observe(el));
860
+
861
+ // Timeline draw
862
+ const tlLine = document.getElementById('tlLine');
863
+ const timeline = document.getElementById('timeline');
864
+ if (tlLine && timeline){
865
+ const iol = new IntersectionObserver((es)=>{
866
+ es.forEach(e=>{
867
+ if (!e.isIntersecting) return;
868
+ tlLine.style.transform = 'scaleY(1)';
869
+ tlLine.style.transition = 'transform 1.6s ease';
870
+ iol.unobserve(timeline);
871
+ });
872
+ },{threshold:.2});
873
+ iol.observe(timeline);
874
+ }
875
+
876
+ // Magnetic buttons
877
+ const magnets = document.querySelectorAll('.magnetic');
878
+ magnets.forEach(btn => {
879
+ let rAF = null;
880
+ const strength = 18;
881
+ function move(e){
882
+ const b = btn.getBoundingClientRect();
883
+ const x = e.clientX - (b.left + b.width/2);
884
+ const y = e.clientY - (b.top + b.height/2);
885
+ cancelAnimationFrame(rAF);
886
+ rAF = requestAnimationFrame(()=> btn.style.transform = `translate(${x/strength}px, ${y/strength}px)`);
887
+ }
888
+ function leave(){ btn.style.transform='translate(0,0)'; }
889
+ btn.addEventListener('mousemove', move);
890
+ btn.addEventListener('mouseleave', leave);
891
+ btn.addEventListener('blur', leave);
892
+ });
893
+
894
+ // Cursor ring
895
+ const ring = document.getElementById('ring');
896
+ let rx=0, ry=0, tx=0, ty=0, raf=null;
897
+ function loop(){
898
+ tx += (rx - tx) * 0.2; ty += (ry - ty) * 0.2;
899
+ ring.style.transform = `translate(${tx}px, ${ty}px)`; raf = requestAnimationFrame(loop);
900
+ }
901
+ window.addEventListener('pointermove', (e)=>{ rx=e.clientX; ry=e.clientY; ring.classList.remove('hide'); if(!raf) loop(); });
902
+ window.addEventListener('pointerleave', ()=>{ ring.classList.add('hide'); cancelAnimationFrame(raf); raf=null; });
903
+
904
+ // Back to top
905
+ document.getElementById('totop').addEventListener('click', () => window.scrollTo({ top: 0, behavior: prefersReduce ? 'auto' : 'smooth' }));
906
+
907
+ // Tilt effect on frame (desktop only)
908
+ (() => {
909
+ if (prefersReduce || window.matchMedia('(pointer: coarse)').matches) return;
910
+ const card = document.querySelector('.frame'); if(!card) return;
911
+ let raf=null;
912
+ card.addEventListener('pointermove', (e)=>{
913
+ const b = card.getBoundingClientRect();
914
+ const x = (e.clientX - b.left)/b.width - 0.5;
915
+ const y = (e.clientY - b.top)/b.height - 0.5;
916
+ cancelAnimationFrame(raf);
917
+ raf=requestAnimationFrame(()=> card.style.transform = `perspective(1100px) rotateX(${(-y)*7}deg) rotateY(${x*7}deg)`);
918
+ });
919
+ card.addEventListener('pointerleave', ()=> card.style.transform = 'perspective(1100px) rotateX(0) rotateY(0)');
920
+ })();
921
+
922
+ // Video lazy load
923
+ const hero = document.getElementById('heroVideo');
924
+ const coverBtn = document.getElementById('coverBtn');
925
+ const loadHero = () => {
926
+ if (hero.querySelector('iframe')) return;
927
+ const f = document.createElement('iframe');
928
+ f.src = '<?php echo $video_url; ?>';
929
+ f.allow = 'autoplay; encrypted-media; picture-in-picture'; f.allowFullscreen = true;
930
+ hero.appendChild(f);
931
+ coverBtn.remove();
932
+ };
933
+ coverBtn.addEventListener('click', loadHero);
934
+ coverBtn.addEventListener('keydown', (e)=>{ if(e.key==='Enter' || e.key===' ') loadHero(); });
935
+ </script>
936
+ </body>
937
+ </html>
michele.jpg ADDED
nautica.PNG ADDED
oft.pdf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3e67231ab1966c0749ddd84af45d6c9b5b92dcfd06acdbc601a382bb7aabe1e8
3
+ size 1419339
setup_db.php ADDED
@@ -0,0 +1,303 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require 'db_connect.php';
3
+
4
+ try {
5
+ // 1. Config Table
6
+ $db->exec("CREATE TABLE IF NOT EXISTS config (
7
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
8
+ key_name TEXT UNIQUE,
9
+ value_text TEXT
10
+ )");
11
+
12
+ $configs = [
13
+ 'brand' => 'OFT MGMT',
14
+ 'hero_h1' => 'Creatività, performance e contenuti che portano <span class="accent">risultati reali</span>.',
15
+ 'hero_sub' => 'Agenzia creativa: marketing, social, foto e video — risultati concreti',
16
+ 'tagline' => 'Agenzia creativa: marketing, social, foto e video — risultati concreti',
17
+ 'email' => 'info@oftagency.com',
18
+ 'phone' => '+39 333 123 4567',
19
+ 'whatsapp_url' => 'https://wa.me/393331234567',
20
+ 'instagram_url' => 'https://instagram.com/oft_mgmt',
21
+ 'instagram_label' => '@oft_mgmt',
22
+ 'tiktok_url' => 'https://tiktok.com/@oft_mgmt',
23
+ 'booking_url' => '#contact',
24
+ 'address' => 'Via G. Origlia, 36 — Nocera Inferiore (SA)',
25
+ 'agency_image_1' => 'team.jpg',
26
+ 'agency_image_2' => 'agenzia.jpg',
27
+ 'video_embed_url' => 'https://www.youtube.com/embed/dQw4w9WgXcQ?autoplay=1&rel=0',
28
+
29
+ // About Section Text
30
+ 'about_title' => 'Chi <span class="accent">siamo</span>',
31
+ 'about_intro' => 'OFT MGMT nasce nel 2025 dall’energia di tre ragazzi che credono nel potere delle idee e aiutano i brand a farsi notare davvero.',
32
+ 'about_text_1' => 'OFT MGMT è nata all’inizio del 2025 da tre ragazzi con un’idea chiara: trasformare la passione per creatività e marketing in risultati concreti. Negli anni abbiamo aiutato attività locali a crescere sui social con contenuti e campagne che fanno la differenza.',
33
+ 'about_text_2' => 'Da passione condivisa a progetto reale: un’agenzia creativa pensata per dare voce ai brand e portarli a un livello superiore.',
34
+
35
+ // Contact Section Text
36
+ 'contact_title' => 'Contatti',
37
+ 'contact_intro' => 'Siamo rapidi a rispondere. Instagram, email o telefono: scegli tu.',
38
+
39
+ 'admin_password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi' // password: password (default)
40
+ ];
41
+
42
+ $stmt = $db->prepare("INSERT OR IGNORE INTO config (key_name, value_text) VALUES (:k, :v)");
43
+ foreach ($configs as $k => $v) {
44
+ $stmt->execute([':k' => $k, ':v' => $v]);
45
+ }
46
+
47
+ // 2. Stats (Metrics)
48
+ $db->exec("CREATE TABLE IF NOT EXISTS stats (
49
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
50
+ label TEXT,
51
+ value TEXT,
52
+ unit TEXT,
53
+ sort_order INTEGER DEFAULT 0
54
+ )");
55
+
56
+ // Check if empty
57
+ $count = $db->query("SELECT COUNT(*) FROM stats")->fetchColumn();
58
+ if ($count == 0) {
59
+ $stats = [
60
+ ['Progetti', '120', '+', 1],
61
+ ['Brand seguiti', '35', '+', 2],
62
+ ['Clienti soddisfatti', '98', '%', 3]
63
+ ];
64
+ $stmt = $db->prepare("INSERT INTO stats (label, value, unit, sort_order) VALUES (?, ?, ?, ?)");
65
+ foreach ($stats as $s) {
66
+ $stmt->execute($s);
67
+ }
68
+ }
69
+
70
+ // 3. Services
71
+ $db->exec("CREATE TABLE IF NOT EXISTS services (
72
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
73
+ icon TEXT,
74
+ title TEXT,
75
+ description TEXT,
76
+ sort_order INTEGER DEFAULT 0
77
+ )");
78
+
79
+ $count = $db->query("SELECT COUNT(*) FROM services")->fetchColumn();
80
+ if ($count == 0) {
81
+ $services = [
82
+ ['🎯', 'Social Media Management', 'Piano editoriale data‑driven, copy, publishing e community.', 1],
83
+ ['📸', 'Produzione Foto', 'Still life, lifestyle, ritratti, cataloghi e ADV.', 2],
84
+ ['🎬', 'Produzione Video', 'Short‑form, brand stories e spot orientati alla conversione.', 3],
85
+ ['📈', 'Campagne Pubblicitarie', 'Meta/TikTok Ads, test A/B, scaling e report.', 4],
86
+ ['🛒', 'Web & Ecommerce', 'Siti veloci e focalizzati su conversioni e brand identity.', 5],
87
+ ['⚡', 'Strategy & Advisory', 'Posizionamento, tone of voice, content system, crescita.', 6]
88
+ ];
89
+ $stmt = $db->prepare("INSERT INTO services (icon, title, description, sort_order) VALUES (?, ?, ?, ?)");
90
+ foreach ($services as $s) {
91
+ $stmt->execute($s);
92
+ }
93
+ }
94
+
95
+ // 4. Founders
96
+ $db->exec("CREATE TABLE IF NOT EXISTS founders (
97
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
98
+ name TEXT,
99
+ role TEXT,
100
+ image_path TEXT,
101
+ sort_order INTEGER DEFAULT 0
102
+ )");
103
+
104
+ $count = $db->query("SELECT COUNT(*) FROM founders")->fetchColumn();
105
+ if ($count == 0) {
106
+ $founders = [
107
+ ['Michele Bisogno', 'Founder & CEO', 'michele.jpg', 1],
108
+ ['Francesco Novi', 'Founder & CEO', 'francesco.jpg', 2],
109
+ ['Eliodoro D’ Acunzo', 'Founder & CEO', 'elio.jpg', 3]
110
+ ];
111
+ $stmt = $db->prepare("INSERT INTO founders (name, role, image_path, sort_order) VALUES (?, ?, ?, ?)");
112
+ foreach ($founders as $f) {
113
+ $stmt->execute($f);
114
+ }
115
+ }
116
+
117
+ // 5. Case Studies
118
+ $db->exec("CREATE TABLE IF NOT EXISTS cases (
119
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
120
+ title TEXT,
121
+ stats_text TEXT,
122
+ role_text TEXT,
123
+ tags TEXT,
124
+ image_path TEXT,
125
+ sort_order INTEGER DEFAULT 0
126
+ )");
127
+
128
+ $count = $db->query("SELECT COUNT(*) FROM cases")->fetchColumn();
129
+ if ($count == 0) {
130
+ $cases = [
131
+ [
132
+ 'Cava Brew Fest 01',
133
+ 'Festival della birra a Cava de’ Tirreni: 80.000 presenze, 3M visualizzazioni, 6.000 nuovi follower e 350k account raggiunti.',
134
+ 'Ruolo: strategia digitale, contenuti virali e promozione online → evento diventato fenomeno social.',
135
+ '#Event,#ShortForm,#IG Growth',
136
+ 'cava.png',
137
+ 1
138
+ ],
139
+ [
140
+ 'IGEM — Nautica & Luxury Experience 02',
141
+ 'Partendo da zero: 1,5M visualizzazioni organiche, 6.000 follower totali e 15 tour venduti in un mese.',
142
+ 'Ruolo: gestione social, contenuti accattivanti e campagne mirate per far crescere rapidamente la brand awareness.',
143
+ '#Luxury,#Tour,#Performance',
144
+ 'nautica.PNG',
145
+ 2
146
+ ]
147
+ ];
148
+ $stmt = $db->prepare("INSERT INTO cases (title, stats_text, role_text, tags, image_path, sort_order) VALUES (?, ?, ?, ?, ?, ?)");
149
+ foreach ($cases as $c) {
150
+ $stmt->execute($c);
151
+ }
152
+ }
153
+
154
+ // 6. Pricing
155
+ $db->exec("CREATE TABLE IF NOT EXISTS pricing (
156
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
157
+ name TEXT,
158
+ price TEXT,
159
+ features TEXT, -- JSON or separator separated
160
+ is_recommended BOOLEAN DEFAULT 0,
161
+ sort_order INTEGER DEFAULT 0
162
+ )");
163
+
164
+ $count = $db->query("SELECT COUNT(*) FROM pricing")->fetchColumn();
165
+ if ($count == 0) {
166
+ $pricing = [
167
+ [
168
+ 'Growth pack',
169
+ '600',
170
+ "12 contenuti verticali|Story set base, grafiche base|Format vincenti + gestione pubblicazioni|Ottimizzazione contenuti e strategie|Gestione Ads (+100€ / mese budget ads)",
171
+ 0,
172
+ 1
173
+ ],
174
+ [
175
+ 'Premium pack',
176
+ '1000',
177
+ "12 contenuti verticali|Story set avanzato + grafiche premium|Copywriting professionale|Shooting extra con fotografo|Format avanzati + trend scouting|Gestione Ads (+200€ / mese budget ads)|Reportistica avanzata e consulenza",
178
+ 1,
179
+ 2
180
+ ]
181
+ ];
182
+ $stmt = $db->prepare("INSERT INTO pricing (name, price, features, is_recommended, sort_order) VALUES (?, ?, ?, ?, ?)");
183
+ foreach ($pricing as $p) {
184
+ $stmt->execute($p);
185
+ }
186
+ }
187
+
188
+ // 7. FAQ
189
+ $db->exec("CREATE TABLE IF NOT EXISTS faq (
190
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
191
+ question TEXT,
192
+ answer TEXT,
193
+ sort_order INTEGER DEFAULT 0
194
+ )");
195
+
196
+ $count = $db->query("SELECT COUNT(*) FROM faq")->fetchColumn();
197
+ if ($count == 0) {
198
+ $faqs = [
199
+ ['Quanto tempo per vedere i risultati?', 'Primi segnali in 2–4 settimane (reach/engagement); 1–3 mesi per KPI di business.', 1],
200
+ ['Quali piattaforme gestite?', 'Instagram, TikTok, Facebook, YouTube (Shorts) e campagne Meta/TikTok Ads.', 2],
201
+ ['Create anche i contenuti?', 'Sì: strategia, shooting foto/video, editing, copy e calendari di pubblicazione.', 3],
202
+ ['Come si inizia?', 'Prenota una call: obiettivi, roadmap e preventivo in 48 ore.', 4],
203
+ ['Esperienza?', 'Food, retail, hospitality, servizi, DTC e PMI locali.', 5],
204
+ ['Dopo posso gestire da solo?', 'Sì, formiamo il tuo team e lasciamo linee guida operative.', 6]
205
+ ];
206
+ $stmt = $db->prepare("INSERT INTO faq (question, answer, sort_order) VALUES (?, ?, ?)");
207
+ foreach ($faqs as $f) {
208
+ $stmt->execute($f);
209
+ }
210
+ }
211
+
212
+ // 8. Solutions (Problem/Solution)
213
+ $db->exec("CREATE TABLE IF NOT EXISTS solutions (
214
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
215
+ title TEXT,
216
+ description TEXT,
217
+ sort_order INTEGER DEFAULT 0
218
+ )");
219
+ if ($db->query("SELECT COUNT(*) FROM solutions")->fetchColumn() == 0) {
220
+ $sols = [
221
+ ['I limiti attuali ❌', 'Ampio seguito (100k+ follower, milioni di views) ma bassa conversione: contenuti generici e identità poco distintiva.', 1],
222
+ ['La nostra soluzione ✅', 'Strategia con contenuti dinamici e autentici (video), format coinvolgenti, pubblicazione costante e storytelling che valorizza qualità ed esperienza.', 2],
223
+ ['Focus operativo', 'Ideazione format, shooting, editing e scheduling. Community, analisi e, quando serve, distribuzione paid per scalare.', 3]
224
+ ];
225
+ $stmt = $db->prepare("INSERT INTO solutions (title, description, sort_order) VALUES (?, ?, ?)");
226
+ foreach($sols as $s) $stmt->execute($s);
227
+ }
228
+
229
+ // 9. Goals
230
+ $db->exec("CREATE TABLE IF NOT EXISTS goals (
231
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
232
+ title TEXT,
233
+ description TEXT,
234
+ sort_order INTEGER DEFAULT 0
235
+ )");
236
+ if ($db->query("SELECT COUNT(*) FROM goals")->fetchColumn() == 0) {
237
+ $goals = [
238
+ ['#1 Awareness & Reputazione', 'Diventare destinazione di qualità ad Angri, valorizzando autenticità e cura in ogni dettaglio.', 1],
239
+ ['#2 Identità forte', 'Stile distintivo che racconta persone e prodotti, con format interattivi e community.', 2],
240
+ ['#3 Esperienza & Qualità', 'Dall’ambiente al servizio fino alle materie prime: un racconto che fidelizza.', 3]
241
+ ];
242
+ $stmt = $db->prepare("INSERT INTO goals (title, description, sort_order) VALUES (?, ?, ?)");
243
+ foreach($goals as $g) $stmt->execute($g);
244
+ }
245
+
246
+ // 10. Roadmap
247
+ $db->exec("CREATE TABLE IF NOT EXISTS roadmap (
248
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
249
+ phase TEXT, -- bold part
250
+ detail TEXT, -- muted part
251
+ sort_order INTEGER DEFAULT 0
252
+ )");
253
+ if ($db->query("SELECT COUNT(*) FROM roadmap")->fetchColumn() == 0) {
254
+ $roads = [
255
+ ['1° mese — Setup e Analisi', 'Audit, posizionamento, definizione KPI e content system.', 1],
256
+ ['1°–2° mese — Lancio comunicazione', 'Format, shooting, pubblicazione e prime iterazioni.', 2],
257
+ ['3° mese — Crescita awareness', 'Ottimizzazioni e distribuzione per accelerare reach.', 3],
258
+ ['4° mese — Focus esperienza', 'Storytelling su qualità e servizio.', 4],
259
+ ['5°–6° mese — Consolidamento identità', 'Consistenza visiva e voce del brand.', 5],
260
+ ['6° mese — Valutazione & Scaling', 'Dati, learnings, piani di crescita.', 6]
261
+ ];
262
+ $stmt = $db->prepare("INSERT INTO roadmap (phase, detail, sort_order) VALUES (?, ?, ?)");
263
+ foreach($roads as $r) $stmt->execute($r);
264
+ }
265
+
266
+ // 11. Bottom Stats
267
+ $db->exec("CREATE TABLE IF NOT EXISTS bottom_stats (
268
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
269
+ value TEXT,
270
+ label TEXT,
271
+ sort_order INTEGER DEFAULT 0
272
+ )");
273
+ if ($db->query("SELECT COUNT(*) FROM bottom_stats")->fetchColumn() == 0) {
274
+ $bstats = [
275
+ ['+5.000.000', 'Visualizzazioni in organico', 1],
276
+ ['+550.000', 'Account raggiunti', 2],
277
+ ['+8.000', 'Nuovi follower', 3]
278
+ ];
279
+ $stmt = $db->prepare("INSERT INTO bottom_stats (value, label, sort_order) VALUES (?, ?, ?)");
280
+ foreach($bstats as $b) $stmt->execute($b);
281
+ }
282
+
283
+ // 12. About Gallery (Dynamic Photos)
284
+ $db->exec("CREATE TABLE IF NOT EXISTS about_gallery (
285
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
286
+ image_path TEXT,
287
+ sort_order INTEGER DEFAULT 0
288
+ )");
289
+ if ($db->query("SELECT COUNT(*) FROM about_gallery")->fetchColumn() == 0) {
290
+ $gallery = [
291
+ ['team.jpg', 1],
292
+ ['agenzia.jpg', 2]
293
+ ];
294
+ $stmt = $db->prepare("INSERT INTO about_gallery (image_path, sort_order) VALUES (?, ?)");
295
+ foreach($gallery as $g) $stmt->execute($g);
296
+ }
297
+
298
+ echo "Database setup completed successfully!";
299
+
300
+ } catch (PDOException $e) {
301
+ die("Setup failed: " . $e->getMessage());
302
+ }
303
+ ?>
site.webmanifest ADDED
@@ -0,0 +1 @@
 
 
1
+ {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
team.jpg ADDED

Git LFS Details

  • SHA256: d3ae577dc4f446d979f52f3dbdd37bda41290479c9b8754b6d864b4a25aef9e1
  • Pointer size: 131 Bytes
  • Size of remote file: 111 kB