Calcolo Rischio CV

28 Mar , 2026 - Uncategorized




<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<title>Calcolatore rischio cardiovascolare (SCORE2 / SCORE2‑OP) – Dr. Giuseppe Lumia</title>
<style>
:root{
--bg:#0a1628; --bg2:#0d1e38; --card:#112244; --text:#f0f6ff; --muted:#9bb5d8;
--primary:#1e5799; --ok:#16a34a; --warn:#ea580c; --high:#b91c1c; --vhigh:#991b1b;
--border:#1e3a6e; --chip:#0d2040; --chip2:#091525;
}
*{box-sizing:border-box}
body{margin:0;background:
radial-gradient(1400px 700px at 20% -10%, rgba(30,87,153,.22), transparent),
radial-gradient(900px 600px at 90% -10%, rgba(255,255,255,.04), transparent),
linear-gradient(180deg,#0d1e38,#070f1e);
color:var(--text);font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial}
.container{max-width:1100px;margin:28px auto;padding:16px}
.card{background:linear-gradient(180deg,var(--bg2),var(--card) 60%, var(--bg));
border:1px solid var(--border); border-radius:18px; box-shadow:0 10px 35px rgba(0,0,0,.45); overflow:hidden}
.hero{padding:16px;background:linear-gradient(90deg,rgba(30,87,153,.18),rgba(7,15,30,.12));border-bottom:1px solid var(--border)}
.hero-top{display:flex;justify-content:space-between;align-items:center;gap:12px}
.title{margin:0;font-size:24px;font-weight:800}
.subtitle{margin:4px 0 0;color:var(--muted);font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:720px}
.brandbox{margin-left:auto; display:flex; align-items:center; gap:10px}
.site-link-top{padding:6px 10px;border:1px solid var(--border);border-radius:999px;color:#fff;text-decoration:none;background:var(--chip)}
.heart{width:26px;height:26px;display:inline-block}
.card-content{padding:18px}
.section-title{margin:6px 0 12px 2px;font-size:16px;color:#fff;opacity:.95;letter-spacing:.2px}
.blocks{display:grid;grid-template-columns:1fr 1.2fr 1.8fr; gap:16px}
fieldset{border:1px solid var(--border);border-radius:14px;padding:12px;background:linear-gradient(180deg,#0d1e38,#091525)}
legend{padding:0 6px;color:#fff}
label{display:block;margin:.35rem 0}
input[type=date],input[type=number],select{width:100%;padding:10px;border-radius:10px;border:1px solid var(--border);background:#070f1e;color:#fff}
.radio{display:inline-flex;align-items:center;gap:8px;margin-right:12px}
.inline{display:flex;align-items:center;gap:10px}
.inline-mini{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.pill{background:var(--chip);border:1px solid var(--border);padding:6px 10px;border-radius:999px}
.pill-badge{display:flex;align-items:center;justify-content:center;min-width:120px;height:60px;border-radius:14px;border:2px solid rgba(255,255,255,.1);background:linear-gradient(180deg,#0d2a50,#091830);font-size:22px;font-weight:900}
.pill-caption{font-size:12px;color:var(--muted);text-align:center;margin-top:6px}
.note{font-size:12px;color:var(--muted)}
.small{font-size:12px}
.age-big{font-size:22px;font-weight:900;color:#fff;background:linear-gradient(90deg,#0d2c54,#1e5799);padding:4px 12px;border-radius:999px;border:1px solid var(--border)}
.arm-wrap{display:flex;align-items:center;gap:10px;margin-top:8px}
.arm-svg{width:110px;height:70px;flex:0 0 auto;filter:drop-shadow(0 2px 2px rgba(0,0,0,.25))}
.lipids-grid{display:grid;grid-template-columns:1.2fr 1fr; gap:12px; align-items:start}
.calc-panel{background:linear-gradient(180deg,#0d2040,#091525);border:1px solid var(--border);border-radius:12px;padding:10px}
.calc-row{display:grid;grid-template-columns:1fr auto;align-items:center}
.calc-row strong{font-size:13px;color:#fff}
.calc-value{justify-self:end}
.ir-row{display:flex;align-items:center;gap:18px;margin-top:14px;flex-wrap:wrap}
.badge{
width:120px;height:120px;border-radius:999px;border:10px solid rgba(255,255,255,.1);
display:flex;align-items:center;justify-content:center;
font-weight:900;font-size:28px;color:white;box-shadow:0 10px 30px rgba(0,0,0,.25);
background:#9ca3af;
}
.ir-legend{display:flex;gap:12px;align-items:center;flex-wrap:wrap}
.dot{width:14px;height:14px;border-radius:999px;display:inline-block;box-shadow:0 1px 2px rgba(0,0,0,.25)}
.legend-pill{display:flex;align-items:center;gap:8px;background:var(--chip);border:1px solid var(--border);padding:8px 10px;border-radius:999px;font-size:13px}
.footer{margin-top:16px;color:var(--muted);font-size:13px}
hr{border:none;border-top:1px solid var(--border);margin:18px 0}
@media (max-width:1100px){.blocks{grid-template-columns:1fr} .lipids-grid{grid-template-columns:1fr} .arm-svg{width:90px;height:58px} .subtitle{white-space:normal;max-width:none}}
</style>
<style>
.control-box{position:relative;display:inline-flex;align-items:center}
.control-box>*{position:relative;z-index:1;pointer-events:auto}
.control-box button,.control-box a{float:none!important}
</style>
</head>
<body>
<div class="container">
<div class="card">
<div class="hero">
<div class="hero-top">
<div>
<h1 class="title">SCORE2 / SCORE2-OP – Calcolatore rischio CV (Italia)</h1>
<p class="subtitle">Stima del rischio a 10 anni di eventi CV fatali e non fatali (Italia, rischio moderato). SCORE2: 40–69 • SCORE2‑OP: 70–89.</p>
</div>
<div class="brandbox">
<a class="site-link-top" href="https://www.giuseppelumia.com" rel="noreferrer">&#8592; Torna indietro</a>
<svg aria-label="cuore" class="heart" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12.1 21.35l-1.1-1.02C5.14 15.24 2 12.36 2 8.98 2 6.41 4.05 4.5 6.57 4.5c1.46 0 2.86.65 3.78 1.71.92-1.06 2.32-1.71 3.78-1.71 2.52 0 4.57 1.91 4.57 4.48 0 3.38-3.14 6.26-8.91 11.36l-1.69 1.01z" fill="rgba(255,255,255,.95)"></path>
</svg>
</div>
</div>
</div>
<div class="card-content">
<h2 class="section-title">Dati</h2>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:16px">
<fieldset>
<legend>Dati anagrafici</legend>
<div class="inline-mini">
<label style="min-width:260px">Data di nascita
<input id="dob" placeholder="gg/mm/aaaa" required type="date"/>
</label>
<span class="age-big">Et&#224;: <span id="ageText">&#8212;</span> aa.</span>
<input id="eta" type="hidden"/>
</div>
</fieldset>
<fieldset>
<legend>Sesso</legend>
<select id="sex" required>
<option value="male">Uomo</option>
<option value="female">Donna</option>
</select>
</fieldset>
</div>
<h2 class="section-title">Fattori</h2>
<div class="blocks">
<fieldset>
<legend>Fumatore</legend>
<div style="margin-top:4px">
<label class="radio"><input name="fumo" required type="radio" value="0"/> No</label>
<label class="radio"><input name="fumo" type="radio" value="1"/> S&#236;</label>
</div>
<p class="note" style="margin-top:8px">Lo stato di fumo entra nella classe di rischio SCORE2/OP.</p>
</fieldset>
<fieldset>
<legend>Pressione arteriosa</legend>
<label>Pressione sistolica (mmHg)
<input id="sbp" placeholder="Es. 132" required step="1" type="number"/>
</label>
<div class="arm-wrap">
<svg aria-label="braccio piegato con bracciale" class="arm-svg" viewBox="0 0 140 90" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="skin" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="#f8e7da"/>
<stop offset="100%" stop-color="#f0d4c0"/>
</linearGradient>
</defs>
<path d="M10,35 C25,20 55,18 80,30 L80,55 C55,45 30,48 15,60 Z" fill="url(#skin)" stroke="#e0bfa8"/>
<path d="M80,30 C100,38 115,50 125,68 L110,78 C100,60 88,50 80,55 Z" fill="url(#skin)" stroke="#e0bfa8"/>
<rect fill="#1e5799" height="24" rx="5" stroke="#0d2c54" width="22" x="55" y="28"/>
<path d="M77,40 C95,45 110,55 120,70" fill="none" stroke="#9ca3af" stroke-width="2"/>
</svg>
<div class="note">
<strong>Come misurare:</strong> seduto, schiena e braccio appoggiati, bracciale all&#8217;altezza del cuore.<br/>
Eseguire 2 misurazioni a 1&#8211;2 minuti, usare la <em>media</em>.
</div>
</div>
</fieldset>
<fieldset id="lipids_fs">
<legend>Lipidi</legend>
<div class="lipids-grid">
<div>
<label>Colesterolo totale (mg/dL) <input id="tc" inputmode="decimal" placeholder="Es. 210" required step="any" type="number"/></label>
<label>HDL (mg/dL) <input id="hdl" inputmode="decimal" placeholder="Es. 48" required step="any" type="number"/></label>
<label>Trigliceridi (mg/dL) <input id="tg" inputmode="decimal" placeholder="Es. 150" required step="any" type="number"/></label>
</div>
<div class="calc-panel">
<div class="calc-row" style="margin-bottom:8px">
<strong>Non&#8209;HDL (TC &#8722; HDL)</strong>
<div class="pill-badge calc-value"><span id="nonhdl_auto">&#8212;</span></div>
</div>
<div class="calc-row">
<strong>LDL (Friedewald)</strong>
<div class="pill-badge calc-value"><span id="ldl_auto">&#8212;</span></div>
</div>
<div class="pill-caption"><span class="small">Dettaglio: LDL = <span id="ldl_dbg_tc">&#8212;</span> &#8722; <span id="ldl_dbg_hdl">&#8212;</span> &#8722; (<span id="ldl_dbg_tg">&#8212;</span>/5) = <span id="ldl_dbg_res">&#8212;</span> mg/dL</span></div>
</div>
</div>
<div class="inline" style="flex-wrap:wrap;gap:8px;margin-top:10px">
<span class="pill">Inseriti: <strong>HDL <span id="hdl_in">&#8212;</span></strong> mg/dL</span>
<span class="pill">Inseriti: <strong>TG <span id="tg_in">&#8212;</span></strong> mg/dL</span>
</div>
<p class="note" style="margin-top:8px">Usa il punto per i decimali. Formula Friedewald valida con TG &lt; 400 mg/dL; meno accurata in non-digiuno/ipertrigliceridemie. Il calcolatore non applica blocchi automatici.</p>
</fieldset>
</div>
<hr/>
<div class="ir-row">
<div class="badge" id="riskBadge">&#8212;</div>
<div style="display:flex;flex-direction:column;gap:6px;min-width:260px">
<div style="display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:6px;">
<div>Indice di rischio a 10 anni: <span id="riskPct">&#8212;</span></div>
<button id="btnReset" style="margin-left:12px;padding:8px 12px;border-radius:10px;border:1px solid #1e3a6e;background:#0d2c54;color:#fff;font-weight:600;cursor:pointer;display:inline-flex;align-items:center;gap:12px;" type="button">Pulisci i campi
<div class="control-box">
<a href="suggerimenti-lumia.html" style="margin-left:12px;white-space:nowrap;text-decoration:none;border:1px solid #1e3a6e;background:#0d2c54;color:#fff;padding:8px 12px;border-radius:10px;font-weight:700;" target="_self">Suggerimenti del Dr. Lumia</a>
</div>
</button>
</div>
<div class="small">Modello: <span id="modelUsed">&#8212;</span></div>
<div class="ir-legend">
<span class="legend-pill"><span class="dot" style="background:var(--ok)"></span> Basso</span>
<span class="legend-pill"><span class="dot" style="background:var(--warn)"></span> Moderato</span>
<span class="legend-pill"><span class="dot" style="background:var(--high)"></span> Alto</span>
</div>
<div class="note" id="irNote">Le soglie colore sono specifiche per fascia d&#8217;et&#224; (ESC 2021).</div>
</div>
</div>
<hr/>
<div class="footer">
<strong>2021 ESC Guidelines on cardiovascular disease prevention in clinical practice</strong> &#8212; <em>European Heart Journal</em> 42: 3227&#8211;3337. Italia: regione di rischio <em>moderato</em> (ESC/HeartScore).<br/>
<span>a cura del Dr. Giuseppe Lumia &#8211; Cardiologo Aritmologo, Roma &#8226; Questo strumento &#232; informativo e non sostituisce il giudizio clinico.</span>
</div>
</div>
</div>
</div>

<script>
function computeAge(dobStr){
if(!dobStr) return null;
const d=new Date(dobStr);
if(isNaN(d)) return null;
const t=new Date();
let age=t.getFullYear()-d.getFullYear();
const m=t.getMonth()-d.getMonth();
if(m<0||(m===0&&t.getDate()<d.getDate())) age--;
return age;
}

function colorForRisk(age,risk){
if(risk==null) return '#9ca3af';
let low,mod;
if(age<50){low=2.5;mod=7.5;}
else if(age<=69){low=5;mod=10;}
else{low=7.5;mod=15;}
const s=getComputedStyle(document.documentElement);
if(risk<low) return s.getPropertyValue('--ok').trim();
if(risk<mod) return s.getPropertyValue('--warn').trim();
return s.getPropertyValue('--high').trim();
}

function score2_or_op(age,sex,smoker,sbp,tot_mmol,hdl_mmol){
const diabetes=0;
let scale1,scale2;
if(age<70){
if(sex==="male"){scale1=-0.1565;scale2=0.8009;}
else{scale1=-0.3143;scale2=0.7701;}
}else{
if(sex==="male"){scale1=0.01;scale2=1.25;}
else{scale1=-0.1;scale2=1.1;}
}
if(age<70){
if(sex==="male"){
const xx=0.3742*((age-60)/5)+0.6012*smoker+0.2777*((sbp-120)/20)+0.6457*diabetes+0.1458*((tot_mmol-6)/1)+(-0.2698)*((hdl_mmol-1.3)/0.5)+(-0.0755)*((age-60)/5)*smoker+(-0.0255)*((age-60)/5)*((sbp-120)/20)+(-0.0281)*((age-60)/5)*((tot_mmol-6)/1)+0.0426*((age-60)/5)*((hdl_mmol-1.3)/0.5)+(-0.0983)*((age-60)/5)*diabetes;
const xx2=1-Math.pow(0.9605,Math.exp(xx));
return(1-Math.exp(-Math.exp(scale1+scale2*Math.log(-Math.log(1-xx2)))))*100;
}else{
const xx=0.4648*((age-60)/5)+0.7744*smoker+0.3131*((sbp-120)/20)+0.8096*diabetes+0.1002*((tot_mmol-6)/1)+(-0.2606)*((hdl_mmol-1.3)/0.5)+(-0.1088)*((age-60)/5)*smoker+(-0.0277)*((age-60)/5)*((sbp-120)/20)+(-0.0226)*((age-60)/5)*((tot_mmol-6)/1)+0.0613*((age-60)/5)*((hdl_mmol-1.3)/0.5)+(-0.1272)*((age-60)/5)*diabetes;
const xx2=1-Math.pow(0.9776,Math.exp(xx));
return(1-Math.exp(-Math.exp(scale1+scale2*Math.log(-Math.log(1-xx2)))))*100;
}
}else{
if(sex==="male"){
const xx=0.0634*(age-73)+0.4245*diabetes+0.3524*smoker+0.0094*(sbp-150)+0.0850*(tot_mmol-6)+(-0.3564)*(hdl_mmol-1.4)+(-0.0174)*(age-73)*diabetes+(-0.0247)*(age-73)*smoker+(-0.0005)*(age-73)*(sbp-150)+0.0073*(age-73)*(tot_mmol-6)+0.0091*(age-73)*(hdl_mmol-1.4);
const xx2=1-Math.pow(0.7576,Math.exp(xx-0.0929));
return(1-Math.exp(-Math.exp(scale1+scale2*Math.log(-Math.log(1-xx2)))))*100;
}else{
const xx=0.0789*(age-73)+0.6010*diabetes+0.4921*smoker+0.0102*(sbp-150)+0.0605*(tot_mmol-6)+(-0.3040)*(hdl_mmol-1.4)+(-0.0107)*(age-73)*diabetes+(-0.0255)*(age-73)*smoker+(-0.0004)*(age-73)*(sbp-150)+(-0.0009)*(age-73)*(tot_mmol-6)+0.0154*(age-73)*(hdl_mmol-1.4);
const xx2=1-Math.pow(0.8082,Math.exp(xx-0.229));
return(1-Math.exp(-Math.exp(scale1+scale2*Math.log(-Math.log(1-xx2)))))*100;
}
}
}

function readRadio(name){
const el=document.querySelector('input[name="'+name+'"]:checked');
return el?parseInt(el.value,10):null;
}

function setBlank(){
document.getElementById('riskPct').textContent='&#8212;';
const b=document.getElementById('riskBadge');
b.textContent='-'; b.style.background='#e5e7eb';
document.getElementById('modelUsed').textContent='&#8212;';
document.getElementById('irNote').textContent='Compila tutti i campi per ottenere l\u2019IR (%).';
}

function updateAll(){
const dobVal=document.getElementById('dob').value;
const sexVal=document.getElementById('sex').value;
const sbpVal=document.getElementById('sbp').value;
const tcVal=document.getElementById('tc').value;
const hdlVal=document.getElementById('hdl').value;
const tgVal=document.getElementById('tg').value;
const fumoVal=readRadio('fumo');

const age=computeAge(dobVal);
document.getElementById('ageText').textContent=(age!=null&&age>=0)?age:'&#8212;';
document.getElementById('eta').value=(age!=null)?age:'';

// derived lipids (update sempre)
const tc=parseFloat(tcVal), hdl=parseFloat(hdlVal), tg=parseFloat(tgVal);
const nonhdl=(isFinite(tc)&&isFinite(hdl))?(tc-hdl):null;
const ldl=(isFinite(tc)&&isFinite(hdl)&&isFinite(tg))?(tc-hdl-(tg/5)):null;
document.getElementById('nonhdl_auto').textContent=(nonhdl!=null)?Math.max(0,Math.round(nonhdl)):'&#8212;';
document.getElementById('ldl_auto').textContent=(ldl!=null)?Math.max(0,Math.round(ldl)):'&#8212;';
document.getElementById('hdl_in').textContent=isFinite(hdl)?Math.round(hdl):'&#8212;';
document.getElementById('tg_in').textContent=isFinite(tg)?Math.round(tg):'&#8212;';
document.getElementById('ldl_dbg_tc').textContent=isFinite(tc)?Math.round(tc):'&#8212;';
document.getElementById('ldl_dbg_hdl').textContent=isFinite(hdl)?Math.round(hdl):'&#8212;';
document.getElementById('ldl_dbg_tg').textContent=isFinite(tg)?Math.round(tg):'&#8212;';
document.getElementById('ldl_dbg_res').textContent=(ldl!=null)?Math.max(0,Math.round(ldl)):'&#8212;';

// blocca se manca qualcosa
if(!sexVal||!dobVal||!sbpVal||!tcVal||!hdlVal||!tgVal||fumoVal===null){
setBlank();
document.getElementById('modelUsed').textContent=(age!=null)?((age<70)?'SCORE2':'SCORE2\u2011OP'):'&#8212;';
return;
}

const sbp=parseFloat(sbpVal);
document.getElementById('modelUsed').textContent=(age!=null)?((age<70)?'SCORE2':'SCORE2\u2011OP'):'&#8212;';

let risk=null;
if(age!=null&&age>=40&&age<=89&&isFinite(sbp)&&isFinite(tc)&&isFinite(hdl)){
risk=score2_or_op(age,sexVal,fumoVal,sbp,tc/38.67,hdl/38.67);
}

const badge=document.getElementById('riskBadge');
const riskPct=document.getElementById('riskPct');
const note=document.getElementById('irNote');

if(risk==null){
badge.textContent='&#8212;'; badge.style.background='#9ca3af';
riskPct.textContent='&#8212;';
note.textContent='Inserisci tutti i campi richiesti per ottenere l\u2019IR (%).';
}else{
const r=Math.max(0,Math.min(100,Math.round(risk*10)/10));
badge.textContent=r.toFixed(1)+'%';
badge.style.background=colorForRisk(age,r);
riskPct.textContent=r.toFixed(1)+'%';
note.textContent='Colori mappati su soglie ESC (fasce d\u2019et\u00e0).';
}
}

// Reset button
document.getElementById('btnReset').addEventListener('click',function(){
['dob','sbp','tc','hdl','tg','eta'].forEach(function(id){
var el=document.getElementById(id); if(el) el.value='';
});
var sel=document.getElementById('sex'); if(sel) sel.selectedIndex=-1;
document.querySelectorAll('input[name="fumo"]').forEach(function(r){r.checked=false;});
document.getElementById('ageText').textContent='&#8212;';
document.getElementById('nonhdl_auto').textContent='&#8212;';
document.getElementById('ldl_auto').textContent='&#8212;';
document.getElementById('hdl_in').textContent='&#8212;';
document.getElementById('tg_in').textContent='&#8212;';
['ldl_dbg_tc','ldl_dbg_hdl','ldl_dbg_tg','ldl_dbg_res'].forEach(function(id){document.getElementById(id).textContent='&#8212;';});
setBlank();
window.scrollTo({top:0,behavior:'smooth'});
});

// Listeners
['dob','sex','sbp','tc','hdl','tg'].forEach(function(id){
document.getElementById(id).addEventListener('input',updateAll);
document.getElementById(id).addEventListener('change',updateAll);
});
document.querySelectorAll('input[name="fumo"]').forEach(function(el){
el.addEventListener('input',updateAll);
el.addEventListener('change',updateAll);
});

// Init
document.addEventListener('DOMContentLoaded',function(){
['dob','sbp','tc','hdl','tg','eta'].forEach(function(id){
var el=document.getElementById(id); if(el) el.value='';
});
var sel=document.getElementById('sex'); if(sel) sel.selectedIndex=-1;
document.querySelectorAll('input[name="fumo"]').forEach(function(r){r.checked=false;});
setBlank();
});
</script>
</body>
</html>

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *