Calculator Tools Calculator Tools
Create

Roulette Row Predictor Pro - Live Pattern & Trend Stats Analyzer

Aug 20, 2026

About this app

Free real-time roulette row prediction tool, statistical trend analyzer, hot/cold street tracker, and AI probability pattern calculator for European & American roulette.

Roulette Row Predictor Pro - Live Pattern & Trend Stats Analyzer Row Predictor Pro Roulette Pattern Engine 0 Spins Tap Winning Number European Grid (0-36) Spin Random Sim +20 Undo Clear AI Row Recommendation Awaiting Input... Confidence 0% Enter winning numbers above or tap "Spin Random" to start prediction engine. Target Cold Numbers: No data Row Distribution & Delay Analysis Row 1 (1,4,7...34) 0 spins ago 33% prob 0% 0 hits Row 2 (2,5,8...35) 0 spins ago 33% prob 0% 0 hits Row 3 (3,6,9...36) 0 spins ago 33% prob 0% 0 hits Side Metrics & Dozens Red 50% Black 50% Doz 1 (1-12) 0 (0%) Doz 2 (13-24) 0 (0%) Doz 3 (25-36) 0 (0%) 0 Evens 0 Odds Spin History Timeline Newest → Oldest

Related apps

Put this on your site

Source

                    <html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">

<title>Roulette Row Predictor Pro - Live Pattern & Trend Stats Analyzer</title>
<meta name="description" content="Free real-time roulette row prediction tool, statistical trend analyzer, hot/cold street tracker, and AI probability pattern calculator for European & American roulette.">
<meta name="keywords" content="roulette predictor, roulette row prediction, roulette column tracker, casino stats, streak analyzer, roulette probability tool">

<!-- Libraries -->
<!-- jQuery (3.6.0) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js" crossorigin="anonymous"></script>
<!-- Bootstrap CSS (5.3.3) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" crossorigin="anonymous">
<!-- Bootstrap JS (5.3.3) -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js" crossorigin="anonymous"></script>
<!-- Font Awesome (6.6.0) -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" crossorigin="anonymous">


