:root {
–primary: #4a90e2;
–primary-dark: #3a7bd5;
–secondary: #f5b041;
–text: #333333;
–light-bg: #f9f9f9;
–border: #e0e0e0;
–success: #2ecc71;
–error: #e74c3c;
–white: #ffffff;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: ‘Segoe UI’, Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: var(–text);
background-color: var(–light-bg);
padding: 0;
margin: 0;
}
.container {
max-width: 100%;
margin: 0 auto;
padding: 20px;
}
.header {
background: linear-gradient(135deg, var(–primary), var(–primary-dark));
color: var(–white);
padding: 30px 0;
text-align: center;
border-radius: 10px 10px 0 0;
margin-bottom: 30px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.header h1 {
margin: 0;
font-size: 2.5rem;
letter-spacing: 1px;
}
.header p {
margin-top: 10px;
font-size: 1.1rem;
opacity: 0.9;
}
.card {
background-color: var(–white);
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
padding: 30px;
margin-bottom: 30px;
}
.form-section-title {
font-size: 1.2rem;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 2px solid var(–primary);
color: var(–primary-dark);
}
.form-group {
margin-bottom: 25px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: var(–text);
}
input, select, textarea {
width: 100%;
padding: 12px 15px;
border: 1px solid var(–border);
border-radius: 6px;
font-size: 1rem;
transition: all 0.3s ease;
}
input:focus, select:focus, textarea:focus {
outline: none;
border-color: var(–primary);
box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.2);
}
select {
appearance: none;
background-image: url(“data:image/svg+xml;charset=utf-8,%3Csvg xmlns=’http://www.w3.org/2000/svg’ width=’16’ height=’16’ viewBox=’0 0 24 24′ fill=’none’ stroke=’%23333′ stroke-width=’2′ stroke-linecap=’round’ stroke-linejoin=’round’%3E%3Cpath d=’M6 9l6 6 6-6’/%3E%3C/svg%3E”);
background-repeat: no-repeat;
background-position: right 15px center;
background-size: 16px;
padding-right: 40px;
}
#otro_horario_container {
display: none;
margin-top: 15px;
padding: 15px;
border-left: 3px solid var(–secondary);
background-color: rgba(245, 176, 65, 0.05);
}
.btn {
background: linear-gradient(to right, var(–primary), var(–primary-dark));
color: var(–white);
border: none;
padding: 14px 25px;
border-radius: 6px;
cursor: pointer;
font-size: 1rem;
font-weight: 600;
letter-spacing: 0.5px;
transition: all 0.3s ease;
display: inline-block;
text-align: center;
box-shadow: 0 4px 6px rgba(58, 123, 213, 0.3);
}
.btn:hover {
background: linear-gradient(to right, var(–primary-dark), var(–primary));
transform: translateY(-2px);
box-shadow: 0 6px 8px rgba(58, 123, 213, 0.4);
}
.btn:active {
transform: translateY(0);
box-shadow: 0 2px 4px rgba(58, 123, 213, 0.4);
}
.btn-payment {
background: linear-gradient(to right, var(–secondary), #e67e22);
box-shadow: 0 4px 6px rgba(230, 126, 34, 0.3);
margin-top: 10px;
}
.btn-payment:hover {
background: linear-gradient(to right, #e67e22, var(–secondary));
box-shadow: 0 6px 8px rgba(230, 126, 34, 0.4);
}
.btn-later {
background: linear-gradient(to right, #7f8c8d, #95a5a6);
box-shadow: 0 4px 6px rgba(127, 140, 141, 0.3);
margin-top: 10px;
margin-left: 10px;
}
.btn-later:hover {
background: linear-gradient(to right, #95a5a6, #7f8c8d);
box-shadow: 0 6px 8px rgba(127, 140, 141, 0.4);
}
.btn-container {
margin-top: 30px;
text-align: center;
}
.alert {
padding: 15px 20px;
border-radius: 6px;
margin-bottom: 25px;
font-weight: 500;
display: flex;
align-items: center;
}
.alert i {
margin-right: 15px;
font-size: 1.2rem;
}
.alert-success {
background-color: rgba(46, 204, 113, 0.15);
color: #27ae60;
border-left: 4px solid #27ae60;
}
.alert-danger {
background-color: rgba(231, 76, 60, 0.15);
color: #c0392b;
border-left: 4px solid #c0392b;
}
#loading {
display: none;
text-align: center;
margin: 30px 0;
}
.spinner {
display: inline-block;
width: 40px;
height: 40px;
border: 4px solid rgba(74, 144, 226, 0.2);
border-radius: 50%;
border-top-color: var(–primary);
animation: spin 1s linear infinite;
}
.input-icon-wrapper {
position: relative;
}
.input-icon {
position: absolute;
left: 10px;
top: 50%;
transform: translateY(-50%);
color: #aaa;
}
.input-with-icon {
padding-left: 40px;
}
.required-mark {
color: var(–error);
margin-left: 3px;
}
.payment-section {
margin-top: 30px;
background-color: rgba(245, 176, 65, 0.1);
padding: 20px;
border-radius: 8px;
text-align: center;
border: 1px dashed var(–secondary);
}
.payment-section h3 {
margin-bottom: 15px;
color: #e67e22;
}
.language-icon {
display: inline-block;
width: 30px;
height: 30px;
margin-right: 10px;
vertical-align: middle;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.footer {
margin-top: 40px;
text-align: center;
color: #777;
font-size: 0.9rem;
}
/* Estilos para la selección de opción de pago */
.payment-options {
margin-top: 20px;
text-align: left;
}
.payment-option {
margin-bottom: 15px;
padding: 15px;
border: 1px solid var(–border);
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
}
.payment-option:hover {
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
}
.payment-option.selected {
border-color: var(–primary);
background-color: rgba(74, 144, 226, 0.05);
box-shadow: 0 2px 10px rgba(74, 144, 226, 0.1);
}
.payment-option input[type=”radio”] {
width: auto;
margin-right: 10px;
}
.payment-option-label {
display: flex;
align-items: center;
font-weight: 600;
}
.payment-option-description {
margin-top: 10px;
font-size: 0.9rem;
color: #666;
padding-left: 25px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@media (max-width: 768px) {
.header h1 {
font-size: 2rem;
}
.btn {
width: 100%;
margin-bottom: 10px;
margin-left: 0 !important;
}
}
Datos Personales
Detalles del Curso
Seleccione una opción
Español 🇪🇸
Inglés 🇬🇧
Francés 🇫🇷
Seleccione una opción
Grupal
Personalizada
Dual (2 personas)
Autogestionada (libre)
Seleccione una opción
Nivel A1 (Principiante)
Nivel A2 (Elemental)
Nivel B1 (Intermedio)
Nivel B2 (Intermedio alto)
Nivel C1 (Avanzado)
Nivel C2 (Dominio)
Horario del Curso
Seleccione una opción
4 horas por día. (4×1) Domingo. De 9am-1pm CDMX (GMT -6)
2 horas por día. (2×2) Sábado y domingo. De 4-6pm CDMX (GMT -6)
2 horas por día. (2×2) Sábado y domingo. De 2-4pm CDMX (GMT -6)
2 horas por día. (2×2) Sábado y domingo. De 7-9am CDMX (GMT -6)
2 horas por día. (2×2) Viernes y Domingo. De 6-8pm CDMX (GMT -6)
2 horas por día. (2×2) Viernes y Domingo. De 9-11pm CDMX (GMT -6)
1 hora por día. (1×4) Lunes – Jueves. De 9-10pm CDMX (GMT -6)
1 hora por día. (1×4) Lunes – Jueves. De 10-11pm CDMX (GMT -6)
Otro horario (especificar)
Opción de Pago
Realiza tu pago
Para completar tu inscripción, realiza el pago correspondiente al curso seleccionado.
Procesando inscripción…
// URL del script de Google Apps Script (¡DEBES ACTUALIZAR ESTA URL CON LA DE TU SCRIPT DESPLEGADO!)
const SCRIPT_URL = ‘https://script.google.com/macros/s/AKfycbwJlMcOqgsyGEevP9deUteWu_gMRksNrRwzS3-i6UPVrAsYdKhLj8SKgRYG21yxcsmO/exec’;
// Función para manejar la selección de la opción de pago
function selectPaymentOption(element, optionId) {
// Remover clase selected de todos los elementos
const paymentOptions = document.querySelectorAll(‘.payment-option’);
paymentOptions.forEach(option => {
option.classList.remove(‘selected’);
});
// Agregar clase selected al elemento seleccionado
element.classList.add(‘selected’);
// Marcar el radio button correspondiente
document.getElementById(optionId).checked = true;
// Mostrar u ocultar la sección de pago según la opción seleccionada
const paymentSection = document.getElementById(‘payment-section’);
if (optionId === ‘pagar_ahora’) {
paymentSection.style.display = ‘block’;
} else {
paymentSection.style.display = ‘none’;
}
}
// Inicializar visibilidad de la sección de pago
document.addEventListener(‘DOMContentLoaded’, function() {
const pagarAhora = document.getElementById(‘pagar_ahora’);
const paymentSection = document.getElementById(‘payment-section’);
if (pagarAhora.checked) {
paymentSection.style.display = ‘block’;
} else {
paymentSection.style.display = ‘none’;
}
});
// Mostrar/ocultar el campo de otro horario según la selección
document.getElementById(‘horario’).addEventListener(‘change’, function() {
const otroHorarioContainer = document.getElementById(‘otro_horario_container’);
const otroHorarioField = document.getElementById(‘otro_horario’);
if (this.value === ‘otro’) {
otroHorarioContainer.style.display = ‘block’;
otroHorarioField.setAttribute(‘required’, ‘required’);
} else {
otroHorarioContainer.style.display = ‘none’;
otroHorarioField.removeAttribute(‘required’);
}
});
// Función para verificar si el mensaje indica éxito
function isSuccessMessage(message) {
const successIndicators = [
‘enviada correctamente’,
‘enviad correctamente’,
‘éxito’,
‘exitoso’,
‘gracias’,
‘recibida’,
‘procesada’,
‘completada’,
‘successful’,
‘success’
];
const lowerMessage = message.toLowerCase();
return successIndicators.some(indicator => lowerMessage.includes(indicator));
}
// Manejar el envío del formulario
document.getElementById(‘inscripcion-form’).addEventListener(‘submit’, async function(e) {
e.preventDefault();
// Mostrar indicador de carga
document.getElementById(‘loading’).style.display = ‘block’;
document.getElementById(‘response-container’).innerHTML = ”;
// Recopilar los datos del formulario
const formData = new FormData(this);
const formDataObject = {};
// Convertir FormData a objeto simple
for (const [key, value] of formData.entries()) {
formDataObject[key] = value;
}
try {
// Método 1: Enviar como JSON (preferido)
const response = await fetch(SCRIPT_URL, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’,
},
body: JSON.stringify(formDataObject),
mode: ‘cors’
});
// Verificar si la respuesta es exitosa
if (!response.ok) {
throw new Error(`Error HTTP: ${response.status}`);
}
// Intentar parsear como JSON primero
let result;
const responseText = await response.text();
try {
result = JSON.parse(responseText);
// Manejar respuesta JSON estructurada
if (result.success === true) {
showSuccessMessage(result.message);
} else if (result.success === false) {
showErrorMessage(result.message || ‘Ha ocurrido un error al procesar la inscripción.’);
} else {
// Si no tiene la propiedad success, verificar el mensaje
if (isSuccessMessage(result.message || ”)) {
showSuccessMessage(result.message);
} else {
showErrorMessage(result.message || ‘Ha ocurrido un error al procesar la inscripción.’);
}
}
} catch (parseError) {
// Si no se puede parsear como JSON, tratar como texto plano
if (isSuccessMessage(responseText)) {
showSuccessMessage(responseText);
} else {
showErrorMessage(responseText || ‘Ha ocurrido un error al procesar la inscripción.’);
}
}
} catch (error) {
console.error(‘Error al enviar el formulario:’, error);
// Si falla el método 1, intentar método alternativo con URLSearchParams
try {
console.log(“Intentando método alternativo…”);
// Convertir objeto a URLSearchParams
const params = new URLSearchParams();
for (const key in formDataObject) {
params.append(key, formDataObject[key]);
}
const backupResponse = await fetch(SCRIPT_URL, {
method: ‘POST’,
body: params,
mode: ‘cors’
});
if (backupResponse.ok) {
const backupResult = await backupResponse.text();
try {
// Intentar parsear como JSON
const jsonResult = JSON.parse(backupResult);
if (jsonResult.success === true) {
showSuccessMessage(jsonResult.message);
} else if (jsonResult.success === false) {
showErrorMessage(jsonResult.message || ‘Ha ocurrido un error al procesar la inscripción.’);
} else {
// Si no tiene la propiedad success, verificar el mensaje
if (isSuccessMessage(jsonResult.message || ”)) {
showSuccessMessage(jsonResult.message);
} else {
showErrorMessage(jsonResult.message || ‘Ha ocurrido un error al procesar la inscripción.’);
}
}
} catch (parseError) {
// Si no se puede parsear como JSON, verificar si es un mensaje de éxito en texto plano
if (isSuccessMessage(backupResult)) {
showSuccessMessage(backupResult);
} else {
showErrorMessage(‘Error de conexión: ‘ + error.message);
}
}
} else {
throw new Error(`Error en método alternativo: ${backupResponse.status}`);
}
} catch (backupError) {
console.error(‘Error en método alternativo:’, backupError);
showErrorMessage(‘Error de conexión: No se pudo conectar con el servidor. Por favor verifica tu conexión a internet y que la URL del script sea correcta.’);
}
} finally {
// Ocultar indicador de carga
document.getElementById(‘loading’).style.display = ‘none’;
}
});
// Función para mostrar mensaje de éxito
function showSuccessMessage(message) {
document.getElementById(‘response-container’).innerHTML = `
${message ? message : ‘Por favor, revisa tu correo electrónico para más información.’}
`;
document.getElementById(‘inscripcion-form’).reset();
// Ocultar campo de otro horario si estaba visible
document.getElementById(‘otro_horario_container’).style.display = ‘none’;
document.getElementById(‘otro_horario’).removeAttribute(‘required’);
// Hacer scroll a la página de pago solo si la opción “Pagar ahora” está seleccionada
if (document.getElementById(‘pagar_ahora’).checked) {
document.querySelector(‘.payment-section’).scrollIntoView({ behavior: ‘smooth’ });
}
}
// Función para mostrar mensaje de error
function showErrorMessage(message) {
document.getElementById(‘response-container’).innerHTML = `
Por favor verifica que la URL del script sea correcta y que el script esté correctamente desplegado como aplicación web.
`;
}
