<!DOCTYPE html>


<html lang="de">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Bitcoin Renten-Rechner</title>

<link href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Syne:wght@400;600;800&display=swap" rel="stylesheet">

<style>

  :root {

    --bg:#0a0a0f; --surface:#12121a; --card:#1a1a26; --border:#2a2a3d;

    --accent:#f7931a; --accent2:#ffd166; --green:#06d6a0; --red:#ef476f;

    --text:#e8e8f0; --muted:#7070a0; --glow:rgba(247,147,26,0.15);

  }

  *{margin:0;padding:0;box-sizing:border-box;}

  body{background:var(--bg);color:var(--text);font-family:'Syne',sans-serif;min-height:100vh;overflow-x:hidden;}

  body::before{

    content:'';position:fixed;top:-50%;left:-50%;width:200%;height:200%;

    background:radial-gradient(ellipse at 20% 20%,rgba(247,147,26,0.06) 0%,transparent 50%),

               radial-gradient(ellipse at 80% 80%,rgba(6,214,160,0.04) 0%,transparent 50%);

    animation:bgPulse 8s ease-in-out infinite alternate;pointer-events:none;z-index:0;

  }

  @keyframes bgPulse{0%{transform:scale(1);}100%{transform:scale(1.08) rotate(2deg);}}

  .container{position:relative;z-index:1;max-width:920px;margin:0 auto;padding:40px 20px;}


header{text-align:center;margin-bottom:48px;}

.btc-icon{

width:52px;height:52px;background:var(–accent);border-radius:50%;

display:inline-flex;align-items:center;justify-content:center;

font-size:26px;font-weight:700;color:#000;

box-shadow:0 0 30px rgba(247,147,26,0.5);

animation:glow 2s ease-in-out infinite alternate;margin-bottom:14px;

}

@keyframes glow{0%{box-shadow:0 0 20px rgba(247,147,26,0.4);}100%{box-shadow:0 0 50px rgba(247,147,26,0.8);}}

