Spaces:
Sleeping
Sleeping
dhruv575 commited on
Commit ·
da24b38
1
Parent(s): b672768
Improvements to structure and spacing
Browse files- static/index.html +18 -27
- static/script.js +60 -43
- static/styles.css +22 -11
static/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
<title>Safe Choices - Prediction Market Simulation</title>
|
| 7 |
-
<link rel="stylesheet" href="/static/styles.css?v=
|
| 8 |
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
| 9 |
</head>
|
| 10 |
<body>
|
|
@@ -49,32 +49,19 @@
|
|
| 49 |
<h2>Parameters</h2>
|
| 50 |
</div>
|
| 51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
<div class="controls-grid">
|
| 53 |
<!-- Base Parameters -->
|
| 54 |
-
<div class="control-group">
|
| 55 |
-
<label class="control-label">Starting Capital</label>
|
| 56 |
-
<input type="number" id="startingCapital" class="control-input" value="10000" min="1000" max="100000" step="1000">
|
| 57 |
-
<div class="control-subtitle">Initial investment amount</div>
|
| 58 |
-
</div>
|
| 59 |
-
|
| 60 |
<div class="control-group">
|
| 61 |
<label class="control-label">Number of Simulations</label>
|
| 62 |
<input type="number" id="numSimulations" class="control-input" value="100" min="10" max="100" step="10">
|
| 63 |
<div class="control-subtitle">Monte Carlo runs (max 100)</div>
|
| 64 |
</div>
|
| 65 |
|
| 66 |
-
<div class="control-group">
|
| 67 |
-
<label class="control-label">Start Date</label>
|
| 68 |
-
<input type="date" id="startDate" class="control-input" value="2025-01-01" min="2025-01-01">
|
| 69 |
-
<div class="control-subtitle">Simulation start date</div>
|
| 70 |
-
</div>
|
| 71 |
-
|
| 72 |
-
<div class="control-group">
|
| 73 |
-
<label class="control-label">Max Duration</label>
|
| 74 |
-
<input type="number" id="maxDuration" class="control-input" value="365" min="30" max="730" step="30">
|
| 75 |
-
<div class="control-subtitle">Maximum days</div>
|
| 76 |
-
</div>
|
| 77 |
-
|
| 78 |
<!-- Probability Thresholds -->
|
| 79 |
<div class="control-group">
|
| 80 |
<label class="control-label">Min Probability 7d</label>
|
|
@@ -96,12 +83,16 @@
|
|
| 96 |
|
| 97 |
<div class="control-group">
|
| 98 |
<label class="control-label">Market Selection Skew</label>
|
| 99 |
-
<
|
| 100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
</div>
|
| 102 |
|
| 103 |
<!-- Threshold-specific controls -->
|
| 104 |
-
<div class="control-group threshold-only"
|
| 105 |
<label class="control-label">Target Return</label>
|
| 106 |
<select id="targetReturn" class="control-input">
|
| 107 |
<option value="4.14">4.14% (Treasury Rate)</option>
|
|
@@ -113,7 +104,7 @@
|
|
| 113 |
</div>
|
| 114 |
|
| 115 |
<!-- Multi-fund specific controls -->
|
| 116 |
-
<div class="control-group multi-only"
|
| 117 |
<label class="control-label">Number of Funds</label>
|
| 118 |
<input type="number" id="numFunds" class="control-input" value="5" min="2" max="10" step="1">
|
| 119 |
<div class="control-subtitle">Independent funds (max 10)</div>
|
|
@@ -194,7 +185,7 @@
|
|
| 194 |
</div>
|
| 195 |
</div>
|
| 196 |
|
| 197 |
-
<div class="stat-card multi-stats"
|
| 198 |
<div class="stat-header">
|
| 199 |
<h3>Portfolio Stats</h3>
|
| 200 |
</div>
|
|
@@ -214,7 +205,7 @@
|
|
| 214 |
</div>
|
| 215 |
</div>
|
| 216 |
|
| 217 |
-
<div class="stat-card threshold-stats"
|
| 218 |
<div class="stat-header">
|
| 219 |
<h3>Target Achievement</h3>
|
| 220 |
</div>
|
|
@@ -255,7 +246,7 @@
|
|
| 255 |
</div>
|
| 256 |
</div>
|
| 257 |
|
| 258 |
-
<div class="chart-card multi-chart"
|
| 259 |
<div class="chart-header">
|
| 260 |
<h3>Fund Survivorship</h3>
|
| 261 |
</div>
|
|
@@ -268,6 +259,6 @@
|
|
| 268 |
</div>
|
| 269 |
</div>
|
| 270 |
|
| 271 |
-
<script src="/static/script.js?v=
|
| 272 |
</body>
|
| 273 |
</html>
|
|
|
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
<title>Safe Choices - Prediction Market Simulation</title>
|
| 7 |
+
<link rel="stylesheet" href="/static/styles.css?v=4">
|
| 8 |
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
| 9 |
</head>
|
| 10 |
<body>
|
|
|
|
| 49 |
<h2>Parameters</h2>
|
| 50 |
</div>
|
| 51 |
|
| 52 |
+
<!-- Hidden default values -->
|
| 53 |
+
<input type="hidden" id="startingCapital" value="10000">
|
| 54 |
+
<input type="hidden" id="startDate" value="2025-01-01">
|
| 55 |
+
<input type="hidden" id="maxDuration" value="365">
|
| 56 |
+
|
| 57 |
<div class="controls-grid">
|
| 58 |
<!-- Base Parameters -->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
<div class="control-group">
|
| 60 |
<label class="control-label">Number of Simulations</label>
|
| 61 |
<input type="number" id="numSimulations" class="control-input" value="100" min="10" max="100" step="10">
|
| 62 |
<div class="control-subtitle">Monte Carlo runs (max 100)</div>
|
| 63 |
</div>
|
| 64 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
<!-- Probability Thresholds -->
|
| 66 |
<div class="control-group">
|
| 67 |
<label class="control-label">Min Probability 7d</label>
|
|
|
|
| 83 |
|
| 84 |
<div class="control-group">
|
| 85 |
<label class="control-label">Market Selection Skew</label>
|
| 86 |
+
<select id="skewFactor" class="control-input">
|
| 87 |
+
<option value="0.1">Low</option>
|
| 88 |
+
<option value="0.3" selected>Medium</option>
|
| 89 |
+
<option value="0.5">High</option>
|
| 90 |
+
</select>
|
| 91 |
+
<div class="control-subtitle">Higher values encourage more trading</div>
|
| 92 |
</div>
|
| 93 |
|
| 94 |
<!-- Threshold-specific controls -->
|
| 95 |
+
<div class="control-group threshold-only">
|
| 96 |
<label class="control-label">Target Return</label>
|
| 97 |
<select id="targetReturn" class="control-input">
|
| 98 |
<option value="4.14">4.14% (Treasury Rate)</option>
|
|
|
|
| 104 |
</div>
|
| 105 |
|
| 106 |
<!-- Multi-fund specific controls -->
|
| 107 |
+
<div class="control-group multi-only">
|
| 108 |
<label class="control-label">Number of Funds</label>
|
| 109 |
<input type="number" id="numFunds" class="control-input" value="5" min="2" max="10" step="1">
|
| 110 |
<div class="control-subtitle">Independent funds (max 10)</div>
|
|
|
|
| 185 |
</div>
|
| 186 |
</div>
|
| 187 |
|
| 188 |
+
<div class="stat-card multi-stats">
|
| 189 |
<div class="stat-header">
|
| 190 |
<h3>Portfolio Stats</h3>
|
| 191 |
</div>
|
|
|
|
| 205 |
</div>
|
| 206 |
</div>
|
| 207 |
|
| 208 |
+
<div class="stat-card threshold-stats">
|
| 209 |
<div class="stat-header">
|
| 210 |
<h3>Target Achievement</h3>
|
| 211 |
</div>
|
|
|
|
| 246 |
</div>
|
| 247 |
</div>
|
| 248 |
|
| 249 |
+
<div class="chart-card multi-chart">
|
| 250 |
<div class="chart-header">
|
| 251 |
<h3>Fund Survivorship</h3>
|
| 252 |
</div>
|
|
|
|
| 259 |
</div>
|
| 260 |
</div>
|
| 261 |
|
| 262 |
+
<script src="/static/script.js?v=4"></script>
|
| 263 |
</body>
|
| 264 |
</html>
|
static/script.js
CHANGED
|
@@ -67,13 +67,13 @@ function selectSimulation(type) {
|
|
| 67 |
});
|
| 68 |
document.querySelector(`[data-sim="${type}"]`).classList.add('active');
|
| 69 |
|
| 70 |
-
// Show/hide conditional controls
|
| 71 |
document.querySelectorAll('.threshold-only').forEach(el => {
|
| 72 |
-
el.
|
| 73 |
});
|
| 74 |
|
| 75 |
document.querySelectorAll('.multi-only').forEach(el => {
|
| 76 |
-
el.
|
| 77 |
});
|
| 78 |
|
| 79 |
updateEstimatedTime();
|
|
@@ -427,7 +427,7 @@ function displayResults(results) {
|
|
| 427 |
// Type-specific statistics
|
| 428 |
if (parameters.simType === 'multi') {
|
| 429 |
document.querySelectorAll('.multi-stats, .multi-chart').forEach(el => {
|
| 430 |
-
el.
|
| 431 |
});
|
| 432 |
|
| 433 |
document.getElementById('avgSurvivingFunds').textContent =
|
|
@@ -439,13 +439,13 @@ function displayResults(results) {
|
|
| 439 |
document.getElementById('diversificationBenefit').textContent = diversificationBenefit;
|
| 440 |
} else {
|
| 441 |
document.querySelectorAll('.multi-stats, .multi-chart').forEach(el => {
|
| 442 |
-
el.
|
| 443 |
});
|
| 444 |
}
|
| 445 |
|
| 446 |
if (parameters.simType === 'threshold') {
|
| 447 |
document.querySelectorAll('.threshold-stats').forEach(el => {
|
| 448 |
-
el.
|
| 449 |
});
|
| 450 |
|
| 451 |
document.getElementById('targetReached').textContent = formatPercentage(summary.targetReachedRate || 0);
|
|
@@ -455,7 +455,7 @@ function displayResults(results) {
|
|
| 455 |
summary.targetReachedRate > 0.5 ? 'Better' : 'Similar';
|
| 456 |
} else {
|
| 457 |
document.querySelectorAll('.threshold-stats').forEach(el => {
|
| 458 |
-
el.
|
| 459 |
});
|
| 460 |
}
|
| 461 |
|
|
@@ -499,24 +499,23 @@ function generateCharts(results) {
|
|
| 499 |
}
|
| 500 |
}
|
| 501 |
|
| 502 |
-
//
|
| 503 |
-
const RETURN_BINS = [];
|
| 504 |
-
for (let i = -100; i <= 500; i += 5) {
|
| 505 |
-
RETURN_BINS.push(i);
|
| 506 |
-
}
|
| 507 |
-
|
| 508 |
-
// Create empty return chart
|
| 509 |
function createEmptyReturnChart() {
|
| 510 |
const ctx = document.getElementById('returnChart').getContext('2d');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 511 |
return new Chart(ctx, {
|
| 512 |
type: 'bar',
|
| 513 |
data: {
|
| 514 |
-
labels:
|
| 515 |
datasets: [{
|
| 516 |
label: 'Frequency',
|
| 517 |
-
data: new Array(
|
| 518 |
-
backgroundColor: 'rgba(
|
| 519 |
-
borderColor: '#
|
| 520 |
borderWidth: 1
|
| 521 |
}]
|
| 522 |
},
|
|
@@ -524,36 +523,49 @@ function createEmptyReturnChart() {
|
|
| 524 |
});
|
| 525 |
}
|
| 526 |
|
| 527 |
-
// Create return distribution chart with
|
| 528 |
function createReturnDistributionChart(runs) {
|
| 529 |
const ctx = document.getElementById('returnChart').getContext('2d');
|
| 530 |
const returns = runs.map(r => r.totalReturn * 100);
|
| 531 |
|
| 532 |
-
//
|
| 533 |
-
const
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 534 |
returns.forEach(ret => {
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
if (ret >= RETURN_BINS[i] && ret < RETURN_BINS[i + 1]) {
|
| 538 |
binCounts[i]++;
|
| 539 |
break;
|
| 540 |
}
|
| 541 |
}
|
| 542 |
// Handle values at or above the last bin
|
| 543 |
-
if (ret >=
|
| 544 |
-
binCounts[
|
| 545 |
}
|
| 546 |
});
|
| 547 |
|
| 548 |
return new Chart(ctx, {
|
| 549 |
type: 'bar',
|
| 550 |
data: {
|
| 551 |
-
labels:
|
| 552 |
datasets: [{
|
| 553 |
label: 'Frequency',
|
| 554 |
data: binCounts,
|
| 555 |
-
backgroundColor: 'rgba(
|
| 556 |
-
borderColor: '#
|
| 557 |
borderWidth: 1
|
| 558 |
}]
|
| 559 |
},
|
|
@@ -578,28 +590,33 @@ function createEmptyCapitalChart() {
|
|
| 578 |
function createCapitalEvolutionChart(runs) {
|
| 579 |
const ctx = document.getElementById('capitalChart').getContext('2d');
|
| 580 |
|
| 581 |
-
// Color palette for dark mode
|
| 582 |
const colors = [
|
| 583 |
-
{ border: '#
|
| 584 |
-
{ border: '#87BFFF', bg: 'rgba(135, 191, 255, 0.
|
|
|
|
| 585 |
{ border: '#87BFFF', bg: 'rgba(135, 191, 255, 0.06)' },
|
| 586 |
-
{ border: '#
|
| 587 |
-
{ border: '#87BFFF', bg: 'rgba(135, 191, 255, 0.02)' }
|
| 588 |
];
|
| 589 |
|
| 590 |
// Sample up to 5 runs
|
| 591 |
const sampleRuns = runs.slice(0, 5);
|
| 592 |
const datasets = sampleRuns.map((run, i) => {
|
| 593 |
-
// Use capitalHistory if available
|
| 594 |
let data = [];
|
| 595 |
if (run.capitalHistory && run.capitalHistory.length > 0) {
|
| 596 |
-
|
| 597 |
-
|
| 598 |
-
|
| 599 |
-
|
|
|
|
|
|
|
| 600 |
} else {
|
| 601 |
-
// Fallback: just show final capital
|
| 602 |
-
data = [
|
|
|
|
|
|
|
|
|
|
| 603 |
}
|
| 604 |
|
| 605 |
return {
|
|
@@ -607,9 +624,9 @@ function createCapitalEvolutionChart(runs) {
|
|
| 607 |
data: data,
|
| 608 |
borderColor: colors[i % colors.length].border,
|
| 609 |
backgroundColor: colors[i % colors.length].bg,
|
| 610 |
-
borderWidth:
|
| 611 |
fill: false,
|
| 612 |
-
tension: 0.
|
| 613 |
pointRadius: 0 // Hide points for cleaner look
|
| 614 |
};
|
| 615 |
});
|
|
|
|
| 67 |
});
|
| 68 |
document.querySelector(`[data-sim="${type}"]`).classList.add('active');
|
| 69 |
|
| 70 |
+
// Show/hide conditional controls using classes
|
| 71 |
document.querySelectorAll('.threshold-only').forEach(el => {
|
| 72 |
+
el.classList.toggle('visible', type === 'threshold');
|
| 73 |
});
|
| 74 |
|
| 75 |
document.querySelectorAll('.multi-only').forEach(el => {
|
| 76 |
+
el.classList.toggle('visible', type === 'multi');
|
| 77 |
});
|
| 78 |
|
| 79 |
updateEstimatedTime();
|
|
|
|
| 427 |
// Type-specific statistics
|
| 428 |
if (parameters.simType === 'multi') {
|
| 429 |
document.querySelectorAll('.multi-stats, .multi-chart').forEach(el => {
|
| 430 |
+
el.classList.add('visible');
|
| 431 |
});
|
| 432 |
|
| 433 |
document.getElementById('avgSurvivingFunds').textContent =
|
|
|
|
| 439 |
document.getElementById('diversificationBenefit').textContent = diversificationBenefit;
|
| 440 |
} else {
|
| 441 |
document.querySelectorAll('.multi-stats, .multi-chart').forEach(el => {
|
| 442 |
+
el.classList.remove('visible');
|
| 443 |
});
|
| 444 |
}
|
| 445 |
|
| 446 |
if (parameters.simType === 'threshold') {
|
| 447 |
document.querySelectorAll('.threshold-stats').forEach(el => {
|
| 448 |
+
el.classList.add('visible');
|
| 449 |
});
|
| 450 |
|
| 451 |
document.getElementById('targetReached').textContent = formatPercentage(summary.targetReachedRate || 0);
|
|
|
|
| 455 |
summary.targetReachedRate > 0.5 ? 'Better' : 'Similar';
|
| 456 |
} else {
|
| 457 |
document.querySelectorAll('.threshold-stats').forEach(el => {
|
| 458 |
+
el.classList.remove('visible');
|
| 459 |
});
|
| 460 |
}
|
| 461 |
|
|
|
|
| 499 |
}
|
| 500 |
}
|
| 501 |
|
| 502 |
+
// Create empty return chart with default range
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 503 |
function createEmptyReturnChart() {
|
| 504 |
const ctx = document.getElementById('returnChart').getContext('2d');
|
| 505 |
+
const defaultBins = [];
|
| 506 |
+
for (let i = -100; i <= 100; i += 2) {
|
| 507 |
+
defaultBins.push(i);
|
| 508 |
+
}
|
| 509 |
+
|
| 510 |
return new Chart(ctx, {
|
| 511 |
type: 'bar',
|
| 512 |
data: {
|
| 513 |
+
labels: defaultBins.map(b => `${b}%`),
|
| 514 |
datasets: [{
|
| 515 |
label: 'Frequency',
|
| 516 |
+
data: new Array(defaultBins.length).fill(0),
|
| 517 |
+
backgroundColor: 'rgba(86, 175, 226, 0.3)',
|
| 518 |
+
borderColor: '#56AFE2',
|
| 519 |
borderWidth: 1
|
| 520 |
}]
|
| 521 |
},
|
|
|
|
| 523 |
});
|
| 524 |
}
|
| 525 |
|
| 526 |
+
// Create return distribution chart with smart 2% bins
|
| 527 |
function createReturnDistributionChart(runs) {
|
| 528 |
const ctx = document.getElementById('returnChart').getContext('2d');
|
| 529 |
const returns = runs.map(r => r.totalReturn * 100);
|
| 530 |
|
| 531 |
+
// Calculate smart range based on data
|
| 532 |
+
const minReturn = Math.min(...returns);
|
| 533 |
+
const maxReturn = Math.max(...returns);
|
| 534 |
+
|
| 535 |
+
// Round to nearest 10% for cleaner bounds, with padding
|
| 536 |
+
const binStart = Math.floor(minReturn / 10) * 10;
|
| 537 |
+
const binEnd = Math.min(Math.ceil(maxReturn / 10) * 10, 200); // Cap at 200%
|
| 538 |
+
|
| 539 |
+
// Generate 2% bins within the smart range
|
| 540 |
+
const bins = [];
|
| 541 |
+
for (let i = binStart; i <= binEnd; i += 2) {
|
| 542 |
+
bins.push(i);
|
| 543 |
+
}
|
| 544 |
+
|
| 545 |
+
// Count returns in bins
|
| 546 |
+
const binCounts = new Array(bins.length).fill(0);
|
| 547 |
returns.forEach(ret => {
|
| 548 |
+
for (let i = 0; i < bins.length - 1; i++) {
|
| 549 |
+
if (ret >= bins[i] && ret < bins[i + 1]) {
|
|
|
|
| 550 |
binCounts[i]++;
|
| 551 |
break;
|
| 552 |
}
|
| 553 |
}
|
| 554 |
// Handle values at or above the last bin
|
| 555 |
+
if (ret >= bins[bins.length - 1]) {
|
| 556 |
+
binCounts[bins.length - 1]++;
|
| 557 |
}
|
| 558 |
});
|
| 559 |
|
| 560 |
return new Chart(ctx, {
|
| 561 |
type: 'bar',
|
| 562 |
data: {
|
| 563 |
+
labels: bins.map(b => `${b}%`),
|
| 564 |
datasets: [{
|
| 565 |
label: 'Frequency',
|
| 566 |
data: binCounts,
|
| 567 |
+
backgroundColor: 'rgba(86, 175, 226, 0.3)',
|
| 568 |
+
borderColor: '#56AFE2',
|
| 569 |
borderWidth: 1
|
| 570 |
}]
|
| 571 |
},
|
|
|
|
| 590 |
function createCapitalEvolutionChart(runs) {
|
| 591 |
const ctx = document.getElementById('capitalChart').getContext('2d');
|
| 592 |
|
| 593 |
+
// Color palette for dark mode using both blues
|
| 594 |
const colors = [
|
| 595 |
+
{ border: '#56AFE2', bg: 'rgba(86, 175, 226, 0.15)' },
|
| 596 |
+
{ border: '#87BFFF', bg: 'rgba(135, 191, 255, 0.12)' },
|
| 597 |
+
{ border: '#56AFE2', bg: 'rgba(86, 175, 226, 0.09)' },
|
| 598 |
{ border: '#87BFFF', bg: 'rgba(135, 191, 255, 0.06)' },
|
| 599 |
+
{ border: '#56AFE2', bg: 'rgba(86, 175, 226, 0.03)' }
|
|
|
|
| 600 |
];
|
| 601 |
|
| 602 |
// Sample up to 5 runs
|
| 603 |
const sampleRuns = runs.slice(0, 5);
|
| 604 |
const datasets = sampleRuns.map((run, i) => {
|
| 605 |
+
// Use capitalHistory if available
|
| 606 |
let data = [];
|
| 607 |
if (run.capitalHistory && run.capitalHistory.length > 0) {
|
| 608 |
+
// Handle both array of numbers and array of objects
|
| 609 |
+
data = run.capitalHistory.map((item, idx) => {
|
| 610 |
+
const capital = typeof item === 'object' ? item.capital : item;
|
| 611 |
+
const day = typeof item === 'object' ? item.day : idx;
|
| 612 |
+
return { x: day, y: capital };
|
| 613 |
+
});
|
| 614 |
} else {
|
| 615 |
+
// Fallback: just show final capital with start and end
|
| 616 |
+
data = [
|
| 617 |
+
{ x: 0, y: 10000 }, // Starting capital
|
| 618 |
+
{ x: 1, y: run.finalCapital }
|
| 619 |
+
];
|
| 620 |
}
|
| 621 |
|
| 622 |
return {
|
|
|
|
| 624 |
data: data,
|
| 625 |
borderColor: colors[i % colors.length].border,
|
| 626 |
backgroundColor: colors[i % colors.length].bg,
|
| 627 |
+
borderWidth: 2,
|
| 628 |
fill: false,
|
| 629 |
+
tension: 0.3, // Smooth curves
|
| 630 |
pointRadius: 0 // Hide points for cleaner look
|
| 631 |
};
|
| 632 |
});
|
static/styles.css
CHANGED
|
@@ -8,6 +8,7 @@
|
|
| 8 |
--text-primary: #ffffff;
|
| 9 |
--text-secondary: #87BFFF;
|
| 10 |
--accent: #87BFFF;
|
|
|
|
| 11 |
--accent-hover: #a8d0ff;
|
| 12 |
--accent-light: rgba(135, 191, 255, 0.1);
|
| 13 |
|
|
@@ -150,8 +151,9 @@ body {
|
|
| 150 |
}
|
| 151 |
|
| 152 |
.sim-tab.active {
|
| 153 |
-
border-color: var(--accent);
|
| 154 |
background: var(--bg-secondary);
|
|
|
|
| 155 |
}
|
| 156 |
|
| 157 |
.tab-title {
|
|
@@ -260,7 +262,7 @@ body {
|
|
| 260 |
}
|
| 261 |
|
| 262 |
.run-button {
|
| 263 |
-
background: var(--accent);
|
| 264 |
color: var(--bg-primary);
|
| 265 |
border: none;
|
| 266 |
padding: 12px 28px;
|
|
@@ -276,7 +278,7 @@ body {
|
|
| 276 |
}
|
| 277 |
|
| 278 |
.run-button:hover:not(:disabled) {
|
| 279 |
-
background: var(--accent
|
| 280 |
}
|
| 281 |
|
| 282 |
.run-button:disabled {
|
|
@@ -389,13 +391,14 @@ body {
|
|
| 389 |
.stats-grid {
|
| 390 |
display: grid;
|
| 391 |
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
| 392 |
-
gap: calc(var(--spacing-unit) *
|
|
|
|
| 393 |
}
|
| 394 |
|
| 395 |
.stat-card {
|
| 396 |
background: var(--bg-secondary);
|
| 397 |
border-radius: var(--radius-card);
|
| 398 |
-
padding: calc(var(--spacing-unit) *
|
| 399 |
border: 1px solid var(--border-color);
|
| 400 |
}
|
| 401 |
|
|
@@ -444,20 +447,20 @@ body {
|
|
| 444 |
}
|
| 445 |
|
| 446 |
.stat-value.neutral {
|
| 447 |
-
color: var(--
|
| 448 |
}
|
| 449 |
|
| 450 |
/* Charts Grid */
|
| 451 |
.charts-grid {
|
| 452 |
display: grid;
|
| 453 |
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
|
| 454 |
-
gap: calc(var(--spacing-unit) *
|
| 455 |
}
|
| 456 |
|
| 457 |
.chart-card {
|
| 458 |
background: var(--bg-secondary);
|
| 459 |
border-radius: var(--radius-card);
|
| 460 |
-
padding: calc(var(--spacing-unit) *
|
| 461 |
border: 1px solid var(--border-color);
|
| 462 |
}
|
| 463 |
|
|
@@ -562,10 +565,18 @@ body {
|
|
| 562 |
}
|
| 563 |
|
| 564 |
/* Conditional visibility classes */
|
| 565 |
-
.
|
| 566 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 567 |
}
|
| 568 |
|
| 569 |
.multi-stats, .threshold-stats, .multi-chart {
|
| 570 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 571 |
}
|
|
|
|
| 8 |
--text-primary: #ffffff;
|
| 9 |
--text-secondary: #87BFFF;
|
| 10 |
--accent: #87BFFF;
|
| 11 |
+
--accent-dark: #56AFE2;
|
| 12 |
--accent-hover: #a8d0ff;
|
| 13 |
--accent-light: rgba(135, 191, 255, 0.1);
|
| 14 |
|
|
|
|
| 151 |
}
|
| 152 |
|
| 153 |
.sim-tab.active {
|
| 154 |
+
border-color: var(--accent-dark);
|
| 155 |
background: var(--bg-secondary);
|
| 156 |
+
border-left: 3px solid var(--accent-dark);
|
| 157 |
}
|
| 158 |
|
| 159 |
.tab-title {
|
|
|
|
| 262 |
}
|
| 263 |
|
| 264 |
.run-button {
|
| 265 |
+
background: var(--accent-dark);
|
| 266 |
color: var(--bg-primary);
|
| 267 |
border: none;
|
| 268 |
padding: 12px 28px;
|
|
|
|
| 278 |
}
|
| 279 |
|
| 280 |
.run-button:hover:not(:disabled) {
|
| 281 |
+
background: var(--accent);
|
| 282 |
}
|
| 283 |
|
| 284 |
.run-button:disabled {
|
|
|
|
| 391 |
.stats-grid {
|
| 392 |
display: grid;
|
| 393 |
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
| 394 |
+
gap: calc(var(--spacing-unit) * 1.5);
|
| 395 |
+
margin-bottom: calc(var(--spacing-unit) * 1.5);
|
| 396 |
}
|
| 397 |
|
| 398 |
.stat-card {
|
| 399 |
background: var(--bg-secondary);
|
| 400 |
border-radius: var(--radius-card);
|
| 401 |
+
padding: calc(var(--spacing-unit) * 1.5);
|
| 402 |
border: 1px solid var(--border-color);
|
| 403 |
}
|
| 404 |
|
|
|
|
| 447 |
}
|
| 448 |
|
| 449 |
.stat-value.neutral {
|
| 450 |
+
color: var(--accent-dark);
|
| 451 |
}
|
| 452 |
|
| 453 |
/* Charts Grid */
|
| 454 |
.charts-grid {
|
| 455 |
display: grid;
|
| 456 |
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
|
| 457 |
+
gap: calc(var(--spacing-unit) * 1.5);
|
| 458 |
}
|
| 459 |
|
| 460 |
.chart-card {
|
| 461 |
background: var(--bg-secondary);
|
| 462 |
border-radius: var(--radius-card);
|
| 463 |
+
padding: calc(var(--spacing-unit) * 1.5);
|
| 464 |
border: 1px solid var(--border-color);
|
| 465 |
}
|
| 466 |
|
|
|
|
| 565 |
}
|
| 566 |
|
| 567 |
/* Conditional visibility classes */
|
| 568 |
+
.threshold-only, .multi-only {
|
| 569 |
+
display: none;
|
| 570 |
+
}
|
| 571 |
+
|
| 572 |
+
.threshold-only.visible, .multi-only.visible {
|
| 573 |
+
display: flex;
|
| 574 |
}
|
| 575 |
|
| 576 |
.multi-stats, .threshold-stats, .multi-chart {
|
| 577 |
+
display: none;
|
| 578 |
+
}
|
| 579 |
+
|
| 580 |
+
.multi-stats.visible, .threshold-stats.visible, .multi-chart.visible {
|
| 581 |
+
display: block;
|
| 582 |
}
|