<script type="text/javascript">
try {
// App Javascript Goes Here
document.addEventListener("DOMContentLoaded", function() {
// Number definitions (European 0-36)
const redNumbers = [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36];
const row1Numbers = [1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34];
const row2Numbers = [2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35];
const row3Numbers = [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36];

let history = [];
let soundEnabled = true;

// Web Audio API Synth
const AudioCtx = window.AudioContext || window.webkitAudioContext;
let audioCtx = null;

function playSound(type) {
if (!soundEnabled) return;
try {
if (!audioCtx) audioCtx = new AudioCtx();
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.connect(gain);
gain.connect(audioCtx.destination);

if (type === 'tap') {
osc.frequency.setValueAtTime(440, audioCtx.currentTime);
osc.frequency.exponentialRampToValueAtTime(880, audioCtx.currentTime + 0.08);
gain.gain.setValueAtTime(0.15, audioCtx.currentTime);
gain.gain.linearRampToValueAtTime(0.01, audioCtx.currentTime + 0.08);
osc.start();
osc.stop(audioCtx.currentTime + 0.08);
} else if (type === 'spin') {
osc.type = 'triangle';
osc.frequency.setValueAtTime(200, audioCtx.currentTime);
osc.frequency.linearRampToValueAtTime(600, audioCtx.currentTime + 0.25);
gain.gain.setValueAtTime(0.2, audioCtx.currentTime);
gain.gain.linearRampToValueAtTime(0.01, audioCtx.currentTime + 0.25);
osc.start();
osc.stop(audioCtx.currentTime + 0.25);
} else if (type === 'clear') {
osc.type = 'sawtooth';
osc.frequency.setValueAtTime(300, audioCtx.currentTime);
osc.frequency.linearRampToValueAtTime(150, audioCtx.currentTime + 0.15);
gain.gain.setValueAtTime(0.15, audioCtx.currentTime);
gain.gain.linearRampToValueAtTime(0.01, audioCtx.currentTime + 0.15);
osc.start();
osc.stop(audioCtx.currentTime + 0.15);
}
} catch (e) {
console.log("Audio not allowed yet");
}
}

// Get metadata for a number
function getNumInfo(num) {
num = parseInt(num, 10);
if (num === 0) {
return { num: 0, color: 'green', row: 0, dozen: 0, parity: 'none', hl: 'none' };
}
const color = redNumbers.includes(num) ? 'red' : 'black';
let row = 1;
if (row2Numbers.includes(num)) row = 2;
if (row3Numbers.includes(num)) row = 3;

let dozen = 1;
if (num > 12 && num <= 24) dozen = 2;
if (num > 24) dozen = 3;

const parity = (num % 2 === 0) ? 'even' : 'odd';
const hl = (num >= 19) ? 'high' : 'low';

return { num, color, row, dozen, parity, hl };
}

// Render Roulette Grid
function buildGrid() {
const gridEl = $('#roulette-grid');
gridEl.empty();

// Zero cell
const zeroCell = $(`<div class="grid-num num-green zero-btn" data-num="0">
<span class="fw-bold">0</span>
</div>`);
gridEl.append(zeroCell);

// Numbers container for 3 rows
const numBoard = $('<div class="num-board"></div>');

// Standard Roulette Layout (Top row: 3,6,9... Middle: 2,5,8... Bottom: 1,4,7...)
const rowsArr = [
{ id: 3, nums: row3Numbers, label: 'Row 3 (3-36)' },
{ id: 2, nums: row2Numbers, label: 'Row 2 (2-35)' },
{ id: 1, nums: row1Numbers, label: 'Row 1 (1-34)' }
];

rowsArr.forEach(r => {
const rowLine = $(`<div class="board-row" data-row-id="${r.id}"></div>`);
r.nums.forEach(n => {
const colClass = redNumbers.includes(n) ? 'num-red' : 'num-black';
rowLine.append(`<button class="grid-num ${colClass}" data-num="${n}">${n}</button>`);
});
// Row label indicator at end
rowLine.append(`<div class="row-label-badge" data-row="${r.id}">R${r.id}</div>`);
numBoard.append(rowLine);
});

gridEl.append(numBoard);
}

// Handle Number Click
$(document).on('click', '.grid-num', function() {
const num = parseInt($(this).data('num'), 10);
addSpin(num);
playSound('tap');
});

// Add spin to history
function addSpin(num) {
const info = getNumInfo(num);
history.unshift(info); // newest first
updateUI();
}

// Random Spin Button
$('#btn-random').on('click', function() {
const rand = Math.floor(Math.random() * 37);
addSpin(rand);
playSound('spin');
});

// Undo Button
$('#btn-undo').on('click', function() {
if (history.length > 0) {
history.shift();
playSound('clear');
updateUI();
}
});

// Clear History
$('#btn-clear').on('click', function() {
if (confirm("Reset all history and statistical predictions?")) {
history = [];
playSound('clear');
updateUI();
}
});

// Sound Toggle
$('#btn-sound').on('click', function() {
soundEnabled = !soundEnabled;
$(this).toggleClass('btn-outline-warning btn-warning');
$(this).html(soundEnabled ? '<i class="fa-solid fa-volume-high"></i>' : '<i class="fa-solid fa-volume-xmark"></i>');
});

// Simulate Batch
$('#btn-sim').on('click', function() {
for (let i = 0; i < 20; i++) {
const rand = Math.floor(Math.random() * 37);
history.unshift(getNumInfo(rand));
}
playSound('spin');
updateUI();
});

// Main Predictor Engine
function calculatePredictions() {
if (history.length === 0) {
return {
bestRow: 'None',
confidence: 0,
reason: 'Enter winning numbers above or tap "Random Spin" to start prediction engine.',
r1: 0, r2: 0, r3: 0,
delay1: 0, delay2: 0, delay3: 0,
count1: 0, count2: 0, count3: 0, zeroCount: 0
};
}

let count1 = 0, count2 = 0, count3 = 0, zeroCount = 0;
let delay1 = -1, delay2 = -1, delay3 = -1;

history.forEach((item, index) => {
if (item.row === 1) { count1++; if (delay1 === -1) delay1 = index; }
if (item.row === 2) { count2++; if (delay2 === -1) delay2 = index; }
if (item.row === 3) { count3++; if (delay3 === -1) delay3 = index; }
if (item.row === 0) { zeroCount++; }
});

if (delay1 === -1) delay1 = history.length;
if (delay2 === -1) delay2 = history.length;
if (delay3 === -1) delay3 = history.length;

// Algorithm Weights
// 1. Due / Delay Factor (Higher delay = higher weight for reversion to mean)
const meanDelay = 3.0; // Theoretical expected hit interval for 12/37 (~32.4%)
const scoreDelay1 = Math.pow(delay1 / meanDelay, 1.4);
const scoreDelay2 = Math.pow(delay2 / meanDelay, 1.4);
const scoreDelay3 = Math.pow(delay3 / meanDelay, 1.4);

// 2. Short-term pattern trend (Last 10 spins)
const recent = history.slice(0, 10);
let r1Recent = 0, r2Recent = 0, r3Recent = 0;
recent.forEach(r => {
if (r.row === 1) r1Recent++;
if (r.row === 2) r2Recent++;
if (r.row === 3) r3Recent++;
});

// 3. Markov chain sequence prediction (Transitions from last spin's row)
let markovWeight1 = 1, markovWeight2 = 1, markovWeight3 = 1;
if (history.length >= 2) {
const lastRow = history[0].row;
if (lastRow !== 0) {
let trans1 = 0, trans2 = 0, trans3 = 0, totalTrans = 0;
for (let i = 0; i < history.length - 1; i++) {
if (history[i+1].row === lastRow) {
totalTrans++;
const nextR = history[i].row;
if (nextR === 1) trans1++;
if (nextR === 2) trans2++;
if (nextR === 3) trans3++;
}
}
if (totalTrans > 0) {
markovWeight1 += (trans1 / totalTrans) * 1.5;
markovWeight2 += (trans2 / totalTrans) * 1.5;
markovWeight3 += (trans3 / totalTrans) * 1.5;
}
}
}

// Combine Scores
let finalScore1 = (scoreDelay1 * 2) + (10 - r1Recent) + markovWeight1;
let finalScore2 = (scoreDelay2 * 2) + (10 - r2Recent) + markovWeight2;
let finalScore3 = (scoreDelay3 * 2) + (10 - r3Recent) + markovWeight3;

const totalScore = finalScore1 + finalScore2 + finalScore3;
const pct1 = Math.round((finalScore1 / totalScore) * 100);
const pct2 = Math.round((finalScore2 / totalScore) * 100);
const pct3 = 100 - pct1 - pct2;

let bestRow = 1;
let maxPct = pct1;
if (pct2 > maxPct) { bestRow = 2; maxPct = pct2; }
if (pct3 > maxPct) { bestRow = 3; maxPct = pct3; }

// Reason text generation
let maxDelay = Math.max(delay1, delay2, delay3);
let reason = "";
if (maxDelay >= 5) {
reason = `Row ${bestRow} is statistically overdue (no hit for ${maxDelay} consecutive spins). High mean-reversion probability.`;
} else if (history.length < 10) {
reason = `Initial trend detected. Row ${bestRow} shows strong Markov transition probability based on small sample size.`;
} else {
reason = `Pattern engine identified Row ${bestRow} as optimal balance of delay cycle and transition frequency.`;
}

return {
bestRow: `ROW ${bestRow}`,
bestRowNum: bestRow,
confidence: Math.min(Math.max(maxPct, 34), 88),
reason,
r1: pct1, r2: pct2, r3: pct3,
delay1, delay2, delay3,
count1, count2, count3, zeroCount
};
}

// Update UI Dashboard
function updateUI() {
const stats = calculatePredictions();

// Spin Count Header Badge
$('#total-spins-badge').text(`${history.length} Spins`);

// Prediction Card Output
if (history.length === 0) {
$('#pred-row-output').html(`<span class="text-muted fs-5">Awaiting Input...</span>`);
$('#pred-confidence').text(`0%`);
$('#pred-bar').css('width', '0%');
$('#pred-reason').text(stats.reason);
$('#rec-numbers-list').html('<span class="text-muted small">No data</span>');
} else {
const rowColorClass = stats.bestRowNum === 1 ? 'badge-r1' : (stats.bestRowNum === 2 ? 'badge-r2' : 'badge-r3');
$('#pred-row-output').html(`<span class="badge ${rowColorClass} fs-3 glow-effect">${stats.bestRow}</span>`);
$('#pred-confidence').text(`${stats.confidence}%`);
$('#pred-bar').css('width', `${stats.confidence}%`);
$('#pred-reason').text(stats.reason);

// Recommend specific numbers from that row
let targetNums = stats.bestRowNum === 1 ? row1Numbers : (stats.bestRowNum === 2 ? row2Numbers : row3Numbers);
// Find numbers in target row that haven't hit recently
let recentNums = history.slice(0, 15).map(x => x.num);
let coldInRow = targetNums.filter(n => !recentNums.includes(n));
if (coldInRow.length === 0) coldInRow = targetNums.slice(0, 5);

let recHtml = coldInRow.slice(0, 5).map(n => {
const c = redNumbers.includes(n) ? 'num-red-sm' : 'num-black-sm';
return `<span class="mini-num-pill ${c}">${n}</span>`;
}).join(' ');
$('#rec-numbers-list').html(recHtml);
}

// Update Row Stat Bars & Delay Counter
const total = history.length || 1;

// Row 1
const p1 = Math.round((stats.count1 / total) * 100);
$('#bar-r1').css('width', `${p1}%`).text(`${p1}%`);
$('#stat-r1-count').text(`${stats.count1} hits`);
$('#delay-r1').text(`${stats.delay1} spins ago`);
$('#prob-r1-tag').text(`${stats.r1}% AI prob`);

// Row 2
const p2 = Math.round((stats.count2 / total) * 100);
$('#bar-r2').css('width', `${p2}%`).text(`${p2}%`);
$('#stat-r2-count').text(`${stats.count2} hits`);
$('#delay-r2').text(`${stats.delay2} spins ago`);
$('#prob-r2-tag').text(`${stats.r2}% AI prob`);

// Row 3
const p3 = Math.round((stats.count3 / total) * 100);
$('#bar-r3').css('width', `${p3}%`).text(`${p3}%`);
$('#stat-r3-count').text(`${stats.count3} hits`);
$('#delay-r3').text(`${stats.delay3} spins ago`);
$('#prob-r3-tag').text(`${stats.r3}% AI prob`);

// Dozens & Color Distribution Breakdown
let reds = 0, blacks = 0, greens = 0;
let doz1 = 0, doz2 = 0, doz3 = 0;
let evens = 0, odds = 0;

history.forEach(item => {
if (item.color === 'red') reds++;
else if (item.color === 'black') blacks++;
else greens++;

if (item.dozen === 1) doz1++;
if (item.dozen === 2) doz2++;
if (item.dozen === 3) doz3++;

if (item.parity === 'even') evens++;
if (item.parity === 'odd') odds++;
});

const redPct = Math.round((reds / total) * 100);
const blkPct = Math.round((blacks / total) * 100);
$('#bar-red').css('width', `${redPct}%`).text(`Red ${redPct}%`);
$('#bar-black').css('width', `${blkPct}%`).text(`Black ${blkPct}%`);

$('#doz-1-cnt').text(`${doz1} (${Math.round(doz1/total*100)}%)`);
$('#doz-2-cnt').text(`${doz2} (${Math.round(doz2/total*100)}%)`);
$('#doz-3-cnt').text(`${doz3} (${Math.round(doz3/total*100)}%)`);

$('#even-cnt').text(`${evens} Evens`);
$('#odd-cnt').text(`${odds} Odds`);

// Update History Tape
const tape = $('#history-tape');
tape.empty();

if (history.length === 0) {
tape.html('<div class="text-muted small py-2">No spins recorded yet. Tap numbers above.</div>');
} else {
history.forEach(item => {
const colorClass = item.color === 'red' ? 'bg-danger' : (item.color === 'black' ? 'bg-dark border border-secondary' : 'bg-success');
const rowText = item.row === 0 ? 'Z' : `R${item.row}`;
const el = $(`
<div class="tape-item ${colorClass} text-white">
<span class="num-val">${item.num}</span>
<span class="row-tag">${rowText}</span>
</div>
`);
tape.append(el);
});
}
}

// Initial Build
buildGrid();
updateUI();
});

} catch (error) {
throw error;
}
</script>