h1{

font-size:clamp(26px,5vw,42px);font-weight:800;letter-spacing:-1px;

background:linear-gradient(135deg,#f7931a,#ffd166,#f7931a);background-size:200% auto;

-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;

animation:shimmer 3s linear infinite;

}

@keyframes shimmer{0%{background-position:0% center;}100%{background-position:200% center;}}

.subtitle{color:var(–muted);font-size:13px;letter-spacing:2px;text-transform:uppercase;margin-top:8px;font-family:‘Space Mono’,monospace;}


/* PRICE BANNER */

.price-banner{

background:linear-gradient(135deg,rgba(247,147,26,0.08),rgba(255,209,102,0.04));

border:1px solid rgba(247,147,26,0.25);border-radius:16px;padding:22px 28px;

display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:16px;margin-bottom:24px;

}

.pbl{display:flex;flex-direction:column;gap:4px;}

.pbl-lbl{font-size:10px;letter-spacing:2px;text-transform:uppercase;color:var(–muted);font-family:‘Space Mono’,monospace;}

.pbl-val{font-size:26px;font-weight:700;font-family:‘Space Mono’,monospace;color:var(–accent);}

.pbl-date{font-size:11px;color:var(–muted);font-family:‘Space Mono’,monospace;}

.pb-stats{display:flex;gap:24px;flex-wrap:wrap;}

.pbs{display:flex;flex-direction:column;gap:3px;}

.pbs-lbl{font-size:9px;letter-spacing:1.5px;text-transform:uppercase;color:var(–muted);font-family:‘Space Mono’,monospace;}

.pbs-val{font-size:15px;font-weight:700;font-family:‘Space Mono’,monospace;}


/* VALUATION CARD */

.valuation-card{

background:var(–card);border:1px solid var(–border);border-radius:20px;

padding:28px;margin-bottom:24px;position:relative;overflow:hidden;

}

.val-title{font-size:11px;letter-spacing:2px;text-transform:uppercase;color:var(–muted);font-family:‘Space Mono’,monospace;margin-bottom:18px;}


.price-input-row{display:flex;align-items:center;gap:16px;margin-bottom:22px;flex-wrap:wrap;}

.price-input-row label{font-size:11px;letter-spacing:1.5px;text-transform:uppercase;color:var(–muted);font-family:‘Space Mono’,monospace;white-space:nowrap;}

.pi-wrap{position:relative;flex:1;min-width:160px;max-width:260px;}

.pi-wrap input{

width:100%;background:var(–surface);border:1px solid var(–border);border-radius:10px;

padding:11px 46px 11px 16px;color:var(–text);font-size:16px;

font-family:‘Space Mono’,monospace;font-weight:700;outline:none;

transition:border-color .3s,box-shadow .3s;

}

.pi-wrap input:focus{border-color:var(–accent);box-shadow:0 0 12px var(–glow);}

.pi-wrap .unit{position:absolute;right:13px;top:50%;transform:translateY(-50%);color:var(–muted);font-family:‘Space Mono’,monospace;font-size:12px;pointer-events:none;}


.heatmap-scale{

position:relative;height:30px;border-radius:15px;overflow:hidden;margin-bottom:12px;

background:linear-gradient(90deg,

#06d6a0 0%, #3ad67a 15%, #a8d630 28%, #ffd166 42%,

#f7931a 58%, #ef6c47 72%, #ef476f 85%, #c0134e 100%);

}

.heatmap-needle{

position:absolute;top:-3px;width:4px;height:36px;background:#fff;border-radius:2px;

box-shadow:0 0 10px rgba(255,255,255,0.9);

transition:left 0.9s cubic-bezier(0.34,1.56,0.64,1);

}

.heatmap-needle::after{

content:’’;position:absolute;bottom:-6px;left:50%;transform:translateX(-50%);

width:0;height:0;border-left:5px solid transparent;border-right:5px solid transparent;border-top:7px solid #fff;

}

.heatmap-labels{

display:flex;justify-content:space-between;

font-size:9px;color:var(–muted);font-family:‘Space Mono’,monospace;

letter-spacing:1px;text-transform:uppercase;margin-bottom:18px;

}

.val-result{display:flex;align-items:center;gap:18px;flex-wrap:wrap;}

.val-pct{font-size:30px;font-weight:800;font-family:‘Space Mono’,monospace;transition:all .5s;min-width:90px;}

.val-badge{padding:9px 20px;border-radius:50px;font-size:15px;font-weight:700;font-family:‘Space Mono’,monospace;transition:all .5s;}

.val-desc{font-size:12px;color:var(–muted);font-family:‘Space Mono’,monospace;line-height:1.7;flex:1;min-width:180px;}


/* GRID */

.grid{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-bottom:24px;}

@media(max-width:600px){.grid{grid-template-columns:1fr;}}

.card{

background:var(–card);border:1px solid var(–border);border-radius:16px;padding:26px;

position:relative;overflow:hidden;transition:border-color .3s,transform .3s;

}

.card:hover{border-color:rgba(247,147,26,0.3);transform:translateY(-2px);}

.card::before{

content:’’;position:absolute;top:0;left:0;right:0;height:2px;

background:linear-gradient(90deg,transparent,var(–accent),transparent);opacity:0;transition:opacity .3s;

}

.card:hover::before{opacity:1;}

.sec-title{font-size:10px;letter-spacing:2px;text-transform:uppercase;color:var(–muted);font-family:‘Space Mono’,monospace;margin-bottom:14px;padding-bottom:8px;border-bottom:1px solid var(–border);}

label{display:block;font-size:11px;letter-spacing:2px;text-transform:uppercase;color:var(–muted);margin-bottom:10px;font-family:‘Space Mono’,monospace;}

input[type=“range”]{

-webkit-appearance:none;width:100%;height:4px;background:var(–border);

border-radius:2px;outline:none;cursor:pointer;margin:12px 0 8px;

}

input[type=“range”]::-webkit-slider-thumb{

-webkit-appearance:none;width:20px;height:20px;border-radius:50%;background:var(–accent);

cursor:pointer;box-shadow:0 0 10px rgba(247,147,26,0.5);transition:box-shadow .2s,transform .2s;

}

input[type=“range”]::-webkit-slider-thumb:hover{box-shadow:0 0 20px rgba(247,147,26,0.8);transform:scale(1.2);}

.ni-wrap{position:relative;}

.ni-wrap input[type=“number”]{

width:100%;background:var(–surface);border:1px solid var(–border);border-radius:10px;

padding:12px 50px 12px 16px;color:var(–text);font-size:18px;

font-family:‘Space Mono’,monospace;font-weight:700;outline:none;

transition:border-color .3s,box-shadow .3s;

}

.ni-wrap input:focus{border-color:var(–accent);box-shadow:0 0 15px var(–glow);}

.ni-wrap .unit{position:absolute;right:14px;top:50%;transform:translateY(-50%);color:var(–muted);font-family:‘Space Mono’,monospace;font-size:13px;pointer-events:none;}

.vsub{font-size:11px;color:var(–muted);font-family:‘Space Mono’,monospace;margin-top:4px;}


/* RESULT */

.result-card{

background:linear-gradient(135deg,var(–card) 0%,rgba(247,147,26,0.08) 100%);

border:1px solid rgba(247,147,26,0.3);border-radius:20px;

padding:36px;margin-bottom:24px;text-align:center;position:relative;overflow:hidden;

}

.result-card::after{content:‘’;position:absolute;right:-20px;bottom:-40px;font-size:160px;opacity:0.03;font-weight:700;color:var(–accent);}

.r-label{font-size:11px;letter-spacing:3px;text-transform:uppercase;color:var(–muted);font-family:‘Space Mono’,monospace;margin-bottom:12px;}

.r-year{font-size:clamp(52px,10vw,80px);font-weight:800;color:var(–accent);line-height:1;text-shadow:0 0 40px rgba(247,147,26,0.4);transition:all .5s;}

.r-sub{color:var(–muted);font-size:13px;margin-top:8px;font-family:‘Space Mono’,monospace;}

.r-badge{display:inline-block;padding:4px 14px;background:rgba(6,214,160,0.1);border:1px solid rgba(6,214,160,0.3);border-radius:20px;color:var(–green);font-size:12px;font-family:‘Space Mono’,monospace;margin-top:10px;}

.already{color:var(–green);font-size:28px;font-weight:700;}


/* STATS */

.stats-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-bottom:24px;}

@media(max-width:500px){.stats-grid{grid-template-columns:1fr 1fr;}.stats-grid .sc:last-child{grid-column:span 2;}}

.sc{background:var(–card);border:1px solid var(–border);border-radius:14px;padding:20px;text-align:center;transition:all .3s;}

.sc:hover{border-color:rgba(6,214,160,0.3);}

.sc-val{font-size:18px;font-weight:700;font-family:‘Space Mono’,monospace;color:var(–green);margin-bottom:4px;transition:all .5s;}

.sc-lbl{font-size:10px;color:var(–muted);text-transform:uppercase;letter-spacing:1.5px;font-family:‘Space Mono’,monospace;}


/* TIMELINE */

.tl-card{background:var(–card);border:1px solid var(–border);border-radius:16px;padding:28px;margin-bottom:24px;}

.tl-title{font-size:11px;letter-spacing:2px;text-transform:uppercase;color:var(–muted);font-family:‘Space Mono’,monospace;margin-bottom:20px;}

.tl-row{display:flex;align-items:center;gap:14px;margin-bottom:12px;padding:10px 14px;border-radius:10px;transition:background .2s;}

.tl-row:hover{background:rgba(255,255,255,0.03);}

.tl-yr{min-width:52px;height:28px;border-radius:6px;background:var(–surface);border:1px solid var(–border);font-family:‘Space Mono’,monospace;font-size:12px;font-weight:700;display:flex;align-items:center;justify-content:center;color:var(–muted);}

.tl-yr.hl{background:rgba(247,147,26,0.15);border-color:var(–accent);color:var(–accent);}

.tl-bw{flex:1;height:8px;background:var(–border);border-radius:4px;overflow:hidden;}

.tl-b{height:100%;border-radius:4px;background:linear-gradient(90deg,var(–accent),var(–accent2));transition:width .8s cubic-bezier(0.34,1.56,0.64,1);}

.tl-amt{min-width:110px;font-family:‘Space Mono’,monospace;font-size:12px;font-weight:700;text-align:right;}

.tl-mark{font-size:14px;min-width:24px;text-align:center;}


.info-box{

background:rgba(247,147,26,0.05);border:1px solid rgba(247,147,26,0.15);

border-radius:12px;padding:20px;font-size:12px;color:var(–muted);

font-family:‘Space Mono’,monospace;line-height:1.8;

}

.info-box strong{color:var(–accent2);}

.fade-in{animation:fi .5s ease forwards;}

@keyframes fi{from{opacity:0;transform:translateY(10px);}to{opacity:1;transform:translateY(0);}}


/* LIVE PRICE */

.live-dot{

display:inline-block;width:8px;height:8px;border-radius:50%;

background:var(–green);margin-right:6px;

box-shadow:0 0 6px var(–green);

animation:blink 1.4s ease-in-out infinite;

}

@keyframes blink{0%,100%{opacity:1;}50%{opacity:.3;}}

.live-dot.loading{background:var(–muted);box-shadow:none;animation:spin 1s linear infinite;}

@keyframes spin{to{transform:rotate(360deg);}}

.live-dot.error{background:var(–red);box-shadow:0 0 6px var(–red);animation:none;}


.market-price-display{

display:flex;flex-direction:column;gap:3px;

padding:14px 20px;background:rgba(6,214,160,0.06);

border:1px solid rgba(6,214,160,0.2);border-radius:12px;

}

.mp-lbl{font-size:9px;letter-spacing:2px;text-transform:uppercase;color:var(–muted);font-family:‘Space Mono’,monospace;}

.mp-val{font-size:22px;font-weight:700;font-family:‘Space Mono’,monospace;color:var(–green);}

.mp-sub{font-size:10px;color:var(–muted);font-family:‘Space Mono’,monospace;}


.refresh-btn{

background:none;border:1px solid var(–border);border-radius:8px;

color:var(–muted);font-family:‘Space Mono’,monospace;font-size:11px;

padding:6px 12px;cursor:pointer;transition:all .2s;white-space:nowrap;

}

.refresh-btn:hover{border-color:var(–accent);color:var(–accent);}

.refresh-btn:disabled{opacity:.4;cursor:not-allowed;}

</style>


</head>

<body>

<div class="container">

  <header>

    <div class="btc-icon"></div>

    <h1>Bitcoin Renten-Rechner</h1>

    <p class="subtitle">Power Law · Rentenziel · Kaufbewertung</p>

  </header>


  <!-- POWER LAW + LIVE PRICE BANNER -->


  <div class="price-banner">

    <div class="pbl">

      <span class="pbl-lbl"> Power Law Median-Preis heute</span>

      <span id="plPriceToday" class="pbl-val">–</span>

      <span id="plDateToday" class="pbl-date">–</span>

    </div>

    <!-- LIVE MARKET PRICE -->

    <div class="market-price-display">

      <span class="mp-lbl"><span class="live-dot loading" id="liveDot"></span>Live Marktpreis (Binance)</span>

      <span id="livePrice" class="mp-val">Lädt…</span>

      <span id="liveSub" class="mp-sub">–</span>

    </div>

    <div class="pb-stats">

      <div class="pbs">

        <span class="pbs-lbl">Unteres Band</span>

        <span id="plFloor" class="pbs-val" style="color:var(--green)">–</span>

      </div>

      <div class="pbs">

        <span class="pbs-lbl">Oberes Band</span>

        <span id="plCeil" class="pbs-val" style="color:var(--red)">–</span>

      </div>

      <div class="pbs">

        <span class="pbs-lbl">Tage seit Genesis</span>

        <span id="plDays" class="pbs-val" style="color:var(--muted)">–</span>

      </div>

      <div class="pbs">

        <span class="pbs-lbl">Ø Wachstum / Jahr (10J)</span>

        <span id="plGrowth" class="pbs-val" style="color:var(--accent2)">–</span>

      </div>

    </div>

  </div>


  <!-- KAUFBEWERTUNG HEATMAP -->


  <div class="valuation-card">

    <div class="val-title">🌡️ Kaufbewertung — Wie teuer ist Bitcoin gerade?</div>

    <div class="price-input-row">

      <label>Aktueller Marktpreis:</label>

      <div class="pi-wrap">

        <input type="number" id="marketPrice" value="85000" min="1000" max="10000000" step="1000">

        <span class="unit">€</span>

      </div>

      <button class="refresh-btn" id="refreshBtn" onclick="fetchLivePrice()"> Aktualisieren</button>

      <span class="vsub" style="flex:1">Wird automatisch geladen</span>

    </div>

    <div class="heatmap-scale">

      <div class="heatmap-needle" id="heatNeedle" style="left:50%"></div>

    </div>

    <div class="heatmap-labels">

      <span>Extrem günstig</span>

      <span>Fair</span>

      <span>Teuer</span>

      <span>Extrem teuer</span>

    </div>

    <div class="val-result">

      <div id="valPct" class="val-pct">–</div>

      <div id="valBadge" class="val-badge">–</div>

      <div id="valDesc" class="val-desc">–</div>

    </div>

  </div>


  <!-- INPUTS -->


  <div class="grid">

    <div class="card">

      <div class="sec-title">Mein Portfolio</div>

      <label>Bitcoin Anzahl (BTC)</label>

      <div class="ni-wrap">

        <input type="number" id="btcAmount" value="0.5" min="0" max="21" step="0.001">

        <span class="unit">BTC</span>

      </div>

      <input type="range" id="btcSlider" min="0" max="10" step="0.01" value="0.5">

      <div class="vsub">Portfolio heute (PL-Preis): <span id="portfolioNow" style="color:var(--accent2)">–</span></div>

    </div>


```

<div class="card">

  <div class="sec-title">Rentenziel</div>

  <label>Monatlicher Bedarf (€)</label>

  <div class="ni-wrap">

    <input type="number" id="monthlyNeed" value="3000" min="100" max="50000" step="100">

    <span class="unit">€/Mo</span>

  </div>

  <input type="range" id="monthlySlider" min="500" max="20000" step="100" value="3000">

  <div class="vsub">Benötigtes Kapital: <span id="targetCapital" style="color:var(--accent2)">–</span></div>

</div>


<div class="card">

  <div class="sec-title">Entnahme-Strategie</div>

  <label>Jährliche Entnahmerate (%)</label>

  <div class="ni-wrap">

    <input type="number" id="withdrawRate" value="4" min="1" max="10" step="0.5">

    <span class="unit">%</span>

  </div>

  <input type="range" id="withdrawSlider" min="1" max="10" step="0.5" value="4">

  <div class="vsub" style="margin-top:4px">4% = Kapital bleibt langfristig erhalten</div>

</div>


<div class="card" style="background:linear-gradient(135deg,var(--card),rgba(247,147,26,0.05));display:flex;flex-direction:column;justify-content:center;gap:16px;">

  <div class="sec-title">Power Law heute</div>

  <div>

    <div style="font-size:9px;letter-spacing:1.5px;text-transform:uppercase;color:var(--muted);font-family:'Space Mono',monospace;margin-bottom:3px;">Median-Preis (Modell)</div>

    <div id="plCardPrice" style="font-size:22px;font-weight:700;font-family:'Space Mono',monospace;color:var(--accent);">–</div>

  </div>

  <div>

    <div style="font-size:9px;letter-spacing:1.5px;text-transform:uppercase;color:var(--muted);font-family:'Space Mono',monospace;margin-bottom:3px;">Ø jährl. Wachstum (10J)</div>

    <div id="plCardGrowth" style="font-size:22px;font-weight:700;font-family:'Space Mono',monospace;color:var(--green);">–</div>

  </div>

</div>

```


  </div>


  <!-- MAIN RESULT -->


  <div class="result-card fade-in">

    <div class="r-label"> Du kannst voraussichtlich in Rente gehen im Jahr</div>

    <div id="retYear" class="r-year">–</div>

    <div id="retSub" class="r-sub">Basierend auf dem Bitcoin Power Law Modell</div>

    <div id="retBadge" class="r-badge">Wird berechnet…</div>

  </div>


  <!-- STATS -->


  <div class="stats-grid">

    <div class="sc"><div id="sPriceRet" class="sc-val">–</div><div class="sc-lbl"> Preis bei Rente</div></div>

    <div class="sc"><div id="sPortRet" class="sc-val">–</div><div class="sc-lbl">Portfolio-Wert</div></div>

    <div class="sc"><div id="sMonthRet" class="sc-val">–</div><div class="sc-lbl">Monatl. Entnahme</div></div>

  </div>


  <!-- TIMELINE -->


  <div class="tl-card">

    <div class="tl-title">📈 Power Law Entwicklung — Dein Weg zur Rente</div>

    <div id="timeline"></div>

  </div>


  <!-- INFO -->


  <div class="info-box">

    <strong>Bitcoin Power Law</strong> (Giovanni Santostasi / Harold Christopher Burger)<br><br>

    <strong>log₁₀(P) = 5.84 × log₁₀(Tage seit Genesis) + B</strong><br>

    B = −17.01 (Median) &nbsp;|&nbsp; −17.668 (Unteres Band) &nbsp;|&nbsp; −16.352 (Oberes Band)<br><br>

    Die <strong>Kaufbewertung</strong> zeigt: Marktpreis ÷ PL-Median. Unter 1,0× = günstig / über 2,0× = historisch teuer.<br><br>

    ⚠️ Keine Anlageberatung. Modellprognosen sind spekulativ. Vergangene Wertentwicklung ist kein Indikator für die Zukunft.

  </div>

</div>


<script>

// ── LIVE PRICE – Fallback-Kette: Binance Kraken manuell ──────────────

// HINWEIS: Funktioniert nur wenn die Datei lokal im Browser geöffnet wird

// (nicht in eingebetteten Iframes wie Claude.ai – dort blockiert die CSP externe Fetches)

let liveMarketPrice = null;


// Versuche 1: Binance (BTCUSDT / EURUSDT)

async function tryBinance() {

  const [btcRes, eurRes] = await Promise.all([

    fetch('https://api.binance.com/api/v3/ticker/24hr?symbol=BTCUSDT', { signal: AbortSignal.timeout(6000) }),

    fetch('https://api.binance.com/api/v3/ticker/24hr?symbol=EURUSDT', { signal: AbortSignal.timeout(6000) })

  ]);

  if(!btcRes.ok || !eurRes.ok) throw new Error('Binance HTTP');

  const btc = await btcRes.json();

  const eur = await eurRes.json();

  const btcEur = parseFloat(btc.lastPrice) / parseFloat(eur.lastPrice);

  return { price: btcEur, change: parseFloat(btc.priceChangePercent), source: 'Binance' };

}


// Versuch 2: Kraken (XBTEUR direkt)

async function tryKraken() {

  const res = await fetch('https://api.kraken.com/0/public/Ticker?pair=XBTEUR', { signal: AbortSignal.timeout(6000) });

  if(!res.ok) throw new Error('Kraken HTTP');

  const data = await res.json();

  if(data.error && data.error.length) throw new Error('Kraken: '+data.error[0]);

  const ticker = data.result['XXBTZEUR'] || data.result['XBTEUR'];

  if(!ticker) throw new Error('Kraken: kein Ticker');

  const price  = parseFloat(ticker.c[0]);

  const open   = parseFloat(ticker.o);

  const change = ((price - open) / open) * 100;

  return { price, change, source: 'Kraken' };

}


// Versuch 3: Coinbase (BTC-EUR)

async function tryCoinbase() {

  const res = await fetch('https://api.coinbase.com/v2/prices/BTC-EUR/spot', { signal: AbortSignal.timeout(6000) });

  if(!res.ok) throw new Error('Coinbase HTTP');

  const data = await res.json();

  const price = parseFloat(data.data.amount);

  return { price, change: null, source: 'Coinbase' };

}


async function fetchLivePrice() {

  const dot     = document.getElementById('liveDot');

  const priceEl = document.getElementById('livePrice');

  const subEl   = document.getElementById('liveSub');

  const btn     = document.getElementById('refreshBtn');


  dot.className = 'live-dot loading';

  priceEl.textContent = 'Lädt…';

  subEl.textContent   = '–';

  if(btn) btn.disabled = true;


  const attempts = [tryBinance, tryKraken, tryCoinbase];

  let result = null;

  let lastErr = '';


  for(const attempt of attempts) {

    try {

      result = await attempt();

      break;

    } catch(e) {

      lastErr = e.message;

      console.warn('Preisfetch fehlgeschlagen:', e.message, '– nächste API…');

    }

  }


  if(result) {

    liveMarketPrice = result.price;

    document.getElementById('marketPrice').value = Math.round(result.price);

    priceEl.textContent = fmt(result.price);

    if(result.change !== null) {

      const sign = result.change >= 0 ? '+' : '';

      subEl.textContent = `${sign}${result.change.toFixed(2)}% (24h) · ${result.source}`;

      subEl.style.color = result.change >= 0 ? 'var(--green)' : 'var(--red)';

    } else {

      subEl.textContent = `via ${result.source}`;

      subEl.style.color = 'var(--muted)';

    }

    dot.className = 'live-dot';

    updateValuation();

  } else {

    dot.className = 'live-dot error';

    priceEl.textContent = 'Nicht verfügbar';

    subEl.textContent   = ' Datei lokal öffnen oder Preis manuell eingeben';

    subEl.style.color   = 'var(--muted)';

    console.warn('Alle APIs fehlgeschlagen. Letzter Fehler:', lastErr);

  }


  if(btn) btn.disabled = false;

}


// ── POWER LAW ──────────────────────────────────────────────────────────────

const PL_A = 5.84;

const PL_B_MED   = -17.01;

const PL_B_FLOOR = -17.668;

const PL_B_CEIL  = -16.352;

const GENESIS = new Date('2009-01-03T00:00:00Z');


function daysSince(date){ return Math.floor((date - GENESIS)/86400000); }

function plPrice(date, B=PL_B_MED){ return Math.pow(10, PL_A * Math.log10(daysSince(date)) + B); }

function plYear(y, B=PL_B_MED){ return plPrice(new Date(y,6,1), B); }


// ── FORMATTERS ─────────────────────────────────────────────────────────────

function fmt(v){

  if(v>=1e9) return (v/1e9).toFixed(2)+' Mrd €';

  if(v>=1e6) return (v/1e6).toFixed(2)+' Mio €';

  if(v>=1e3) return Math.round(v).toLocaleString('de-DE')+' €';

  return v.toFixed(0)+' €';

}

function fmtS(v){

  if(v>=1e9) return (v/1e9).toFixed(1)+'Mrd';

  if(v>=1e6) return (v/1e6).toFixed(1)+'Mio';

  return Math.round(v).toLocaleString('de-DE');

}

function fmtK(v){

  if(v>=1e6) return (v/1e6).toFixed(0)+'M €';

  if(v>=1e3) return (v/1e3).toFixed(0)+'K €';

  return Math.round(v)+' €';

}


// ── INIT CONSTANTS ─────────────────────────────────────────────────────────

const TODAY = new Date();

const CY    = TODAY.getFullYear();

const PL_TODAY   = plPrice(TODAY);

const PL_F_TODAY = plPrice(TODAY, PL_B_FLOOR);

const PL_C_TODAY = plPrice(TODAY, PL_B_CEIL);

const DAYS_TODAY = daysSince(TODAY);

const growth10 = (Math.pow(PL_TODAY / plYear(CY-10), 0.1) - 1) * 100;


// Fill banner

document.getElementById('plPriceToday').textContent = fmt(PL_TODAY);

document.getElementById('plDateToday').textContent  = 'Stand: '+TODAY.toLocaleDateString('de-DE',{day:'2-digit',month:'long',year:'numeric'});

document.getElementById('plFloor').textContent      = fmtK(PL_F_TODAY);

document.getElementById('plCeil').textContent       = fmtK(PL_C_TODAY);

document.getElementById('plDays').textContent       = DAYS_TODAY.toLocaleString('de-DE');

document.getElementById('plGrowth').textContent     = '+'+growth10.toFixed(1)+'% p.a.';

document.getElementById('plCardPrice').textContent  = fmt(PL_TODAY);

document.getElementById('plCardGrowth').textContent = '+'+growth10.toFixed(1)+'% p.a.';


// ── VALUATION ──────────────────────────────────────────────────────────────

function getVal(ratio){

  if(ratio<0.5)  return{l:'Extrem günstig',c:'#06d6a0',d:'Historisch seltene Kaufgelegenheit – weit unter dem Power Law Median.'};

  if(ratio<0.8)  return{l:'Günstig',       c:'#3ad67a',d:'Unter dem Modell-Median. Historisch gutes Einstiegsniveau.'};

  if(ratio<1.0)  return{l:'Leicht günstig',c:'#a8d630',d:'Etwas unter dem Median. Solides Kaufniveau laut Power Law.'};

  if(ratio<1.2)  return{l:'Fair bewertet', c:'#ffd166',d:'Nahe am Power Law Median. Faire Bewertung nach dem Modell.'};

  if(ratio<1.8)  return{l:'Erhöht',        c:'#f7931a',d:'Über dem Median. Kein Schnäppchen, aber noch im normalen Bereich.'};

  if(ratio<2.5)  return{l:'Teuer',         c:'#ef6c47',d:'Deutlich über dem Median – historisch erhöhtes Korrekturrisiko.'};

  if(ratio<4.0)  return{l:'Sehr teuer',    c:'#ef476f',d:'Weit über dem Power Law. Entspricht historischen Blasen-Niveaus.'};

                 return{l:'Extrem teuer',  c:'#c0134e',d:'Extremes Niveau – historisch kurz vor starken Korrekturen.'};

}


function updateValuation(){

  const mp = parseFloat(document.getElementById('marketPrice').value)||PL_TODAY;

  const ratio = mp / PL_TODAY;

  const v = getVal(ratio);


  // Needle: log-scale, ratio 0.25…5 2%…98%

  const lMin=Math.log(0.25), lMax=Math.log(5);

  const lR=Math.log(Math.max(0.25,Math.min(5,ratio)));

  const pct = 2 + ((lR-lMin)/(lMax-lMin))*96;

  document.getElementById('heatNeedle').style.left = pct.toFixed(1)+'%';


  const sign = ratio>=1?'+':'';

  const diff = ((ratio-1)*100).toFixed(0);

  const pctEl = document.getElementById('valPct');

  pctEl.textContent = sign+diff+'%';

  pctEl.style.color = v.c;


  const badge = document.getElementById('valBadge');

  badge.textContent = v.l;

  badge.style.background = v.c+'22';

  badge.style.border = '1px solid '+v.c+'55';

  badge.style.color = v.c;


  document.getElementById('valDesc').textContent = v.d;

}


// ── RETIREMENT CALC ────────────────────────────────────────────────────────

function calculate(){

  const btc  = parseFloat(document.getElementById('btcAmount').value)||0;

  const mn   = parseFloat(document.getElementById('monthlyNeed').value)||3000;

  const wr   = parseFloat(document.getElementById('withdrawRate').value)/100||0.04;

  const yn   = mn*12;

  const target = yn/wr;


  document.getElementById('portfolioNow').textContent = fmt(btc*PL_TODAY);

  document.getElementById('targetCapital').textContent = fmt(target);


  let ry=null, rp=null, rv=null;

  for(let y=CY;y<=2070;y++){

    const p=plYear(y), pv=btc*p;

    if(pv>=target){ry=y;rp=p;rv=pv;break;}

  }


  const yEl=document.getElementById('retYear');

  const sEl=document.getElementById('retSub');

  const bEl=document.getElementById('retBadge');


  if(ry===null){

    yEl.innerHTML='<span style="color:var(--muted);font-size:40px">Nach 2070</span>';

    sEl.textContent='Mehr BTC oder niedrigeres Monatsziel nötig';

    bEl.textContent='> 44 Jahre'; bEl.style.color='var(--muted)';

  } else if(ry<=CY){

    yEl.innerHTML='<span class="already">Heute! 🎉</span>';

    sEl.textContent='Du könntest schon jetzt in Rente gehen!';

    bEl.textContent=' Bereits erreicht!'; bEl.style.color='var(--green)';

  } else {

    yEl.textContent=ry;

    const yl=ry-CY;

    sEl.textContent=' Preis laut Power Law bei '+fmt(rp);

    bEl.textContent=yl+' Jahr'+(yl===1?'':'e')+' bis zur Rente';

    bEl.style.color='var(--green)';

  }


  const fp=rp||PL_TODAY, fv=rv||(btc*PL_TODAY);

  document.getElementById('sPriceRet').textContent = fmtS(fp)+' €';

  document.getElementById('sPortRet').textContent  = fmtS(fv)+' €';

  document.getElementById('sMonthRet').textContent = fmt((fv*wr)/12);


  buildTimeline(btc, target, ry, wr);

}


// ── TIMELINE ───────────────────────────────────────────────────────────────

function buildTimeline(btc, target, ry, wr){

  const c=document.getElementById('timeline');

  c.innerHTML='';

  const end=Math.min(ry?ry+2:CY+20, 2060);

  let yrs=[];

  const span=end-CY, step=Math.max(1,Math.ceil(span/10));

  for(let y=CY;y<=end;y+=step) yrs.push(y);

  if(ry&&!yrs.includes(ry)) yrs.push(ry);

  yrs=[...new Set(yrs)].sort((a,b)=>a-b);


  const maxPV=btc*plYear(end)*1.2||1;


  yrs.forEach(y=>{

    const p=plYear(y), pv=btc*p;

    const pct=Math.min((pv/maxPV)*100,100);

    const isRet=ry&&y===ry, reached=pv>=target;


    const row=document.createElement('div');

    row.className='tl-row';

    row.innerHTML=`

      <div class="tl-yr ${isRet?'hl':''}">${y}</div>

      <div class="tl-bw"><div class="tl-b" style="width:0%;background:${isRet?'linear-gradient(90deg,var(--accent),var(--green))':'linear-gradient(90deg,var(--accent),var(--accent2))'}"></div></div>

      <div class="tl-amt">${fmt(pv)}</div>

      <div class="tl-mark">${isRet?'🎯':reached?'':''}</div>`;

    c.appendChild(row);

    setTimeout(()=>{row.querySelector('.tl-b').style.width=pct+'%';},50);

  });

}


// ── SYNC ───────────────────────────────────────────────────────────────────

function sync(iId,sId,cb){

  const i=document.getElementById(iId), s=document.getElementById(sId);

  i.addEventListener('input',()=>{s.value=i.value;cb();});

  s.addEventListener('input',()=>{i.value=s.value;cb();});

}

sync('btcAmount','btcSlider',calculate);

sync('monthlyNeed','monthlySlider',calculate);

sync('withdrawRate','withdrawSlider',calculate);

document.getElementById('marketPrice').addEventListener('input',updateValuation);


updateValuation();

calculate();


// Live-Preis beim Start laden

fetchLivePrice();

</script>


</body>

</html>