| Server IP : 167.235.67.158 / Your IP : 216.73.216.95 Web Server : Apache System : Linux ubuntu-8gb-nbg1-1 6.8.0-111-generic #111-Ubuntu SMP PREEMPT_DYNAMIC Sat Apr 11 23:16:02 UTC 2026 x86_64 User : upstairsbar.co.uk ( 982) PHP Version : 8.3.6 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/bc.the-word.com/timer/ |
Upload File : |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Fractions Counter</title>
<style>
:root {
--bg: #0f172a;
--panel: #1e293b;
--accent: #38bdf8;
--accent-2: #fbbf24;
--text: #f1f5f9;
--muted: #94a3b8;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body {
height: 100%;
}
body {
font-family: "Segoe UI", system-ui, -apple-system, Roboto, Helvetica, Arial, sans-serif;
background: radial-gradient(circle at top, #1e293b 0%, var(--bg) 70%);
color: var(--text);
min-height: 100vh;
display: flex;
flex-direction: column;
overflow: hidden;
}
header {
display: flex;
justify-content: space-between;
align-items: flex-start;
padding: clamp(16px, 4vw, 40px);
gap: 16px;
}
/* Top-left fraction */
.fraction {
display: inline-flex;
flex-direction: column;
align-items: center;
line-height: 1;
color: var(--accent);
font-weight: 700;
font-size: clamp(2.2rem, 9vw, 5rem);
min-width: 0;
}
.fraction .num,
.fraction .den {
padding: 0.1em 0.25em;
font-variant-numeric: tabular-nums;
}
.fraction .bar {
width: 100%;
min-width: 2.2ch;
height: 0.08em;
background: var(--accent);
border-radius: 999px;
margin: 0.06em 0;
}
/* Top-right index */
.index {
text-align: right;
flex-shrink: 0;
}
.index .label {
font-size: clamp(0.7rem, 2.5vw, 1rem);
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.15em;
}
.index .value {
font-size: clamp(2rem, 8vw, 4.5rem);
font-weight: 700;
color: var(--accent-2);
font-variant-numeric: tabular-nums;
}
/* Center decimal */
main {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
padding: 16px;
}
.decimal-label {
font-size: clamp(0.8rem, 3vw, 1.2rem);
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.2em;
margin-bottom: 0.3em;
}
.decimal {
font-size: clamp(3rem, 18vw, 11rem);
font-weight: 800;
font-variant-numeric: tabular-nums;
line-height: 1;
word-break: break-all;
}
footer {
text-align: center;
padding: clamp(12px, 3vw, 24px);
color: var(--muted);
font-size: clamp(0.7rem, 2.5vw, 0.95rem);
}
.done {
color: var(--accent-2);
}
</style>
</head>
<body>
<header>
<div class="fraction" id="fraction" aria-label="current fraction">
<span class="num" id="num">1</span>
<span class="bar"></span>
<span class="den" id="den">100</span>
</div>
<div class="index">
<div class="label">Index</div>
<div class="value" id="index">#1</div>
</div>
</header>
<main>
<div class="decimal-label">Decimal value</div>
<div class="decimal" id="decimal">0.01</div>
</main>
<footer id="footer">Counting up every second · refresh to restart</footer>
<script>
// Build the ordered list of fractions.
// Every fraction x/y with x,y in 1..100, sorted ascending by value.
// Duplicate values (e.g. 1/50 and 2/100) are collapsed to lowest terms,
// so the sequence is the unique coprime fractions from 1/100 up to 100/1.
function gcd(a, b) {
while (b) {
[a, b] = [b, a % b];
}
return a;
}
function buildFractions(max) {
const fractions = [];
for (let p = 1; p <= max; p++) {
for (let q = 1; q <= max; q++) {
if (gcd(p, q) === 1) {
fractions.push({ num: p, den: q, value: p / q });
}
}
}
fractions.sort((a, b) => a.value - b.value);
return fractions;
}
const fractions = buildFractions(100);
const numEl = document.getElementById("num");
const denEl = document.getElementById("den");
const indexEl = document.getElementById("index");
const decimalEl = document.getElementById("decimal");
const footerEl = document.getElementById("footer");
// Show a clean, readable decimal without long floating-point tails.
function formatDecimal(value) {
if (Number.isInteger(value)) return String(value);
return parseFloat(value.toFixed(6)).toString();
}
// Read a starting index from the URL hash, e.g. #3600 starts at index 3600.
// The hash uses the same 1-based numbering shown in the top-right (#1 = first).
function startIndexFromHash() {
const raw = window.location.hash.replace("#", "").trim();
const parsed = parseInt(raw, 10);
if (!Number.isFinite(parsed) || parsed < 1) return 0;
return Math.min(parsed - 1, fractions.length - 1);
}
let i = startIndexFromHash();
function render() {
const f = fractions[i];
numEl.textContent = f.num;
denEl.textContent = f.den;
indexEl.textContent = "#" + (i + 1);
decimalEl.textContent = formatDecimal(f.value);
}
render();
const timer = setInterval(() => {
if (i >= fractions.length - 1) {
clearInterval(timer);
footerEl.textContent = "Finished at 100/1 \u2013 refresh to restart";
footerEl.classList.add("done");
return;
}
i++;
render();
}, 1000);
</script>
</body>
</html>