Skip to content

Instantly share code, notes, and snippets.

@adrielcruz9966-a11y
Created November 26, 2025 00:48
Show Gist options
  • Select an option

  • Save adrielcruz9966-a11y/3bf88da5153b78923bf8fb25c2ffd2ed to your computer and use it in GitHub Desktop.

Select an option

Save adrielcruz9966-a11y/3bf88da5153b78923bf8fb25c2ffd2ed to your computer and use it in GitHub Desktop.
Untitled
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Wealth Tracker | R$ 1.000.000</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;600&family=Inter:wght@300;400;500&display=swap" rel="stylesheet">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', sans-serif;
background: linear-gradient(135deg, #0c0c0c 0%, #1a1a1a 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
color: #e0e0e0;
}
.luxury-card {
background: rgba(18, 18, 18, 0.95);
border-radius: 16px;
padding: 50px 40px;
width: 100%;
max-width: 500px;
text-align: center;
border: 1px solid rgba(255, 215, 0, 0.1);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.5);
position: relative;
overflow: hidden;
}
.luxury-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(90deg, transparent, #ffd700, transparent);
}
.header {
margin-bottom: 40px;
}
h1 {
font-family: 'Playfair Display', serif;
font-size: 2.2rem;
font-weight: 600;
color: #ffd700;
margin-bottom: 8px;
letter-spacing: 0.5px;
}
.subtitle {
color: #b0b0b0;
font-size: 1rem;
font-weight: 300;
letter-spacing: 1px;
}
.target-display {
position: relative;
margin: 50px 0;
height: 120px;
display: flex;
justify-content: center;
align-items: center;
}
.target-number {
font-size: 4rem;
font-weight: 300;
color: rgba(255, 255, 255, 0.03);
position: absolute;
letter-spacing: 4px;
font-family: 'Playfair Display', serif;
}
.current-value {
font-size: 3.2rem;
font-weight: 300;
color: #ffffff;
position: relative;
transition: all 8s cubic-bezier(0.16, 1, 0.3, 1);
letter-spacing: 2px;
font-family: 'Playfair Display', serif;
}
.currency {
font-size: 1.8rem;
color: #ffd700;
margin-right: 8px;
font-weight: 300;
}
.input-section {
margin: 40px 0 30px;
}
.input-container {
position: relative;
margin-bottom: 25px;
}
.input-icon {
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
color: #ffd700;
font-size: 1.1rem;
}
input {
width: 100%;
padding: 16px 16px 16px 50px;
font-size: 1.1rem;
background: rgba(30, 30, 30, 0.8);
border: 1px solid rgba(255, 215, 0, 0.2);
border-radius: 8px;
color: #ffffff;
transition: all 0.3s;
font-weight: 300;
}
input:focus {
outline: none;
border-color: #ffd700;
box-shadow: 0 0 0 1px rgba(255, 215, 0, 0.2);
}
input::placeholder {
color: #666;
}
.luxury-button {
background: transparent;
color: #ffd700;
border: 1px solid rgba(255, 215, 0, 0.3);
padding: 16px 30px;
font-size: 1rem;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s;
width: 100%;
font-weight: 400;
letter-spacing: 1px;
position: relative;
overflow: hidden;
}
.luxury-button:hover {
background: rgba(255, 215, 0, 0.05);
border-color: rgba(255, 215, 0, 0.5);
transform: translateY(-2px);
}
.luxury-button:active {
transform: translateY(0);
}
.progress-section {
margin: 40px 0;
}
.progress-header {
display: flex;
justify-content: space-between;
margin-bottom: 12px;
font-size: 0.9rem;
color: #b0b0b0;
}
.progress-percent {
color: #ffd700;
}
.progress-bar-container {
height: 2px;
background: rgba(255, 255, 255, 0.1);
border-radius: 1px;
overflow: hidden;
margin-bottom: 15px;
}
.progress-bar {
height: 100%;
background: #ffd700;
width: 0%;
transition: width 8s cubic-bezier(0.16, 1, 0.3, 1);
position: relative;
}
.progress-bar::after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
width: 20px;
background: linear-gradient(90deg, transparent, rgba(255, 215, 0, 0.7));
}
.milestones {
display: flex;
justify-content: space-between;
margin-top: 30px;
position: relative;
}
.milestone {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
flex: 1;
}
.milestone::before {
content: '';
position: absolute;
top: 10px;
left: 50%;
transform: translateX(-50%);
width: 8px;
height: 8px;
border-radius: 50%;
background: rgba(255, 215, 0, 0.3);
z-index: 2;
}
.milestone.active::before {
background: #ffd700;
box-shadow: 0 0 10px rgba(255, 215, 0, 0.5);
}
.milestone-line {
position: absolute;
top: 14px;
left: 0;
right: 0;
height: 1px;
background: rgba(255, 255, 255, 0.1);
z-index: 1;
}
.milestone-label {
margin-top: 20px;
font-size: 0.8rem;
color: #888;
}
.milestone.active .milestone-label {
color: #ffd700;
}
.stats {
display: flex;
justify-content: space-between;
margin-top: 40px;
padding-top: 30px;
border-top: 1px solid rgba(255, 255, 255, 0.05);
}
.stat {
text-align: center;
flex: 1;
}
.stat-value {
font-size: 1.4rem;
color: #ffd700;
margin-bottom: 5px;
font-weight: 300;
}
.stat-label {
font-size: 0.75rem;
color: #888;
letter-spacing: 0.5px;
}
.footer {
margin-top: 30px;
font-size: 0.75rem;
color: #666;
letter-spacing: 0.5px;
}
@media (max-width: 600px) {
.luxury-card {
padding: 40px 25px;
}
h1 {
font-size: 1.8rem;
}
.target-number {
font-size: 3rem;
}
.current-value {
font-size: 2.5rem;
}
}
</style>
</head>
<body>
<div class="luxury-card">
<div class="header">
<h1>Wealth Progress</h1>
<p class="subtitle">TRACKING TOWARDS FINANCIAL FREEDOM</p>
</div>
<div class="target-display">
<div class="target-number">1.000.000</div>
<div class="current-value">
<span class="currency">R$</span>
<span id="currentNumber">0</span>
</div>
</div>
<div class="input-section">
<div class="input-container">
<div class="input-icon">
<i class="fas fa-pen"></i>
</div>
<input type="number" id="currentValue" placeholder="Enter current balance" min="0" max="1000000">
</div>
<button class="luxury-button" id="animateButton">
UPDATE PROGRESS
</button>
</div>
<div class="progress-section">
<div class="progress-header">
<span>Progress</span>
<span class="progress-percent" id="progressPercent">0%</span>
</div>
<div class="progress-bar-container">
<div class="progress-bar" id="progressBar"></div>
</div>
<div class="milestones">
<div class="milestone-line"></div>
<div class="milestone" id="milestone1">
<div class="milestone-label">250K</div>
</div>
<div class="milestone" id="milestone2">
<div class="milestone-label">500K</div>
</div>
<div class="milestone" id="milestone3">
<div class="milestone-label">750K</div>
</div>
<div class="milestone" id="milestone4">
<div class="milestone-label">1M</div>
</div>
</div>
</div>
<div class="stats">
<div class="stat">
<div class="stat-value" id="remainingValue">R$ 1.000.000</div>
<div class="stat-label">REMAINING</div>
</div>
<div class="stat">
<div class="stat-value" id="percentageValue">0%</div>
<div class="stat-label">ACHIEVED</div>
</div>
</div>
<div class="footer">
<p>Wealth Tracker • Designed for Excellence</p>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const currentNumber = document.getElementById('currentNumber');
const currentValue = document.getElementById('currentValue');
const animateButton = document.getElementById('animateButton');
const progressBar = document.getElementById('progressBar');
const progressPercent = document.getElementById('progressPercent');
const remainingValue = document.getElementById('remainingValue');
const percentageValue = document.getElementById('percentageValue');
const milestones = [
document.getElementById('milestone1'),
document.getElementById('milestone2'),
document.getElementById('milestone3'),
document.getElementById('milestone4')
];
// Formatar número com separadores de milhar
function formatNumber(num) {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}
// Atualizar milestones
function updateMilestones(value) {
const milestoneValues = [250000, 500000, 750000, 1000000];
milestones.forEach((milestone, index) => {
if (value >= milestoneValues[index]) {
milestone.classList.add('active');
} else {
milestone.classList.remove('active');
}
});
}
// Atualizar estatísticas
function updateStats(value) {
const percent = (value / 1000000) * 100;
const remaining = 1000000 - value;
progressPercent.textContent = percent.toFixed(1) + '%';
remainingValue.textContent = 'R$ ' + formatNumber(remaining);
percentageValue.textContent = percent.toFixed(1) + '%';
updateMilestones(value);
}
// Animação do contador
function animateCounter(targetValue) {
// Limpar qualquer animação anterior
currentNumber.style.transition = 'none';
currentNumber.style.transform = 'translateY(0)';
// Definir valores iniciais
const startValue = 0;
const endValue = targetValue;
const duration = 8000; // 8 segundos
const startTime = performance.now();
// Atualizar a barra de progresso
const progressPercentValue = (targetValue / 1000000) * 100;
progressBar.style.width = '0%';
// Função de animação
function updateCounter(currentTime) {
const elapsedTime = currentTime - startTime;
const progress = Math.min(elapsedTime / duration, 1);
// Calcular valor atual com easing
const easeProgress = 1 - Math.pow(1 - progress, 3);
const currentValue = Math.floor(startValue + (endValue - startValue) * easeProgress);
// Atualizar display
currentNumber.textContent = formatNumber(currentValue);
// Atualizar barra de progresso
progressBar.style.width = `${progressPercentValue * progress}%`;
// Atualizar estatísticas
updateStats(currentValue);
// Aplicar efeito de subida
currentNumber.style.transform = `translateY(${-10 * progress}px)`;
// Continuar animação se não terminou
if (progress < 1) {
requestAnimationFrame(updateCounter);
} else {
// Finalizar animação
currentNumber.textContent = formatNumber(endValue);
progressBar.style.width = `${progressPercentValue}%`;
updateStats(endValue);
}
}
// Iniciar animação
requestAnimationFrame(updateCounter);
}
// Iniciar animação quando o botão for clicado
animateButton.addEventListener('click', function() {
const targetValue = parseInt(currentValue.value);
if (isNaN(targetValue) || targetValue < 0) {
alert('Please enter a valid value greater than or equal to zero.');
return;
}
if (targetValue > 1000000) {
alert('Value cannot be greater than 1,000,000.');
return;
}
animateCounter(targetValue);
});
// Permitir Enter para iniciar a animação
currentValue.addEventListener('keyup', function(event) {
if (event.key === 'Enter') {
animateButton.click();
}
});
// Exemplo inicial
currentValue.value = '350000';
animateCounter(350000);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment