CommandPrompt commited on
Commit
6917ab6
·
verified ·
1 Parent(s): 67f6005

I want it all in Spanish even more high tech and called simply >_teleprompter

Browse files
Files changed (4) hide show
  1. components/footer.js +16 -19
  2. components/navbar.js +9 -12
  3. index.html +45 -51
  4. script.js +73 -97
components/footer.js CHANGED
@@ -10,7 +10,6 @@ class CustomFooter extends HTMLElement {
10
  padding: 2rem 0;
11
  margin-top: 3rem;
12
  }
13
-
14
  .footer-container {
15
  max-width: 1200px;
16
  margin: 0 auto;
@@ -63,21 +62,19 @@ class CustomFooter extends HTMLElement {
63
  color: rgba(255, 255, 255, 0.4);
64
  font-size: 0.9rem;
65
  }
66
-
67
- @media (max-width: 768px) {
68
  .footer-container {
69
  grid-template-columns: 1fr;
70
  padding: 0 1rem;
71
  }
72
  }
73
  </style>
74
-
75
  <footer>
76
  <div class="footer-container">
77
  <div class="footer-section">
78
- <h3>Teleprompter Factory</h3>
79
  <p style="color: rgba(255, 255, 255, 0.6); line-height: 1.5;">
80
- Professional teleprompter software for presenters, broadcasters, and content creators.
81
  </p>
82
  <div class="social-links">
83
  <a href="#" class="social-link"><i data-feather="twitter"></i></a>
@@ -87,20 +84,20 @@ class CustomFooter extends HTMLElement {
87
  </div>
88
  </div>
89
  <div class="footer-section">
90
- <h3>Quick Links</h3>
91
  <div class="footer-links">
92
- <a href="/" class="footer-link">Home</a>
93
- <a href="/features" class="footer-link">Features</a>
94
- <a href="/pricing" class="footer-link">Pricing</a>
95
- <a href="/templates" class="footer-link">Templates</a>
96
  </div>
97
  </div>
98
  <div class="footer-section">
99
- <h3>Resources</h3>
100
  <div class="footer-links">
101
  <a href="/blog" class="footer-link">Blog</a>
102
- <a href="/tutorials" class="footer-link">Tutorials</a>
103
- <a href="/support" class="footer-link">Support</a>
104
  <a href="/faq" class="footer-link">FAQ</a>
105
  </div>
106
  </div>
@@ -108,18 +105,18 @@ class CustomFooter extends HTMLElement {
108
  <div class="footer-section">
109
  <h3>Legal</h3>
110
  <div class="footer-links">
111
- <a href="/privacy" class="footer-link">Privacy Policy</a>
112
- <a href="/terms" class="footer-link">Terms of Service</a>
113
- <a href="/cookies" class="footer-link">Cookie Policy</a>
114
  </div>
115
  </div>
116
  </div>
117
 
118
  <div class="copyright">
119
- &copy; ${new Date().getFullYear()} Teleprompter Factory Deluxe. All rights reserved.
120
  </div>
121
  </footer>
122
- `;
123
  }
124
  }
125
 
 
10
  padding: 2rem 0;
11
  margin-top: 3rem;
12
  }
 
13
  .footer-container {
14
  max-width: 1200px;
15
  margin: 0 auto;
 
62
  color: rgba(255, 255, 255, 0.4);
63
  font-size: 0.9rem;
64
  }
65
+ @media (max-width: 768px) {
 
66
  .footer-container {
67
  grid-template-columns: 1fr;
68
  padding: 0 1rem;
69
  }
70
  }
71
  </style>
 
72
  <footer>
73
  <div class="footer-container">
74
  <div class="footer-section">
75
+ <h3>>_teleprompter</h3>
76
  <p style="color: rgba(255, 255, 255, 0.6); line-height: 1.5;">
77
+ Software profesional de teleprompter para presentadores, emisoras y creadores de contenido.
78
  </p>
79
  <div class="social-links">
80
  <a href="#" class="social-link"><i data-feather="twitter"></i></a>
 
84
  </div>
85
  </div>
86
  <div class="footer-section">
87
+ <h3>Enlaces Rápidos</h3>
88
  <div class="footer-links">
89
+ <a href="/" class="footer-link">Inicio</a>
90
+ <a href="/features" class="footer-link">Características</a>
91
+ <a href="/pricing" class="footer-link">Precios</a>
92
+ <a href="/templates" class="footer-link">Plantillas</a>
93
  </div>
94
  </div>
95
  <div class="footer-section">
96
+ <h3>Recursos</h3>
97
  <div class="footer-links">
98
  <a href="/blog" class="footer-link">Blog</a>
99
+ <a href="/tutorials" class="footer-link">Tutoriales</a>
100
+ <a href="/support" class="footer-link">Soporte</a>
101
  <a href="/faq" class="footer-link">FAQ</a>
102
  </div>
103
  </div>
 
105
  <div class="footer-section">
106
  <h3>Legal</h3>
107
  <div class="footer-links">
108
+ <a href="/privacy" class="footer-link">Política de Privacidad</a>
109
+ <a href="/terms" class="footer-link">Términos de Servicio</a>
110
+ <a href="/cookies" class="footer-link">Política de Cookies</a>
111
  </div>
112
  </div>
113
  </div>
114
 
115
  <div class="copyright">
116
+ &copy; ${new Date().getFullYear()} >_teleprompter. Todos los derechos reservados.
117
  </div>
118
  </footer>
119
+ `;
120
  }
121
  }
122
 
components/navbar.js CHANGED
@@ -17,7 +17,6 @@ class CustomNavbar extends HTMLElement {
17
  justify-content: space-between;
18
  align-items: center;
19
  }
20
-
21
  .logo {
22
  font-weight: 700;
23
  font-size: 1.25rem;
@@ -40,8 +39,7 @@ class CustomNavbar extends HTMLElement {
40
  .nav-link:hover {
41
  color: white;
42
  }
43
-
44
- @media (max-width: 768px) {
45
  .nav-container {
46
  flex-direction: column;
47
  padding: 1rem;
@@ -54,23 +52,22 @@ class CustomNavbar extends HTMLElement {
54
  }
55
  }
56
  </style>
57
-
58
  <nav>
59
  <div class="nav-container">
60
  <a href="/" class="logo">
61
- <i data-feather="tv"></i>
62
- Teleprompter Factory
63
  </a>
64
  <div class="nav-links">
65
- <a href="/" class="nav-link">Home</a>
66
- <a href="/templates" class="nav-link">Templates</a>
67
- <a href="/features" class="nav-link">Features</a>
68
- <a href="/pricing" class="nav-link">Pricing</a>
69
- <a href="/contact" class="nav-link">Contact</a>
70
  </div>
71
  </div>
72
  </nav>
73
- `;
74
  }
75
  }
76
 
 
17
  justify-content: space-between;
18
  align-items: center;
19
  }
 
20
  .logo {
21
  font-weight: 700;
22
  font-size: 1.25rem;
 
39
  .nav-link:hover {
40
  color: white;
41
  }
42
+ @media (max-width: 768px) {
 
43
  .nav-container {
44
  flex-direction: column;
45
  padding: 1rem;
 
52
  }
53
  }
54
  </style>
 
55
  <nav>
56
  <div class="nav-container">
57
  <a href="/" class="logo">
58
+ <i data-feather="terminal"></i>
59
+ >_teleprompter
60
  </a>
61
  <div class="nav-links">
62
+ <a href="/" class="nav-link">Inicio</a>
63
+ <a href="/templates" class="nav-link">Plantillas</a>
64
+ <a href="/features" class="nav-link">Características</a>
65
+ <a href="/pricing" class="nav-link">Precios</a>
66
+ <a href="/contact" class="nav-link">Contacto</a>
67
  </div>
68
  </div>
69
  </nav>
70
+ `;
71
  }
72
  }
73
 
index.html CHANGED
@@ -3,8 +3,8 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Teleprompter Factory Deluxe</title>
7
- <link rel="stylesheet" href="style.css">
8
  <script src="https://cdn.tailwindcss.com"></script>
9
  <script src="https://unpkg.com/feather-icons"></script>
10
  <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
@@ -42,50 +42,47 @@
42
  <i data-feather="x" class="w-4 h-4"></i>
43
  </button>
44
  </div>
45
- <h1 class="text-3xl font-bold">ScrollGenius 3000</h1>
46
- <p class="text-gray-200 mt-2">Professional Teleprompter Widget</p>
47
  </div>
48
- <div class="p-6 grid grid-cols-1 lg:grid-cols-3 gap-6 relative">
49
  <div class="absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-primary-500 to-secondary-500"></div>
50
  <div class="lg:col-span-1 space-y-6">
51
  <div>
52
  <label class="block text-sm font-medium text-gray-300 mb-1 flex items-center justify-between">
53
- <span>Script Title</span>
54
  <span class="text-xs text-gray-400">Ctrl+T</span>
55
  </label>
56
  <div class="relative">
57
- <input type="text" id="script-title" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-2 focus:ring-2 focus:ring-primary-500 focus:border-primary-500 outline-none transition pr-10" placeholder="My Presentation">
58
  <button class="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-white">
59
  <i data-feather="edit-2" class="w-4 h-4"></i>
60
  </button>
61
  </div>
62
  </div>
63
-
64
  <div>
65
  <label class="block text-sm font-medium text-gray-300 mb-1 flex items-center justify-between">
66
- <span>Scroll Speed</span>
67
  <span class="text-xs text-gray-400" id="speed-value">1.0x</span>
68
  </label>
69
  <input type="range" id="speed-slider" min="0.1" max="5" step="0.1" value="1" class="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer accent-primary-500">
70
  <div class="flex justify-between text-xs text-gray-400 mt-1">
71
- <span>Slow</span>
72
- <span>Medium</span>
73
- <span>Fast</span>
74
  </div>
75
  </div>
76
-
77
  <div>
78
- <label class="block text-sm font-medium text-gray-300 mb-1">Text Size</label>
79
  <select id="text-size" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-2 focus:ring-2 focus:ring-primary-500 focus:border-primary-500 outline-none transition">
80
- <option value="small">Small</option>
81
- <option value="medium" selected>Medium</option>
82
- <option value="large">Large</option>
83
- <option value="x-large">Extra Large</option>
84
  </select>
85
  </div>
86
-
87
  <div>
88
- <label class="block text-sm font-medium text-gray-300 mb-1">Theme</label>
89
  <div class="grid grid-cols-3 gap-2 theme-selector">
90
  <button class="bg-blue-500 h-10 rounded-lg theme-btn active" data-theme="blue"></button>
91
  <button class="bg-green-500 h-10 rounded-lg theme-btn" data-theme="green"></button>
@@ -95,9 +92,8 @@
95
  <button class="bg-pink-500 h-10 rounded-lg theme-btn" data-theme="pink"></button>
96
  </div>
97
  </div>
98
-
99
  <div>
100
- <label class="block text-sm font-medium text-gray-300 mb-1">Text Alignment</label>
101
  <div class="grid grid-cols-3 gap-2">
102
  <button id="align-left" class="p-2 bg-gray-700 rounded-lg hover:bg-gray-600 flex items-center justify-center">
103
  <i data-feather="align-left" class="w-4 h-4"></i>
@@ -110,88 +106,86 @@
110
  </button>
111
  </div>
112
  </div>
113
-
114
  <div>
115
- <label class="block text-sm font-medium text-gray-300 mb-1">Font Style</label>
116
  <div class="grid grid-cols-2 gap-2">
117
  <button id="font-sans" class="p-2 bg-gray-700 rounded-lg hover:bg-gray-600 active">Sans Serif</button>
118
  <button id="font-serif" class="p-2 bg-gray-700 rounded-lg hover:bg-gray-600">Serif</button>
119
  </div>
120
  </div>
121
- </div>
122
 
123
  <div class="lg:col-span-2 flex flex-col gap-4">
124
  <div class="bg-gray-700 rounded-lg p-4 flex-grow relative group">
125
  <div class="absolute top-2 right-2 flex gap-1 z-10">
126
- <button id="format-bold" class="p-1 bg-gray-600 rounded hover:bg-gray-500" title="Bold">
127
  <i data-feather="bold" class="w-4 h-4"></i>
128
  </button>
129
- <button id="format-italic" class="p-1 bg-gray-600 rounded hover:bg-gray-500" title="Italic">
130
  <i data-feather="italic" class="w-4 h-4"></i>
131
  </button>
132
- <button id="format-underline" class="p-1 bg-gray-600 rounded hover:bg-gray-500" title="Underline">
133
  <i data-feather="underline" class="w-4 h-4"></i>
134
  </button>
135
  </div>
136
- <textarea id="script-textarea" class="w-full h-64 bg-transparent resize-none outline-none text-gray-200 placeholder-gray-500" placeholder="Enter your script here...">Welcome to ScrollGenius 3000!
137
 
138
- This is a professional teleprompter solution with advanced features:
139
 
140
- Real-time scrolling control
141
- Multiple themes and customization
142
- Text formatting options
143
- Keyboard shortcuts for efficiency
144
- Script saving and loading
145
 
146
- Try adjusting the scroll speed to see how it works!</textarea>
147
  <div class="absolute bottom-4 right-4 opacity-0 group-hover:opacity-100 transition flex gap-2">
148
- <button id="import-script" class="p-2 bg-gray-600 rounded-lg hover:bg-gray-500" title="Import Script">
149
  <i data-feather="upload" class="w-4 h-4"></i>
150
  </button>
151
- <button id="clear-script" class="p-2 bg-gray-600 rounded-lg hover:bg-gray-500" title="Clear All">
152
  <i data-feather="trash-2" class="w-4 h-4"></i>
153
  </button>
154
  </div>
155
  </div>
156
-
157
  <div class="bg-gray-700 rounded-lg p-4">
158
  <div class="flex justify-between items-center mb-2">
159
- <h3 class="font-medium">Preview</h3>
160
  <div class="flex gap-2">
161
- <button id="toggle-preview" class="px-3 py-1 bg-gray-600 hover:bg-gray-500 rounded text-sm">Toggle View</button>
162
- <button id="mirror-preview" class="px-3 py-1 bg-gray-600 hover:bg-gray-500 rounded text-sm">Mirror</button>
163
  </div>
164
  </div>
165
  <div id="preview-container" class="bg-black rounded p-4 h-40 overflow-hidden relative">
166
  <div id="preview-text" class="text-white text-center text-lg leading-relaxed">
167
- Welcome to ScrollGenius 3000! This is a professional teleprompter solution with advanced features.
168
  </div>
169
  </div>
170
  </div>
171
- </div>
172
  </div>
173
 
174
  <div class="p-6 bg-gray-700 border-t border-gray-600 flex flex-wrap justify-between gap-4">
175
  <div class="flex gap-2">
176
  <button id="save-script" class="px-4 py-2 bg-gray-600 hover:bg-gray-500 rounded-lg font-medium transition flex items-center gap-2 text-sm">
177
- <i data-feather="save" class="w-4 h-4"></i> Save
178
  </button>
179
  <button id="load-script" class="px-4 py-2 bg-gray-600 hover:bg-gray-500 rounded-lg font-medium transition flex items-center gap-2 text-sm">
180
- <i data-feather="folder" class="w-4 h-4"></i> Load
181
  </button>
182
  <button id="export-script" class="px-4 py-2 bg-gray-600 hover:bg-gray-500 rounded-lg font-medium transition flex items-center gap-2 text-sm">
183
- <i data-feather="download" class="w-4 h-4"></i> Export
184
  </button>
185
  </div>
186
  <div class="flex gap-2">
187
  <button id="help-btn" class="px-4 py-2 bg-gray-600 hover:bg-gray-500 rounded-lg font-medium transition flex items-center gap-2 text-sm">
188
- <i data-feather="help-circle" class="w-4 h-4"></i> Help
189
  </button>
190
  <button id="start-scroll" class="px-6 py-2 bg-primary-500 hover:bg-primary-600 rounded-lg font-medium transition flex items-center gap-2 text-sm glow">
191
- <i data-feather="play" class="w-4 h-4"></i> Start Scrolling
192
  </button>
193
  </div>
194
- </div>
195
  </div>
196
  </main>
197
 
@@ -199,7 +193,7 @@ Try adjusting the scroll speed to see how it works!</textarea>
199
  <input type="file" id="file-input" accept=".txt,.doc,.docx" class="hidden">
200
  <custom-footer></custom-footer>
201
  <help-modal></help-modal>
202
- <script src="components/navbar.js"></script>
203
  <script src="components/footer.js"></script>
204
  <script src="components/help-modal.js"></script>
205
  <script src="script.js"></script>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>>_teleprompter</title>
7
+ <link rel="stylesheet" href="style.css">
8
  <script src="https://cdn.tailwindcss.com"></script>
9
  <script src="https://unpkg.com/feather-icons"></script>
10
  <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
 
42
  <i data-feather="x" class="w-4 h-4"></i>
43
  </button>
44
  </div>
45
+ <h1 class="text-3xl font-bold">>_teleprompter</h1>
46
+ <p class="text-gray-200 mt-2">Sistema Profesional de Teleprompter</p>
47
  </div>
48
+ <div class="p-6 grid grid-cols-1 lg:grid-cols-3 gap-6 relative">
49
  <div class="absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-primary-500 to-secondary-500"></div>
50
  <div class="lg:col-span-1 space-y-6">
51
  <div>
52
  <label class="block text-sm font-medium text-gray-300 mb-1 flex items-center justify-between">
53
+ <span>Título del Script</span>
54
  <span class="text-xs text-gray-400">Ctrl+T</span>
55
  </label>
56
  <div class="relative">
57
+ <input type="text" id="script-title" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-2 focus:ring-2 focus:ring-primary-500 focus:border-primary-500 outline-none transition pr-10" placeholder="Mi Presentación">
58
  <button class="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-white">
59
  <i data-feather="edit-2" class="w-4 h-4"></i>
60
  </button>
61
  </div>
62
  </div>
 
63
  <div>
64
  <label class="block text-sm font-medium text-gray-300 mb-1 flex items-center justify-between">
65
+ <span>Velocidad de Desplazamiento</span>
66
  <span class="text-xs text-gray-400" id="speed-value">1.0x</span>
67
  </label>
68
  <input type="range" id="speed-slider" min="0.1" max="5" step="0.1" value="1" class="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer accent-primary-500">
69
  <div class="flex justify-between text-xs text-gray-400 mt-1">
70
+ <span>Lento</span>
71
+ <span>Medio</span>
72
+ <span>Rápido</span>
73
  </div>
74
  </div>
 
75
  <div>
76
+ <label class="block text-sm font-medium text-gray-300 mb-1">Tamaño del Texto</label>
77
  <select id="text-size" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-2 focus:ring-2 focus:ring-primary-500 focus:border-primary-500 outline-none transition">
78
+ <option value="small">Pequeño</option>
79
+ <option value="medium" selected>Mediano</option>
80
+ <option value="large">Grande</option>
81
+ <option value="x-large">Extra Grande</option>
82
  </select>
83
  </div>
 
84
  <div>
85
+ <label class="block text-sm font-medium text-gray-300 mb-1">Tema</label>
86
  <div class="grid grid-cols-3 gap-2 theme-selector">
87
  <button class="bg-blue-500 h-10 rounded-lg theme-btn active" data-theme="blue"></button>
88
  <button class="bg-green-500 h-10 rounded-lg theme-btn" data-theme="green"></button>
 
92
  <button class="bg-pink-500 h-10 rounded-lg theme-btn" data-theme="pink"></button>
93
  </div>
94
  </div>
 
95
  <div>
96
+ <label class="block text-sm font-medium text-gray-300 mb-1">Alineación del Texto</label>
97
  <div class="grid grid-cols-3 gap-2">
98
  <button id="align-left" class="p-2 bg-gray-700 rounded-lg hover:bg-gray-600 flex items-center justify-center">
99
  <i data-feather="align-left" class="w-4 h-4"></i>
 
106
  </button>
107
  </div>
108
  </div>
 
109
  <div>
110
+ <label class="block text-sm font-medium text-gray-300 mb-1">Estilo de Fuente</label>
111
  <div class="grid grid-cols-2 gap-2">
112
  <button id="font-sans" class="p-2 bg-gray-700 rounded-lg hover:bg-gray-600 active">Sans Serif</button>
113
  <button id="font-serif" class="p-2 bg-gray-700 rounded-lg hover:bg-gray-600">Serif</button>
114
  </div>
115
  </div>
116
+ </div>
117
 
118
  <div class="lg:col-span-2 flex flex-col gap-4">
119
  <div class="bg-gray-700 rounded-lg p-4 flex-grow relative group">
120
  <div class="absolute top-2 right-2 flex gap-1 z-10">
121
+ <button id="format-bold" class="p-1 bg-gray-600 rounded hover:bg-gray-500" title="Negrita">
122
  <i data-feather="bold" class="w-4 h-4"></i>
123
  </button>
124
+ <button id="format-italic" class="p-1 bg-gray-600 rounded hover:bg-gray-500" title="Cursiva">
125
  <i data-feather="italic" class="w-4 h-4"></i>
126
  </button>
127
+ <button id="format-underline" class="p-1 bg-gray-600 rounded hover:bg-gray-500" title="Subrayado">
128
  <i data-feather="underline" class="w-4 h-4"></i>
129
  </button>
130
  </div>
131
+ <textarea id="script-textarea" class="w-full h-64 bg-transparent resize-none outline-none text-gray-200 placeholder-gray-500" placeholder="Ingrese su script aquí...">¡Bienvenido a >_teleprompter!
132
 
133
+ Esta es una solución profesional de teleprompter con características avanzadas:
134
 
135
+ Control de desplazamiento en tiempo real
136
+ Múltiples temas y personalización
137
+ Opciones de formato de texto
138
+ Atajos de teclado para eficiencia
139
+ Guardado y carga de scripts
140
 
141
+ ¡Intenta ajustar la velocidad de desplazamiento para ver cómo funciona!</textarea>
142
  <div class="absolute bottom-4 right-4 opacity-0 group-hover:opacity-100 transition flex gap-2">
143
+ <button id="import-script" class="p-2 bg-gray-600 rounded-lg hover:bg-gray-500" title="Importar Script">
144
  <i data-feather="upload" class="w-4 h-4"></i>
145
  </button>
146
+ <button id="clear-script" class="p-2 bg-gray-600 rounded-lg hover:bg-gray-500" title="Limpiar Todo">
147
  <i data-feather="trash-2" class="w-4 h-4"></i>
148
  </button>
149
  </div>
150
  </div>
 
151
  <div class="bg-gray-700 rounded-lg p-4">
152
  <div class="flex justify-between items-center mb-2">
153
+ <h3 class="font-medium">Vista Previa</h3>
154
  <div class="flex gap-2">
155
+ <button id="toggle-preview" class="px-3 py-1 bg-gray-600 hover:bg-gray-500 rounded text-sm">Alternar Vista</button>
156
+ <button id="mirror-preview" class="px-3 py-1 bg-gray-600 hover:bg-gray-500 rounded text-sm">Espejo</button>
157
  </div>
158
  </div>
159
  <div id="preview-container" class="bg-black rounded p-4 h-40 overflow-hidden relative">
160
  <div id="preview-text" class="text-white text-center text-lg leading-relaxed">
161
+ ¡Bienvenido a >_teleprompter! Esta es una solución profesional de teleprompter con características avanzadas.
162
  </div>
163
  </div>
164
  </div>
165
+ </div>
166
  </div>
167
 
168
  <div class="p-6 bg-gray-700 border-t border-gray-600 flex flex-wrap justify-between gap-4">
169
  <div class="flex gap-2">
170
  <button id="save-script" class="px-4 py-2 bg-gray-600 hover:bg-gray-500 rounded-lg font-medium transition flex items-center gap-2 text-sm">
171
+ <i data-feather="save" class="w-4 h-4"></i> Guardar
172
  </button>
173
  <button id="load-script" class="px-4 py-2 bg-gray-600 hover:bg-gray-500 rounded-lg font-medium transition flex items-center gap-2 text-sm">
174
+ <i data-feather="folder" class="w-4 h-4"></i> Cargar
175
  </button>
176
  <button id="export-script" class="px-4 py-2 bg-gray-600 hover:bg-gray-500 rounded-lg font-medium transition flex items-center gap-2 text-sm">
177
+ <i data-feather="download" class="w-4 h-4"></i> Exportar
178
  </button>
179
  </div>
180
  <div class="flex gap-2">
181
  <button id="help-btn" class="px-4 py-2 bg-gray-600 hover:bg-gray-500 rounded-lg font-medium transition flex items-center gap-2 text-sm">
182
+ <i data-feather="help-circle" class="w-4 h-4"></i> Ayuda
183
  </button>
184
  <button id="start-scroll" class="px-6 py-2 bg-primary-500 hover:bg-primary-600 rounded-lg font-medium transition flex items-center gap-2 text-sm glow">
185
+ <i data-feather="play" class="w-4 h-4"></i> Iniciar Desplazamiento
186
  </button>
187
  </div>
188
+ </div>
189
  </div>
190
  </main>
191
 
 
193
  <input type="file" id="file-input" accept=".txt,.doc,.docx" class="hidden">
194
  <custom-footer></custom-footer>
195
  <help-modal></help-modal>
196
+ <script src="components/navbar.js"></script>
197
  <script src="components/footer.js"></script>
198
  <script src="components/help-modal.js"></script>
199
  <script src="script.js"></script>
script.js CHANGED
@@ -1,5 +1,5 @@
1
 
2
- // Global variables
3
  let isScrolling = false;
4
  let scrollInterval;
5
  let currentSpeed = 1;
@@ -9,7 +9,7 @@ let currentAlignment = 'center';
9
  let currentFont = 'sans';
10
  let mirroredView = false;
11
 
12
- // DOM Elements
13
  const elements = {
14
  speedSlider: document.getElementById('speed-slider'),
15
  speedValue: document.getElementById('speed-value'),
@@ -20,46 +20,44 @@ const elements = {
20
  scriptTitle: document.getElementById('script-title'),
21
  fileInput: document.getElementById('file-input')
22
  };
23
-
24
- // Initialize all components
25
  function initializeComponents() {
26
  setupEventListeners();
27
  loadSettings();
28
  updatePreview();
29
  setupKeyboardShortcuts();
30
  }
31
-
32
- // Set up event listeners
33
  function setupEventListeners() {
34
- // Speed control
35
  elements.speedSlider.addEventListener('input', handleSpeedChange);
36
 
37
- // Text area changes
38
  elements.scriptTextarea.addEventListener('input', updatePreview);
39
 
40
- // Text size changes
41
  elements.textSizeSelect.addEventListener('change', handleTextSizeChange);
42
 
43
- // Theme selection
44
  document.querySelectorAll('.theme-btn').forEach(button => {
45
  button.addEventListener('click', () => handleThemeChange(button.dataset.theme));
46
  });
47
 
48
- // Text alignment
49
  document.getElementById('align-left').addEventListener('click', () => handleAlignmentChange('left'));
50
  document.getElementById('align-center').addEventListener('click', () => handleAlignmentChange('center'));
51
  document.getElementById('align-right').addEventListener('click', () => handleAlignmentChange('right'));
52
 
53
- // Font style
54
  document.getElementById('font-sans').addEventListener('click', () => handleFontChange('sans'));
55
  document.getElementById('font-serif').addEventListener('click', () => handleFontChange('serif'));
56
 
57
- // Formatting buttons
58
  document.getElementById('format-bold').addEventListener('click', () => toggleFormatting('bold'));
59
  document.getElementById('format-italic').addEventListener('click', () => toggleFormatting('italic'));
60
  document.getElementById('format-underline').addEventListener('click', () => toggleFormatting('underline'));
61
 
62
- // Control buttons
63
  document.getElementById('start-scroll').addEventListener('click', toggleScrolling);
64
  document.getElementById('save-script').addEventListener('click', saveScript);
65
  document.getElementById('load-script').addEventListener('click', loadScript);
@@ -69,14 +67,13 @@ function setupEventListeners() {
69
  document.getElementById('toggle-preview').addEventListener('click', togglePreviewMode);
70
  document.getElementById('mirror-preview').addEventListener('click', toggleMirrorView);
71
 
72
- // File input
73
  elements.fileInput.addEventListener('change', importScriptFromFile);
74
 
75
- // Window events
76
  window.addEventListener('beforeunload', saveSettings);
77
  }
78
-
79
- // Handle speed change
80
  function handleSpeedChange() {
81
  currentSpeed = parseFloat(elements.speedSlider.value);
82
  elements.speedValue.textContent = `${currentSpeed.toFixed(1)}x`;
@@ -86,24 +83,22 @@ function handleSpeedChange() {
86
  startScrolling();
87
  }
88
  }
89
-
90
- // Handle text size change
91
  function handleTextSizeChange() {
92
  currentTextSize = elements.textSizeSelect.value;
93
  updatePreview();
94
  }
95
-
96
- // Handle theme change
97
  function handleThemeChange(theme) {
98
  currentTheme = theme;
99
 
100
- // Update active button
101
  document.querySelectorAll('.theme-btn').forEach(btn => {
102
  btn.classList.remove('active');
103
  });
104
  document.querySelector(`.theme-btn[data-theme="${theme}"]`).classList.add('active');
105
 
106
- // Apply theme to preview
107
  const themeColors = {
108
  blue: 'from-blue-500 to-blue-700',
109
  green: 'from-green-500 to-green-700',
@@ -118,12 +113,11 @@ function handleThemeChange(theme) {
118
 
119
  updatePreview();
120
  }
121
-
122
- // Handle alignment change
123
  function handleAlignmentChange(alignment) {
124
  currentAlignment = alignment;
125
 
126
- // Update active button
127
  document.querySelectorAll('#align-left, #align-center, #align-right').forEach(btn => {
128
  btn.classList.remove('active');
129
  });
@@ -131,33 +125,30 @@ function handleAlignmentChange(alignment) {
131
 
132
  updatePreview();
133
  }
134
-
135
- // Handle font change
136
  function handleFontChange(font) {
137
  currentFont = font;
138
 
139
- // Update active button
140
  document.getElementById('font-sans').classList.toggle('active', font === 'sans');
141
  document.getElementById('font-serif').classList.toggle('active', font === 'serif');
142
 
143
  updatePreview();
144
  }
145
-
146
- // Toggle text formatting
147
  function toggleFormatting(format) {
148
  const button = document.getElementById(`format-${format}`);
149
  button.classList.toggle('active');
150
 
151
- // In a real implementation, this would apply formatting to selected text
152
- showToast(`Toggled ${format} formatting`);
153
  }
154
-
155
- // Update preview
156
  function updatePreview() {
157
- const text = elements.scriptTextarea.value || "Your script will appear here...";
158
  elements.previewText.textContent = text;
159
 
160
- // Apply text size
161
  const sizeClasses = {
162
  small: 'text-sm',
163
  medium: 'text-base',
@@ -167,67 +158,63 @@ function updatePreview() {
167
 
168
  elements.previewText.className = sizeClasses[currentTextSize] || 'text-base';
169
 
170
- // Apply alignment
171
  elements.previewText.classList.remove('text-left', 'text-center', 'text-right');
172
  elements.previewText.classList.add(`text-${currentAlignment}`);
173
 
174
- // Apply font
175
  elements.previewText.classList.toggle('font-serif', currentFont === 'serif');
176
 
177
- // Apply formatting classes
178
  elements.previewText.classList.toggle('bold', document.getElementById('format-bold').classList.contains('active'));
179
  elements.previewText.classList.toggle('italic', document.getElementById('format-italic').classList.contains('active'));
180
  elements.previewText.classList.toggle('underline', document.getElementById('format-underline').classList.contains('active'));
181
  }
182
-
183
- // Toggle scrolling
184
  function toggleScrolling() {
185
  const button = document.getElementById('start-scroll');
186
 
187
  if (isScrolling) {
188
  stopScrolling();
189
- button.innerHTML = '<i data-feather="play" class="w-4 h-4"></i> Start Scrolling';
190
  feather.replace();
191
  } else {
192
  startScrolling();
193
- button.innerHTML = '<i data-feather="pause" class="w-4 h-4"></i> Pause Scrolling';
194
  feather.replace();
195
  }
196
  }
197
-
198
- // Start scrolling animation
199
  function startScrolling() {
200
  isScrolling = true;
201
 
202
- // Clear any existing interval
203
  if (scrollInterval) {
204
  clearInterval(scrollInterval);
205
  }
206
 
207
- // Calculate duration based on speed (in seconds)
208
- const baseDuration = 30; // Base duration for 1x speed
209
- const duration = (baseDuration / currentSpeed) * 1000; // Convert to milliseconds
210
 
211
- // Reset animation
212
  elements.previewText.style.animation = 'none';
213
- void elements.previewText.offsetWidth; // Trigger reflow
214
 
215
- // Apply scrolling animation
216
  elements.previewText.style.animation = `scroll ${duration}ms linear infinite`;
217
 
218
- // Add scrolling class for styling
219
  elements.previewContainer.classList.add('scrolling');
220
  }
221
-
222
- // Stop scrolling animation
223
  function stopScrolling() {
224
  isScrolling = false;
225
  clearInterval(scrollInterval);
226
  elements.previewText.style.animation = 'none';
227
  elements.previewContainer.classList.remove('scrolling');
228
  }
229
-
230
- // Save script to localStorage
231
  function saveScript() {
232
  const scriptData = {
233
  title: elements.scriptTitle.value,
@@ -240,10 +227,9 @@ function saveScript() {
240
  };
241
 
242
  localStorage.setItem('teleprompterScript', JSON.stringify(scriptData));
243
- showToast('Script saved successfully!');
244
  }
245
-
246
- // Load script from localStorage
247
  function loadScript() {
248
  const savedData = localStorage.getItem('teleprompterScript');
249
 
@@ -264,13 +250,12 @@ function loadScript() {
264
  handleFontChange(scriptData.font || 'sans');
265
 
266
  updatePreview();
267
- showToast('Script loaded successfully!');
268
  } else {
269
- showToast('No saved script found.');
270
  }
271
  }
272
-
273
- // Export script as file
274
  function exportScript() {
275
  const content = elements.scriptTextarea.value;
276
  const title = elements.scriptTitle.value || 'teleprompter-script';
@@ -289,10 +274,9 @@ function exportScript() {
289
  URL.revokeObjectURL(url);
290
  }, 100);
291
 
292
- showToast('Script exported successfully!');
293
  }
294
-
295
- // Import script from file
296
  function importScriptFromFile(event) {
297
  const file = event.target.files[0];
298
  if (!file) return;
@@ -300,71 +284,67 @@ function importScriptFromFile(event) {
300
  const reader = new FileReader();
301
  reader.onload = function(e) {
302
  elements.scriptTextarea.value = e.target.result;
303
- elements.scriptTitle.value = file.name.replace(/\.[^/.]+$/, ""); // Remove extension
304
  updatePreview();
305
- showToast('Script imported successfully!');
306
  };
307
  reader.readAsText(file);
308
 
309
- // Reset file input
310
  elements.fileInput.value = '';
311
  }
312
-
313
- // Clear script
314
  function clearScript() {
315
- if (confirm('Are you sure you want to clear the current script?')) {
316
  elements.scriptTextarea.value = '';
317
  elements.scriptTitle.value = '';
318
  updatePreview();
319
- showToast('Script cleared.');
320
  }
321
  }
322
-
323
- // Toggle preview mode
324
  function togglePreviewMode() {
325
  elements.previewContainer.classList.toggle('bg-black');
326
  elements.previewContainer.classList.toggle('bg-gray-900');
327
- showToast('Preview mode toggled.');
328
  }
329
-
330
- // Toggle mirror view
331
  function toggleMirrorView() {
332
  mirroredView = !mirroredView;
333
  elements.previewContainer.classList.toggle('mirror', mirroredView);
334
- showToast(mirroredView ? 'Mirror view enabled.' : 'Mirror view disabled.');
335
  }
336
-
337
- // Setup keyboard shortcuts
338
  function setupKeyboardShortcuts() {
339
  document.addEventListener('keydown', function(e) {
340
- // Only trigger shortcuts when not in input fields
341
  if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
342
 
343
- // Spacebar to toggle scrolling
344
  if (e.code === 'Space') {
345
  e.preventDefault();
346
  toggleScrolling();
347
  }
348
 
349
- // Ctrl+S to save
350
  if (e.ctrlKey && e.code === 'KeyS') {
351
  e.preventDefault();
352
  saveScript();
353
  }
354
 
355
- // Ctrl+O to load
356
  if (e.ctrlKey && e.code === 'KeyO') {
357
  e.preventDefault();
358
  loadScript();
359
  }
360
 
361
- // Ctrl+E to export
362
  if (e.ctrlKey && e.code === 'KeyE') {
363
  e.preventDefault();
364
  exportScript();
365
  }
366
 
367
- // Up/Down arrows to adjust speed
368
  if (e.code === 'ArrowUp') {
369
  e.preventDefault();
370
  const newValue = Math.min(5, parseFloat(elements.speedSlider.value) + 0.1);
@@ -380,8 +360,7 @@ function setupKeyboardShortcuts() {
380
  }
381
  });
382
  }
383
-
384
- // Save settings to localStorage
385
  function saveSettings() {
386
  const settings = {
387
  speed: currentSpeed,
@@ -394,8 +373,7 @@ function saveSettings() {
394
 
395
  localStorage.setItem('teleprompterSettings', JSON.stringify(settings));
396
  }
397
-
398
- // Load settings from localStorage
399
  function loadSettings() {
400
  const savedSettings = localStorage.getItem('teleprompterSettings');
401
 
@@ -419,8 +397,7 @@ function loadSettings() {
419
  }
420
  }
421
  }
422
-
423
- // Show toast notification
424
  function showToast(message) {
425
  const toast = document.createElement('div');
426
  toast.className = 'toast show';
@@ -435,6 +412,5 @@ function showToast(message) {
435
  }, 300);
436
  }, 3000);
437
  }
438
-
439
  // Initialize when DOM is loaded
440
  document.addEventListener('DOMContentLoaded', initializeComponents);
 
1
 
2
+ // Variables globales
3
  let isScrolling = false;
4
  let scrollInterval;
5
  let currentSpeed = 1;
 
9
  let currentFont = 'sans';
10
  let mirroredView = false;
11
 
12
+ // Elementos DOM
13
  const elements = {
14
  speedSlider: document.getElementById('speed-slider'),
15
  speedValue: document.getElementById('speed-value'),
 
20
  scriptTitle: document.getElementById('script-title'),
21
  fileInput: document.getElementById('file-input')
22
  };
23
+ // Inicializar todos los componentes
 
24
  function initializeComponents() {
25
  setupEventListeners();
26
  loadSettings();
27
  updatePreview();
28
  setupKeyboardShortcuts();
29
  }
30
+ // Configurar escuchadores de eventos
 
31
  function setupEventListeners() {
32
+ // Control de velocidad
33
  elements.speedSlider.addEventListener('input', handleSpeedChange);
34
 
35
+ // Cambios en el área de texto
36
  elements.scriptTextarea.addEventListener('input', updatePreview);
37
 
38
+ // Cambios en tamaño de texto
39
  elements.textSizeSelect.addEventListener('change', handleTextSizeChange);
40
 
41
+ // Selección de tema
42
  document.querySelectorAll('.theme-btn').forEach(button => {
43
  button.addEventListener('click', () => handleThemeChange(button.dataset.theme));
44
  });
45
 
46
+ // Alineación de texto
47
  document.getElementById('align-left').addEventListener('click', () => handleAlignmentChange('left'));
48
  document.getElementById('align-center').addEventListener('click', () => handleAlignmentChange('center'));
49
  document.getElementById('align-right').addEventListener('click', () => handleAlignmentChange('right'));
50
 
51
+ // Estilo de fuente
52
  document.getElementById('font-sans').addEventListener('click', () => handleFontChange('sans'));
53
  document.getElementById('font-serif').addEventListener('click', () => handleFontChange('serif'));
54
 
55
+ // Botones de formato
56
  document.getElementById('format-bold').addEventListener('click', () => toggleFormatting('bold'));
57
  document.getElementById('format-italic').addEventListener('click', () => toggleFormatting('italic'));
58
  document.getElementById('format-underline').addEventListener('click', () => toggleFormatting('underline'));
59
 
60
+ // Botones de control
61
  document.getElementById('start-scroll').addEventListener('click', toggleScrolling);
62
  document.getElementById('save-script').addEventListener('click', saveScript);
63
  document.getElementById('load-script').addEventListener('click', loadScript);
 
67
  document.getElementById('toggle-preview').addEventListener('click', togglePreviewMode);
68
  document.getElementById('mirror-preview').addEventListener('click', toggleMirrorView);
69
 
70
+ // Entrada de archivo
71
  elements.fileInput.addEventListener('change', importScriptFromFile);
72
 
73
+ // Eventos de ventana
74
  window.addEventListener('beforeunload', saveSettings);
75
  }
76
+ // Manejar cambio de velocidad
 
77
  function handleSpeedChange() {
78
  currentSpeed = parseFloat(elements.speedSlider.value);
79
  elements.speedValue.textContent = `${currentSpeed.toFixed(1)}x`;
 
83
  startScrolling();
84
  }
85
  }
86
+ // Manejar cambio de tamaño de texto
 
87
  function handleTextSizeChange() {
88
  currentTextSize = elements.textSizeSelect.value;
89
  updatePreview();
90
  }
91
+ // Manejar cambio de tema
 
92
  function handleThemeChange(theme) {
93
  currentTheme = theme;
94
 
95
+ // Actualizar botón activo
96
  document.querySelectorAll('.theme-btn').forEach(btn => {
97
  btn.classList.remove('active');
98
  });
99
  document.querySelector(`.theme-btn[data-theme="${theme}"]`).classList.add('active');
100
 
101
+ // Aplicar tema a la vista previa
102
  const themeColors = {
103
  blue: 'from-blue-500 to-blue-700',
104
  green: 'from-green-500 to-green-700',
 
113
 
114
  updatePreview();
115
  }
116
+ // Manejar cambio de alineación
 
117
  function handleAlignmentChange(alignment) {
118
  currentAlignment = alignment;
119
 
120
+ // Actualizar botón activo
121
  document.querySelectorAll('#align-left, #align-center, #align-right').forEach(btn => {
122
  btn.classList.remove('active');
123
  });
 
125
 
126
  updatePreview();
127
  }
128
+ // Manejar cambio de fuente
 
129
  function handleFontChange(font) {
130
  currentFont = font;
131
 
132
+ // Actualizar botón activo
133
  document.getElementById('font-sans').classList.toggle('active', font === 'sans');
134
  document.getElementById('font-serif').classList.toggle('active', font === 'serif');
135
 
136
  updatePreview();
137
  }
138
+ // Alternar formato de texto
 
139
  function toggleFormatting(format) {
140
  const button = document.getElementById(`format-${format}`);
141
  button.classList.toggle('active');
142
 
143
+ // En una implementación real, esto aplicaría formato al texto seleccionado
144
+ showToast(`Alternado formato ${format}`);
145
  }
146
+ // Actualizar vista previa
 
147
  function updatePreview() {
148
+ const text = elements.scriptTextarea.value || "Su script aparecerá aquí...";
149
  elements.previewText.textContent = text;
150
 
151
+ // Aplicar tamaño de texto
152
  const sizeClasses = {
153
  small: 'text-sm',
154
  medium: 'text-base',
 
158
 
159
  elements.previewText.className = sizeClasses[currentTextSize] || 'text-base';
160
 
161
+ // Aplicar alineación
162
  elements.previewText.classList.remove('text-left', 'text-center', 'text-right');
163
  elements.previewText.classList.add(`text-${currentAlignment}`);
164
 
165
+ // Aplicar fuente
166
  elements.previewText.classList.toggle('font-serif', currentFont === 'serif');
167
 
168
+ // Aplicar clases de formato
169
  elements.previewText.classList.toggle('bold', document.getElementById('format-bold').classList.contains('active'));
170
  elements.previewText.classList.toggle('italic', document.getElementById('format-italic').classList.contains('active'));
171
  elements.previewText.classList.toggle('underline', document.getElementById('format-underline').classList.contains('active'));
172
  }
173
+ // Alternar desplazamiento
 
174
  function toggleScrolling() {
175
  const button = document.getElementById('start-scroll');
176
 
177
  if (isScrolling) {
178
  stopScrolling();
179
+ button.innerHTML = '<i data-feather="play" class="w-4 h-4"></i> Iniciar Desplazamiento';
180
  feather.replace();
181
  } else {
182
  startScrolling();
183
+ button.innerHTML = '<i data-feather="pause" class="w-4 h-4"></i> Pausar Desplazamiento';
184
  feather.replace();
185
  }
186
  }
187
+ // Iniciar animación de desplazamiento
 
188
  function startScrolling() {
189
  isScrolling = true;
190
 
191
+ // Limpiar cualquier intervalo existente
192
  if (scrollInterval) {
193
  clearInterval(scrollInterval);
194
  }
195
 
196
+ // Calcular duración basada en velocidad (en segundos)
197
+ const baseDuration = 30; // Duración base para velocidad 1x
198
+ const duration = (baseDuration / currentSpeed) * 1000; // Convertir a milisegundos
199
 
200
+ // Reiniciar animación
201
  elements.previewText.style.animation = 'none';
202
+ void elements.previewText.offsetWidth; // Activar reflow
203
 
204
+ // Aplicar animación de desplazamiento
205
  elements.previewText.style.animation = `scroll ${duration}ms linear infinite`;
206
 
207
+ // Agregar clase de desplazamiento para estilizar
208
  elements.previewContainer.classList.add('scrolling');
209
  }
210
+ // Detener animación de desplazamiento
 
211
  function stopScrolling() {
212
  isScrolling = false;
213
  clearInterval(scrollInterval);
214
  elements.previewText.style.animation = 'none';
215
  elements.previewContainer.classList.remove('scrolling');
216
  }
217
+ // Guardar script en localStorage
 
218
  function saveScript() {
219
  const scriptData = {
220
  title: elements.scriptTitle.value,
 
227
  };
228
 
229
  localStorage.setItem('teleprompterScript', JSON.stringify(scriptData));
230
+ showToast('¡Script guardado exitosamente!');
231
  }
232
+ // Cargar script desde localStorage
 
233
  function loadScript() {
234
  const savedData = localStorage.getItem('teleprompterScript');
235
 
 
250
  handleFontChange(scriptData.font || 'sans');
251
 
252
  updatePreview();
253
+ showToast('¡Script cargado exitosamente!');
254
  } else {
255
+ showToast('No se encontró script guardado.');
256
  }
257
  }
258
+ // Exportar script como archivo
 
259
  function exportScript() {
260
  const content = elements.scriptTextarea.value;
261
  const title = elements.scriptTitle.value || 'teleprompter-script';
 
274
  URL.revokeObjectURL(url);
275
  }, 100);
276
 
277
+ showToast('¡Script exportado exitosamente!');
278
  }
279
+ // Importar script desde archivo
 
280
  function importScriptFromFile(event) {
281
  const file = event.target.files[0];
282
  if (!file) return;
 
284
  const reader = new FileReader();
285
  reader.onload = function(e) {
286
  elements.scriptTextarea.value = e.target.result;
287
+ elements.scriptTitle.value = file.name.replace(/\.[^/.]+$/, ""); // Eliminar extensión
288
  updatePreview();
289
+ showToast('¡Script importado exitosamente!');
290
  };
291
  reader.readAsText(file);
292
 
293
+ // Reiniciar entrada de archivo
294
  elements.fileInput.value = '';
295
  }
296
+ // Limpiar script
 
297
  function clearScript() {
298
+ if (confirm('¿Está seguro de que desea limpiar el script actual?')) {
299
  elements.scriptTextarea.value = '';
300
  elements.scriptTitle.value = '';
301
  updatePreview();
302
+ showToast('Script limpiado.');
303
  }
304
  }
305
+ // Alternar modo de vista previa
 
306
  function togglePreviewMode() {
307
  elements.previewContainer.classList.toggle('bg-black');
308
  elements.previewContainer.classList.toggle('bg-gray-900');
309
+ showToast('Modo de vista previa alternado.');
310
  }
311
+ // Alternar vista espejo
 
312
  function toggleMirrorView() {
313
  mirroredView = !mirroredView;
314
  elements.previewContainer.classList.toggle('mirror', mirroredView);
315
+ showToast(mirroredView ? 'Vista espejo habilitada.' : 'Vista espejo deshabilitada.');
316
  }
317
+ // Configurar atajos de teclado
 
318
  function setupKeyboardShortcuts() {
319
  document.addEventListener('keydown', function(e) {
320
+ // Solo activar atajos cuando no esté en campos de entrada
321
  if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
322
 
323
+ // Barra espaciadora para alternar desplazamiento
324
  if (e.code === 'Space') {
325
  e.preventDefault();
326
  toggleScrolling();
327
  }
328
 
329
+ // Ctrl+S para guardar
330
  if (e.ctrlKey && e.code === 'KeyS') {
331
  e.preventDefault();
332
  saveScript();
333
  }
334
 
335
+ // Ctrl+O para cargar
336
  if (e.ctrlKey && e.code === 'KeyO') {
337
  e.preventDefault();
338
  loadScript();
339
  }
340
 
341
+ // Ctrl+E para exportar
342
  if (e.ctrlKey && e.code === 'KeyE') {
343
  e.preventDefault();
344
  exportScript();
345
  }
346
 
347
+ // Flechas Arriba/Abajo para ajustar velocidad
348
  if (e.code === 'ArrowUp') {
349
  e.preventDefault();
350
  const newValue = Math.min(5, parseFloat(elements.speedSlider.value) + 0.1);
 
360
  }
361
  });
362
  }
363
+ // Guardar configuraciones en localStorage
 
364
  function saveSettings() {
365
  const settings = {
366
  speed: currentSpeed,
 
373
 
374
  localStorage.setItem('teleprompterSettings', JSON.stringify(settings));
375
  }
376
+ // Cargar configuraciones desde localStorage
 
377
  function loadSettings() {
378
  const savedSettings = localStorage.getItem('teleprompterSettings');
379
 
 
397
  }
398
  }
399
  }
400
+ // Mostrar notificación toast
 
401
  function showToast(message) {
402
  const toast = document.createElement('div');
403
  toast.className = 'toast show';
 
412
  }, 300);
413
  }, 3000);
414
  }
 
415
  // Initialize when DOM is loaded
416
  document.addEventListener('DOMContentLoaded', initializeComponents);