{"id":4758,"date":"2026-02-08T09:05:30","date_gmt":"2026-02-08T09:05:30","guid":{"rendered":"https:\/\/sawahsolutions.com\/national\/?page_id=4758"},"modified":"2026-02-08T09:54:39","modified_gmt":"2026-02-08T09:54:39","slug":"war-meter","status":"publish","type":"page","link":"https:\/\/sawahsolutions.com\/national\/war-meter\/","title":{"rendered":"War Meter"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"4758\" class=\"elementor elementor-4758\">\n\t\t\t\t\t\t<section class=\"has-el-gap el-gap-default elementor-section elementor-top-section elementor-element elementor-element-dc7f1c2 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"dc7f1c2\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-no\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-dae2a1e\" data-id=\"dae2a1e\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-f5bf150 elementor-widget elementor-widget-html\" data-id=\"f5bf150\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!-- =========================\r\n     NSN WAR METER (Elementor HTML)\r\n     Uses your working proxy (no CORS):\r\n     \/national\/wp-content\/themes\/smart-mag\/gdelt-proxy.php\r\n     ========================= -->\r\n\r\n<section class=\"wmeter\" aria-label=\"War Meter dashboard\">\r\n  <header class=\"wmeter__top\">\r\n    <div class=\"wmeter__brand\">\r\n      <div class=\"wmeter__mark\">WAR METER<\/div>\r\n      <div class=\"wmeter__sub\">Real-time signals from global open-source reporting (GDELT)<\/div>\r\n    <\/div>\r\n\r\n    <div class=\"wmeter__meta\">\r\n      <div class=\"wmeter__time\" id=\"wmeterTime\">Updating\u2026<\/div>\r\n      <div class=\"wmeter__toggles\">\r\n        <button type=\"button\" class=\"wmeter__btn is-active\" data-span=\"7d\">7D<\/button>\r\n        <button type=\"button\" class=\"wmeter__btn\" data-span=\"30d\">30D<\/button>\r\n      <\/div>\r\n    <\/div>\r\n  <\/header>\r\n\r\n  <div class=\"wmeter__grid\">\r\n    <!-- LEFT -->\r\n    <aside class=\"wmeter__panel\">\r\n      <div class=\"wmeter__panelHead\">\r\n        <h2>War Probability (news signal)<\/h2>\r\n        <span class=\"wmeter__pill\">LIVE<\/span>\r\n      <\/div>\r\n\r\n      <div class=\"wmeter__countries\" id=\"wmeterCountries\">\r\n        <div class=\"wmeter__skeleton\"><\/div>\r\n        <div class=\"wmeter__skeleton\"><\/div>\r\n        <div class=\"wmeter__skeleton\"><\/div>\r\n      <\/div>\r\n\r\n      <p class=\"wmeter__fine\">\r\n        This list ranks locations by volume of conflict-related coverage in the selected time window.\r\n      <\/p>\r\n    <\/aside>\r\n\r\n    <!-- CENTER -->\r\n    <main class=\"wmeter__panel\">\r\n      <div class=\"wmeter__panelHead\">\r\n        <h2>War Meter Assessment<\/h2>\r\n        <span class=\"wmeter__pill wmeter__pill--blue\">MONITORING<\/span>\r\n      <\/div>\r\n\r\n      <div class=\"wmeter__indexRow\">\r\n        <div class=\"wmeter__index\">\r\n          <div class=\"wmeter__indexLabel\">Current Index<\/div>\r\n          <div class=\"wmeter__indexValue\"><span id=\"wmeterIndex\">\u2014<\/span> <small>\/ 10<\/small><\/div>\r\n          <div class=\"wmeter__bar\">\r\n            <span class=\"wmeter__barFill\" id=\"wmeterBar\"><\/span>\r\n          <\/div>\r\n          <div class=\"wmeter__legend\">\r\n            <span>Low<\/span><span>Guarded<\/span><span>Elevated<\/span><span>High<\/span><span>Severe<\/span>\r\n          <\/div>\r\n        <\/div>\r\n\r\n        <div class=\"wmeter__threatBox\">\r\n          <div class=\"wmeter__threatTitle\">Threat Level<\/div>\r\n          <div class=\"wmeter__threatPct\"><span id=\"wmeterPct\">\u2014<\/span>%<\/div>\r\n          <div class=\"wmeter__threatSub\">Global Conflict Index<\/div>\r\n          <div class=\"wmeter__badge\" id=\"wmeterBadge\">\u2014<\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <div class=\"wmeter__chartWrap\">\r\n        <canvas id=\"wmeterTrend\" height=\"110\"><\/canvas>\r\n      <\/div>\r\n\r\n      <div class=\"wmeter__headlineRow\">\r\n        <h3>Latest conflict headlines<\/h3>\r\n        <div class=\"wmeter__articles\" id=\"wmeterArticles\">\r\n          <div class=\"wmeter__skeleton\"><\/div>\r\n          <div class=\"wmeter__skeleton\"><\/div>\r\n          <div class=\"wmeter__skeleton\"><\/div>\r\n        <\/div>\r\n      <\/div>\r\n    <\/main>\r\n\r\n    <!-- RIGHT -->\r\n    <aside class=\"wmeter__panel\">\r\n      <div class=\"wmeter__panelHead\">\r\n        <h2>Trend<\/h2>\r\n        <span class=\"wmeter__pill wmeter__pill--amber\" id=\"wmeterTrendPill\">\u2014<\/span>\r\n      <\/div>\r\n\r\n      <div class=\"wmeter__miniChart\">\r\n        <canvas id=\"wmeterMini\" height=\"120\"><\/canvas>\r\n      <\/div>\r\n\r\n      <div class=\"wmeter__panelHead\" style=\"margin-top:14px;\">\r\n        <h2>Method<\/h2>\r\n      <\/div>\r\n      <p class=\"wmeter__fine\">\r\n        Index is derived from the volume of conflict-related reporting (GDELT) using a transparent scaling function.\r\n        It is a signal, not a prediction.\r\n      <\/p>\r\n\r\n      <a class=\"wmeter__link\" href=\"https:\/\/www.gdeltproject.org\/\" target=\"_blank\" rel=\"noopener\">Data source: GDELT Project<\/a>\r\n    <\/aside>\r\n  <\/div>\r\n\r\n  <div class=\"wmeter__status\" id=\"wmeterStatus\" aria-live=\"polite\"><\/div>\r\n<\/section>\r\n\r\n<!-- Chart.js -->\r\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/chart.js@4.4.1\/dist\/chart.umd.min.js\"><\/script>\r\n\r\n<style>\r\n\/* Light\/Dark tokens match SmartMag body classes: .s-light and .s-dark *\/\r\n.s-light .wmeter{\r\n  --bg:#f4f6fb;--panel:rgba(255,255,255,.86);--panel2:rgba(255,255,255,.70);\r\n  --border:rgba(15,23,42,.14);--text:#0f172a;--muted:rgba(15,23,42,.70);\r\n  --grid:rgba(15,23,42,.08);--glow:rgba(2,6,23,.10);--accent:#c01822;\r\n  --blue:#1d4ed8;--amber:#f59e0b;--good:#22c55e;--warn:#f59e0b;--bad:#ef4444;\r\n}\r\n.s-dark .wmeter{\r\n  --bg:rgba(2,6,23,.25);--panel:rgba(17,24,39,.55);--panel2:rgba(17,24,39,.35);\r\n  --border:rgba(255,255,255,.10);--text:rgba(255,255,255,.92);--muted:rgba(255,255,255,.65);\r\n  --grid:rgba(255,255,255,.08);--glow:rgba(0,0,0,.50);--accent:#d11e2b;\r\n  --blue:#60a5fa;--amber:#fbbf24;--good:#22c55e;--warn:#f59e0b;--bad:#ef4444;\r\n}\r\n\r\n.wmeter{color:var(--text);background:linear-gradient(180deg,var(--bg),transparent 65%);border-radius:18px;padding:18px;border:1px solid var(--border)}\r\n.wmeter__top{display:flex;justify-content:space-between;align-items:flex-end;gap:12px;padding:8px 6px 16px;border-bottom:1px solid var(--grid);margin-bottom:16px}\r\n.wmeter__mark{font-weight:900;letter-spacing:.14em;text-transform:uppercase;font-size:14px}\r\n.wmeter__sub{margin-top:6px;color:var(--muted);font-size:13px}\r\n.wmeter__time{font-size:12px;color:var(--muted);text-align:right;margin-bottom:8px}\r\n.wmeter__toggles{display:flex;gap:8px;justify-content:flex-end}\r\n.wmeter__btn{border:1px solid var(--border);background:var(--panel2);color:var(--text);padding:8px 10px;border-radius:10px;font-weight:800;font-size:12px;cursor:pointer}\r\n.wmeter__btn.is-active{background:var(--accent);color:#fff;border-color:rgba(255,255,255,.12)}\r\n.wmeter__grid{display:grid;grid-template-columns:1fr 2.1fr 1fr;gap:14px}\r\n.wmeter__panel{background:var(--panel);border:1px solid var(--border);border-radius:16px;box-shadow:0 16px 36px var(--glow);padding:14px;backdrop-filter:blur(10px)}\r\n.wmeter__panelHead{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:12px}\r\n.wmeter__panel h2{font-size:13px;letter-spacing:.08em;text-transform:uppercase;margin:0;color:var(--muted)}\r\n.wmeter__pill{font-size:11px;font-weight:900;letter-spacing:.12em;padding:6px 9px;border-radius:999px;border:1px solid var(--border);background:rgba(255,255,255,.04);color:var(--text)}\r\n.wmeter__pill--blue{color:var(--blue)} .wmeter__pill--amber{color:var(--amber)}\r\n\r\n.wmeter__countries{display:flex;flex-direction:column;gap:10px}\r\n.wmeter__country{display:grid;grid-template-columns:1fr auto;gap:10px;align-items:center;padding:10px;border-radius:12px;border:1px solid var(--grid);background:rgba(255,255,255,.03)}\r\n.wmeter__countryName{font-weight:900;letter-spacing:.06em;text-transform:uppercase;font-size:12px}\r\n.wmeter__countryMeta{display:flex;gap:8px;align-items:center;color:var(--muted);font-size:12px}\r\n.wmeter__progress{grid-column:1\/-1;height:8px;border-radius:999px;background:rgba(127,127,127,.18);overflow:hidden;border:1px solid rgba(127,127,127,.20)}\r\n.wmeter__progress>span{display:block;height:100%;width:0%;border-radius:999px;background:linear-gradient(90deg,var(--good),var(--warn),var(--bad))}\r\n\r\n.wmeter__indexRow{display:grid;grid-template-columns:1.6fr .8fr;gap:12px;margin-bottom:12px}\r\n.wmeter__indexLabel{color:var(--muted);font-size:12px;text-transform:uppercase;letter-spacing:.08em}\r\n.wmeter__indexValue{font-size:34px;font-weight:900;margin:6px 0 10px}\r\n.wmeter__indexValue small{font-size:14px;color:var(--muted);font-weight:800}\r\n.wmeter__bar{height:10px;border-radius:999px;background:rgba(127,127,127,.18);border:1px solid rgba(127,127,127,.20);overflow:hidden}\r\n.wmeter__barFill{display:block;height:100%;width:0%;background:linear-gradient(90deg,var(--good),var(--warn),var(--bad))}\r\n.wmeter__legend{display:flex;justify-content:space-between;margin-top:8px;color:var(--muted);font-size:11px}\r\n\r\n.wmeter__threatBox{border:1px solid var(--grid);border-radius:16px;padding:12px;background:rgba(0,0,0,.06);text-align:center}\r\n.s-light .wmeter__threatBox{background:rgba(11,31,58,.05)}\r\n.wmeter__threatTitle{color:var(--muted);font-size:12px;letter-spacing:.08em;text-transform:uppercase}\r\n.wmeter__threatPct{font-size:40px;font-weight:900;margin:8px 0 6px}\r\n.wmeter__threatSub{color:var(--muted);font-size:12px}\r\n.wmeter__badge{margin-top:10px;display:inline-block;padding:8px 10px;border-radius:999px;font-weight:900;letter-spacing:.12em;text-transform:uppercase;font-size:11px;border:1px solid var(--border)}\r\n\r\n.wmeter__chartWrap,.wmeter__miniChart{border:1px solid var(--grid);border-radius:16px;padding:10px;background:rgba(255,255,255,.03)}\r\n.wmeter__headlineRow{margin-top:14px}\r\n.wmeter__headlineRow h3{margin:0 0 10px;font-size:13px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}\r\n.wmeter__articles{display:flex;flex-direction:column;gap:10px}\r\n.wmeter__article{border:1px solid var(--grid);border-radius:14px;padding:10px;background:rgba(255,255,255,.03)}\r\n.wmeter__article a{color:var(--text);text-decoration:none;font-weight:800;line-height:1.35}\r\n.wmeter__article a:hover{text-decoration:underline;text-underline-offset:3px}\r\n.wmeter__articleMeta{margin-top:6px;font-size:12px;color:var(--muted);display:flex;gap:10px;flex-wrap:wrap}\r\n\r\n.wmeter__fine{margin:12px 4px 0;color:var(--muted);font-size:12px;line-height:1.5}\r\n.wmeter__link{display:inline-block;margin-top:10px;font-weight:900;text-decoration:none;color:var(--text)}\r\n.wmeter__link:hover{text-decoration:underline;text-underline-offset:3px}\r\n.wmeter__status{margin-top:12px;font-size:12px;color:var(--muted)}\r\n\r\n.wmeter__skeleton{height:46px;border-radius:14px;border:1px solid var(--grid);background:linear-gradient(90deg,rgba(127,127,127,.08),rgba(127,127,127,.18),rgba(127,127,127,.08));background-size:200% 100%;animation:wmskel 1.2s infinite linear}\r\n@keyframes wmskel{0%{background-position:0% 0}100%{background-position:200% 0}}\r\n\r\n@media (max-width:1024px){\r\n  .wmeter__grid{grid-template-columns:1fr}\r\n  .wmeter__indexRow{grid-template-columns:1fr}\r\n}\r\n<\/style>\r\n\r\n<script>\r\n(function(){\r\n  \/\/ Your working proxy (subdirectory-safe)\r\n  const PROXY = \"https:\/\/sawahsolutions.com\/national\/wp-content\/themes\/smart-mag\/gdelt-proxy.php\";\r\n\r\n  const state = {\r\n    span: \"7d\",\r\n    \/\/ Conflict signal query (you can tweak words later)\r\n    query: [\r\n      '\"military strike\"', '\"air strike\"', '\"missile strike\"', '\"rocket attack\"',\r\n      '\"troop deployment\"', '\"border clash\"', '\"armed conflict\"', '\"ground offensive\"',\r\n      '\"drone attack\"', '\"shelling\"', '\"ceasefire\"', '\"mobilization\"', '\"incursion\"',\r\n      '\"war crimes\"', '\"terror attack\"', '\"counterterrorism\"', '\"hostage\"', '\"insurgent\"'\r\n    ].join(\" OR \")\r\n  };\r\n\r\n  const els = {\r\n    time: document.getElementById(\"wmeterTime\"),\r\n    index: document.getElementById(\"wmeterIndex\"),\r\n    pct: document.getElementById(\"wmeterPct\"),\r\n    bar: document.getElementById(\"wmeterBar\"),\r\n    badge: document.getElementById(\"wmeterBadge\"),\r\n    trendPill: document.getElementById(\"wmeterTrendPill\"),\r\n    countries: document.getElementById(\"wmeterCountries\"),\r\n    articles: document.getElementById(\"wmeterArticles\"),\r\n    status: document.getElementById(\"wmeterStatus\"),\r\n    buttons: Array.from(document.querySelectorAll(\".wmeter__btn\"))\r\n  };\r\n\r\n  function escapeHtml(str){\r\n    return String(str).replace(\/[&<>\"']\/g, s => ({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;',\"'\":'&#39;'}[s]));\r\n  }\r\n  function fmt(n){ return (n ?? 0).toLocaleString(); }\r\n\r\n  function setTimes(){\r\n    const now = new Date();\r\n    const uk = new Intl.DateTimeFormat('en-GB', { timeZone:'Europe\/London', dateStyle:'medium', timeStyle:'short' }).format(now);\r\n    const us = new Intl.DateTimeFormat('en-US', { timeZone:'America\/New_York', dateStyle:'medium', timeStyle:'short' }).format(now);\r\n    els.time.textContent = `Updated: UK ${uk} \u2022 US ${us}`;\r\n  }\r\n\r\n  function toIndex(volume){\r\n    const v = Math.max(1, volume || 1);\r\n    \/\/ simple, stable scaling for a \"signal\" 0-10\r\n    const idx = Math.min(10, Math.max(0, (Math.log10(v) - 2) * 2.5));\r\n    return Math.round(idx * 10) \/ 10;\r\n  }\r\n\r\n  function levelFromIndex(idx){\r\n    if (idx < 2.5) return {label:'LOW', color:'var(--good)'};\r\n    if (idx < 4.5) return {label:'GUARDED', color:'var(--good)'};\r\n    if (idx < 6.2) return {label:'ELEVATED', color:'var(--warn)'};\r\n    if (idx < 8.2) return {label:'HIGH ALERT', color:'var(--bad)'};\r\n    return {label:'SEVERE', color:'var(--bad)'};\r\n  }\r\n\r\n  function buildProxyUrl(endpoint, span, query){\r\n    const u = new URL(PROXY);\r\n    u.searchParams.set(\"endpoint\", endpoint); \/\/ timeline | country | articles\r\n    u.searchParams.set(\"span\", span);         \/\/ 7d | 30d\r\n    u.searchParams.set(\"query\", query);\r\n    return u.toString();\r\n  }\r\n\r\n  async function fetchProxy(endpoint){\r\n  const u = new URL(PROXY);\r\n  u.searchParams.set(\"endpoint\", endpoint);\r\n  u.searchParams.set(\"span\", state.span);\r\n  u.searchParams.set(\"query\", state.query);\r\n\r\n  const res = await fetch(u.toString(), { cache: \"no-store\" });\r\n  const text = await res.text();\r\n\r\n  let json;\r\n  try {\r\n    json = JSON.parse(text);\r\n  } catch (e) {\r\n    console.error(\"Proxy returned non-JSON:\", text.slice(0, 300));\r\n    throw new Error(\"Proxy returned non-JSON (see console). First chars: \" + text.slice(0, 60));\r\n  }\r\n\r\n  if (!json.success) {\r\n    console.error(\"Proxy JSON error:\", json);\r\n    throw new Error(json.error || \"Proxy error\");\r\n  }\r\n\r\n  return json.data;\r\n}\r\n\r\n\r\n  let trendChart, miniChart;\r\n\r\n  function getVar(name){\r\n    return getComputedStyle(document.querySelector(\".wmeter\")).getPropertyValue(name).trim();\r\n  }\r\n\r\n  function buildCharts(labels, values){\r\n    const text = getVar('--text');\r\n    const grid = getVar('--grid');\r\n    const accent = getVar('--accent');\r\n    const blue = getVar('--blue');\r\n\r\n    const baseCfg = {\r\n      type: \"line\",\r\n      data: { labels, datasets: [{ data: values, borderColor: accent, backgroundColor: \"transparent\", tension: 0.35, borderWidth: 2, pointRadius: 0 }] },\r\n      options: {\r\n        responsive: true,\r\n        maintainAspectRatio: false,\r\n        plugins: { legend: { display: false } },\r\n        scales: {\r\n          x: { ticks: { color: text, maxTicksLimit: 8 }, grid: { color: grid } },\r\n          y: { ticks: { color: text, maxTicksLimit: 5 }, grid: { color: grid } }\r\n        }\r\n      }\r\n    };\r\n\r\n    const miniCfg = JSON.parse(JSON.stringify(baseCfg));\r\n    miniCfg.data.datasets[0].borderColor = blue;\r\n\r\n    const ctx = document.getElementById(\"wmeterTrend\");\r\n    const ctxMini = document.getElementById(\"wmeterMini\");\r\n\r\n    if (trendChart) trendChart.destroy();\r\n    if (miniChart) miniChart.destroy();\r\n\r\n    trendChart = new Chart(ctx, baseCfg);\r\n    miniChart = new Chart(ctxMini, miniCfg);\r\n  }\r\n\r\n  function renderCountries(rows){\r\n    const top = (rows || []).slice(0, 12);\r\n    if (!top.length){\r\n      els.countries.innerHTML = '<p class=\"wmeter__fine\">No country data returned.<\/p>';\r\n      return;\r\n    }\r\n    const max = Math.max(...top.map(x => x.count || 0), 1);\r\n\r\n    els.countries.innerHTML = top.map(x => {\r\n      const pct = Math.round(((x.count || 0) \/ max) * 100);\r\n      return `\r\n        <div class=\"wmeter__country\">\r\n          <div class=\"wmeter__countryName\">${escapeHtml(x.country)}<\/div>\r\n          <div class=\"wmeter__countryMeta\"><span>${fmt(x.count)}<\/span><span>${pct}%<\/span><\/div>\r\n          <div class=\"wmeter__progress\"><span style=\"width:${pct}%\"><\/span><\/div>\r\n        <\/div>\r\n      `;\r\n    }).join(\"\");\r\n  }\r\n\r\n  function renderArticles(articles){\r\n    const items = (articles || []).slice(0, 8);\r\n    if (!items.length){\r\n      els.articles.innerHTML = '<p class=\"wmeter__fine\">No recent headlines returned.<\/p>';\r\n      return;\r\n    }\r\n\r\n    els.articles.innerHTML = items.map(a => {\r\n      const title = a.title || \"Read more\";\r\n      const url = a.url || \"#\";\r\n      const domain = a.domain || \"\";\r\n      const date = a.seendate ? new Date(a.seendate).toLocaleString() : \"\";\r\n      return `\r\n        <div class=\"wmeter__article\">\r\n          <a href=\"${escapeHtml(url)}\" target=\"_blank\" rel=\"noopener\">${escapeHtml(title)}<\/a>\r\n          <div class=\"wmeter__articleMeta\">\r\n            ${domain ? `<span>${escapeHtml(domain)}<\/span>` : \"\"}\r\n            ${date ? `<span>${escapeHtml(date)}<\/span>` : \"\"}\r\n          <\/div>\r\n        <\/div>\r\n      `;\r\n    }).join(\"\");\r\n  }\r\n\r\n  function parseTimeline(data){\r\n    \/\/ GDELT timelinevolraw commonly returns { timeline:[{date,value},...] }\r\n    const tl = data.timeline || data.data || [];\r\n    const labels = [];\r\n    const values = [];\r\n\r\n    if (Array.isArray(tl)){\r\n      for (const row of tl){\r\n        const d = row.date || row.day || row.datetime || row.startdate;\r\n        const v = row.value ?? row.count ?? row.volume ?? row.numarticles ?? 0;\r\n        if (!d) continue;\r\n        labels.push(String(d).slice(0,10));\r\n        values.push(Number(v) || 0);\r\n      }\r\n    }\r\n    return { labels, values };\r\n  }\r\n\r\n  function parseCountries(data){\r\n    \/\/ GDELT geo\/country often returns GeoJSON {features:[{properties:{name,value}}]}\r\n    let rows = [];\r\n    if (Array.isArray(data.features)){\r\n      rows = data.features.map(f => ({\r\n        country: f.properties?.name || f.properties?.country || \"Unknown\",\r\n        count: Number(f.properties?.value ?? f.properties?.count ?? 0)\r\n      }));\r\n    } else if (Array.isArray(data.data)) {\r\n      rows = data.data.map(r => ({\r\n        country: r.name || r.country || \"Unknown\",\r\n        count: Number(r.value || r.count || 0)\r\n      }));\r\n    }\r\n\r\n    return rows.filter(x => x.country && x.count).sort((a,b) => b.count - a.count);\r\n  }\r\n\r\n  function parseArticles(data){\r\n    \/\/ GDELT artlist returns { articles:[...] }\r\n    return data.articles || data.data || data.results || [];\r\n  }\r\n\r\n  async function refresh(){\r\n    setTimes();\r\n    els.status.textContent = \"Loading live data\u2026\";\r\n\r\n    try {\r\n      const [timelineData, countryData, articlesData] = await Promise.all([\r\n        fetchProxy(\"timeline\"),\r\n        fetchProxy(\"country\"),\r\n        fetchProxy(\"articles\")\r\n      ]);\r\n\r\n      \/\/ Timeline + index\r\n      const { labels, values } = parseTimeline(timelineData);\r\n      const latestVol = values.length ? values[values.length - 1] : 1;\r\n      const idx = toIndex(latestVol);\r\n      const pct = Math.round((idx \/ 10) * 100);\r\n\r\n      els.index.textContent = idx.toFixed(1);\r\n      els.pct.textContent = String(pct);\r\n      els.bar.style.width = pct + \"%\";\r\n\r\n      const lvl = levelFromIndex(idx);\r\n      els.badge.textContent = lvl.label;\r\n      els.badge.style.borderColor = lvl.color;\r\n      els.badge.style.color = lvl.color;\r\n      els.badge.style.background = \"rgba(0,0,0,.10)\";\r\n\r\n      \/\/ Trend pill (simple delta)\r\n      const change = values.length >= 8 ? (values[values.length-1] - values[values.length-8]) : 0;\r\n      els.trendPill.textContent = change > 0 ? \"TRENDING UP\" : (change < 0 ? \"COOLING\" : \"STABLE\");\r\n      els.trendPill.style.color = change > 0 ? \"var(--bad)\" : (change < 0 ? \"var(--good)\" : \"var(--amber)\");\r\n\r\n      \/\/ Charts\r\n      if (labels.length && values.length) buildCharts(labels, values);\r\n\r\n      \/\/ Countries\r\n      const countryRows = parseCountries(countryData);\r\n      renderCountries(countryRows);\r\n\r\n      \/\/ Articles\r\n      const artList = parseArticles(articlesData);\r\n      renderArticles(artList);\r\n\r\n      els.status.textContent = \"Live data loaded.\";\r\n\r\n    } catch (err) {\r\n      console.error(err);\r\n      els.status.textContent = \"Error: \" + (err?.message || \"Unknown error\");\r\n      els.countries.innerHTML = '<p class=\"wmeter__fine\">Could not load live data right now. Please refresh.<\/p>';\r\n      els.articles.innerHTML = '<p class=\"wmeter__fine\">Could not load headlines right now. Please refresh.<\/p>';\r\n      els.index.textContent = \"\u2014\";\r\n      els.pct.textContent = \"\u2014\";\r\n      els.bar.style.width = \"0%\";\r\n      els.badge.textContent = \"\u2014\";\r\n      els.trendPill.textContent = \"\u2014\";\r\n    }\r\n  }\r\n\r\n  function setSpan(span){\r\n    state.span = span;\r\n    els.buttons.forEach(b => b.classList.toggle(\"is-active\", b.dataset.span === span));\r\n    refresh();\r\n  }\r\n\r\n  els.buttons.forEach(b => b.addEventListener(\"click\", () => setSpan(b.dataset.span)));\r\n\r\n  refresh();\r\n  setInterval(refresh, 10 * 60 * 1000);\r\n})();\r\n<\/script>\r\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>WAR METER Real-time signals from global open-source reporting (GDELT) Updating\u2026 7D 30D War Probability (news signal) LIVE This list ranks locations by volume of conflict-related coverage in the selected time window. War Meter Assessment MONITORING Current Index \u2014 \/ 10 LowGuardedElevatedHighSevere Threat Level \u2014% Global Conflict Index \u2014 Latest conflict headlines Trend \u2014 Method Index<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"page-templates\/no-wrapper.php","meta":{"footnotes":""},"class_list":["post-4758","page","type-page","status-publish"],"_links":{"self":[{"href":"https:\/\/sawahsolutions.com\/national\/wp-json\/wp\/v2\/pages\/4758","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sawahsolutions.com\/national\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/sawahsolutions.com\/national\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/sawahsolutions.com\/national\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sawahsolutions.com\/national\/wp-json\/wp\/v2\/comments?post=4758"}],"version-history":[{"count":25,"href":"https:\/\/sawahsolutions.com\/national\/wp-json\/wp\/v2\/pages\/4758\/revisions"}],"predecessor-version":[{"id":4786,"href":"https:\/\/sawahsolutions.com\/national\/wp-json\/wp\/v2\/pages\/4758\/revisions\/4786"}],"wp:attachment":[{"href":"https:\/\/sawahsolutions.com\/national\/wp-json\/wp\/v2\/media?parent=4758"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}