generated from marquez.juan/Ejercicio-inicial--git-y-HTML
feat(UI): Enhance form functionality and add progress bar for improved user experience
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="progress-bar"></div>
|
||||
<header id="site-header">
|
||||
<nav id="main-nav">
|
||||
<a href="#" class="nav-logo">Brew<span>Box</span></a>
|
||||
@@ -135,6 +136,14 @@
|
||||
Completá el formulario y recibís tu primer envío en menos de 72hs.
|
||||
Estudiantes obtienen un descuento del 20%.
|
||||
</p>
|
||||
<div class="plan-preview" id="plan-preview">
|
||||
<div class="plan-preview-inner">
|
||||
<span class="plan-preview-label">Plan seleccionado</span>
|
||||
<span class="plan-preview-name" id="plan-preview-name">—</span>
|
||||
<span class="plan-preview-price" id="plan-preview-price"></span>
|
||||
<ul class="plan-preview-features" id="plan-preview-features"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form action="#" method="post">
|
||||
@@ -144,15 +153,24 @@
|
||||
<div class="field-group">
|
||||
<label for="name">Nombre</label>
|
||||
<input type="text" id="name" name="name" required />
|
||||
<span class="field-error-msg"
|
||||
>Ingresá al menos 2 caracteres</span
|
||||
>
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="lastname">Apellido</label>
|
||||
<input type="text" id="lastname" name="lastname" required />
|
||||
<span class="field-error-msg"
|
||||
>Ingresá al menos 2 caracteres</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="email">Correo electrónico</label>
|
||||
<input type="email" id="email" name="email" required />
|
||||
<span class="field-error-msg"
|
||||
>Ingresá un correo electrónico válido</span
|
||||
>
|
||||
</div>
|
||||
<div class="field-group checkbox-group">
|
||||
<input type="checkbox" id="student" name="student" />
|
||||
@@ -178,6 +196,7 @@
|
||||
<div class="field-group">
|
||||
<label for="reason">¿Por qué te suscribís?</label>
|
||||
<textarea id="reason" name="reason" rows="4"></textarea>
|
||||
<span class="char-counter" id="reason-counter">0 / 300</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
@@ -191,6 +210,16 @@
|
||||
<option value="debit">Tarjeta de débito</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field-group" id="cuotas-group" style="display: none">
|
||||
<label for="cuotas">Cantidad de cuotas</label>
|
||||
<input
|
||||
type="number"
|
||||
id="cuotas"
|
||||
name="cuotas"
|
||||
min="1"
|
||||
max="12"
|
||||
placeholder="1"
|
||||
/>
|
||||
<div class="field-group field-group--icon">
|
||||
<label for="card">Número de tarjeta</label>
|
||||
<div class="input-icon-wrapper">
|
||||
@@ -213,10 +242,12 @@
|
||||
type="text"
|
||||
id="card"
|
||||
name="card"
|
||||
placeholder="1234 5678 9012 3456"
|
||||
placeholder="XXXX-XXXX-XXXX-XXXX"
|
||||
required
|
||||
/>
|
||||
<span class="card-brand" id="card-brand"></span>
|
||||
</div>
|
||||
<span class="field-error-msg">Número de tarjeta inválido</span>
|
||||
</div>
|
||||
<div class="field-row">
|
||||
<div class="field-group">
|
||||
@@ -228,6 +259,7 @@
|
||||
placeholder="MM/AA"
|
||||
required
|
||||
/>
|
||||
<span class="field-error-msg">Formato MM/AA</span>
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<label for="cvv">CVV</label>
|
||||
@@ -238,6 +270,7 @@
|
||||
placeholder="123"
|
||||
required
|
||||
/>
|
||||
<span class="field-error-msg">Ingresá un CVV válido</span>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
@@ -314,6 +347,31 @@
|
||||
<button type="submit" class="cta-button">Suscribirme</button>
|
||||
</div>
|
||||
</form>
|
||||
<div id="form-confirmation">
|
||||
<div class="confirmation-icon">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<polyline points="20 6 9 17 4 12"></polyline>
|
||||
</svg>
|
||||
</div>
|
||||
<p class="confirmation-title">¡Bienvenido a BrewBox!</p>
|
||||
<p class="confirmation-text">
|
||||
Tu suscripción fue registrada. En las próximas horas vas a recibir
|
||||
un email de confirmación con los detalles de tu primer envío.
|
||||
</p>
|
||||
<p class="confirmation-detail">
|
||||
Primer envío estimado: <span id="confirm-date"></span>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
|
||||
308
src/script.js
308
src/script.js
@@ -0,0 +1,308 @@
|
||||
// Smooth scrolling for anchor links
|
||||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||
anchor.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
const target = document.querySelector(this.getAttribute('href'));
|
||||
if (target) {
|
||||
target.scrollIntoView({ behavior: 'smooth' });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Scroll progress bar
|
||||
const progressBar = document.getElementById('progress-bar');
|
||||
|
||||
window.addEventListener('scroll', () => {
|
||||
const scrollTop = window.scrollY;
|
||||
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
|
||||
const progress = (scrollTop / docHeight) * 100;
|
||||
progressBar.style.width = progress + '%';
|
||||
});
|
||||
|
||||
// Student discount logic
|
||||
const studentCheckbox = document.getElementById('student');
|
||||
|
||||
const plans = {
|
||||
normal: { full: 10, label: 'Normal' },
|
||||
premium: { full: 15, label: 'Premium' }
|
||||
};
|
||||
|
||||
function updatePrices() {
|
||||
const isStudent = studentCheckbox.checked;
|
||||
|
||||
document.querySelectorAll('.radio-group label').forEach(lbl => {
|
||||
const input = lbl.querySelector('input[type="radio"]');
|
||||
if (!input) return;
|
||||
|
||||
const plan = plans[input.value];
|
||||
if (!plan) return;
|
||||
|
||||
const discounted = (plan.full * 0.7).toFixed(2);
|
||||
|
||||
if (isStudent) {
|
||||
lbl.innerHTML = `
|
||||
<input type="radio" name="plan" value="${input.value}" ${input.checked ? 'checked' : ''} ${input.required ? 'required' : ''}>
|
||||
${plan.label} —
|
||||
<span class="price-original">$${plan.full}/mes</span>
|
||||
<span class="price-discount">20% OFF</span>
|
||||
<span class="price-new">$${discounted}/mes</span>
|
||||
`;
|
||||
} else {
|
||||
lbl.innerHTML = `
|
||||
<input type="radio" name="plan" value="${input.value}" ${input.checked ? 'checked' : ''} ${input.required ? 'required' : ''}>
|
||||
${plan.label} — $${plan.full}/mes
|
||||
`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
studentCheckbox.addEventListener('change', updatePrices);
|
||||
|
||||
// Character counter for textarea
|
||||
const textarea = document.getElementById('reason');
|
||||
const counter = document.getElementById('reason-counter');
|
||||
const MAX_CHARS = 300;
|
||||
|
||||
textarea.addEventListener('input', () => {
|
||||
const len = textarea.value.length;
|
||||
counter.textContent = `${len} / ${MAX_CHARS}`;
|
||||
|
||||
counter.classList.remove('near-limit', 'at-limit');
|
||||
|
||||
if (len >= MAX_CHARS) {
|
||||
textarea.value = textarea.value.slice(0, MAX_CHARS);
|
||||
counter.classList.add('at-limit');
|
||||
} else if (len >= MAX_CHARS * 0.8) {
|
||||
counter.classList.add('near-limit');
|
||||
}
|
||||
});
|
||||
|
||||
// Form validation
|
||||
function setFieldState(input, isValid) {
|
||||
const group = input.closest('.field-group');
|
||||
if (!group) return;
|
||||
group.classList.remove('error', 'success');
|
||||
if (input.value.trim() === '') return;
|
||||
group.classList.add(isValid ? 'success' : 'error');
|
||||
}
|
||||
|
||||
// Name and Lastname
|
||||
['name', 'lastname'].forEach(id => {
|
||||
document.getElementById(id).addEventListener('input', function() {
|
||||
setFieldState(this, this.value.trim().length >= 2);
|
||||
});
|
||||
});
|
||||
|
||||
// Email
|
||||
document.getElementById('email').addEventListener('input', function() {
|
||||
const valid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(this.value);
|
||||
setFieldState(this, valid);
|
||||
});
|
||||
|
||||
// MMAA validation
|
||||
document.getElementById('expiry').addEventListener('input', function() {
|
||||
this.value = this.value.replace(/[^\d]/g, '').slice(0, 4);
|
||||
if (this.value.length > 2) {
|
||||
this.value = this.value.slice(0, 2) + '/' + this.value.slice(2);
|
||||
}
|
||||
const valid = /^(0[1-9]|1[0-2])\/\d{2}$/.test(this.value);
|
||||
setFieldState(this, valid);
|
||||
});
|
||||
|
||||
// CVV
|
||||
document.getElementById('cvv').addEventListener('input', function() {
|
||||
this.value = this.value.replace(/\D/g, '').slice(0, 4);
|
||||
setFieldState(this, this.value.length >= 3);
|
||||
});
|
||||
|
||||
|
||||
// Plan preview logic
|
||||
const planData = {
|
||||
normal: {
|
||||
name: 'Normal',
|
||||
price: '$10/mes',
|
||||
priceStudent: '$7.00/mes',
|
||||
features: [
|
||||
'250 g por envío',
|
||||
'1 café de origen único por mes',
|
||||
'Envío gratuito',
|
||||
'Guía de preparación'
|
||||
]
|
||||
},
|
||||
premium: {
|
||||
name: 'Premium',
|
||||
price: '$15/mes',
|
||||
priceStudent: '$10.50/mes',
|
||||
features: [
|
||||
'500 g por envío',
|
||||
'2 cafés de origen único por mes',
|
||||
'Envío gratuito',
|
||||
'Guía de preparación',
|
||||
'Acceso a lotes exclusivos'
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const planPreview = document.getElementById('plan-preview');
|
||||
const planPreviewName = document.getElementById('plan-preview-name');
|
||||
const planPreviewPrice = document.getElementById('plan-preview-price');
|
||||
const planPreviewFeatures = document.getElementById('plan-preview-features');
|
||||
|
||||
function updatePlanPreview() {
|
||||
const selected = document.querySelector('input[name="plan"]:checked');
|
||||
if (!selected) {
|
||||
planPreview.classList.remove('visible');
|
||||
return;
|
||||
}
|
||||
|
||||
const plan = planData[selected.value];
|
||||
const isStudent = document.getElementById('student').checked;
|
||||
|
||||
planPreviewName.textContent = plan.name;
|
||||
planPreviewPrice.textContent = isStudent ? plan.priceStudent : plan.price;
|
||||
|
||||
planPreviewFeatures.innerHTML = plan.features
|
||||
.map(f => `<li>${f}</li>`)
|
||||
.join('');
|
||||
|
||||
planPreview.classList.add('visible');
|
||||
}
|
||||
|
||||
document.querySelectorAll('input[name="plan"]').forEach(radio => {
|
||||
radio.addEventListener('change', updatePlanPreview);
|
||||
});
|
||||
|
||||
// Update prices and preview when student checkbox changes
|
||||
studentCheckbox.addEventListener('change', () => {
|
||||
updatePrices();
|
||||
updatePlanPreview();
|
||||
});
|
||||
|
||||
// Credit card validation and brand detection
|
||||
const cardInput = document.getElementById('card');
|
||||
const cardBrand = document.getElementById('card-brand');
|
||||
|
||||
const cardPatterns = {
|
||||
Visa: /^4/,
|
||||
Mastercard: /^5[1-5]|^2[2-7]/,
|
||||
Amex: /^3[47]/,
|
||||
Naranja: /^589562/,
|
||||
Cabal: /^604201|^589657/,
|
||||
};
|
||||
|
||||
function detectCardBrand(number) {
|
||||
const clean = number.replace(/\s/g, '');
|
||||
for (const [brand, pattern] of Object.entries(cardPatterns)) {
|
||||
if (pattern.test(clean)) return brand;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function validateCard(number) {
|
||||
const clean = number.replace(/\s/g, '');
|
||||
if (clean.length < 13) return false;
|
||||
|
||||
// Luhn algorithm
|
||||
let sum = 0;
|
||||
let alternate = false;
|
||||
for (let i = clean.length - 1; i >= 0; i--) {
|
||||
let n = parseInt(clean[i]);
|
||||
if (alternate) {
|
||||
n *= 2;
|
||||
if (n > 9) n -= 9;
|
||||
}
|
||||
sum += n;
|
||||
alternate = !alternate;
|
||||
}
|
||||
return sum % 10 === 0;
|
||||
}
|
||||
|
||||
cardInput.addEventListener('input', function() {
|
||||
// Remove non-digits and limit to 16 characters
|
||||
let val = this.value.replace(/\D/g, '').slice(0, 16);
|
||||
this.value = val.replace(/(.{4})/g, '$1 ').trim();
|
||||
|
||||
const brand = detectCardBrand(this.value);
|
||||
const valid = validateCard(this.value);
|
||||
|
||||
if (brand) {
|
||||
cardBrand.textContent = brand;
|
||||
cardBrand.classList.add('visible');
|
||||
} else {
|
||||
cardBrand.classList.remove('visible');
|
||||
}
|
||||
|
||||
setFieldState(this, valid);
|
||||
});
|
||||
|
||||
// Payment cuotas logic
|
||||
const paymentSelect = document.getElementById('payment');
|
||||
const cuotasGroup = document.getElementById('cuotas-group');
|
||||
const cuotasInput = document.getElementById('cuotas');
|
||||
|
||||
paymentSelect.addEventListener('change', function() {
|
||||
if (this.value === 'credit') {
|
||||
cuotasGroup.style.display = 'flex';
|
||||
cuotasInput.setAttribute('required', '');
|
||||
} else {
|
||||
cuotasGroup.style.display = 'none';
|
||||
cuotasInput.removeAttribute('required');
|
||||
cuotasInput.value = '';
|
||||
}
|
||||
});
|
||||
|
||||
// Cuotas validation
|
||||
cuotasInput.addEventListener('input', function() {
|
||||
const val = parseInt(this.value);
|
||||
setFieldState(this, val >= 1 && val <= 12);
|
||||
});
|
||||
|
||||
// Form submission logic
|
||||
const form = document.querySelector('form');
|
||||
const submitBtn = document.querySelector('.cta-button[type="submit"]');
|
||||
const confirmation = document.getElementById('form-confirmation');
|
||||
const confirmDate = document.getElementById('confirm-date');
|
||||
const subsCounter = document.querySelector('.hero-stats .stat-item:last-child .stat-number');
|
||||
|
||||
form.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// loading state
|
||||
submitBtn.classList.add('loading');
|
||||
submitBtn.innerHTML = '<span class="spinner"></span> Procesando...';
|
||||
|
||||
setTimeout(() => {
|
||||
// Hidden form
|
||||
form.style.transition = 'opacity 0.3s ease';
|
||||
form.style.opacity = '0';
|
||||
|
||||
setTimeout(() => {
|
||||
form.style.display = 'none';
|
||||
|
||||
// Calculate delivery date (7 days from now)
|
||||
const delivery = new Date();
|
||||
delivery.setDate(delivery.getDate() + 7);
|
||||
confirmDate.textContent = delivery.toLocaleDateString('es-AR', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric'
|
||||
});
|
||||
|
||||
// Show confirmation
|
||||
confirmation.style.display = 'flex';
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
confirmation.classList.add('visible');
|
||||
});
|
||||
});
|
||||
|
||||
// +1 to subscriber counter
|
||||
if (subsCounter) {
|
||||
const current = parseInt(subsCounter.textContent);
|
||||
subsCounter.textContent = current + 1;
|
||||
}
|
||||
|
||||
}, 300);
|
||||
|
||||
}, 2000); // simulate processing delay
|
||||
});
|
||||
255
src/styles.css
255
src/styles.css
@@ -23,6 +23,16 @@ a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
input[type="number"]::-webkit-outer-spin-button,
|
||||
input[type="number"]::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
/* Navbar */
|
||||
#site-header {
|
||||
position: sticky;
|
||||
@@ -537,6 +547,7 @@ label {
|
||||
|
||||
input[type="text"],
|
||||
input[type="email"],
|
||||
input[type="number"],
|
||||
textarea,
|
||||
select {
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
@@ -595,6 +606,7 @@ textarea {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
flex-wrap: wrap;
|
||||
font-size: 0.88rem;
|
||||
letter-spacing: 0.03em;
|
||||
text-transform: none;
|
||||
@@ -735,6 +747,238 @@ textarea {
|
||||
}
|
||||
}
|
||||
|
||||
.price-original {
|
||||
text-decoration: line-through;
|
||||
color: rgba(245, 240, 232, 0.25);
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.price-discount {
|
||||
color: #c8a96e;
|
||||
font-size: 0.72rem;
|
||||
letter-spacing: 0.1em;
|
||||
border: 1px solid rgba(200, 169, 110, 0.3);
|
||||
padding: 0.1rem 0.4rem;
|
||||
border-radius: 2px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.price-new {
|
||||
color: #f5f0e8;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.char-counter {
|
||||
font-size: 0.68rem;
|
||||
letter-spacing: 0.08em;
|
||||
color: rgba(245, 240, 232, 0.2);
|
||||
text-align: right;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.char-counter.near-limit {
|
||||
color: #c8a96e;
|
||||
}
|
||||
|
||||
.char-counter.at-limit {
|
||||
color: rgba(220, 80, 80, 0.7);
|
||||
}
|
||||
|
||||
.field-group.error input,
|
||||
.field-group.error textarea,
|
||||
.field-group.error select {
|
||||
border-bottom-color: rgba(220, 80, 80, 0.6);
|
||||
background: rgba(220, 80, 80, 0.04);
|
||||
}
|
||||
|
||||
.field-group.success input,
|
||||
.field-group.success textarea,
|
||||
.field-group.success select {
|
||||
border-bottom-color: rgba(100, 200, 130, 0.5);
|
||||
background: rgba(100, 200, 130, 0.03);
|
||||
}
|
||||
|
||||
.field-error-msg {
|
||||
font-size: 0.68rem;
|
||||
letter-spacing: 0.05em;
|
||||
color: rgba(220, 80, 80, 0.7);
|
||||
margin-top: 0.25rem;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.field-group.error .field-error-msg {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.plan-preview {
|
||||
margin-top: 2rem;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.06);
|
||||
padding-top: 1.5rem;
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
transition: opacity 0.3s ease, transform 0.3s ease;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.plan-preview.visible {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.plan-preview-label {
|
||||
display: block;
|
||||
font-size: 0.65rem;
|
||||
letter-spacing: 0.2em;
|
||||
text-transform: uppercase;
|
||||
color: rgba(245, 240, 232, 0.25);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.plan-preview-name {
|
||||
display: block;
|
||||
font-size: 1.3rem;
|
||||
font-weight: normal;
|
||||
color: #f5f0e8;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.plan-preview-price {
|
||||
display: block;
|
||||
font-size: 0.85rem;
|
||||
color: #c8a96e;
|
||||
margin-bottom: 1.25rem;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.plan-preview-features {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.6rem;
|
||||
}
|
||||
|
||||
.plan-preview-features li {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 0.75rem;
|
||||
font-size: 0.8rem;
|
||||
color: rgba(245, 240, 232, 0.45);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.plan-preview-features li::before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 12px;
|
||||
min-width: 12px;
|
||||
height: 1px;
|
||||
background: #c8a96e;
|
||||
margin-top: 0.65em;
|
||||
}
|
||||
|
||||
.card-brand {
|
||||
position: absolute;
|
||||
right: 0.75rem;
|
||||
font-size: 0.65rem;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
color: #c8a96e;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.card-brand.visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Loading State */
|
||||
.spinner {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: 2px solid rgba(10, 10, 10, 0.3);
|
||||
border-top-color: #0a0a0a;
|
||||
border-radius: 50%;
|
||||
animation: spin 0.7s linear infinite;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.cta-button.loading {
|
||||
opacity: 0.8;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
/* Confirmación */
|
||||
#form-confirmation {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
padding: 3rem 0;
|
||||
opacity: 0;
|
||||
transform: translateY(12px);
|
||||
transition: opacity 0.4s ease, transform 0.4s ease;
|
||||
}
|
||||
|
||||
#form-confirmation.visible {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.confirmation-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border: 1px solid rgba(200, 169, 110, 0.3);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.confirmation-icon svg {
|
||||
color: #c8a96e;
|
||||
}
|
||||
|
||||
.confirmation-title {
|
||||
font-size: 1.8rem;
|
||||
font-weight: normal;
|
||||
color: #f5f0e8;
|
||||
letter-spacing: -0.01em;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.confirmation-text {
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.8;
|
||||
color: rgba(245, 240, 232, 0.4);
|
||||
max-width: 38ch;
|
||||
}
|
||||
|
||||
.confirmation-detail {
|
||||
font-size: 0.72rem;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
color: rgba(245, 240, 232, 0.2);
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.06);
|
||||
padding-top: 1.5rem;
|
||||
}
|
||||
|
||||
.confirmation-detail span {
|
||||
color: #c8a96e;
|
||||
}
|
||||
|
||||
|
||||
/* Footer */
|
||||
|
||||
#site-footer {
|
||||
@@ -802,3 +1046,14 @@ textarea {
|
||||
gap: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
#progress-bar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 0%;
|
||||
height: 2px;
|
||||
background: #c8a96e;
|
||||
z-index: 9999;
|
||||
transition: width 0.1s linear;
|
||||
}
|
||||
Reference in New Issue
Block a user