<style>
/* Base Mobile-First Styles */
*, *::before, *::after { box-sizing: border-box; }
html, body {
margin: 0;
padding: 0;
width: 100%;
max-width: 100%;
background-color: #0d1117;
color: #e6edf3;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
-webkit-text-size-adjust: 100%;
}

#main-container {
width: 100%;
max-width: 800px;
margin: 0 auto;
padding: 0.75rem;
padding-bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
}

/* Custom Casino Theme Components */
.app-header {
background: linear-gradient(135deg, #161b22 0%, #21262d 100%);
border: 1px solid #30363d;
border-radius: 12px;
padding: 0.75rem 1rem;
margin-bottom: 0.75rem;
}

.app-title {
font-size: 1.25rem;
font-weight: 800;
background: linear-gradient(90deg, #f1e05a, #d4af37);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin: 0;
}

/* Interactive Grid Layout */
.grid-card {
background: #161b22;
border: 1px solid #30363d;
border-radius: 12px;
padding: 0.75rem;
margin-bottom: 0.75rem;
}

#roulette-grid {
display: flex;
gap: 4px;
user-select: none;
overflow-x: auto;
padding-bottom: 4px;
}

.zero-btn {
width: 38px;
min-width: 38px;
display: flex;
align-items: center;
justify-content: center;
background: #198754;
color: white;
border-radius: 6px;
cursor: pointer;
border: 1px solid #2abe74;
}
.zero-btn:active { transform: scale(0.95); }

.num-board {
display: flex;
flex-direction: column;
gap: 4px;
flex-grow: 1;
}

.board-row {
display: flex;
gap: 4px;
}

.grid-num {
flex: 1;
min-width: 26px;
height: 38px;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.85rem;
font-weight: 700;
border-radius: 4px;
border: none;
color: white;
cursor: pointer;
transition: transform 0.1s ease;
}
.grid-num:active { transform: scale(0.92); }

.num-red { background-color: #dc3545; border: 1px solid #ea6270; }
.num-black { background-color: #212529; border: 1px solid #495057; }
.num-green { background-color: #198754; border: 1px solid #2abe74; }

.row-label-badge {
width: 32px;
min-width: 32px;
height: 38px;
display: flex;
align-items: center;
justify-content: center;
background: #0d1117;
border: 1px solid #454c54;
border-radius: 4px;
font-size: 0.75rem;
font-weight: 800;
color: #f1e05a;
}

/* Quick Controls Bar */
.control-btn-group {
display: flex;
gap: 6px;
flex-wrap: wrap;
margin-top: 0.5rem;
}
.control-btn-group .btn {
flex: 1;
min-width: 80px;
font-size: 0.8rem;
font-weight: 600;
padding: 0.4rem 0.5rem;
}

/* Prediction Engine Box */
.prediction-card {
background: linear-gradient(145deg, #1c2128 0%, #161b22 100%);
border: 2px solid #d4af37;
border-radius: 12px;
padding: 1rem;
margin-bottom: 0.75rem;
box-shadow: 0 4px 15px rgba(212, 175, 55, 0.15);
}

.badge-r1 { background-color: #0d6efd; color: white; }
.badge-r2 { background-color: #fd7e14; color: white; }
.badge-r3 { background-color: #6f42c1; color: white; }

.glow-effect {
box-shadow: 0 0 10px rgba(255, 255, 255, 0.3);
padding: 0.25rem 0.75rem;
border-radius: 6px;
}

.confidence-meter {
height: 8px;
background-color: #21262d;
border-radius: 4px;
overflow: hidden;
}
.confidence-bar {
height: 100%;
background: linear-gradient(90deg, #20c997, #f1e05a);
width: 0%;
transition: width 0.4s ease;
}

.mini-num-pill {
display: inline-block;
width: 26px;
height: 26px;
line-height: 26px;
text-align: center;
border-radius: 50%;
font-size: 0.75rem;
font-weight: 700;
color: white;
margin-right: 4px;
}
.num-red-sm { background-color: #dc3545; }
.num-black-sm { background-color: #343a40; border: 1px solid #6c757d; }

/* Detailed Stats Breakdown */
.stats-card {
background: #161b22;
border: 1px solid #30363d;
border-radius: 12px;
padding: 0.85rem;
margin-bottom: 0.75rem;
}

.stat-row-item {
margin-bottom: 0.65rem;
}
.stat-row-item:last-child { margin-bottom: 0; }

.row-progress {
height: 16px;
background-color: #21262d;
border-radius: 8px;
overflow: hidden;
font-size: 0.7rem;
font-weight: 700;
}

/* History Tape */
.tape-container {
display: flex;
gap: 6px;
overflow-x: auto;
padding: 0.25rem 0;
white-space: nowrap;
scrollbar-width: thin;
}

.tape-item {
display: inline-flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 36px;
min-width: 36px;
height: 44px;
border-radius: 6px;
font-size: 0.85rem;
font-weight: 700;
flex-shrink: 0;
}
.tape-item .row-tag {
font-size: 0.6rem;
opacity: 0.85;
font-weight: 400;
}

/* Secondary stats pills */
.stat-pill-sm {
background: #21262d;
border: 1px solid #30363d;
border-radius: 6px;
padding: 0.25rem 0.5rem;
font-size: 0.75rem;
}
</style>
</head>
<body>
<div id="main-container">
<!-- Header -->
<div class="app-header d-flex align-items-center justify-content-between">
<div>
<h1 class="app-title"><i class="fa-solid fa-chart-line me-1"></i> Row Predictor Pro</h1>
<div class="text-secondary small">Roulette Pattern Engine</div>
</div>
<div class="d-flex align-items-center gap-2">
<span id="total-spins-badge" class="badge bg-secondary">0 Spins</span>
<button id="btn-sound" class="btn btn-sm btn-outline-warning" title="Toggle Sound">
<i class="fa-solid fa-volume-high"></i>
</button>
</div>
</div>

<!-- Interactive Roulette Grid -->
<div class="grid-card">
<div class="d-flex justify-content-between align-items-center mb-2">
<span class="small fw-bold text-uppercase text-secondary"><i class="fa-solid fa-hand-pointer me-1"></i> Tap Winning Number</span>
<span class="small text-muted">European Grid (0-36)</span>
</div>

<div id="roulette-grid">
<!-- Dynamic Grid JS -->
</div>

<!-- Action Controls -->
<div class="control-btn-group">
<button id="btn-random" class="btn btn-primary"><i class="fa-solid fa-dice me-1"></i> Spin Random</button>
<button id="btn-sim" class="btn btn-outline-info"><i class="fa-solid fa-bolt me-1"></i> Sim +20</button>
<button id="btn-undo" class="btn btn-outline-secondary"><i class="fa-solid fa-rotate-left me-1"></i> Undo</button>
<button id="btn-clear" class="btn btn-outline-danger"><i class="fa-solid fa-trash me-1"></i> Clear</button>
</div>
</div>

<!-- AI Prediction Card -->
<div class="prediction-card">
<div class="d-flex justify-content-between align-items-start mb-2">
<div>
<span class="text-uppercase fw-bold text-warning small tracking-wide"><i class="fa-solid fa-brain me-1"></i> AI Row Recommendation</span>
<div id="pred-row-output" class="mt-1">
<span class="text-muted fs-5">Awaiting Input...</span>
</div>
</div>
<div class="text-end">
<span class="text-secondary small">Confidence</span>
<div id="pred-confidence" class="fs-4 fw-bold text-success">0%</div>
</div>
</div>

<div class="confidence-meter mb-2">
<div id="pred-bar" class="confidence-bar"></div>
</div>

<div id="pred-reason" class="small text-secondary mb-2">
Enter winning numbers above or tap "Spin Random" to start prediction engine.
</div>

<div class="d-flex align-items-center justify-content-between pt-2 border-top border-secondary">
<span class="small fw-bold text-light">Target Cold Numbers:</span>
<div id="rec-numbers-list">
<span class="text-muted small">No data</span>
</div>
</div>
</div>

<!-- Statistical Breakdown Cards -->
<div class="stats-card">
<div class="fw-bold small text-uppercase text-secondary mb-2"><i class="fa-solid fa-bars-staggered me-1"></i> Row Distribution & Delay Analysis</div>

<!-- Row 1 -->
<div class="stat-row-item">
<div class="d-flex justify-content-between align-items-center small mb-1">
<span class="fw-bold text-primary">Row 1 <span class="text-muted fw-normal">(1,4,7...34)</span></span>
<div>
<span id="delay-r1" class="badge bg-dark border border-secondary text-light me-1">0 spins ago</span>
<span id="prob-r1-tag" class="badge bg-primary">33% prob</span>
</div>
</div>
<div class="progress row-progress">
<div id="bar-r1" class="progress-bar bg-primary" role="progressbar" style="width: 0%">0%</div>
</div>
<div id="stat-r1-count" class="text-end text-muted small mt-1">0 hits</div>
</div>

<!-- Row 2 -->
<div class="stat-row-item">
<div class="d-flex justify-content-between align-items-center small mb-1">
<span class="fw-bold" style="color: #fd7e14;">Row 2 <span class="text-muted fw-normal">(2,5,8...35)</span></span>
<div>
<span id="delay-r2" class="badge bg-dark border border-secondary text-light me-1">0 spins ago</span>
<span id="prob-r2-tag" class="badge bg-warning text-dark">33% prob</span>
</div>
</div>
<div class="progress row-progress">
<div id="bar-r2" class="progress-bar bg-warning" role="progressbar" style="width: 0%">0%</div>
</div>
<div id="stat-r2-count" class="text-end text-muted small mt-1">0 hits</div>
</div>

<!-- Row 3 -->
<div class="stat-row-item">
<div class="d-flex justify-content-between align-items-center small mb-1">
<span class="fw-bold" style="color: #a370f7;">Row 3 <span class="text-muted fw-normal">(3,6,9...36)</span></span>
<div>
<span id="delay-r3" class="badge bg-dark border border-secondary text-light me-1">0 spins ago</span>
<span id="prob-r3-tag" class="badge bg-info text-dark">33% prob</span>
</div>
</div>
<div class="progress row-progress">
<div id="bar-r3" class="progress-bar bg-info" role="progressbar" style="width: 0%">0%</div>
</div>
<div id="stat-r3-count" class="text-end text-muted small mt-1">0 hits</div>
</div>
</div>

<!-- Secondary Stats Grid -->
<div class="stats-card">
<div class="fw-bold small text-uppercase text-secondary mb-2"><i class="fa-solid fa-chart-pie me-1"></i> Side Metrics & Dozens</div>
<div class="row g-2">
<div class="col-12 mb-1">
<div class="progress" style="height: 14px;">
<div id="bar-red" class="progress-bar bg-danger" role="progressbar" style="width: 50%">Red 50%</div>
<div id="bar-black" class="progress-bar bg-dark" role="progressbar" style="width: 50%">Black 50%</div>
</div>
</div>
<div class="col-4">
<div class="stat-pill-sm text-center">
<div class="text-muted small">Doz 1 (1-12)</div>
<div id="doz-1-cnt" class="fw-bold">0 (0%)</div>
</div>
</div>
<div class="col-4">
<div class="stat-pill-sm text-center">
<div class="text-muted small">Doz 2 (13-24)</div>
<div id="doz-2-cnt" class="fw-bold">0 (0%)</div>
</div>
</div>
<div class="col-4">
<div class="stat-pill-sm text-center">
<div class="text-muted small">Doz 3 (25-36)</div>
<div id="doz-3-cnt" class="fw-bold">0 (0%)</div>
</div>
</div>
<div class="col-6">
<div class="stat-pill-sm text-center">
<span id="even-cnt" class="fw-bold text-info">0 Evens</span>
</div>
</div>
<div class="col-6">
<div class="stat-pill-sm text-center">
<span id="odd-cnt" class="fw-bold text-warning">0 Odds</span>
</div>
</div>
</div>
</div>

<!-- Live Spin History Tape -->
<div class="stats-card">
<div class="d-flex justify-content-between align-items-center mb-2">
<span class="fw-bold small text-uppercase text-secondary"><i class="fa-solid fa-clock-rotate-left me-1"></i> Spin History Timeline</span>
<span class="small text-muted">Newest &rarr; Oldest</span>
</div>
<div id="history-tape" class="tape-container">
<!-- History JS -->
</div>
</div>
</div>
</body>
</html>