doctorlinux commited on
Commit
6ff7c96
·
verified ·
1 Parent(s): 74dbd0b

Upload index.html

Browse files
Files changed (1) hide show
  1. index.html +310 -430
index.html CHANGED
@@ -1,457 +1,337 @@
1
  <!DOCTYPE html>
2
  <html lang="es">
3
  <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>DoctorLinux - Cuestionario de Seguridad</title>
7
- <style>
8
- * {
9
- margin: 0;
10
- padding: 0;
11
- box-sizing: border-box;
12
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
13
- }
14
-
15
- body {
16
- background: linear-gradient(135deg, #1a2a6c, #2a3a7c);
17
- color: #fff;
18
- min-height: 100vh;
19
- padding: 20px;
20
- }
21
-
22
- .container {
23
- max-width: 1000px;
24
- margin: 0 auto;
25
- background: rgba(255, 255, 255, 0.1);
26
- backdrop-filter: blur(10px);
27
- border-radius: 20px;
28
- padding: 40px;
29
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
30
- border: 1px solid rgba(255, 255, 255, 0.2);
31
- }
32
-
33
- header {
34
- text-align: center;
35
- margin-bottom: 40px;
36
- }
37
-
38
- .logo {
39
- font-size: 2.5rem;
40
- font-weight: 700;
41
- margin-bottom: 10px;
42
- color: #4fc3f7;
43
- }
44
-
45
- .subtitle {
46
- font-size: 1.2rem;
47
- opacity: 0.8;
48
- margin-bottom: 10px;
49
- }
50
-
51
- .progress-bar {
52
- width: 100%;
53
- height: 8px;
54
- background: rgba(255, 255, 255, 0.2);
55
- border-radius: 4px;
56
- margin: 20px 0;
57
- overflow: hidden;
58
- }
59
-
60
- .progress {
61
- height: 100%;
62
- background: linear-gradient(to right, #4fc3f7, #2979ff);
63
- width: 0%;
64
- transition: width 0.3s ease;
65
- }
66
-
67
- .question-section {
68
- display: none;
69
- }
70
-
71
- .question-section.active {
72
- display: block;
73
- }
74
-
75
- .question {
76
- background: rgba(255, 255, 255, 0.05);
77
- padding: 25px;
78
- border-radius: 15px;
79
- margin-bottom: 25px;
80
- border-left: 4px solid #4fc3f7;
81
- }
82
-
83
- .question h3 {
84
- margin-bottom: 15px;
85
- color: #4fc3f7;
86
- font-size: 1.3rem;
87
- }
88
-
89
- .options {
90
- display: flex;
91
- flex-direction: column;
92
- gap: 12px;
93
- }
94
-
95
- .option {
96
- padding: 15px 20px;
97
- background: rgba(255, 255, 255, 0.1);
98
- border: 2px solid rgba(255, 255, 255, 0.2);
99
- border-radius: 10px;
100
- cursor: pointer;
101
- transition: all 0.3s ease;
102
- }
103
-
104
- .option:hover {
105
- background: rgba(255, 255, 255, 0.15);
106
- border-color: #4fc3f7;
107
- }
108
-
109
- .option.selected {
110
- background: rgba(79, 195, 247, 0.2);
111
- border-color: #4fc3f7;
112
- }
113
-
114
- .text-input {
115
- width: 100%;
116
- padding: 15px;
117
- background: rgba(255, 255, 255, 0.1);
118
- border: 2px solid rgba(255, 255, 255, 0.2);
119
- border-radius: 10px;
120
- color: white;
121
- font-size: 1rem;
122
- margin-top: 10px;
123
- }
124
-
125
- .text-input::placeholder {
126
- color: rgba(255, 255, 255, 0.6);
127
- }
128
-
129
- .navigation {
130
- display: flex;
131
- justify-content: space-between;
132
- margin-top: 30px;
133
- }
134
-
135
- .btn {
136
- padding: 15px 30px;
137
- background: linear-gradient(to right, #4fc3f7, #2979ff);
138
- color: white;
139
- border: none;
140
- border-radius: 50px;
141
- font-size: 1rem;
142
- font-weight: 600;
143
- cursor: pointer;
144
- transition: all 0.3s ease;
145
- }
146
-
147
- .btn:hover {
148
- transform: translateY(-2px);
149
- box-shadow: 0 5px 15px rgba(41, 121, 255, 0.4);
150
- }
151
-
152
- .btn-secondary {
153
- background: rgba(255, 255, 255, 0.1);
154
- border: 2px solid rgba(255, 255, 255, 0.3);
155
- }
156
-
157
- .btn:disabled {
158
- opacity: 0.5;
159
- cursor: not-allowed;
160
- transform: none;
161
- }
162
-
163
- .results-section {
164
- display: none;
165
- text-align: center;
166
- }
167
-
168
- .results-section.active {
169
- display: block;
170
- }
171
-
172
- .results-section h2 {
173
- color: #4fc3f7;
174
- margin-bottom: 20px;
175
- font-size: 2rem;
176
- }
177
-
178
- .download-btn {
179
- display: inline-block;
180
- background: linear-gradient(to right, #4fc3f7, #2979ff);
181
- color: white;
182
- padding: 18px 50px;
183
- font-size: 1.3rem;
184
- font-weight: 600;
185
- border: none;
186
- border-radius: 50px;
187
- cursor: pointer;
188
- transition: all 0.3s ease;
189
- text-decoration: none;
190
- margin: 20px 0;
191
- box-shadow: 0 5px 15px rgba(41, 121, 255, 0.4);
192
- }
193
-
194
- .download-btn:hover {
195
- transform: translateY(-3px);
196
- box-shadow: 0 8px 20px rgba(41, 121, 255, 0.6);
197
- }
198
-
199
- .features {
200
- display: grid;
201
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
202
- gap: 20px;
203
- margin-top: 30px;
204
- }
205
-
206
- .feature {
207
- background: rgba(255, 255, 255, 0.05);
208
- padding: 20px;
209
- border-radius: 10px;
210
- text-align: center;
211
- }
212
-
213
- .feature-icon {
214
- font-size: 2.5rem;
215
- margin-bottom: 10px;
216
- color: #4fc3f7;
217
- }
218
- </style>
219
  </head>
220
- <body>
221
- <div class="container">
222
- <header>
223
- <div class="logo">DoctorLinux</div>
224
- <div class="subtitle">Cuestionario de Evaluación de Seguridad</div>
225
- <div class="progress-bar">
226
- <div class="progress" id="progress"></div>
227
- </div>
228
- </header>
229
-
230
- <!-- SECCIÓN 1: INFRAESTRUCTURA -->
231
- <div class="question-section active" id="section-1">
232
- <div class="question">
233
- <h3>1. ¿Qué tipo de infraestructura utilizas principalmente?</h3>
234
- <div class="options">
235
- <div class="option" data-value="onprem">Servidores físicos on-premise</div>
236
- <div class="option" data-value="cloud">Infraestructura en la nube (AWS, Azure, GCP)</div>
237
- <div class="option" data-value="hybrid">Infraestructura híbrida</div>
238
- <div class="option" data-value="virtual">Servidores virtualizados</div>
239
- </div>
240
- </div>
241
-
242
- <div class="question">
243
- <h3>2. ¿Cuántos servidores gestionas actualmente?</h3>
244
- <div class="options">
245
- <div class="option" data-value="1-5">1-5 servidores</div>
246
- <div class="option" data-value="6-20">6-20 servidores</div>
247
- <div class="option" data-value="21-50">21-50 servidores</div>
248
- <div class="option" data-value="50+">Más de 50 servidores</div>
249
- </div>
250
- </div>
251
 
252
- <div class="navigation">
253
- <button class="btn btn-secondary" disabled>Anterior</button>
254
- <button class="btn" onclick="nextSection(1)">Siguiente</button>
255
- </div>
256
- </div>
 
 
 
257
 
258
- <!-- SECCIÓN 2: SEGURIDAD DE RED -->
259
- <div class="question-section" id="section-2">
260
- <div class="question">
261
- <h3>3. ¿Cómo gestionas los firewalls en tu infraestructura?</h3>
262
- <div class="options">
263
- <div class="option" data-value="enterprise">Firewall empresarial dedicado</div>
264
- <div class="option" data-value="cloud">Firewalls cloud nativos</div>
265
- <div class="option" data-value="basic">Firewall básico del sistema</div>
266
- <div class="option" data-value="none">Sin firewall configurado</div>
267
- </div>
268
- </div>
269
 
270
- <div class="question">
271
- <h3>4. ¿Qué políticas de acceso tienes implementadas?</h3>
272
- <div class="options">
273
- <div class="option" data-value="mfa">MFA (Autenticación de múltiples factores)</div>
274
- <div class="option" data-value="vpn">Acceso solo por VPN</div>
275
- <div class="option" data-value="ip">Restricción por IP</div>
276
- <div class="option" data-value="basic">Usuario y contraseña básicos</div>
277
- </div>
278
- </div>
279
 
280
- <div class="navigation">
281
- <button class="btn btn-secondary" onclick="prevSection(2)">Anterior</button>
282
- <button class="btn" onclick="nextSection(2)">Siguiente</button>
283
- </div>
284
- </div>
 
 
 
 
 
 
 
 
 
285
 
286
- <!-- SECCIÓN 3: BACKUP Y RECUPERACIÓN -->
287
- <div class="question-section" id="section-3">
288
- <div class="question">
289
- <h3>5. ¿Qué estrategia de backup implementas?</h3>
290
- <div class="options">
291
- <div class="option" data-value="321">Estrategia 3-2-1 (3 copias, 2 medios, 1 externa)</div>
292
- <div class="option" data-value="cloud">Backup en la nube</div>
293
- <div class="option" data-value="local">Backup local solamente</div>
294
- <div class="option" data-value="none">Sin estrategia definida</div>
295
- </div>
296
- </div>
297
 
298
- <div class="question">
299
- <h3>6. ¿Con qué frecuencia realizas backups?</h3>
300
- <div class="options">
301
- <div class="option" data-value="daily">Diariamente</div>
302
- <div class="option" data-value="weekly">Semanalmente</div>
303
- <div class="option" data-value="monthly">Mensualmente</div>
304
- <div class="option" data-value="rarely">Ocasionalmente</div>
305
- </div>
306
- </div>
307
 
308
- <div class="navigation">
309
- <button class="btn btn-secondary" onclick="prevSection(3)">Anterior</button>
310
- <button class="btn" onclick="nextSection(3)">Siguiente</button>
311
- </div>
312
- </div>
 
313
 
314
- <!-- SECCIÓN 4: GESTIÓN DE PARCHES -->
315
- <div class="question-section" id="section-4">
316
- <div class="question">
317
- <h3>7. ¿Cómo gestionas las actualizaciones de seguridad?</h3>
318
- <div class="options">
319
- <div class="option" data-value="auto">Actualizaciones automáticas</div>
320
- <div class="option" data-value="manual">Actualizaciones manuales programadas</div>
321
- <div class="option" data-value="testing">Testing antes de implementar</div>
322
- <div class="option" data-value="rarely">Actualizaciones poco frecuentes</div>
323
- </div>
324
- </div>
325
 
326
- <div class="question">
327
- <h3>8. ¿Qué sistemas operativos utilizas principalmente?</h3>
328
- <div class="options">
329
- <div class="option" data-value="linux">Distribuciones Linux</div>
330
- <div class="option" data-value="windows">Windows Server</div>
331
- <div class="option" data-value="mixed">Mixed (Linux y Windows)</div>
332
- <div class="option" data-value="other">Otros sistemas</div>
333
- </div>
334
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
335
 
336
- <div class="navigation">
337
- <button class="btn btn-secondary" onclick="prevSection(4)">Anterior</button>
338
- <button class="btn" onclick="nextSection(4)">Siguiente</button>
339
- </div>
340
- </div>
 
341
 
342
- <!-- SECCIÓN 5: MONITOREO Y DETECCIÓN -->
343
- <div class="question-section" id="section-5">
344
- <div class="question">
345
- <h3>9. ¿Qué sistema de monitoreo utilizas?</h3>
346
- <div class="options">
347
- <div class="option" data-value="siem">SIEM empresarial</div>
348
- <div class="option" data-value="monitoring">Herramientas de monitoreo (Zabbix, Nagios)</div>
349
- <div class="option" data-value="basic">Monitoreo básico del sistema</div>
350
- <div class="option" data-value="none">Sin sistema de monitoreo</div>
351
- </div>
352
- </div>
353
 
354
- <div class="question">
355
- <h3>10. ¿Tienes políticas de respuesta a incidentes?</h3>
356
- <div class="options">
357
- <div class="option" data-value="documented">Políticas documentadas y probadas</div>
358
- <div class="option" data-value="basic">Procedimientos básicos establecidos</div>
359
- <div class="option" data-value="informal">Procedimientos informales</div>
360
- <div class="option" data-value="none">Sin políticas definidas</div>
361
- </div>
362
- </div>
363
 
364
- <div class="navigation">
365
- <button class="btn btn-secondary" onclick="prevSection(5)">Anterior</button>
366
- <button class="btn" onclick="showResults()">Generar Análisis</button>
367
- </div>
368
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
369
 
370
- <!-- SECCIÓN DE RESULTADOS -->
371
- <div class="results-section" id="results-section">
372
- <h2>Análisis de Seguridad Completado</h2>
373
- <p>Hemos evaluado tu infraestructura basado en tus respuestas</p>
374
-
375
- <a href="#" class="download-btn">Descargar Análisis IA Avanzado</a>
376
-
377
- <div class="features">
378
- <div class="feature">
379
- <div class="feature-icon">📊</div>
380
- <div>Evaluación Personalizada</div>
381
- </div>
382
- <div class="feature">
383
- <div class="feature-icon">🔒</div>
384
- <div>Recomendaciones de Seguridad</div>
385
- </div>
386
- <div class="feature">
387
- <div class="feature-icon">🤖</div>
388
- <div>Análisis con IA</div>
389
- </div>
390
- <div class="feature">
391
- <div class="feature-icon">⚡</div>
392
- <div>Plan de Acción</div>
393
- </div>
394
- </div>
395
- </div>
396
- </div>
397
 
398
- <script>
399
- let currentSection = 1;
400
- const totalSections = 5;
401
- const userAnswers = {};
 
402
 
403
- // Inicializar opciones
404
- document.querySelectorAll('.option').forEach(option => {
405
- option.addEventListener('click', function() {
406
- // Remover selección anterior en la misma pregunta
407
- const question = this.closest('.question');
408
- question.querySelectorAll('.option').forEach(opt => {
409
- opt.classList.remove('selected');
410
- });
411
-
412
- // Seleccionar nueva opción
413
- this.classList.add('selected');
414
-
415
- // Guardar respuesta
416
- const questionText = question.querySelector('h3').textContent;
417
- userAnswers[questionText] = this.getAttribute('data-value');
418
- });
419
- });
420
 
421
- function updateProgress() {
422
- const progress = (currentSection / totalSections) * 100;
423
- document.getElementById('progress').style.width = `${progress}%`;
424
- }
 
 
 
 
 
 
425
 
426
- function nextSection(current) {
427
- if (current === currentSection) {
428
- document.getElementById(`section-${currentSection}`).classList.remove('active');
429
- currentSection++;
430
- document.getElementById(`section-${currentSection}`).classList.add('active');
431
- updateProgress();
432
- }
433
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
434
 
435
- function prevSection(current) {
436
- if (current === currentSection) {
437
- document.getElementById(`section-${currentSection}`).classList.remove('active');
438
- currentSection--;
439
- document.getElementById(`section-${currentSection}`).classList.add('active');
440
- updateProgress();
441
- }
442
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
 
444
- function showResults() {
445
- document.getElementById(`section-${currentSection}`).classList.remove('active');
446
- document.getElementById('results-section').classList.add('active');
447
- document.getElementById('progress').style.width = '100%';
448
-
449
- // Aquí procesaríamos las respuestas y generaríamos el análisis
450
- console.log('Respuestas del usuario:', userAnswers);
451
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
452
 
453
- // Inicializar progreso
454
- updateProgress();
455
- </script>
456
  </body>
457
  </html>
 
1
  <!DOCTYPE html>
2
  <html lang="es">
3
  <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Autoevaluación de Ciberseguridad Operativa - Doctor Linux</title>
7
+ <style>
8
+ body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Inter,Arial,sans-serif;background:#f5f6f5;margin:0;padding:0}
9
+ .dlx-wrap{max-width:960px;margin:auto;padding:16px}
10
+ .dlx-card{background:#fff;border:1px solid #e6ebef;border-radius:16px;box-shadow:0 6px 24px rgba(0,0,0,.06);padding:22px;margin:14px 0}
11
+ .dlx-title{font-size:28px;margin:0 0 4px;color:#214424}
12
+ .dlx-sub{color:#5c6b5f;margin-bottom:16px}
13
+ .dlx-progress{height:10px;background:#eff4f0;border-radius:999px;overflow:hidden;margin:10px 0 18px}
14
+ .dlx-bar{height:100%;width:0;background:#7fbf7f;transition:width .3s}
15
+ .dlx-q h4{margin:0 0 6px;font-size:18px}
16
+ .dlx-options{display:flex;gap:10px;flex-wrap:wrap;margin:6px 0 12px}
17
+ .dlx-pill{border:1px solid #d7e1d9;padding:8px 12px;border-radius:999px;cursor:pointer}
18
+ .dlx-pill input{display:none}
19
+ .dlx-pill.active{background:#214424;color:#fff;border-color:#214424}
20
+ .dlx-nav{display:flex;gap:10px;justify-content:space-between;margin-top:8px}
21
+ .dlx-btn{background:#214424;color:#fff;border:none;border-radius:10px;padding:12px 16px;cursor:pointer;transition:all 0.3s}
22
+ .dlx-btn:hover{background:#1a361c}
23
+ .dlx-btn[disabled]{opacity:.5;cursor:not-allowed}
24
+ .dlx-meter{display:grid;grid-template-columns:1fr auto;gap:6px 10px;margin:8px 0}
25
+ .dlx-badge{font-weight:600}
26
+ .dlx-tag{display:inline-block;background:#eff4f0;border:1px solid #dfe9e2;border-radius:8px;padding:6px 10px;margin:6px 6px 0 0}
27
+ .dlx-note{color:#6a786d}
28
+ .dlx-score{font-size:40px;font-weight:800;color:#214424}
29
+ .dlx-muted{color:#7b8b7f}
30
+ </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  </head>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
+ <body>
34
+ <div class="dlx-wrap" id="dlxApp">
35
+ <div class="dlx-card">
36
+ <h2 class="dlx-title">Autoevaluación de Ciberseguridad Operativa</h2>
37
+ <div class="dlx-sub">Responde con honestidad. Obtendrás tu <b>puntaje</b>, los <b>riesgos clave</b> y un plan sugerido de mejora.</div>
38
+ <div class="dlx-progress"><div class="dlx-bar" id="dlxBar"></div></div>
39
+ <div class="dlx-note dlx-muted" id="dlxStepNote"></div>
40
+ </div>
41
 
42
+ <div id="dlxSteps"></div>
 
 
 
 
 
 
 
 
 
 
43
 
44
+ <div class="dlx-card" id="dlxNavBox">
45
+ <div class="dlx-nav">
46
+ <button class="dlx-btn" id="prevBtn">← Anterior</button>
47
+ <button class="dlx-btn" id="nextBtn">Siguiente →</button>
48
+ </div>
49
+ </div>
 
 
 
50
 
51
+ <div class="dlx-card" id="dlxResult" style="display:none">
52
+ <h3 class="dlx-title">Tu diagnóstico</h3>
53
+ <div class="dlx-sub">Este resultado es orientativo. Si quieres un informe firmado por ingeniería, solicita el <b>diagnóstico gratuito</b>.</div>
54
+ <div style="display:flex;gap:24px;align-items:center;flex-wrap:wrap">
55
+ <div>
56
+ <div class="dlx-muted">Puntaje global</div>
57
+ <div class="dlx-score" id="dlxScore">—%</div>
58
+ <div class="dlx-tag" id="dlxLabel">—</div>
59
+ </div>
60
+ <div style="flex:1;min-width:260px">
61
+ <div class="dlx-progress"><div class="dlx-bar" id="dlxBarFinal" style="background:#3aa655"></div></div>
62
+ <div class="dlx-note">≈ Mayor a 80%: postura sólida. 60–79%: revisar. Menor a 60%: riesgo elevado.</div>
63
+ </div>
64
+ </div>
65
 
66
+ <div class="dlx-card" style="margin-top:16px">
67
+ <h4 style="margin:0 0 8px">Detalle por dominio</h4>
68
+ <div id="dlxBreakdown" class="dlx-meter"></div>
69
+ </div>
 
 
 
 
 
 
 
70
 
71
+ <div class="dlx-card">
72
+ <h4 style="margin:0 0 8px">Recomendaciones inmediatas</h4>
73
+ <div id="dlxRecs"></div>
74
+ <div class="dlx-note" style="margin-top:8px">Tip: prioriza los dominios con menor puntaje. Podemos ayudarte a cerrar brechas con <b>hardening, firewalls, backups 3-2-1 y monitoreo 24/7</b>.</div>
75
+ </div>
 
 
 
 
76
 
77
+ <!-- BOTONES DE ACCIÓN SIMPLIFICADOS -->
78
+ <div class="dlx-nav" style="margin-top:25px">
79
+ <button class="dlx-btn" onclick="window.location.reload()">🔄 Nueva Evaluación</button>
80
+ <button class="dlx-btn" id="analyzeBtn">🤖 Análisis con IA</button>
81
+ <button class="dlx-btn" onclick="downloadPDF()" style="background:#3aa655">📄 Descargar PDF</button>
82
+ </div>
83
 
84
+ <div id="iaBox" class="dlx-card" style="display:none;margin-top:16px">
85
+ <h4>Análisis generado por IA</h4>
86
+ <pre id="iaOutput" style="white-space:pre-wrap;"></pre>
87
+ </div>
88
+ </div>
89
+ </div>
 
 
 
 
 
90
 
91
+ <script>
92
+ /* === CONFIGURACIÓN INICIAL === */
93
+ const DOMAINS = [
94
+ { id:'perimetro', name:'Perímetro / Firewall', qs:[
95
+ '¿Usas un firewall dedicado (Mikrotik/OPNsense/etc.) con reglas mínimas por servicio?',
96
+ '¿Tienes listas de acceso/geo-bloqueo/IPS/DoS activas?',
97
+ '¿Los servicios expuestos están detrás de NAT o Port-Forward controlado?',
98
+ '¿Hay políticas VPN de acceso remoto con 2FA?'
99
+ ]},
100
+ { id:'servers', name:'Servidores / Hardening', qs:[
101
+ '¿Cuentas con hardening básico (SSH seguro, usuarios/roles, auditoría)?',
102
+ '¿Actualizaciones y parches aplicados regularmente?',
103
+ '¿Servicios innecesarios deshabilitados/controlados?'
104
+ ]},
105
+ { id:'backups', name:'Backups y Recuperación', qs:[
106
+ '¿Aplicas la regla 3-2-1 (3 copias, 2 medios, 1 offsite)?',
107
+ '¿Pruebas de restauración realizadas en los últimos 6 meses?',
108
+ '¿Backups protegidos contra ransomware (inmutables/air-gap)?'
109
+ ]},
110
+ { id:'monitor', name:'Monitoreo y Alertas', qs:[
111
+ '¿Monitoreo centralizado (Zabbix/PRTG/Grafana) con alertas 24/7?',
112
+ '¿Métricas revisadas mensualmente?',
113
+ '¿Alertas integradas con soporte?'
114
+ ]},
115
+ { id:'network', name:'Red y Conectividad', qs:[
116
+ '¿Segmentación VLANs para aislar servicios críticos?',
117
+ '¿Control de ancho de banda/Proxy/filtrado de contenidos?',
118
+ '¿Wi-Fi empresarial con WPA2-Enterprise?'
119
+ ]},
120
+ { id:'endpoints', name:'Usuarios / Estaciones', qs:[
121
+ '¿Antimalware/EDR y políticas de actualización?',
122
+ '¿Gestión de contraseñas y MFA?',
123
+ '¿Políticas de mínimo privilegio + bloqueo de USB?'
124
+ ]},
125
+ { id:'webmail', name:'Web y Correo', qs:[
126
+ '¿Sitios con HTTPS válido y cabeceras seguras?',
127
+ '¿Correo con SPF, DKIM y DMARC publicados?',
128
+ '¿WAF/antispam/antiphishing activos?'
129
+ ]}
130
+ ];
131
 
132
+ const SCALE = [
133
+ {label:'No',score:0},
134
+ {label:'Parcial',score:50},
135
+ {label:'Sí',score:100},
136
+ {label:'No sé',score:null}
137
+ ];
138
 
139
+ const RECS = {
140
+ perimetro:'Endurecer perímetro: reglas mínimo necesario, VPN 2FA, IDS/IPS y protección DoS.',
141
+ servers:'Aplicar hardening, cuentas/roles y mantener parches al día.',
142
+ backups:'Implementar 3-2-1 con pruebas de restauración y backups inmutables.',
143
+ monitor:'Centralizar monitoreo (Zabbix/PRTG) y definir umbrales.',
144
+ network:'Segregar VLANs, reforzar proxy y aislar Wi-Fi invitados.',
145
+ endpoints:'Mínimo privilegio, EDR/antimalware y MFA.',
146
+ webmail:'Forzar HTTPS, cabeceras OWASP, SPF+DKIM+DMARC y WAF.'
147
+ };
 
 
148
 
149
+ let current = 0, answers = {};
150
+ const steps = document.getElementById('dlxSteps'),
151
+ bar = document.getElementById('dlxBar'),
152
+ note = document.getElementById('dlxStepNote'),
153
+ prev = document.getElementById('prevBtn'),
154
+ next = document.getElementById('nextBtn'),
155
+ result = document.getElementById('dlxResult'),
156
+ nav = document.getElementById('dlxNavBox');
 
157
 
158
+ /* === FUNCIONES PRINCIPALES === */
159
+ function render() {
160
+ steps.innerHTML = '';
161
+ const d = DOMAINS[current];
162
+ note.innerHTML = `<b>${current+1}/${DOMAINS.length}</b> · ${d.name}`;
163
+ const card = document.createElement('div');
164
+ card.className = 'dlx-card';
165
+ card.innerHTML = `<h3 class="dlx-title">${d.name}</h3>`;
166
+ d.qs.forEach((q, i) => {
167
+ const b = document.createElement('div');
168
+ b.className = 'dlx-q';
169
+ b.innerHTML = `<h4>${q}</h4>`;
170
+ const row = document.createElement('div');
171
+ row.className = 'dlx-options';
172
+ SCALE.forEach(opt => {
173
+ const lbl = document.createElement('label');
174
+ lbl.className = 'dlx-pill';
175
+ lbl.textContent = opt.label;
176
+ lbl.onclick = () => {
177
+ row.querySelectorAll('.dlx-pill').forEach(p => p.classList.remove('active'));
178
+ lbl.classList.add('active');
179
+ if (!answers[d.id]) answers[d.id] = [];
180
+ answers[d.id][i] = opt.score;
181
+ updateButtons();
182
+ };
183
+ if (answers[d.id] && answers[d.id][i] === opt.score) lbl.classList.add('active');
184
+ row.appendChild(lbl);
185
+ });
186
+ b.appendChild(row);
187
+ card.appendChild(b);
188
+ });
189
+ steps.appendChild(card);
190
+ bar.style.width = Math.round(current / DOMAINS.length * 100) + '%';
191
+ updateButtons();
192
+ }
193
 
194
+ function allAnswered(i) {
195
+ const d = DOMAINS[i];
196
+ return answers[d.id] && answers[d.id].length === d.qs.length && answers[d.id].every(v => v !== undefined);
197
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
 
199
+ function avg(a) {
200
+ const nums = a.filter(v => typeof v === 'number' && isFinite(v));
201
+ if (nums.length === 0) return 0;
202
+ return nums.reduce((x, y) => x + y, 0) / nums.length;
203
+ }
204
 
205
+ function updateButtons() {
206
+ prev.disabled = current === 0;
207
+ const last = current === DOMAINS.length - 1;
208
+ next.textContent = last ? 'Ver resultado →' : 'Siguiente →';
209
+ next.disabled = !allAnswered(current);
210
+ }
 
 
 
 
 
 
 
 
 
 
 
211
 
212
+ prev.onclick = () => { if (current > 0) { current--; render(); } };
213
+ next.onclick = () => {
214
+ if (current < DOMAINS.length - 1) {
215
+ if (!allAnswered(current)) return;
216
+ current++; render();
217
+ } else {
218
+ if (!allAnswered(current)) return;
219
+ showResult();
220
+ }
221
+ };
222
 
223
+ function showResult() {
224
+ bar.style.width = '100%';
225
+ nav.style.display = 'none';
226
+ steps.style.display = 'none';
227
+ note.style.display = 'none';
228
+ result.style.display = 'block';
229
+ let weighted = 0, total = 0;
230
+ const breakdown = document.getElementById('dlxBreakdown'),
231
+ recs = document.getElementById('dlxRecs');
232
+ breakdown.innerHTML = '';
233
+ recs.innerHTML = '';
234
+ DOMAINS.forEach(d => {
235
+ const a = answers[d.id] ? avg(answers[d.id]) : 0;
236
+ weighted += a; total += 100;
237
+ const pct = Math.round(a);
238
+ breakdown.innerHTML += `<div>${d.name}</div><div><b>${pct}%</b></div>`;
239
+ if (pct < 75) { recs.innerHTML += `<div class="dlx-tag">• ${RECS[d.id]}</div>`; }
240
+ });
241
+ const global = Math.round(weighted / DOMAINS.length);
242
+ document.getElementById('dlxScore').textContent = global + '%';
243
+ document.getElementById('dlxBarFinal').style.width = global + '%';
244
+ const label = document.getElementById('dlxLabel');
245
+ if (global >= 80) { label.textContent = 'Nivel Sólido'; label.style.background = '#e7f7e7'; }
246
+ else if (global >= 60) { label.textContent = 'Nivel Medio (revisar)'; label.style.background = '#fff6e1'; }
247
+ else { label.textContent = 'Riesgo Alto'; label.style.background = '#ffe9e9'; }
248
+
249
+ // Guardar datos para el análisis IA
250
+ window.finalData = {
251
+ overall: global,
252
+ domains: DOMAINS.map(d => ({
253
+ name: d.name,
254
+ score: Math.round(avg(answers[d.id]))
255
+ }))
256
+ };
257
+ }
258
 
259
+ /* === DESCARGAR PDF SIMPLIFICADO === */
260
+ function downloadPDF() {
261
+ const global = window.finalData.overall;
262
+ const date = new Date().toLocaleDateString('es-ES');
263
+
264
+ // Crear contenido simple para el PDF
265
+ const content = `
266
+ INFORME DE CIBERSEGURIDAD - DOCTOR LINUX
267
+ ========================================
268
+
269
+ Fecha: ${date}
270
+ Puntaje Global: ${global}%
271
+
272
+ RESUMEN:
273
+ ${global >= 80 ? '✅ POSTURA SÓLIDA' : global >= 60 ? '⚠️ MEJORAS NECESARIAS' : '🚨 RIESGO ELEVADO'}
274
+
275
+ DETALLE POR DOMINIO:
276
+ ${window.finalData.domains.map(d => `• ${d.name}: ${d.score}%`).join('\n')}
277
+
278
+ RECOMENDACIONES:
279
+ 1. Revisar configuración de firewall y accesos
280
+ 2. Implementar estrategia de backups 3-2-1
281
+ 3. Establecer monitoreo continuo 24/7
282
+ 4. Aplicar hardening en servidores
283
+ 5. Implementar autenticación multifactor
284
+
285
+ ---
286
+ Generado por Doctor Linux - www.doctorlinux.com
287
+ `;
288
+
289
+ // Crear y descargar archivo de texto simple
290
+ const blob = new Blob([content], { type: 'text/plain' });
291
+ const url = URL.createObjectURL(blob);
292
+ const a = document.createElement('a');
293
+ a.href = url;
294
+ a.download = `informe-ciberseguridad-${date}.txt`;
295
+ document.body.appendChild(a);
296
+ a.click();
297
+ document.body.removeChild(a);
298
+ URL.revokeObjectURL(url);
299
+
300
+ alert('📄 Informe descargado como archivo de texto');
301
+ }
302
 
303
+ /* === ANÁLISIS CON IA === */
304
+ document.getElementById('analyzeBtn').onclick = async function() {
305
+ const box = document.getElementById('iaBox');
306
+ const out = document.getElementById('iaOutput');
307
+ const btn = this;
308
+
309
+ box.style.display = 'block';
310
+ out.textContent = 'Generando análisis detallado...';
311
+ btn.disabled = true;
312
+
313
+ try {
314
+ const res = await fetch('/analyze', {
315
+ method: 'POST',
316
+ headers: {'Content-Type': 'application/json'},
317
+ body: JSON.stringify(window.finalData)
318
+ });
319
+
320
+ if (res.ok) {
321
+ const data = await res.json();
322
+ out.textContent = data.analysis || 'Análisis completado.';
323
+ } else {
324
+ throw new Error('Error del servidor');
325
+ }
326
+ } catch (error) {
327
+ out.textContent = 'El análisis detallado no está disponible en este momento.\n\nPuntaje: ' + window.finalData.overall + '%\n\nPara un diagnóstico completo, contacta a Doctor Linux.';
328
+ } finally {
329
+ btn.disabled = false;
330
+ }
331
+ };
332
 
333
+ // Inicializar aplicación
334
+ render();
335
+ </script>
336
  </body>
337
  </html>