Interactive calculator: enter annual hours target + vacation days, shows actual billable hours per working day after subtracting weekends, vacation, and public holidays. Makes the absurdity of 2400h targets visible.
419 lines
11 KiB
HTML
419 lines
11 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Billable Aua.</title>
|
|
<meta name="description" content="Billable Hours. Das Vergütungsmodell, das Effizienz bestraft und Leidensfähigkeit belohnt.">
|
|
<meta name="robots" content="noindex, nofollow">
|
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>.</text></svg>">
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@300;400;600;700;900&display=swap" rel="stylesheet">
|
|
<style>
|
|
*, *::before, *::after {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
:root {
|
|
--bg: #0a0a0a;
|
|
--text: #e8e8e8;
|
|
--text-dim: #777;
|
|
--text-muted: #444;
|
|
--red: #cc2222;
|
|
--red-glow: rgba(204, 34, 34, 0.15);
|
|
}
|
|
|
|
html { scroll-behavior: smooth; }
|
|
|
|
body {
|
|
font-family: 'Barlow Condensed', 'Arial Narrow', sans-serif;
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
line-height: 1.5;
|
|
-webkit-font-smoothing: antialiased;
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
body::before {
|
|
content: '';
|
|
position: fixed;
|
|
inset: 0;
|
|
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.04'/%3E%3C/svg%3E");
|
|
pointer-events: none;
|
|
z-index: 9999;
|
|
}
|
|
|
|
.wrap {
|
|
max-width: 800px;
|
|
margin: 0 auto;
|
|
padding: 0 24px;
|
|
}
|
|
|
|
/* Hero */
|
|
.hero {
|
|
min-height: 100vh;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
position: relative;
|
|
}
|
|
|
|
.hero::after {
|
|
content: '';
|
|
position: absolute;
|
|
bottom: 60px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: 1px;
|
|
height: 80px;
|
|
background: linear-gradient(to bottom, var(--text-muted), transparent);
|
|
animation: pulse 2s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes pulse {
|
|
0%, 100% { opacity: 0.3; }
|
|
50% { opacity: 0.8; }
|
|
}
|
|
|
|
h1 {
|
|
font-size: clamp(5rem, 15vw, 12rem);
|
|
font-weight: 900;
|
|
letter-spacing: -0.03em;
|
|
line-height: 0.9;
|
|
text-transform: uppercase;
|
|
text-align: center;
|
|
animation: fadeIn 1.2s ease-out;
|
|
}
|
|
|
|
h1 .dot {
|
|
color: var(--red);
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; transform: translateY(30px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
/* Divider */
|
|
.line {
|
|
height: 1px;
|
|
background: var(--text-muted);
|
|
opacity: 0.3;
|
|
}
|
|
|
|
/* Numbers */
|
|
.numbers {
|
|
padding: 120px 0;
|
|
text-align: center;
|
|
}
|
|
|
|
.numbers p {
|
|
font-size: clamp(1.3rem, 3vw, 1.8rem);
|
|
font-weight: 300;
|
|
color: var(--text-dim);
|
|
line-height: 1.8;
|
|
max-width: 640px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.numbers .num {
|
|
color: var(--red);
|
|
font-weight: 700;
|
|
font-size: 1.15em;
|
|
}
|
|
|
|
/* Kritik */
|
|
.kritik {
|
|
padding: 80px 0 120px;
|
|
}
|
|
|
|
.kritik-item {
|
|
padding: 48px 0;
|
|
border-bottom: 1px solid rgba(68, 68, 68, 0.3);
|
|
}
|
|
|
|
.kritik-item:first-child {
|
|
border-top: 1px solid rgba(68, 68, 68, 0.3);
|
|
}
|
|
|
|
.kritik-item p {
|
|
font-size: clamp(1.5rem, 4vw, 2.4rem);
|
|
font-weight: 600;
|
|
letter-spacing: -0.01em;
|
|
line-height: 1.3;
|
|
color: var(--text);
|
|
}
|
|
|
|
.kritik-item .num {
|
|
color: var(--red);
|
|
font-weight: 700;
|
|
}
|
|
|
|
.kritik-item .dim {
|
|
color: var(--text-dim);
|
|
font-weight: 300;
|
|
}
|
|
|
|
/* Rechner */
|
|
.rechner {
|
|
padding: 120px 0;
|
|
}
|
|
|
|
.rechner h2 {
|
|
font-size: clamp(2.5rem, 7vw, 4rem);
|
|
font-weight: 900;
|
|
letter-spacing: -0.02em;
|
|
text-transform: uppercase;
|
|
margin-bottom: 48px;
|
|
}
|
|
|
|
.rechner h2 .dot { color: var(--red); }
|
|
|
|
.rechner-grid {
|
|
display: flex;
|
|
gap: 32px;
|
|
margin-bottom: 48px;
|
|
}
|
|
|
|
.rechner-input {
|
|
flex: 1;
|
|
}
|
|
|
|
.rechner-input label {
|
|
display: block;
|
|
font-size: 0.9rem;
|
|
color: var(--text-dim);
|
|
font-weight: 300;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.rechner-input input {
|
|
width: 100%;
|
|
background: transparent;
|
|
border: 1px solid var(--text-muted);
|
|
color: var(--text);
|
|
font-family: inherit;
|
|
font-size: 2.4rem;
|
|
font-weight: 700;
|
|
padding: 12px 16px;
|
|
text-align: center;
|
|
outline: none;
|
|
transition: border-color 0.3s;
|
|
-moz-appearance: textfield;
|
|
}
|
|
|
|
.rechner-input input::-webkit-inner-spin-button,
|
|
.rechner-input input::-webkit-outer-spin-button {
|
|
-webkit-appearance: none;
|
|
}
|
|
|
|
.rechner-input input:focus {
|
|
border-color: var(--red);
|
|
}
|
|
|
|
.rechner-result {
|
|
font-size: clamp(1.3rem, 3vw, 1.8rem);
|
|
font-weight: 300;
|
|
color: var(--text-dim);
|
|
line-height: 2;
|
|
}
|
|
|
|
.rechner-result .num {
|
|
color: var(--red);
|
|
font-weight: 700;
|
|
font-size: 1.15em;
|
|
}
|
|
|
|
.rechner-result .verdict {
|
|
display: block;
|
|
margin-top: 24px;
|
|
font-size: clamp(1.5rem, 4vw, 2.2rem);
|
|
font-weight: 600;
|
|
color: var(--text);
|
|
}
|
|
|
|
@media (max-width: 640px) {
|
|
.rechner { padding: 80px 0; }
|
|
.rechner-grid { flex-direction: column; gap: 24px; }
|
|
}
|
|
|
|
/* Silence */
|
|
.silence {
|
|
padding: 160px 0;
|
|
text-align: center;
|
|
}
|
|
|
|
.silence p {
|
|
font-size: clamp(1rem, 2vw, 1.2rem);
|
|
color: var(--text-muted);
|
|
font-weight: 300;
|
|
letter-spacing: 0.15em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
/* Footer */
|
|
footer {
|
|
padding: 40px 0;
|
|
text-align: center;
|
|
border-top: 1px solid rgba(68, 68, 68, 0.2);
|
|
}
|
|
|
|
footer p {
|
|
color: var(--text-muted);
|
|
font-size: 0.85rem;
|
|
font-weight: 400;
|
|
letter-spacing: 0.05em;
|
|
}
|
|
|
|
/* Scroll reveal */
|
|
.reveal {
|
|
opacity: 0;
|
|
transform: translateY(20px);
|
|
transition: opacity 0.8s ease, transform 0.8s ease;
|
|
}
|
|
|
|
.reveal.visible {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
|
|
/* Responsive */
|
|
@media (max-width: 640px) {
|
|
.numbers { padding: 80px 0; }
|
|
.kritik { padding: 40px 0 80px; }
|
|
.kritik-item { padding: 32px 0; }
|
|
.silence { padding: 100px 0; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<section class="hero">
|
|
<h1>Billable<br>Aua<span class="dot">.</span></h1>
|
|
</section>
|
|
|
|
<div class="line"></div>
|
|
|
|
<section class="numbers">
|
|
<div class="wrap">
|
|
<p class="reveal">
|
|
<span class="num">2.400</span> Stunden pro Jahr.<br>
|
|
<span class="num">6,5</span> Stunden pro Tag, die du „verkaufst“.<br>
|
|
Jede Minute dokumentiert.<br>
|
|
Jede Pause ein Verlust.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="line"></div>
|
|
|
|
<section class="rechner">
|
|
<div class="wrap">
|
|
<h2 class="reveal">Rechne selbst<span class="dot">.</span></h2>
|
|
<div class="rechner-grid reveal">
|
|
<div class="rechner-input">
|
|
<label>Billable-Stunden / Jahr</label>
|
|
<input type="number" id="hours" value="2400" min="0" max="5000">
|
|
</div>
|
|
<div class="rechner-input">
|
|
<label>Urlaubstage</label>
|
|
<input type="number" id="vacation" value="25" min="0" max="60">
|
|
</div>
|
|
</div>
|
|
<div class="rechner-result reveal" id="result"></div>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="line"></div>
|
|
|
|
<section class="kritik">
|
|
<div class="wrap">
|
|
|
|
<div class="kritik-item reveal">
|
|
<p>Du wirst nach Zeit bezahlt, <span class="dim">nicht nach Ergebnis.</span></p>
|
|
</div>
|
|
|
|
<div class="kritik-item reveal">
|
|
<p>Effizienz wird bestraft. <span class="dim">Wer schneller arbeitet, verdient weniger.</span></p>
|
|
</div>
|
|
|
|
<div class="kritik-item reveal">
|
|
<p>Der Mandant zahlt <span class="dim">für deine Lernkurve.</span></p>
|
|
</div>
|
|
|
|
<div class="kritik-item reveal">
|
|
<p><span class="num">8</span> Stunden Arbeit = <span class="num">6,5</span> billable. <span class="dim">Die restlichen 1,5? Dein Problem.</span></p>
|
|
</div>
|
|
|
|
<div class="kritik-item reveal">
|
|
<p>Partnertrack heißt: <span class="dim"><span class="num">10</span> Jahre beweisen, dass du leidensfähig bist.</span></p>
|
|
</div>
|
|
|
|
</div>
|
|
</section>
|
|
|
|
<div class="line"></div>
|
|
|
|
<section class="silence">
|
|
<div class="wrap">
|
|
<p class="reveal">Kein Kontakt. Kein Newsletter. Kein Impressum.</p>
|
|
</div>
|
|
</section>
|
|
|
|
<footer>
|
|
<div class="wrap">
|
|
<p>billableaua.de — 2026</p>
|
|
</div>
|
|
</footer>
|
|
|
|
<script>
|
|
const observer = new IntersectionObserver((entries) => {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) {
|
|
entry.target.classList.add('visible');
|
|
}
|
|
});
|
|
}, { threshold: 0.15 });
|
|
|
|
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
|
|
|
|
// Rechner
|
|
function calculate() {
|
|
const hours = parseInt(document.getElementById('hours').value) || 0;
|
|
const vacation = parseInt(document.getElementById('vacation').value) || 0;
|
|
const weekends = 104;
|
|
const feiertage = 10;
|
|
const workingDays = 365 - weekends - vacation - feiertage;
|
|
const perDay = workingDays > 0 ? (hours / workingDays) : 0;
|
|
const perDayStr = perDay.toFixed(1).replace('.', ',');
|
|
|
|
let verdict = '';
|
|
if (perDay > 10) {
|
|
verdict = '<span class="verdict">Das ist kein Job. <span class="dim">Das ist ein Lifestyle.</span></span>';
|
|
} else if (perDay > 8) {
|
|
verdict = '<span class="verdict">Jeden Tag über <span class="num">8</span> Stunden billable. <span class="dim">Ohne Mittagspause, ohne Admin, ohne Atmen.</span></span>';
|
|
} else if (perDay > 6) {
|
|
verdict = '<span class="verdict">Klingt machbar? <span class="dim">Vergiss nicht: billable ≠ Arbeitszeit.</span></span>';
|
|
}
|
|
|
|
document.getElementById('result').innerHTML =
|
|
'<span class="num">' + workingDays + '</span> Arbeitstage ' +
|
|
'<span class="dim">(365 − ' + weekends + ' Wochenenden − ' + vacation + ' Urlaub − ' + feiertage + ' Feiertage)</span><br>' +
|
|
'<span class="num">' + hours.toLocaleString('de-DE') + '</span> Stunden ÷ <span class="num">' + workingDays + '</span> Tage = ' +
|
|
'<span class="num">' + perDayStr + '</span> Stunden pro Tag.' +
|
|
verdict;
|
|
}
|
|
|
|
document.getElementById('hours').addEventListener('input', calculate);
|
|
document.getElementById('vacation').addEventListener('input', calculate);
|
|
calculate();
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|