A creation shared by its maker. The page below runs in a sandbox that cannot read anything of yours or talk to any server. Read the source before you run it anywhere else.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fibonacci Calculator</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
background: #0d1117; color: #e6edf3; min-height: 100vh;
display: flex; flex-direction: column; align-items: center;
padding: 2.5rem 1.5rem; gap: 2rem;
}
h1 {
font-size: clamp(1.8rem, 5vw, 2.8rem); font-weight: 900; letter-spacing: -1px;
background: linear-gradient(90deg, #ff7b72, #d2a8ff, #79c0ff);
-webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
.sub { color: #8b949e; margin-top: -.5rem; }
.tabs { display: flex; gap: .5rem; background: #161b22; padding: .4rem; border-radius: 12px; flex-wrap: wrap; }
.tab {
padding: .6rem 1.2rem; border-radius: 8px; cursor: pointer; font-weight: 600;
color: #8b949e; border: none; background: transparent; font-size: .95rem; transition: .15s;
}
.tab.active { background: #21262d; color: #e6edf3; }
.panel { width: 100%; max-width: 640px; background: #161b22; border: 1px solid #30363d;
border-radius: 16px; padding: 2rem; display: none; }
.panel.active { display: block; }
label { display: block; font-size: .85rem; color: #8b949e; margin-bottom: .4rem; }
input {
width: 100%; background: #0d1117; border: 1px solid #30363d; color: #e6edf3;
padding: .75rem .9rem; border-radius: 10px; font-size: 1.1rem; font-family: inherit;
}
input:focus { outline: none; border-color: #79c0ff; box-shadow: 0 0 0 3px rgba(121,192,255,.18); }
.row { display: flex; gap: 1rem; align-items: flex-end; margin-bottom: 1.2rem; flex-wrap: wrap; }
.row > div { flex: 1; min-width: 140px; }
button.calc {
background: linear-gradient(90deg, #ff7b72, #d2a8ff); color: #0d1117; border: none;
padding: .75rem 1.8rem; border-radius: 10px; font-weight: 800; font-size: 1rem; cursor: pointer;
transition: transform .12s;
}
button.calc:hover { transform: translateY(-2px); }
.result {
margin-top: 1.4rem; padding: 1.2rem 1.4rem; background: #0d1117; border-radius: 12px;
border: 1px solid #30363d; font-size: 1.05rem; line-height: 1.7;
}
.result .big { font-size: 1.8rem; font-weight: 900; color: #79c0ff; word-break: break-all; }
.result .label { color: #8b949e; font-size: .85rem; text-transform: uppercase; letter-spacing: .08em; }
.seq { font-family: 'SF Mono', ui-monospace, monospace; font-size: .9rem; line-height: 1.9;
word-break: break-all; color: #d2a8ff; }
.err { color: #ff7b72; font-weight: 600; }
.spiral { display: flex; justify-content: center; margin-top: 1rem; }
footer { color: #484f58; font-size: .8rem; text-align: center; }
code { background: #21262d; padding: .15rem .4rem; border-radius: 5px; font-size: .85em; }
</style>
</head>
<body>
<h1>🔢 Fibonacci Calculator</h1>
<p class="sub">The sequence where each number is the sum of the two before it: 0, 1, 1, 2, 3, 5, 8…</p>
<div class="tabs">
<button class="tab active" data-tab="nth">Nth Term</button>
<button class="tab" data-tab="seq">Generate Sequence</button>
<button class="tab" data-tab="check">Is It Fibonacci?</button>
</div>
<!-- NTH -->
<div class="panel active" id="nth">
<label for="n-input">Which term? (n = position, starting at 0)</label>
<input id="n-input" type="number" min="0" max="2000" placeholder="e.g. 20" value="20">
<div class="row" style="margin-top:1rem;">
<button class="calc" onclick="computeNth()">Compute F(n)</button>
</div>
<div class="result" id="nth-result"><span class="label">Result</span><div class="big">—</div></div>
</div>
<!-- SEQUENCE -->
<div class="panel" id="seq">
<div class="row">
<div>
<label for="seq-from">From (n)</label>
<input id="seq-from" type="number" min="0" max="2000" value="0">
</div>
<div>
<label for="seq-to">To (n)</label>
<input id="seq-to" type="number" min="0" max="2000" value="15">
</div>
</div>
<button class="calc" onclick="computeSeq()">Generate</button>
<div class="result" id="seq-result"><span class="label">Sequence</span><div class="seq">—</div></div>
</div>
<!-- CHECK -->
<div class="panel" id="check">
<label for="check-input">Enter a number to test</label>
<input id="check-input" type="number" placeholder="e.g. 34" value="34">
<div class="row" style="margin-top:1rem;">
<button class="calc" onclick="checkFib()">Check</button>
</div>
<div class="result" id="check-result"><span class="label">Verdict</span><div class="big">—</div></div>
</div>
<footer>Built for nahstalgic · no external dependencies</footer>
<script>
function tabSwitch() {
document.querySelectorAll('.tab').forEach(t => {
t.onclick = () => {
document.querySelectorAll('.tab').forEach(x => x.classList.remove('active'));
document.querySelectorAll('.panel').forEach(x => x.classList.remove('active'));
t.classList.add('active');
document.getElementById(t.dataset.tab).classList.add('active');
};
});
}
tabSwitch();
// Big-int safe nth Fibonacci via fast doubling (handles huge n)
function fib(n) {
if (n < 0) return null;
let a = 0n, b = 1n; // F(0), F(1)
n = BigInt(n);
for (let bit = n.toString(2); bit.length; bit = bit.slice(1)) {
const c = a * (2n * b - a);
const d = a * a + b * b;
if (bit[0] === '1') { a = d; b = c + d; }
else { a = c; b = d; }
}
return a;
}
function computeNth() {
const el = document.getElementById('n-input');
const out = document.getElementById('nth-result');
const n = parseInt(el.value);
if (isNaN(n) || n < 0) { out.innerHTML = '<span class="err">Enter a non-negative integer.</span>'; return; }
if (n > 2000) { out.innerHTML = '<span class="err">Keep n ≤ 2000 (that\'s already ~418 digits!).</span>'; return; }
const val = fib(n);
out.innerHTML = `<span class="label">F(${n})</span><div class="big">${val}</div><div style="color:#8b949e;margin-top:.4rem">${val.toString().length} digits</div>`;
}
function computeSeq() {
const f = parseInt(document.getElementById('seq-from').value);
const t = parseInt(document.getElementById('seq-to').value);
const out = document.getElementById('seq-result');
if (isNaN(f) || isNaN(t) || f < 0 || t < f) { out.innerHTML = '<span class="err">Enter valid from ≤ to, both ≥ 0.</span>'; return; }
if (t - f > 200) { out.innerHTML = '<span class="err">Max 200 terms per view.</span>'; return; }
const terms = [];
for (let i = f; i <= t; i++) terms.push(`F(${i})=${fib(i)}`);
out.innerHTML = `<span class="label">Terms F(${f}) … F(${t})</span><div class="seq">${terms.join('<br>')}</div>`;
}
function isPerfectSquare(x) {
if (x < 0n) return false;
if (x < 2n) return true;
let lo = 0n, hi = x;
while (lo <= hi) {
const mid = (lo + hi) / 2n;
const sq = mid * mid;
if (sq === x) return true;
if (sq < x) lo = mid + 1n; else hi = mid - 1n;
}
return false;
}
function checkFib() {
const el = document.getElementById('check-input');
const out = document.getElementById('check-result');
const v = el.value.trim();
if (!/^\d+$/.test(v)) { out.innerHTML = '<span class="err">Enter a non-negative integer.</span>'; return; }
const n = BigInt(v);
// n is Fibonacci iff 5n^2 + 4 or 5n^2 - 4 is a perfect square
const t1 = 5n * n * n + 4n;
const t2 = 5n * n * n - 4n;
if (isPerfectSquare(t1) || isPerfectSquare(t2)) {
out.innerHTML = `<span class="label">${n} is a Fibonacci number</span><div class="big">✓ YES</div>`;
} else {
out.innerHTML = `<span class="label">${n} is NOT Fibonacci</span><div class="big">✗ NO</div>`;
}
}
computeNth(); // demo on load
</script>
</body>
</html>