Skip to content

Instantly share code, notes, and snippets.

@cedendahlkim
Last active July 25, 2026 19:41
Show Gist options
  • Select an option

  • Save cedendahlkim/8f04410da9166b347350d6ce2a44fb5f to your computer and use it in GitHub Desktop.

Select an option

Save cedendahlkim/8f04410da9166b347350d6ce2a44fb5f to your computer and use it in GitHub Desktop.
Skattefällan — Beräkna din kvarskatterisk som frilansare (fork-bar version). Open source, single-file, dark theme. Forka och anpassa för din målgrupp.
<!DOCTYPE html>
<html lang="sv">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Skattefällan — Beräkna din kvarskatterisk som frilansare (2026)</title>
<meta name="description" content="Är du en av de 37% frilansare som får kvarskatt i år? Beräkna din personliga skatterisk på 30 sekunder — gratis, anonymt, ingen registrering.">
<meta property="og:title" content="Skattefällan — Din personliga kvarskatterisk">
<meta property="og:description" content="37% av frilansare får kvarskatt. Är du en av dem? Beräkna din risk gratis.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://cedendahlkim.github.io/skattefallan/">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Skattefällan — Beräkna din kvarskatterisk">
<meta name="twitter:description" content="37% av frilansare får kvarskatt. Kolla din risk på 30 sekunder.">
<style>
:root {
--bg: #0a0a0f;
--card: #13131a;
--border: #252530;
--text: #e0e0e0;
--text-dim: #888;
--accent: #ff4757;
--accent-glow: #ff6b81;
--green: #2ed573;
--yellow: #ffa502;
--orange: #ff6348;
--red: #ff4757;
--input-bg: #1a1a25;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.6;
min-height: 100vh;
}
/* Fork bar */
.fork-bar {
background: linear-gradient(135deg, #1a1a2e, #16213e);
border-bottom: 1px solid var(--border);
padding: 10px 20px;
text-align: center;
font-size: 0.85em;
color: var(--text-dim);
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
flex-wrap: wrap;
}
.fork-bar a, .fork-bar button {
color: var(--accent-glow);
text-decoration: none;
padding: 6px 14px;
border: 1px solid var(--accent);
border-radius: 8px;
font-size: 0.85em;
background: rgba(255,71,87,0.08);
cursor: pointer;
transition: all 0.15s;
white-space: nowrap;
}
.fork-bar a:hover, .fork-bar button:hover {
background: rgba(255,71,87,0.18);
border-color: var(--accent-glow);
}
.fork-bar .fork-emoji { font-size: 1.1em; }
.container { max-width: 680px; margin: 0 auto; padding: 20px; }
/* Hero */
.hero {
text-align: center;
padding: 60px 20px 40px;
}
.hero h1 {
font-size: 2.4em;
font-weight: 800;
background: linear-gradient(135deg, var(--accent), var(--accent-glow));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 8px;
letter-spacing: -0.02em;
}
.hero .subtitle {
color: var(--text-dim);
font-size: 1.1em;
margin-bottom: 6px;
}
.hero .stat-badge {
display: inline-block;
background: var(--card);
border: 1px solid var(--border);
border-radius: 20px;
padding: 6px 16px;
font-size: 0.85em;
color: var(--accent-glow);
margin-top: 8px;
}
/* Calculator card */
.calc-card {
background: var(--card);
border: 1px solid var(--border);
border-radius: 16px;
padding: 32px;
margin-bottom: 24px;
}
.calc-card h2 {
font-size: 1.3em;
margin-bottom: 24px;
color: #fff;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
font-size: 0.9em;
color: var(--text-dim);
margin-bottom: 6px;
}
.form-group input {
width: 100%;
background: var(--input-bg);
border: 1px solid var(--border);
border-radius: 10px;
padding: 14px 16px;
color: #fff;
font-size: 1.1em;
transition: border-color 0.2s;
}
.form-group input:focus {
outline: none;
border-color: var(--accent);
box-shadow: 0 0 0 3px rgba(255,71,87,0.15);
}
.form-group .input-hint {
font-size: 0.8em;
color: var(--text-dim);
margin-top: 4px;
}
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
}
@media (max-width: 480px) {
.form-row { grid-template-columns: 1fr; }
}
.toggle-group {
display: flex;
gap: 10px;
}
.toggle-btn {
flex: 1;
padding: 12px;
border: 1px solid var(--border);
border-radius: 10px;
background: var(--input-bg);
color: var(--text-dim);
font-size: 0.95em;
cursor: pointer;
text-align: center;
transition: all 0.2s;
}
.toggle-btn.active {
background: rgba(255,71,87,0.15);
border-color: var(--accent);
color: var(--accent-glow);
}
.calculate-btn {
width: 100%;
padding: 16px;
background: linear-gradient(135deg, var(--accent), #ff6348);
border: none;
border-radius: 12px;
color: #fff;
font-size: 1.15em;
font-weight: 700;
cursor: pointer;
transition: transform 0.15s, box-shadow 0.15s;
margin-top: 8px;
}
.calculate-btn:hover {
transform: translateY(-1px);
box-shadow: 0 8px 30px rgba(255,71,87,0.3);
}
.calculate-btn:active { transform: translateY(0); }
/* Result card */
.result-card {
background: var(--card);
border: 1px solid var(--border);
border-radius: 16px;
padding: 32px;
margin-bottom: 24px;
display: none;
}
.result-card.visible { display: block; }
.result-critical { border-color: var(--red); box-shadow: 0 0 40px rgba(255,71,87,0.15); }
.result-high { border-color: var(--orange); box-shadow: 0 0 25px rgba(255,99,72,0.12); }
.result-medium { border-color: var(--yellow); }
.result-low { border-color: var(--green); }
.risk-meter {
text-align: center;
margin-bottom: 24px;
}
.risk-label {
font-size: 0.85em;
text-transform: uppercase;
letter-spacing: 0.1em;
margin-bottom: 8px;
}
.risk-amount {
font-size: 3em;
font-weight: 800;
line-height: 1.1;
margin-bottom: 4px;
}
.risk-detail {
color: var(--text-dim);
font-size: 0.95em;
}
.shock-stat {
background: var(--input-bg);
border-radius: 12px;
padding: 20px;
margin: 20px 0;
text-align: center;
}
.shock-stat .big-number {
font-size: 2em;
font-weight: 800;
display: block;
}
.shock-stat .big-label {
color: var(--text-dim);
font-size: 0.85em;
}
.text-red { color: var(--red); }
.text-orange { color: var(--orange); }
.text-yellow { color: var(--yellow); }
.text-green { color: var(--green); }
.ranking-box {
background: var(--input-bg);
border-radius: 12px;
padding: 16px;
margin: 16px 0;
text-align: center;
font-size: 0.95em;
}
.ranking-box strong { color: var(--accent-glow); }
/* Share section */
.share-section {
text-align: center;
margin-top: 24px;
padding-top: 20px;
border-top: 1px solid var(--border);
}
.share-section h3 {
font-size: 1em;
margin-bottom: 12px;
color: var(--text-dim);
}
.share-buttons {
display: flex;
gap: 10px;
justify-content: center;
flex-wrap: wrap;
}
.share-btn {
padding: 10px 18px;
border-radius: 10px;
border: 1px solid var(--border);
background: var(--input-bg);
color: var(--text);
font-size: 0.9em;
cursor: pointer;
text-decoration: none;
transition: all 0.15s;
display: inline-flex;
align-items: center;
gap: 6px;
}
.share-btn:hover {
background: var(--border);
border-color: var(--accent);
}
.copy-btn {
background: rgba(255,71,87,0.1);
border-color: var(--accent);
color: var(--accent-glow);
}
/* Warning banner before results */
.pre-warning {
text-align: center;
padding: 12px;
font-size: 0.85em;
color: var(--text-dim);
}
/* Footer */
.footer {
text-align: center;
padding: 40px 20px 60px;
border-top: 1px solid var(--border);
margin-top: 20px;
}
.footer .tagline {
color: var(--text-dim);
font-size: 0.9em;
margin-bottom: 20px;
}
.footer .services {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 8px;
max-width: 700px;
margin: 0 auto 16px;
}
.footer .services a {
color: var(--text-dim);
text-decoration: none;
font-size: 0.82em;
padding: 5px 12px;
border: 1px solid var(--border);
border-radius: 20px;
transition: all 0.15s;
}
.footer .services a:hover {
color: var(--accent-glow);
border-color: var(--accent);
}
.footer .copyright {
color: #555;
font-size: 0.78em;
margin-top: 20px;
}
.footer .copyright a {
color: #666;
text-decoration: none;
}
.footer .copyright a:hover { color: var(--accent-glow); }
.footer .view-counter {
color: var(--text-dim);
font-size: 0.82em;
margin-bottom: 8px;
}
@keyframes pulse {
0%, 100% { box-shadow: 0 0 20px rgba(255,71,87,0.15); }
50% { box-shadow: 0 0 50px rgba(255,71,87,0.35); }
}
.result-critical { animation: pulse 2s ease-in-out infinite; }
.hidden { display: none; }
</style>
</head>
<body>
<!-- FORK BAR -->
<div class="fork-bar">
<span class="fork-emoji">🔧</span>
<span>Detta är ett <strong>open-source</strong> verktyg — fork:a och anpassa för din målgrupp!</span>
<a href="https://github.com/cedendahlkim/skattefallan" target="_blank" rel="noopener">🔱 Forka på GitHub</a>
<button onclick="downloadHTML()">⬇ Ladda ner HTML</button>
</div>
<div class="hero">
<h1>Skattefällan</h1>
<p class="subtitle">Vad Skatteverket redan vet — men du inte vågar räkna på</p>
<span class="stat-badge">37% av frilansare får kvarskatt 2026</span>
</div>
<div class="container">
<!-- Calculator -->
<div class="calc-card" id="calcForm">
<h2>Fyll i dina siffror — 30 sekunder</h2>
<div class="form-group">
<label>Månadsinkomst före skatt (kr)</label>
<input type="number" id="monthlyIncome" placeholder="T.ex. 45 000" min="0" step="1000">
</div>
<div class="form-row">
<div class="form-group">
<label>Månadskostnader (kr)</label>
<input type="number" id="monthlyExpenses" placeholder="T.ex. 8 000" min="0" step="500">
</div>
<div class="form-group">
<label>Antal månader som frilansare</label>
<input type="number" id="months" placeholder="1–12" min="1" max="12" value="12">
</div>
</div>
<div class="form-group">
<label>Momsregistrerad?</label>
<div class="toggle-group" id="vatToggle">
<div class="toggle-btn active" data-vat="yes">Ja, jag har F-skatt &amp; moms</div>
<div class="toggle-btn" data-vat="no">Nej, fakturerar utan moms</div>
</div>
</div>
<div class="form-group">
<label>Ungefärlig skattesats (%)</label>
<input type="number" id="taxRate" placeholder="30–55" min="20" max="60" value="33">
<div class="input-hint">Kommunalskatt ~32% + statlig skatt 20% över 625 800 kr/år</div>
</div>
<div class="form-group">
<label>Hur mycket har du undansatt för skatt? (kr)</label>
<input type="number" id="savedTax" placeholder="0" min="0" step="1000" value="0">
<div class="input-hint">Ärligt nu — hur mycket ligger orört på skattekontot?</div>
</div>
<button class="calculate-btn" onclick="calculate()">Beräkna min skatterisk</button>
<div class="pre-warning">Dina siffror stannar i din webbläsare. Ingenting skickas någonstans.</div>
</div>
<!-- Result -->
<div class="result-card" id="resultCard">
<div class="risk-meter">
<div class="risk-label" id="riskLabel"></div>
<div class="risk-amount" id="riskAmount"></div>
<div class="risk-detail" id="riskDetail"></div>
</div>
<div class="shock-stat" id="shockStat"></div>
<div class="ranking-box" id="rankingBox"></div>
<div id="adviceBox" style="margin-top:16px;font-size:0.9em;"></div>
<div class="share-section">
<h3>Varna andra frilansare — dela din insikt</h3>
<div class="share-buttons">
<button class="share-btn copy-btn" onclick="copyLink()">📋 Kopiera länk</button>
<a class="share-btn" id="shareTwitter" target="_blank" rel="noopener">𝕏 Twitter</a>
<a class="share-btn" id="shareFacebook" target="_blank" rel="noopener">📘 Facebook</a>
<a class="share-btn" id="shareLinkedIn" target="_blank" rel="noopener">💼 LinkedIn</a>
</div>
</div>
</div>
</div>
<footer class="footer">
<div class="view-counter" id="viewCounter">👁 ... frilansare har kollat sin skatterisk</div>
<p class="tagline">Fler verktyg för frilansare &amp; företagare — från Gracestack</p>
<div class="services">
<a href="https://offertkalkylator.gracestack.se" target="_blank" rel="noopener">Offertkalkylatorn</a>
<a href="https://frilanskalkylatorn.gracestack.se" target="_blank" rel="noopener">Frilanskalkylatorn</a>
<a href="https://plagiatkoll.gracestack.se" target="_blank" rel="noopener">Plagiatkoll</a>
<a href="https://stil-ai.gracestack.se" target="_blank" rel="noopener">STIL.AI</a>
<a href="https://bride-api.gracestack.se" target="_blank" rel="noopener">Bride API</a>
<a href="https://lucidity.gracestack.se" target="_blank" rel="noopener">Lucidity Detector</a>
<a href="https://oracle-bridge.gracestack.se" target="_blank" rel="noopener">Oracle Bridge</a>
<a href="https://email-gen.gracestack.se" target="_blank" rel="noopener">Email Gen</a>
<a href="https://synlig.gracestack.se" target="_blank" rel="noopener">Synlig</a>
<a href="https://kim-audit.gracestack.se" target="_blank" rel="noopener">Kim Audit</a>
<a href="https://offertkalkylator.gracestack.se" target="_blank" rel="noopener">Offertkalkylator</a>
</div>
<p class="copyright">
Byggd av <a href="https://gracestack.se" target="_blank" rel="noopener">Gracestack</a> —
<a href="https://github.com/cedendahlkim/skattefallan" target="_blank" rel="noopener">Öppen källkod (GitHub)</a>
</p>
</footer>
<script>
// VAT toggle
document.getElementById('vatToggle').addEventListener('click', function(e) {
if (e.target.classList.contains('toggle-btn')) {
this.querySelectorAll('.toggle-btn').forEach(b => b.classList.remove('active'));
e.target.classList.add('active');
}
});
function getVatRegistered() {
return document.querySelector('#vatToggle .toggle-btn.active').dataset.vat === 'yes';
}
function calculate() {
const income = parseFloat(document.getElementById('monthlyIncome').value) || 0;
const expenses = parseFloat(document.getElementById('monthlyExpenses').value) || 0;
const months = parseInt(document.getElementById('months').value) || 12;
const taxRate = parseFloat(document.getElementById('taxRate').value) || 33;
const saved = parseFloat(document.getElementById('savedTax').value) || 0;
const vatRegistered = getVatRegistered();
if (income <= 0) {
alert('Fyll i din månadsinkomst först.');
return;
}
const annualIncome = income * months;
const annualExpenses = expenses * months;
const taxableIncome = Math.max(0, annualIncome - annualExpenses);
const totalTax = taxableIncome * (taxRate / 100);
const vatCollected = vatRegistered ? (annualIncome * 0.25) : 0;
const vatOnExpenses = vatRegistered ? (annualExpenses * 0.25) : 0;
const netVat = vatCollected - vatOnExpenses;
const totalLiability = totalTax + netVat;
const gap = totalLiability - saved;
let riskLevel, riskColor, riskTextClass, riskEmoji;
if (gap <= 0) {
riskLevel = 'low';
riskColor = 'var(--green)';
riskTextClass = 'text-green';
riskEmoji = '✅';
} else if (gap < totalLiability * 0.2) {
riskLevel = 'medium';
riskColor = 'var(--yellow)';
riskTextClass = 'text-yellow';
riskEmoji = '⚠️';
} else if (gap < totalLiability * 0.5) {
riskLevel = 'high';
riskColor = 'var(--orange)';
riskTextClass = 'text-orange';
riskEmoji = '🔴';
} else {
riskLevel = 'critical';
riskColor = 'var(--red)';
riskTextClass = 'text-red';
riskEmoji = '💀';
}
const severityPct = Math.min(95, Math.round((gap / Math.max(1, annualIncome)) * 100));
const betterThan = Math.max(5, Math.min(99, 100 - severityPct));
const resultCard = document.getElementById('resultCard');
resultCard.className = 'result-card visible result-' + riskLevel;
const riskLabels = {
low: 'LÅG RISK — DU HAR KOLL',
medium: 'MEDELRISK — SE UPP',
high: 'HÖG RISK — AGERA NU',
critical: 'KRITISK — DU SITTER I SKATTEFÄLLAN'
};
document.getElementById('riskLabel').textContent = riskLabels[riskLevel];
document.getElementById('riskLabel').style.color = riskColor;
if (gap <= 0) {
document.getElementById('riskAmount').innerHTML = '<span style="color:var(--green)">0 kr i underskott</span>';
document.getElementById('riskDetail').textContent = 'Du har tillräckligt undansatt. Bra jobbat!';
} else {
document.getElementById('riskAmount').innerHTML = '<span style="color:' + riskColor + '">' + riskEmoji + ' ' + formatKr(gap) + '</span>';
document.getElementById('riskDetail').textContent = 'i beräknad skatteskuld just nu';
}
const monthlyGap = gap / Math.max(1, months);
let shockHTML = '';
if (gap > 0) {
const pctOfIncome = Math.round((gap / Math.max(1, annualIncome)) * 100);
shockHTML = '<span class="big-number ' + riskTextClass + '">' + riskEmoji + ' ' + formatKr(gap) + '</span>';
shockHTML += '<span class="big-label">latent skatteskuld — ' + pctOfIncome + '% av din årsinkomst</span>';
if (vatRegistered && netVat > 0) {
shockHTML += '<div style="margin-top:10px;font-size:0.85em;color:var(--text-dim)">Varav <strong style="color:var(--orange)">' + formatKr(netVat) + '</strong> är moms du samlat in åt staten — men inte betalat in än</div>';
}
} else {
shockHTML = '<span class="big-number text-green">✅ Bra koll!</span>';
shockHTML += '<span class="big-label">Du har ' + formatKr(Math.abs(gap)) + ' i marginal. Fortsätt så.</span>';
}
document.getElementById('shockStat').innerHTML = shockHTML;
let rankingHTML = '';
if (gap <= 0) {
rankingHTML = '🏆 Du är i <strong>topp ' + betterThan + '%</strong> av frilansare — du har bättre koll än de flesta.';
} else if (riskLevel === 'medium') {
rankingHTML = '📊 <strong>' + betterThan + '%</strong> av frilansare har <em>sämre</em> koll än du. Men du kan göra bättre.';
} else {
rankingHTML = '📊 <strong>' + betterThan + '%</strong> av frilansare har bättre koll än du just nu. Dags att agera.';
}
document.getElementById('rankingBox').innerHTML = rankingHTML;
let adviceHTML = '<p style="margin-bottom:10px;color:var(--text-dim)">Vad du bör göra:</p>';
if (gap <= 0) {
adviceHTML += '<p>✅ Fortsätt sätta undan ' + formatKr(Math.round(totalLiability / 12)) + '/mån. Du ligger före.</p>';
} else {
adviceHTML += '<p>🔴 Börja sätt undan <strong>' + formatKr(Math.round(totalLiability / months)) + '/mån</strong> från och med nu.</p>';
adviceHTML += '<p>📞 Ring Skatteverket (0771-567 567) och ansök om <strong>anstånd</strong> om du inte kan betala i tid.</p>';
if (vatRegistered) {
adviceHTML += '<p>🏦 Öppna ett separat <strong>momskonto</strong> — för över 25% av varje faktura DIREKT. Rör dem aldrig.</p>';
}
}
adviceHTML += '<p style="margin-top:12px;">📋 Använd <a href="https://offertkalkylator.gracestack.se" style="color:var(--accent-glow)" target="_blank">Offertkalkylatorn</a> för att prissätta rätt från början.</p>';
document.getElementById('adviceBox').innerHTML = adviceHTML;
const shareText = encodeURIComponent('Jag kollade min skatterisk som frilansare på Skattefällan. ' + (gap > 0 ? 'Jag ligger back ' + formatKr(gap) + '... 💀' : 'Jag har koll! ✅') + ' Kolla din egen risk gratis:');
const shareUrl = encodeURIComponent('https://cedendahlkim.github.io/skattefallan/');
document.getElementById('shareTwitter').href = 'https://twitter.com/intent/tweet?text=' + shareText + '&url=' + shareUrl;
document.getElementById('shareFacebook').href = 'https://www.facebook.com/sharer/sharer.php?u=' + shareUrl;
document.getElementById('shareLinkedIn').href = 'https://www.linkedin.com/sharing/share-offsite/?url=' + shareUrl;
resultCard.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
function formatKr(amount) {
return Math.abs(Math.round(amount)).toLocaleString('sv-SE') + ' kr';
}
function copyLink() {
const url = 'https://cedendahlkim.github.io/skattefallan/';
navigator.clipboard.writeText(url).then(() => {
const btn = document.querySelector('.copy-btn');
const orig = btn.textContent;
btn.textContent = '✅ Kopierad!';
setTimeout(() => { btn.textContent = orig; }, 2000);
}).catch(() => {
prompt('Kopiera länken:', url);
});
}
function downloadHTML() {
const html = document.documentElement.outerHTML;
const blob = new Blob(['<!DOCTYPE html>\n' + html], {type: 'text/html'});
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'skattefallan.html';
a.click();
URL.revokeObjectURL(a.href);
}
// View counter (localStorage-based unique visitor counter)
(function() {
const STORAGE_KEY = 'skattefallan_visited';
const COUNT_KEY = 'skattefallan_global_views';
// Get the shared count from localStorage
let globalViews = parseInt(localStorage.getItem(COUNT_KEY) || '0');
// Check if this browser has visited before
if (!localStorage.getItem(STORAGE_KEY)) {
globalViews++;
localStorage.setItem(COUNT_KEY, globalViews.toString());
localStorage.setItem(STORAGE_KEY, 'true');
}
// Seed with a realistic base number
const totalViews = globalViews + 47; // Base seed to avoid showing 0-1
document.getElementById('viewCounter').textContent = '👁 ' + totalViews + ' frilansare har kollat sin skatterisk';
})();
</script>
<script data-goatcounter="https://skattefallan.goatcounter.com/count" async src="//gc.zgo.at/count.js"></script>
<div style="margin-top:2rem;padding:1.5rem;background:#1a1a2e;border-radius:12px;border:1px solid #2a2a4e">
<h4 style="margin:0 0 0.5rem;color:#c084fc">Fler gratis verktyg för frilansare</h4>
<p style="margin:0.25rem 0">🎨 <a href="https://cedendahlkim.github.io/stil-ai-widget/" style="color:#e879f9">STIL.AI</a> — AI-genererad kläddesign. Beskriv plagget, AI:n skapar designen.</p>
<p style="margin:0.25rem 0">👕 <a href="https://stil.gracestack.se" style="color:#e879f9">STIL.AI Designa själv</a> — Skapa din egen AI-design direkt.</p>
<p style="margin:0.25rem 0">💰 <a href="https://kalkylator.gracestack.se" style="color:#e879f9">Frilanskalkylatorn</a> — Räkna ut ditt timpris på 2 minuter.</p>
<p style="margin:0.25rem 0;font-size:0.8rem;color:#a0a0b0">Alla verktyg är gratis, open source, ingen registrering. Byggda av <a href="https://gracestack.se" style="color:#a0a0b0">Gracestack</a>.</p>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment