{"id":166,"date":"2025-10-19T08:24:57","date_gmt":"2025-10-19T08:24:57","guid":{"rendered":"https:\/\/aman360.org\/?page_id=166"},"modified":"2025-10-19T10:52:50","modified_gmt":"2025-10-19T10:52:50","slug":"cross-hazard-impact-explorer","status":"publish","type":"page","link":"https:\/\/aman360.org\/ar\/tools\/cross-hazard-impact-explorer\/","title":{"rendered":"Cross-Hazard Impact Explorer"},"content":{"rendered":"\n<!doctype html>\n<html lang=\"ar\" dir=\"rtl\">\n<head>\n<meta charset=\"utf-8\"\/>\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"\/>\n<title>Aman360 \u2022 Cross-Hazard Impact Explorer<\/title>\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Tajawal:wght@400;600;800&#038;family=Inter:wght@400;600;800&#038;display=swap\" rel=\"stylesheet\">\n<!-- Charts + plugins -->\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/chart.js@4.4.1\"><\/script>\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/chartjs-chart-matrix@2.0.1\"><\/script>\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/html2canvas@1.4.1\/dist\/html2canvas.min.js\"><\/script>\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/papaparse@5.4.1\/papaparse.min.js\"><\/script>\n<style>\n:root{--bg:#0b1224;--panel:#0f1b36;--ink:#e6f0ff;--mut:#9fb3d9;--brand:#22a3ff;--line:#21335d;--chip:#0a1531;--ok:#22c55e;--warn:#f59e0b;--bad:#ef4444}\n*{box-sizing:border-box}\nbody{margin:0;background:var(--bg);color:var(--ink);font-family:Tajawal,Inter,system-ui,Segoe UI,Roboto,Arial,sans-serif}\n.container{max-width:1250px;margin:36px auto;padding:0 16px}\n.header{display:flex;gap:12px;justify-content:space-between;align-items:center;margin-bottom:12px}\n.h-title{font-weight:800;font-size:28px}\n.controls{display:flex;gap:8px;flex-wrap:wrap}\n.btn{background:var(--brand);color:#00162b;border:none;padding:10px 14px;border-radius:10px;font-weight:700;cursor:pointer}\n.btn.alt{background:#1b2f59;color:var(--ink)}\n.input,select{background:#0a1330;border:1px solid var(--line);color:var(--ink);border-radius:10px;padding:8px 10px}\n.card{background:linear-gradient(180deg,#0f1b36,#0c1630);border:1px solid var(--line);border-radius:16px;padding:14px}\n.grid{display:grid;gap:14px}\n@media(min-width:1080px){.grid-2{grid-template-columns:1.05fr .95fr}}\n.label{color:var(--mut);font-size:13px;margin-bottom:6px}\n.row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}\n.sep{height:1px;background:var(--line);border:0;margin:10px 0}\n.small{font-size:12px;color:var(--mut)}\n.badge{display:inline-block;background:#12366a;color:#cfe4ff;border:1px solid #1f4c93;padding:3px 8px;border-radius:999px}\n.table{width:100%;border-collapse:separate;border-spacing:0 6px}\n.table tr{background:#0a1531;border:1px solid var(--line)}\n.table td,.table th{padding:8px 10px}\n.kpis{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}\n.kpi{background:#0a1531;border:1px solid var(--line);border-radius:12px;padding:10px}\n.kpi h3{margin:0;font-size:22px}\n.hstack{display:flex;gap:8px;flex-wrap:wrap}\n.legend-dot{width:10px;height:10px;border-radius:50%}\n.notice{background:#0a1531;border:1px dashed var(--line);padding:10px;border-radius:12px}\n<\/style>\n<\/head>\n<body>\n<div class=\"container\" id=\"capture\">\n  <div class=\"header\">\n    <div class=\"h-title\" id=\"title\">\u0645\u0633\u062a\u0643\u0634\u0641 \u0627\u0644\u0623\u062b\u0631 \u0627\u0644\u0645\u062a\u0642\u0627\u0637\u0639 \u0628\u064a\u0646 \u0627\u0644\u0645\u062e\u0627\u0637\u0631<\/div>\n    <div class=\"controls\">\n      <select id=\"lang\" class=\"input\">\n        <option value=\"ar\" selected>\u0627\u0644\u0639\u0631\u0628\u064a\u0629<\/option>\n        <option value=\"en\">English<\/option>\n      <\/select>\n      <input type=\"file\" id=\"csvFile\" accept=\".csv\" class=\"input\">\n      <button class=\"btn alt\" id=\"btnSample\">Load sample<\/button>\n      <button class=\"btn alt\" id=\"btnMatrixCsv\">Matrix CSV<\/button>\n      <button class=\"btn alt\" id=\"btnPng\">PNG<\/button>\n      <button class=\"btn\" id=\"btnRun\">\u062a\u062d\u062f\u064a\u062b<\/button>\n    <\/div>\n  <\/div>\n\n  <div class=\"grid grid-2\">\n    <!-- Left: Settings & Heatmap -->\n    <div class=\"card\">\n      <div class=\"row\">\n        <div>\n          <div class=\"label\" data-i=\"hazCols\">\u0623\u0639\u0645\u062f\u0629 \u0627\u0644\u0645\u062e\u0627\u0637\u0631 (Hazards)<\/div>\n          <select id=\"hazards\" class=\"input\" multiple size=\"6\" style=\"min-width:230px\"><\/select>\n        <\/div>\n        <div>\n          <div class=\"label\" data-i=\"outCols\">\u0623\u0639\u0645\u062f\u0629 \u0627\u0644\u0646\u062a\u0627\u0626\u062c\/\u0627\u0644\u0642\u0627\u0628\u0644\u064a\u0629 (Outcomes)<\/div>\n          <select id=\"outcomes\" class=\"input\" multiple size=\"6\" style=\"min-width:230px\"><\/select>\n        <\/div>\n        <div>\n          <div class=\"label\" data-i=\"filter\">\u062a\u0635\u0641\u064a\u0629 \u0627\u0644\u0642\u064a\u0645 \u0627\u0644\u0645\u0641\u0642\u0648\u062f\u0629<\/div>\n          <select id=\"na\" class=\"input\">\n            <option value=\"pairwise\">Pairwise (\u0627\u0641\u062a\u0631\u0627\u0636\u064a)<\/option>\n            <option value=\"listwise\">Listwise<\/option>\n          <\/select>\n          <div class=\"small\" id=\"rowsInfo\">\u2014<\/div>\n        <\/div>\n      <\/div>\n\n      <hr class=\"sep\">\n      <div class=\"row small\">\n        <span class=\"badge\" id=\"note\">\u0627\u0646\u0642\u0631 \u0623\u064a \u062e\u0644\u064a\u0629 \u0644\u0631\u0624\u064a\u0629 Scatter + \u0627\u0644\u0627\u0646\u062d\u062f\u0627\u0631<\/span>\n        <div class=\"hstack\">\n          <span><span class=\"legend-dot\" style=\"background:#ef4444\"><\/span> r \u2264 -0.7<\/span>\n          <span><span class=\"legend-dot\" style=\"background:#f59e0b\"><\/span> -0.7 \u2026 0<\/span>\n          <span><span class=\"legend-dot\" style=\"background:#60a5fa\"><\/span> 0 \u2026 0.7<\/span>\n          <span><span class=\"legend-dot\" style=\"background:#22c55e\"><\/span> r \u2265 0.7<\/span>\n        <\/div>\n      <\/div>\n      <canvas id=\"heat\" height=\"420\" style=\"margin-top:8px\"><\/canvas>\n    <\/div>\n\n    <!-- Right: Scatter + Insights -->\n    <div class=\"card\">\n      <div class=\"kpis\">\n        <div class=\"kpi\"><div class=\"label\" data-i=\"topPos\">\u0623\u0639\u0644\u0649 \u0627\u0631\u062a\u0628\u0627\u0637\u0627\u062a \u0645\u0648\u062c\u0628\u0629<\/div><h3 id=\"kTopPos\">\u2014<\/h3><\/div>\n        <div class=\"kpi\"><div class=\"label\" data-i=\"topNeg\">\u0623\u0639\u0644\u0649 \u0627\u0631\u062a\u0628\u0627\u0637\u0627\u062a \u0633\u0627\u0644\u0628\u0629<\/div><h3 id=\"kTopNeg\">\u2014<\/h3><\/div>\n        <div class=\"kpi\"><div class=\"label\" data-i=\"nObs\">\u0639\u062f\u062f \u0627\u0644\u0645\u0634\u0627\u0647\u062f\u0627\u062a<\/div><h3 id=\"kN\">\u2014<\/h3><\/div>\n      <\/div>\n      <hr class=\"sep\">\n      <div class=\"row\">\n        <div class=\"badge\" id=\"pairTitle\">\u2014<\/div>\n      <\/div>\n      <canvas id=\"scatter\" height=\"240\" style=\"margin-top:8px\"><\/canvas>\n      <div class=\"notice small\" id=\"explain\">\u2014<\/div>\n      <hr class=\"sep\">\n      <div class=\"small\" id=\"tips\">\u2014<\/div>\n    <\/div>\n  <\/div>\n<\/div>\n\n<script>\n\/* ================= i18n ================= *\/\nconst I18N={\n  ar:{\n    title:\"\u0645\u0633\u062a\u0643\u0634\u0641 \u0627\u0644\u0623\u062b\u0631 \u0627\u0644\u0645\u062a\u0642\u0627\u0637\u0639 \u0628\u064a\u0646 \u0627\u0644\u0645\u062e\u0627\u0637\u0631\",\n    hazCols:\"\u0623\u0639\u0645\u062f\u0629 \u0627\u0644\u0645\u062e\u0627\u0637\u0631 (Hazards)\",\n    outCols:\"\u0623\u0639\u0645\u062f\u0629 \u0627\u0644\u0646\u062a\u0627\u0626\u062c\/\u0627\u0644\u0642\u0627\u0628\u0644\u064a\u0629 (Outcomes)\",\n    filter:\"\u062a\u0635\u0641\u064a\u0629 \u0627\u0644\u0642\u064a\u0645 \u0627\u0644\u0645\u0641\u0642\u0648\u062f\u0629\",\n    topPos:\"\u0623\u0639\u0644\u0649 \u0627\u0631\u062a\u0628\u0627\u0637\u0627\u062a \u0645\u0648\u062c\u0628\u0629\",\n    topNeg:\"\u0623\u0639\u0644\u0649 \u0627\u0631\u062a\u0628\u0627\u0637\u0627\u062a \u0633\u0627\u0644\u0628\u0629\",\n    nObs:\"\u0639\u062f\u062f \u0627\u0644\u0645\u0634\u0627\u0647\u062f\u0627\u062a\",\n    clickNote:\"\u0627\u0646\u0642\u0631 \u0623\u064a \u062e\u0644\u064a\u0629 \u0644\u0631\u0624\u064a\u0629 Scatter + \u0627\u0644\u0627\u0646\u062d\u062f\u0627\u0631\",\n    pair:(x,y,r)=>`\u0627\u0644\u0639\u0644\u0627\u0642\u0629: ${x} \u00d7 ${y} \u2022 r=${r}`,\n    explain:(x,y,r,p)=>`\u0627\u0644\u0627\u0631\u062a\u0628\u0627\u0637 (Pearson) \u0628\u064a\u0646 \u00ab${x}\u00bb \u0648\u00ab${y}\u00bb = ${r}. \u0642\u064a\u0645\u0629 p\u2248${p}.`,\n    tipsHigh:\"\u0627\u0631\u062a\u0628\u0627\u0637 \u0645\u0631\u062a\u0641\u0639: \u062a\u062d\u0642\u0642 \u0645\u0646 \u0627\u0644\u0633\u0628\u0628\u064a\u0629\/\u0627\u0644\u0639\u0648\u0627\u0645\u0644 \u0627\u0644\u0648\u0633\u064a\u0637\u0629\u060c \u0648\u0637\u0628\u0651\u0642 \u0627\u062e\u062a\u0628\u0627\u0631\u0627\u062a \u062d\u0633\u0627\u0633\u064a\u0629.\",\n    tipsMid:\"\u0627\u0631\u062a\u0628\u0627\u0637 \u0645\u062a\u0648\u0633\u0637: \u0645\u0641\u064a\u062f \u0643\u0645\u0624\u0634\u0631 \u062a\u0646\u0641\u064a\u0630\u064a\u060c \u0631\u0627\u0642\u0628 \u0628\u0645\u0631\u0648\u0631 \u0627\u0644\u0632\u0645\u0646.\",\n    tipsLow:\"\u0627\u0631\u062a\u0628\u0627\u0637 \u0636\u0639\u064a\u0641: \u0642\u062f \u062a\u0643\u0648\u0646 \u0627\u0644\u0639\u0644\u0627\u0642\u0629 \u063a\u064a\u0631 \u062e\u0637\u064a\u0629 \u0623\u0648 \u0645\u062a\u0623\u062b\u0631\u0629 \u0628\u0642\u064a\u0645 \u0645\u062a\u0637\u0631\u0641\u0629.\",\n    run:\"\u062a\u062d\u062f\u064a\u062b\", png:\"PNG\", sample:\"\u062a\u062d\u0645\u064a\u0644 \u0646\u0645\u0648\u0630\u062c\", matrixCsv:\"Matrix CSV\"\n  },\n  en:{\n    title:\"Cross-Hazard Impact Explorer\",\n    hazCols:\"Hazard columns\",\n    outCols:\"Outcome\/Vulnerability columns\",\n    filter:\"Missing-value filter\",\n    topPos:\"Top positive correlations\",\n    topNeg:\"Top negative correlations\",\n    nObs:\"Observations\",\n    clickNote:\"Click any cell to see scatter + regression\",\n    pair:(x,y,r)=>`Pair: ${x} \u00d7 ${y} \u2022 r=${r}`,\n    explain:(x,y,r,p)=>`Pearson correlation between \u201c${x}\u201d and \u201c${y}\u201d = ${r}. Approx. p-value \u2248 ${p}.`,\n    tipsHigh:\"High correlation: check causality\/mediators, run sensitivity checks.\",\n    tipsMid:\"Moderate correlation: useful operational signal; monitor over time.\",\n    tipsLow:\"Low correlation: relationship may be non-linear or outlier-driven.\",\n    run:\"Run\", png:\"PNG\", sample:\"Load sample\", matrixCsv:\"Matrix CSV\"\n  }\n};\n\n\/* ============== State ============== *\/\nconst els={\n  title:document.getElementById('title'),\n  lang:document.getElementById('lang'),\n  csvFile:document.getElementById('csvFile'),\n  btnSample:document.getElementById('btnSample'),\n  btnRun:document.getElementById('btnRun'),\n  btnPng:document.getElementById('btnPng'),\n  btnMatrixCsv:document.getElementById('btnMatrixCsv'),\n  hazards:document.getElementById('hazards'),\n  outcomes:document.getElementById('outcomes'),\n  na:document.getElementById('na'),\n  rowsInfo:document.getElementById('rowsInfo'),\n  kTopPos:document.getElementById('kTopPos'),\n  kTopNeg:document.getElementById('kTopNeg'),\n  kN:document.getElementById('kN'),\n  pairTitle:document.getElementById('pairTitle'),\n  explain:document.getElementById('explain'),\n  note:document.getElementById('note'),\n  tips:document.getElementById('tips'),\n  heat:document.getElementById('heat'),\n  scatter:document.getElementById('scatter')\n};\n\nlet DATA=[];        \/\/ rows as objects {col:value}\nlet COLS=[];        \/\/ column names\nlet HEAT, SCATTER;  \/\/ charts\nlet lastMatrix=null, lastPairs=[];\n\n\/* ============== UI Lang ============== *\/\nfunction applyLang(){\n  const t=I18N[els.lang.value];\n  document.documentElement.lang=els.lang.value;\n  document.documentElement.dir=(els.lang.value==='ar')?'rtl':'ltr';\n  els.title.textContent=t.title;\n  document.querySelectorAll('[data-i]').forEach(e=>{\n    const key=e.getAttribute('data-i'); e.textContent=t[key];\n  });\n  els.note.textContent=t.clickNote;\n}\n\n\/* ============== Helpers ============== *\/\nconst isNum=v=>v!==null && v!=='' && !isNaN(+v);\nfunction cleanPairwise(rows, x, y){\n  return rows.map(r=>[+r[x], +r[y]]).filter(a=>isNum(a[0])&&isNum(a[1]));\n}\nfunction cleanListwise(rows, cols){\n  return rows.filter(r=>cols.every(c=>isNum(r[c])));\n}\nfunction mean(a){return a.reduce((s,x)=>s+x,0)\/a.length}\nfunction sd(a){const m=mean(a);return Math.sqrt(a.reduce((s,x)=>s+(x-m)*(x-m),0)\/(a.length-1))}\nfunction pearson(x,y){\n  const n=x.length; if(n<3) return {r:0,p:1};\n  const mx=mean(x), my=mean(y);\n  let num=0,dx=0,dy=0;\n  for(let i=0;i<n;i++){ const vx=x[i]-mx, vy=y[i]-my; num+=vx*vy; dx+=vx*vx; dy+=vy*vy; }\n  const r = (dx===0||dy===0)?0:(num\/Math.sqrt(dx*dy));\n  \/\/ p-value (approx) via t-stat\n  const t = r*Math.sqrt((n-2)\/(1-r*r||1e-9));\n  const p = 2*(1 - studentTCDF(Math.abs(t), n-2));\n  return {r, p};\n}\n\/\/ Student's t CDF approximation\nfunction studentTCDF(t, df){\n  \/\/ using regularized incomplete beta approximation\n  function betacf(x,a,b){\n    const maxIter=200, eps=3e-7;\n    let am=1, bm=1, az=1, qab=a+b, qap=a+1, qam=a-1, bz=1 - qab*x\/qap;\n    let aold=0, em=0, tem=0, d=0, ap=0, bp=0, app=0, bpp=0;\n    for(let m=1;m<=maxIter;m++){\n      em=m; tem=em+em; d=em*(b-m)*x\/((qam+tem)*(a+tem));\n      ap=az+d*am; bp=bz+d*bm;\n      d=-(a+em)*(qab+em)*x\/((a+tem)*(qap+tem));\n      app=ap+d*az; bpp=bp+d*bz;\n      aold=az; am=ap\/bpp; bm=bp\/bpp; az=app\/bpp; bz=1;\n      if(Math.abs(az-aold)<(eps*Math.abs(az))) return az;\n    }\n    return az;\n  }\n  function betai(a,b,x){\n    const bt = (x===0||x===1)?0: Math.exp(gammaln(a+b)-gammaln(a)-gammaln(b)+a*Math.log(x)+b*Math.log(1-x));\n    if(x< (a+1)\/(a+b+2)) return bt*betacf(x,a,b)\/a;\n    return 1 - bt*betacf(1-x,b,a)\/b;\n  }\n  function gammaln(z){\n    const g=7, p=[0.99999999999980993,676.5203681218851,-1259.1392167224028,771.32342877765313,-176.61502916214059,12.507343278686905,-0.13857109526572012,9.9843695780195716e-6,1.5056327351493116e-7];\n    if(z<0.5) return Math.log(Math.PI)-Math.log(Math.sin(Math.PI*z))-gammaln(1-z);\n    z-=1; let x=p[0]; for(let i=1;i<g+2;i++){ x+=p[i]\/(z+i); }\n    const t=z+g+0.5; return 0.5*Math.log(2*Math.PI)+(z+0.5)*Math.log(t)-t+Math.log(x)-Math.log(z+1);\n  }\n  const x = df\/(df + t*t);\n  return 1 - 0.5*betai(df\/2, 0.5, x);\n}\nfunction linreg(data){ \/\/ [[x,y],...]\n  const n=data.length; if(n<2) return {a:0,b:0};\n  const xs=data.map(d=>d[0]), ys=data.map(d=>d[1]);\n  const mx=mean(xs), my=mean(ys);\n  let num=0, den=0;\n  for(let i=0;i<n;i++){ num += (xs[i]-mx)*(ys[i]-my); den += (xs[i]-mx)*(xs[i]-mx); }\n  const b = den===0?0:num\/den;\n  const a = my - b*mx;\n  return {a,b};\n}\nfunction colorForR(r){\n  if(r>=0.7) return '#22c55e';\n  if(r>=0.0) return '#60a5fa';\n  if(r<=-0.7) return '#ef4444';\n  return '#f59e0b';\n}\n\n\/* ============== Sample dataset ============== *\/\nconst SAMPLE_CSV =\n`country,flood_risk,drought_risk,quake_risk,price_shock,poverty,unemployment,youth_share,services_access,index_vuln\nA,0.65,0.30,0.10,0.55,0.38,0.22,0.19,0.70,0.52\nB,0.40,0.52,0.12,0.60,0.30,0.18,0.16,0.75,0.47\nC,0.20,0.70,0.30,0.40,0.45,0.25,0.22,0.60,0.58\nD,0.55,0.35,0.15,0.50,0.33,0.20,0.18,0.72,0.49\nE,0.10,0.20,0.65,0.30,0.28,0.15,0.14,0.80,0.42\nF,0.25,0.60,0.40,0.45,0.41,0.23,0.20,0.62,0.56\nG,0.70,0.25,0.10,0.58,0.36,0.21,0.17,0.74,0.50\nH,0.35,0.50,0.20,0.52,0.34,0.19,0.18,0.68,0.51\nI,0.18,0.68,0.35,0.38,0.44,0.26,0.23,0.58,0.59\nJ,0.12,0.22,0.60,0.32,0.27,0.14,0.13,0.82,0.41`;\n\n\/* ============== CSV load ============== *\/\nfunction setColumns(names){\n  COLS = names;\n  const hz = ['flood','drought','quake','price'];\n  els.hazards.innerHTML='';\n  els.outcomes.innerHTML='';\n  names.forEach(c=>{\n    const o1=document.createElement('option'); o1.value=c; o1.textContent=c;\n    const o2=document.createElement('option'); o2.value=c; o2.textContent=c;\n    \/\/ \u062a\u062e\u0645\u064a\u0646 \u0628\u0633\u064a\u0637: \u0627\u0644\u062d\u0642\u0648\u0644 \u0627\u0644\u062a\u064a \u062a\u062d\u062a\u0648\u064a risk\/quake\/price \u062a\u064f\u0639\u062f\u0651 \"\u0645\u062e\u0627\u0637\u0631\"\n    if(\/risk|quake|price\/i.test(c)) els.hazards.appendChild(o1); else els.outcomes.appendChild(o1);\n    if(!\/risk|quake|price\/i.test(c)) els.outcomes.appendChild(o2); else els.hazards.appendChild(o2);\n  });\n  \/\/ \u062a\u062d\u062f\u064a\u062f \u0627\u0641\u062a\u0631\u0627\u0636\u064a\n  [...els.hazards.options].forEach(o=>{ if(\/flood|drought|quake|price\/i.test(o.value)) o.selected=true; });\n  [...els.outcomes.options].forEach(o=>{ if(\/poverty|unemployment|youth|services|index\/i.test(o.value)) o.selected=true; });\n}\nfunction loadSample(){\n  const parsed = Papa.parse(SAMPLE_CSV, {header:true, dynamicTyping:true, skipEmptyLines:true});\n  DATA = parsed.data; setColumns(parsed.meta.fields);\n  els.rowsInfo.textContent = `${DATA.length} rows`;\n}\nfunction loadCSVFile(file){\n  Papa.parse(file, {\n    header:true, dynamicTyping:true, skipEmptyLines:true,\n    complete: res=>{\n      DATA = res.data; setColumns(res.meta.fields);\n      els.rowsInfo.textContent = `${DATA.length} rows`;\n    },\n    error: ()=>alert('CSV parse error')\n  });\n}\n\n\/* ============== Matrix computation\/draw ============== *\/\nfunction runMatrix(){\n  if(!DATA.length) loadSample();\n  const haz = [...els.hazards.selectedOptions].map(o=>o.value);\n  const out = [...els.outcomes.selectedOptions].map(o=>o.value);\n  const t=I18N[els.lang.value];\n\n  \/\/ rows filtering mode\n  let rows = DATA;\n  if(els.na.value==='listwise'){\n    rows = cleanListwise(DATA, [...haz,...out]);\n  }\n  els.kN.textContent = rows.length;\n\n  \/\/ compute r for each (h x o)\n  const matrix=[]; lastPairs=[];\n  let topPos={r:-2,p:1,h:'\u2014',o:'\u2014'}, topNeg={r:2,p:1,h:'\u2014',o:'\u2014'};\n  haz.forEach(hc=>{\n    out.forEach(oc=>{\n      const pairs = (els.na.value==='pairwise') ? cleanPairwise(rows, hc, oc) : cleanPairwise(rows, hc, oc);\n      const X=pairs.map(p=>p[0]), Y=pairs.map(p=>p[1]);\n      const {r,p} = (X.length>2)?pearson(X,Y):{r:0,p:1};\n      matrix.push({x:oc, y:hc, r, p, n:X.length});\n      lastPairs.push({h:hc,o:oc,r,p});\n      if(r>topPos.r) topPos={r,p,h:hc,o:oc};\n      if(r<topNeg.r) topNeg={r,p,h:hc,o:oc};\n    });\n  });\n\n  els.kTopPos.textContent = `${topPos.h}\u00d7${topPos.o} = ${topPos.r.toFixed(2)}`;\n  els.kTopNeg.textContent = `${topNeg.h}\u00d7${topNeg.o} = ${topNeg.r.toFixed(2)}`;\n\n  lastMatrix = {haz, out, cells:matrix};\n\n  \/\/ draw heatmap\n  const xLabels = out;\n  const yLabels = haz;\n  const data = {\n    datasets: [{\n      label:'r',\n      data: matrix.map(m=>({x:xLabels.indexOf(m.x), y:yLabels.indexOf(m.y), v:m.r})),\n      width: ({chart})=> (chart.chartArea.width \/ Math.max(1,xLabels.length))-2,\n      height:({chart})=> (chart.chartArea.height\/ Math.max(1,yLabels.length))-2,\n      backgroundColor: ctx=>{\n        const v=ctx.raw.v;\n        return colorForR(v);\n      },\n      borderWidth:1,\n      borderColor:'#1d2e57'\n    }]\n  };\n  const options = {\n    responsive:true,\n    plugins:{legend:{display:false}, tooltip:{callbacks:{\n      title:(it)=>`${yLabels[it[0].raw.y]} \u00d7 ${xLabels[it[0].raw.x]}`,\n      label:(it)=>`r=${it.raw.v.toFixed(2)}`\n    }}},\n    scales:{\n      x:{type:'linear', min:-0.5, max:xLabels.length-0.5, ticks:{callback:(v)=>xLabels[v], color:'#9fb3d9'}, grid:{display:false}},\n      y:{type:'linear', min:-0.5, max:yLabels.length-0.5, ticks:{callback:(v)=>yLabels[v], color:'#9fb3d9'}, grid:{display:false}, reverse:true}\n    },\n    onClick:(evt, elsChart)=>{\n      const p=elsChart[0]; if(!p) return;\n      const xi=Math.round(p.element.x); const yi=Math.round(p.element.y);\n      const cell = matrix.find(m=>xLabels.indexOf(m.x)===xi && yLabels.indexOf(m.y)===yi);\n      if(cell) drawScatter(cell.y, cell.x);\n    }\n  };\n  if(HEAT) HEAT.destroy();\n  HEAT = new Chart(els.heat.getContext('2d'), {type:'matrix', data, options});\n\n  \/\/ default selection: top positive\n  drawScatter(topPos.h, topPos.o);\n}\n\nfunction drawScatter(hc, oc){\n  const t=I18N[els.lang.value];\n  \/\/ prepare pairwise data\n  const pairs = DATA.map(r=>[r[hc], r[oc]]).filter(a=>isNum(a[0])&&isNum(a[1]));\n  const X = pairs.map(p=>+p[0]), Y=pairs.map(p=>+p[1]);\n  let {r,p} = (X.length>2)?pearson(X,Y):{r:0,p:1};\n  const lr = linreg(pairs);\n  \/\/ title & explain\n  els.pairTitle.textContent = t.pair(hc, oc, r.toFixed(2));\n  els.explain.textContent = t.explain(hc, oc, r.toFixed(2), p.toFixed(3));\n  \/\/ tips by band\n  els.tips.textContent = (Math.abs(r)>=0.7)?t.tipsHigh: (Math.abs(r)>=0.3)?t.tipsMid: t.tipsLow;\n\n  \/\/ build scatter dataset + regression line\n  const pts = pairs.map(p=>({x:p[0], y:p[1]}));\n  \/\/ regression line range\n  const xmin=Math.min(...X), xmax=Math.max(...X);\n  const y1 = lr.a + lr.b * xmin;\n  const y2 = lr.a + lr.b * xmax;\n\n  if(SCATTER) SCATTER.destroy();\n  SCATTER = new Chart(els.scatter.getContext('2d'), {\n    type:'scatter',\n    data:{\n      datasets:[\n        {label:'', data:pts, pointRadius:3, backgroundColor:'#60a5fa'},\n        {label:'', data:[{x:xmin,y:y1},{x:xmax,y:y2}], type:'line', borderColor:'#22c55e', borderWidth:2, pointRadius:0}\n      ]\n    },\n    options:{\n      plugins:{legend:{display:false}},\n      scales:{x:{grid:{color:'#1d2e57'}, ticks:{color:'#9fb3d9'}}, y:{grid:{color:'#1d2e57'}, ticks:{color:'#9fb3d9'}}}\n    }\n  });\n}\n\n\/* ============== Exports ============== *\/\ndocument.getElementById('btnPng').onclick=()=>{\n  html2canvas(document.getElementById('capture'),{backgroundColor:'#0b1224',scale:2}).then(c=>{\n    const a=document.createElement('a'); a.href=c.toDataURL('image\/png'); a.download='aman360-cross-hazard.png'; a.click();\n  });\n};\ndocument.getElementById('btnMatrixCsv').onclick=()=>{\n  if(!lastMatrix){alert('Run the matrix first');return;}\n  const rows=[['hazard','outcome','r','p','n']];\n  lastMatrix.cells.forEach(c=>rows.push([c.y,c.x,c.r.toFixed(4),c.p.toFixed(6),c.n]));\n  const csv = rows.map(r=>r.join(',')).join('\\n');\n  const blob=new Blob([csv],{type:'text\/csv;charset=utf-8'}); const url=URL.createObjectURL(blob);\n  const a=document.createElement('a'); a.href=url; a.download='aman360-cross-hazard-matrix.csv'; a.click(); URL.revokeObjectURL(url);\n};\n\n\/* ============== Events ============== *\/\nels.lang.onchange=applyLang;\nels.btnSample.onclick=loadSample;\nels.csvFile.onchange=(e)=>{ if(e.target.files?.[0]) loadCSVFile(e.target.files[0]); };\nels.btnRun.onclick=runMatrix;\n\n\/* init *\/\napplyLang(); loadSample(); runMatrix();\n<\/script>\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>Aman360 \u2022 Cross-Hazard Impact Explorer \u0645\u0633\u062a\u0643\u0634\u0641 \u0627\u0644\u0623\u062b\u0631 \u0627\u0644\u0645\u062a\u0642\u0627\u0637\u0639 \u0628\u064a\u0646 \u0627\u0644\u0645\u062e\u0627\u0637\u0631 \u0627\u0644\u0639\u0631\u0628\u064a\u0629English Load sample Matrix CSV PNG \u062a\u062d\u062f\u064a\u062b \u0623\u0639\u0645\u062f\u0629 \u0627\u0644\u0645\u062e\u0627\u0637\u0631 (Hazards) \u0623\u0639\u0645\u062f\u0629 \u0627\u0644\u0646\u062a\u0627\u0626\u062c\/\u0627\u0644\u0642\u0627\u0628\u0644\u064a\u0629 (Outcomes) \u062a\u0635\u0641\u064a\u0629 \u0627\u0644\u0642\u064a\u0645 \u0627\u0644\u0645\u0641\u0642\u0648\u062f\u0629 Pairwise (\u0627\u0641\u062a\u0631\u0627\u0636\u064a)Listwise \u2014 \u0627\u0646\u0642\u0631 \u0623\u064a \u062e\u0644\u064a\u0629 \u0644\u0631\u0624\u064a\u0629 Scatter + \u0627\u0644\u0627\u0646\u062d\u062f\u0627\u0631 r \u2264 -0.7 -0.7 \u2026 0 0 \u2026 0.7 r \u2265 0.7 \u0623\u0639\u0644\u0649 \u0627\u0631\u062a\u0628\u0627\u0637\u0627\u062a \u0645\u0648\u062c\u0628\u0629 \u2014 \u0623\u0639\u0644\u0649 \u0627\u0631\u062a\u0628\u0627\u0637\u0627\u062a \u0633\u0627\u0644\u0628\u0629 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":148,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"page-with-title","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"class_list":["post-166","page","type-page","status-publish","hentry"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/aman360.org\/ar\/wp-json\/wp\/v2\/pages\/166","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/aman360.org\/ar\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/aman360.org\/ar\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/aman360.org\/ar\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/aman360.org\/ar\/wp-json\/wp\/v2\/comments?post=166"}],"version-history":[{"count":2,"href":"https:\/\/aman360.org\/ar\/wp-json\/wp\/v2\/pages\/166\/revisions"}],"predecessor-version":[{"id":168,"href":"https:\/\/aman360.org\/ar\/wp-json\/wp\/v2\/pages\/166\/revisions\/168"}],"up":[{"embeddable":true,"href":"https:\/\/aman360.org\/ar\/wp-json\/wp\/v2\/pages\/148"}],"wp:attachment":[{"href":"https:\/\/aman360.org\/ar\/wp-json\/wp\/v2\/media?parent=166"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}