:root{
–bg:#f7f9fc;
–card:#ffffff;
–text:#0f172a;
–muted:#64748b;
–primary:#16a34a;
–primary-contrast:#ffffff;
–border:#e2e8f0;
–danger:#dc2626;
–focus:#2563eb;
}
*{box-sizing:border-box}
.container{width:100%;}
.title{margin:0 0 16px; font-weight:800; letter-spacing:-0.02em}
.subtitle{margin:0 0 24px; color:var(–muted)}
.card{
background:var(–card); border:1px solid var(–border); border-radius:16px; box-shadow:0 6px 24px rgba(2,6,23,.06);
padding:24px;
}
.grid{display:grid; gap:16px}
@media (min-width: 860px){
.grid{grid-template-columns: repeat(2, minmax(0,1fr));}
}
label{font-size:14px; font-weight:600; color:var(–text)}
.field{display:flex; flex-direction:column; gap:8px}
input, select{
width:100%; padding:12px 14px; border-radius:10px; border:1px solid var(–border); background:#fff;
font-size:16px; outline:none; transition:border-color .15s, box-shadow .15s;
}
input:focus, select:focus{border-color:var(–focus); box-shadow:0 0 0 4px rgba(37,99,235,.1)}
.row{display:flex; gap:12px; align-items:center}
.row > *{flex:1}
.actions{display:flex; flex-wrap:wrap; gap:12px; margin-top:8px}
.btn{
display:inline-flex; align-items:center; justify-content:center; gap:8px;
padding:12px 18px; border-radius:12px; text-decoration:none; font-weight:800; letter-spacing:.2px;
border:1px solid var(–border); background:#fff; color:var(–text);
transition:transform .06s ease, box-shadow .2s ease, background .2s ease;
user-select:none;
!important}
.btn:hover{transform:translateY(-1px); box-shadow:0 6px 18px rgba(2,6,23,.08) !important}
.btn:focus{outline:none; box-shadow:0 0 0 4px rgba(37,99,235,.15) !important}
.btn-primary{
background:var(–primary) !important; color:var(–primary-contrast) !important; border-color:transparent !important;
}
.btn-primary:hover{filter:brightness(1.05) !important}
.btn-ghost{background:#fff !important}
.btn-danger{border-color:transparent !important; background:var(–danger) !important; color:#fff !important}
.error{display:none; margin-top:8px; padding:10px 12px; border-radius:10px; background:#fee2e2; color:#991b1b; font-weight:600}
.error.show{display:block}
.results{margin-top:20px; display:grid; gap:12px}
.kpis{display:grid; gap:12px}
@media (min-width: 860px){
.kpis{grid-template-columns: repeat(3, minmax(0,1fr));}
}
.kpi{background:#fff; border:1px solid var(–border); border-radius:14px; padding:16px}
.kpi .label{color:var(–muted); font-size:13px; margin-bottom:6px}
.kpi .value{font-size:22px; font-weight:800}
details{background:#fff; border:1px solid var(–border); border-radius:14px; padding:14px}
details > summary{cursor:pointer; font-weight:700}
table{width:100%; border-collapse:collapse; margin-top:12px; font-size:14px}
th, td{padding:10px; border-bottom:1px solid var(–border); text-align:right}
th:first-child, td:first-child{text-align:left}
.muted{color:var(–muted)}
.right{ text-align:right }
/* força a tabela a abrir sempre no topo */
#detailsTabela[open] {
scroll-margin-top: 80px;
}
document.getElementById(id);
const fmt = new Intl.NumberFormat(‘pt-BR’, { style:’currency’, currency:’BRL’ });
function validar(){
const valor = parseFloat(el(‘valor’).value);
const taxa = parseFloat(el(‘taxa’).value);
const prazo = parseInt(el(‘prazo’).value, 10);
if(!(valor>0 && taxa>=0 && prazo>0)){
el(‘erro’).textContent = ‘Preencha todos os campos corretamente.’;
el(‘erro’).classList.add(‘show’);
return null;
}
el(‘erro’).classList.remove(‘show’);
return {valor,taxa,prazo};
}
function taxaMensal(raw,periodo){
return periodo===’ao_mes’ ? raw/100 : Math.pow(1+raw/100,1/12)-1;
}
function prazoMeses(prazo,u){return u===’anos’?prazo*12:prazo;}
function calculaPrice(P,i,n){
const parcela = (i===0)?(P/n):(P*(i*Math.pow(1+i,n))/(Math.pow(1+i,n)-1));
const linhas=[]; let saldo=P;
for(let k=1;k{
const tr=document.createElement(‘tr’);
tr.innerHTML=`${L.num} ${fmt.format(L.saldoIni)} ${fmt.format(L.juros)} ${fmt.format(L.amort)} ${fmt.format(L.parcela)} ${fmt.format(L.saldoFim)} `;
tbody.appendChild(tr);
});
}
el(‘btnCalcular’).addEventListener(‘click’,e=>{
e.preventDefault();
const d=validar(); if(!d) return;
const i=taxaMensal(d.taxa,el(‘periodoTaxa’).value);
const n=prazoMeses(d.prazo,el(‘unidadePrazo’).value);
render(calculaPrice(d.valor,i,n));
});
el(‘btnTabela’).addEventListener(‘click’,e=>{
e.preventDefault();
el(‘detailsTabela’).open=!el(‘detailsTabela’).open;
if(el(‘detailsTabela’).open){
el(‘detailsTabela’).scrollIntoView({behavior:’smooth’,block:’start’});
}
});
el(‘btnLimpar’).addEventListener(‘click’,e=>{
e.preventDefault();
[‘valor’,’taxa’,’prazo’].forEach(id=>el(id).value=”);
el(‘results’).hidden=true;
el(‘tabela’).querySelector(‘tbody’).innerHTML=”;
el(‘kpiParcela’).textContent=’—’;
el(‘kpiTotal’).textContent=’—’;
el(‘kpiJuros’).textContent=’—’;
});
//–>
Simule parcelas com juros compostos (sistema francês – Price, modelo mais utilizado com parcelas fixas) para empréstimo pessoal, consignado e empréstimo com garantia.
% ao mês
% ao ano
meses
anos
Parcela mensal
—
Total pago
—
Juros totais
—
Tabela de amortização
| # | Saldo Inicial | Juros | Amortização | Parcela | Saldo Final |
|---|