Widget:Solvency2 BalanceSheet: Difference between revisions
Content deleted Content added
Created page with "<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Solvency II Balance Sheet</title> <link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display&family=IBM+Plex+Sans:wght@300;400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet"> <style> :root { --bg: #0c1018; --surface: #141b27; --surface2: #1a2234; --border: #253044; --tex..." |
No edit summary |
||
Line 5:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Solvency II Balance Sheet</title>
<style>
:root {
--bg: #
--surface: #
--surface2: #
--border: #
--
--text
--text-
--
--
/* Monochrome block palette — dark-to-light for visual hierarchy */
--
--
--
--scr-fill: #a2a9b1;
--
--
}
Line 38 ⟶ 31:
background: var(--bg);
color: var(--text);
font-family:
-webkit-font-smoothing: auto;
}
.container {
max-width:
margin: 0 auto;
padding:
}
/* ---- Header ---- */
header {
border-bottom: 2px solid var(--border-heavy);
margin-bottom: 20px;
}
header h1 {
font-
font-
line-height: 1.
}
header p {
font-size:
color: var(--text-dim);
}
/*
.main-grid {
display: grid;
grid-template-columns: 1fr
gap:
align-items: start;
}
@media (max-width: 760px) {
.main-grid { grid-template-columns: 1fr; }
}
/*
.bs-visual {
border: 1px solid var(--border);
padding:
}
Line 135 ⟶ 85:
display: flex;
justify-content: space-between;
margin-bottom:
}
.bs-col-label {
font-
font-
text-transform: uppercase;
color: var(--text-muted);
Line 149 ⟶ 98:
.bs-columns {
display: grid;
grid-template-columns: 1fr
}
Line 157 ⟶ 105:
display: flex;
flex-direction: column;
gap:
}
.bs-separator {
display: flex;
align-items:
justify-content: center;
}
.bs-separator .line {
width: 1px;
background: var(--border);
}
/* ---- Blocks ---- */
.bs-block {
position: relative;
cursor: pointer;
transition:
display: flex;
flex-direction: column;
justify-content: center;
border: 1px solid transparent;
color: #fff;
}
.bs-block .label {
font-size:
font-weight:
}
.bs-block .sublabel {
font-size:
opacity: 0.
}
.bs-block .value {
font-
font-
font-variant-numeric: tabular-nums;
}
.bs-block:hover {
box-shadow: 0 0 0 2px var(--border-heavy);
z-index: 2;
}
.bs-block.active {
z-index: 3;
}
.block-assets { background:
.block-bel { background: var(--bel-fill); }
.block-rm
.block-
.block-mcr { background: var(--mcr-fill); color: var(--text); }
.block-surplus { background: var(--surplus-fill); color: var(--text); border: 1px solid var(--border); }
/* ---- Legend ---- */
.legend-strip {
display: flex;
flex-wrap: wrap;
gap: 4px;
margin-top: 16px;
border-top: 1px solid var(--border);
padding-top: 12px;
}
.legend-item {
display: flex;
align-items: center;
gap: 5px;
padding: 3px 8px;
font-size: 0.75em;
color: var(--text-dim);
cursor: pointer;
border: 1px solid transparent;
border-radius: 2px;
transition: border-color 0.15s ease;
}
.
.legend-dot {
width: 10px; height: 10px;
border-radius: 1px;
flex-shrink: 0;
}
/* ---- Status bar ---- */
.status-bar {
display: flex;
gap: 16px;
flex-wrap: wrap;
margin-top: 12px;
}
.status-item {
display: flex;
align-items: center;
}
.status-dot {
width: 7px; height: 7px;
border-radius: 50%;
}
.status-dot.ok { background: var(--text); }
.status-dot.warn { background: var(--text-muted); }
.status-dot.fail { border: 2px solid var(--text); background: transparent; }
/* ---- Side panel ---- */
.side-panel {
display: flex;
flex-direction: column;
gap:
}
.info-card {
border: 1px solid var(--border);
padding:
}
font-
font-
letter-spacing:
text-transform: uppercase;
color: var(--text-muted);
margin-bottom: 10px;
}
/* ---- Gauge ---- */
.gauge-card { text-align: center; padding: 18px; }
.
font-weight: bold;
color: var(--text);
}
.gauge-label {
font-size: 0.78em;
color: var(--text-muted);
}
.gauge-bar-track {
margin-top: 14px;
overflow: hidden;
}
.gauge-bar-fill {
height: 100%;
}
.gauge-thresholds {
display: flex;
justify-content: space-between;
margin-top:
color: var(--text-muted);
}
/*
.slider-group { margin-bottom: 14px; }
.slider-group:last-child { margin-bottom: 0; }
.slider-header {
display: flex;
justify-content: space-between;
align-items:
margin-bottom:
}
.slider-header label {
font-size:
color: var(--text-dim);
}
.slider-val {
font-size: 0.8em;
font-
font-
}
Line 444 ⟶ 296:
-webkit-appearance: none;
width: 100%;
height:
background: var(--surface2);
border-radius: 2px;
outline: none;
cursor: pointer;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width:
border-radius: 50%;
background: var(--
cursor: pointer;
box-shadow: 0 0 0 1px var(--border);
}
input[type="range"]::-moz-range-thumb {
width: 14px; height: 14px;
background: var(--text);
cursor: pointer;
box-shadow: 0 0 0 1px var(--border);
}
/* ---- Detail card ---- */
.info-card h3 {
font-size: 1.05em;
font-weight: bold;
color: var(--text);
margin-bottom: 6px;
line-height: 1.3;
}
.info-card p {
font-size: 0.84em;
line-height:
}
.formula {
margin-top: 10px;
padding: 8px 12px;
border: 1px solid var(--surface2);
font-family: "Nimbus Roman No9 L", "Times New Roman", Times, serif;
font-size: 0.88em;
color: var(--text);
}
/* ---- MCR badge inside SCR ---- */
.tier-badge {
display: inline-block;
padding:
border-radius:
font-
font-
cursor: pointer;
}
.block-scr .tier-badge { background: rgba(0,0,0,0.08); }
/* ---- Deficit block ---- */
.block-deficit {
border: 2px dashed var(--text);
color: var(--text);
}
/* ---- Print ---- */
@media print {
.main-grid { grid-template-columns: 1fr; }
.container { padding: 0; }
.bs-visual { border: 1px solid #000; }
}
</style>
Line 652 ⟶ 377:
<div class="container">
<header>
<h1>Solvency II Balance Sheet</h1>
<p>
</header>
<div class="main-grid">
<!-- Left
<div>
<div class="bs-visual" id="bsVisual">
<div class="bs-title-row">
<span class="bs-col-label">Assets</span>
<span class="bs-col-label">Liabilities & Own Funds</span>
</div>
<div class="bs-columns" id="bsColumns">
<div class="bs-col" id="assetsCol"></div>
<
<div class="bs-col" id="liabCol"></div>
</div>
<div class="legend-strip" id="legend"></div>
</div>
<div class="status-bar" id="statusBar"></div>
</div>
<!-- Right column:
<div class="side-panel">
<!-- Solvency ratio -->
<div class="info-card gauge-card">
<div class="card-label">Solvency Ratio</div>
<div class="gauge-value" id="ratioValue">
<div class="gauge-label">Eligible Own Funds / SCR</div>
<div class="gauge-bar-track"><div class="gauge-bar-fill" id="ratioBar"></div></div>
<div class="gauge-thresholds">
<span
<span
<span
<span>300%</
</div>
</div>
<!--
<div class="info
<div class="card-label">Adjust Values (
<div class="slider-group">
<div class="slider-header">
<label>Total Assets</label>
<span class="slider-val" id="valAssets
</div>
<input type="range" id="sliderAssets" min="80" max="250" value="150">
Line 714 ⟶ 430:
<div class="slider-header">
<label>Best Estimate Liabilities</label>
<span class="slider-val" id="valBEL
</div>
<input type="range" id="sliderBEL" min="30" max="180" value="85">
Line 722 ⟶ 438:
<div class="slider-header">
<label>Risk Margin</label>
<span class="slider-val" id="valRM
</div>
<input type="range" id="sliderRM" min="1" max="30" value="8">
Line 730 ⟶ 446:
<div class="slider-header">
<label>SCR</label>
<span class="slider-val" id="valSCR
</div>
<input type="range" id="sliderSCR" min="10" max="80" value="35">
Line 738 ⟶ 454:
<div class="slider-header">
<label>MCR (% of SCR)</label>
<span class="slider-val" id="valMCR
</div>
<input type="range" id="sliderMCR" min="20" max="50" value="35">
Line 747 ⟶ 463:
<div class="info-card" id="detailCard">
<div class="card-label">Component Detail</div>
<h3 id="detailTitle">
<p id="detailDesc">Click or hover on any
<div class="formula" id="detailFormula" style="display:none;"></div>
</div>
Line 754 ⟶ 470:
</div>
</div>
<script>
const data = { assets: 150, bel: 85, rm: 8, scr: 35, mcrPct: 35 };
const descriptions = {
Line 775 ⟶ 483:
title: 'Best Estimate Liabilities (BEL)',
desc: 'The probability-weighted average of future cash flows for insurance obligations, discounted using the relevant risk-free interest rate term structure prescribed by EIOPA. It represents the expected cost of meeting policyholder obligations.',
formula: 'BEL =
},
rm: {
title: 'Risk Margin',
desc: 'An additional amount over the BEL to ensure technical provisions are sufficient. Calculated as the cost of holding eligible own funds equal to the SCR over the lifetime of the obligations, using a prescribed cost-of-capital rate (currently 6%).',
formula: 'RM = CoC
},
tp: {
title: 'Technical Provisions (TP)',
desc: 'The total value of insurance liabilities
formula: 'TP = BEL + Risk Margin'
},
Line 790 ⟶ 498:
title: 'Solvency Capital Requirement',
desc: 'The capital buffer required to absorb significant unforeseen losses over a 1-year period with a 99.5% confidence level (i.e. a 1-in-200 year event). Can be calculated via the Standard Formula or an approved Internal Model.',
formula: 'SCR =
},
mcr: {
title: 'Minimum Capital Requirement',
desc: 'The minimum level of security below which
formula: 'MCR = max(25%
},
surplus: {
title: 'Free Surplus',
desc: 'Own funds in excess of the SCR
formula: 'Surplus = Own Funds
},
ownfunds: {
title: 'Eligible Own Funds',
desc: 'Total own funds available to cover the SCR and MCR. Classified into Tier 1 (highest quality
formula: 'Own Funds = Assets
}
};
const legendItems = [
{ id: 'assets', label: 'Assets', color: 'var(--assets-
{ id: 'bel', label: 'BEL', color: 'var(--bel-
{ id: 'rm', label: 'Risk Margin', color: 'var(--rm-
{ id: 'scr', label: 'SCR', color: 'var(--scr-
{ id: '
{ id: '
{ id: 'ownfunds', label: 'Own Funds', color: '#c8ccd1' },
];
Line 831 ⟶ 540:
const total = data.assets;
const totalLiab = tp + data.scr + Math.max(0, surplus);
const ref = Math.max(total, totalLiab, 1);
const totalH = 480;
const pxPer = totalH / ref;
// Assets
const
ac.appendChild(makeBlock('assets', 'block-assets', 'Total Assets', 'Market value', '\u20AC' + data.assets + 'bn', totalH));
// Liabilities
const lc = document.getElementById('liabCol');
lc.innerHTML = '';
const belH = Math.max(32, data.bel * pxPer);
const rmH = Math.max(26, data.rm * pxPer);
lc.appendChild(makeBlock('rm', 'block-rm', 'Risk Margin', 'Cost-of-capital provision', '\u20AC' + data.rm + 'bn', rmH));
const scrH = Math.max(40, data.scr * pxPer);
const scrBlock = makeBlock('scr', 'block-scr', 'SCR',
const mcrBadge = document.createElement('div');
mcrBadge.className = 'tier-badge
mcrBadge.textContent =
mcrBadge.style.cursor = 'pointer';
mcrBadge.dataset.block = 'mcr';
mcrBadge.addEventListener('click', function(e) { e.stopPropagation(); showDetail('mcr'); });
scrBlock.appendChild(mcrBadge);
if (surplus > 0) {
const surpH = Math.max(
} else if (ownFunds < data.scr) {
const defBlock = makeBlock('surplus', 'block-deficit', 'Capital Shortfall', 'Own funds < SCR', '\u20AC' + Math.round(data.scr - ownFunds) + 'bn deficit', 32);
lc.appendChild(defBlock);
}
// Ratio
rVal.textContent =
rBar.style.
// Status
sb.innerHTML =
'<div class="status-item"><div class="status-dot ' + (scrOk ? 'ok' : 'fail') + '"></div><span>SCR ' + (scrOk ? 'covered' : 'breached') + '</span></div>' +
'<div
'<div class="status-item"><div class="status-dot ' + (ratio >= 150 ? 'ok' : ratio >= 100 ? 'warn' : 'fail') + '"></div><span>Ratio: ' + Math.round(ratio) + '%</span></div>' +
'<div class="status-item" style="cursor:pointer" onclick="showDetail(\'ownfunds\')"><span style="font-weight:bold">Own Funds: \u20AC' + Math.round(ownFunds) + 'bn</span></div>';
// Legend
legendItems.forEach(function(l
});
}
function makeBlock(id, cls, label, sublabel, value, height) {
el.className =
el.style.height = height + 'px';
el.dataset.block = id;
el.innerHTML =
'<div class="label">
'<div class="value">
el.addEventListener('mouseenter', function() { showDetail(id); });
el.addEventListener('
return el;
}
function showDetail(id) {
if (!info) return;
document.getElementById('detailTitle').textContent = info.title;
document.getElementById('detailDesc').textContent = info.desc;
if (info.formula) { fEl.style.display = 'block'; fEl.textContent = info.formula; }
else { fEl.style.display = '
document.querySelectorAll('.bs-block').forEach(function(b) { b.classList.remove('active'); });
document.querySelectorAll('.bs-block[data-block="' + id + '"]').forEach(function(b) { b.classList.add('active'); });
}
function bindSlider(sid, vid, key, suffix) {
var s = document.getElementById(sid);
s.addEventListener('input', function() {
data[key] = parseInt(s.value);
render();
});
}
bindSlider('sliderAssets', 'valAssets', 'assets', '');
bindSlider('sliderBEL', 'valBEL', 'bel', '');
bindSlider('sliderRM', 'valRM', 'rm', '');
bindSlider('sliderSCR', 'valSCR', 'scr', '');
bindSlider('sliderMCR', 'valMCR', 'mcrPct', '%');
render();
</script>
| |||