whiplash-index 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/embed_square.html +68 -0
- package/embed_wide.html +69 -0
- package/package.json +7 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>The Whiplash Index</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
8
|
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap">
|
|
9
|
+
<style>
|
|
10
|
+
:root { color-scheme: light;
|
|
11
|
+
--surface-1:#fcfcfb; --page:#f9f9f7; --ink-1:#0b0b0b; --ink-2:#52514e; --muted:#898781;
|
|
12
|
+
--grid:#e1e0d9; --baseline:#c3c2b7; --border:rgba(11,11,11,0.10);
|
|
13
|
+
--good:#0ca30c; --warning:#fab219; --serious:#ec835a; --accent:#2a78d6; }
|
|
14
|
+
@media (prefers-color-scheme: dark) { :root { color-scheme: dark;
|
|
15
|
+
--surface-1:#1a1a19; --page:#0d0d0d; --ink-1:#ffffff; --ink-2:#c3c2b7; --muted:#898781;
|
|
16
|
+
--grid:#2c2c2a; --baseline:#383835; --border:rgba(255,255,255,0.10); --accent:#3987e5; } }
|
|
17
|
+
* { margin:0; padding:0; box-sizing:border-box; }
|
|
18
|
+
body { font-family: 'Inter', system-ui, -apple-system, "Segoe UI", sans-serif; background:var(--page); color:var(--ink-1); line-height:1.55; padding:12px; }
|
|
19
|
+
.card { max-width:820px; margin:0 auto; }
|
|
20
|
+
h1 { font-size:18px; font-weight:700; margin-bottom:2px; letter-spacing:-0.01em; }
|
|
21
|
+
.sub { font-size:12.5px; color:var(--muted); margin-bottom:12px; }
|
|
22
|
+
.copy p { font-size:14px; margin-bottom:8px; }
|
|
23
|
+
.copy p:last-child { margin-bottom:0; }
|
|
24
|
+
.method { margin-top:14px; border-top:1px solid var(--grid); padding-top:10px; }
|
|
25
|
+
.method summary { font-size:13px; font-weight:600; color:var(--ink-2); cursor:pointer; user-select:none; }
|
|
26
|
+
.method p { font-size:12.5px; color:var(--ink-2); margin-top:8px; }
|
|
27
|
+
.cols { display:flex; flex-wrap:wrap; gap:20px; align-items:center; }
|
|
28
|
+
.cols .chart { flex:1 1 340px; text-align:center; }
|
|
29
|
+
.cols .side { flex:1 1 280px; }
|
|
30
|
+
</style>
|
|
31
|
+
</head>
|
|
32
|
+
<body>
|
|
33
|
+
<div class="card">
|
|
34
|
+
<h1>The Whiplash Index</h1>
|
|
35
|
+
<div class="sub">Where the economy stands vs the story being told about it · updated September 7, 2026</div>
|
|
36
|
+
<div class="cols"><div class="chart"><svg viewBox="0 0 400 400" role="img" aria-label="The Whiplash Index quadrant: real economy vs story extension, 3-year quarterly path. Current position: contracting and overhyped." style="max-width:400px;width:100%;">
|
|
37
|
+
<rect x="30" y="30" width="300" height="300" fill="none" stroke="var(--grid)"/>
|
|
38
|
+
<line x1="180" y1="30" x2="180" y2="330" stroke="var(--grid)" stroke-width="1.5"/>
|
|
39
|
+
<line x1="30" y1="180" x2="330" y2="180" stroke="var(--baseline)" stroke-width="1.5"/>
|
|
40
|
+
<ellipse cx="246" cy="180" rx="52" ry="34" fill="var(--good)" opacity="0.10"/>
|
|
41
|
+
<ellipse cx="246" cy="180" rx="52" ry="34" fill="none" stroke="var(--good)" stroke-dasharray="5 5"/>
|
|
42
|
+
<text x="246" y="184" text-anchor="middle" font-size="10.5" fill="var(--good)" font-weight="700">SWEET SPOT</text>
|
|
43
|
+
<text x="38" y="48" font-size="11" font-weight="700" text-anchor="start" fill="var(--serious)">DENIAL</text><text x="38" y="62" font-size="9.5" text-anchor="start" fill="var(--muted)">shrinking, story says fine</text><text x="322" y="48" font-size="11" font-weight="700" text-anchor="end" fill="var(--warning)">RUNNING HOT</text><text x="322" y="62" font-size="9.5" text-anchor="end" fill="var(--muted)">growing, but overhyped</text><text x="38" y="306" font-size="11" font-weight="700" text-anchor="start" fill="var(--muted)">DESPAIR</text><text x="38" y="320" font-size="9.5" text-anchor="start" fill="var(--muted)">shrinking, story too gloomy</text><text x="322" y="306" font-size="11" font-weight="700" text-anchor="end" fill="var(--muted)">UNDERRATED</text><text x="322" y="320" font-size="9.5" text-anchor="end" fill="var(--muted)">growing, story too gloomy</text>
|
|
44
|
+
<text x="180" y="352" text-anchor="middle" font-size="10.5" fill="var(--ink-2)">Real economy (private data): shrinking ← → growing</text>
|
|
45
|
+
<text x="13" y="180" font-size="10.5" fill="var(--ink-2)" transform="rotate(-90 13 180)" text-anchor="middle">Story vs reality: too gloomy ← → too hot</text>
|
|
46
|
+
<g id="trail"><polyline points="54,93 117,75 81,87 156,93 180,75 204,123 231,180 255,135 267,118 255,111 177,93 147,68" fill="none" stroke="var(--accent)" stroke-width="1.5" opacity="0.45" stroke-dasharray="4 4"/><circle cx="54" cy="93" r="3.5" fill="var(--accent)" opacity="0.22"/><text x="62" y="85" font-size="9.5" text-anchor="start" fill="var(--muted)">Q4 '23</text><circle cx="117" cy="75" r="3.7" fill="var(--accent)" opacity="0.27"/><circle cx="81" cy="87" r="3.9" fill="var(--accent)" opacity="0.32"/><circle cx="156" cy="93" r="4.0" fill="var(--accent)" opacity="0.37"/><circle cx="180" cy="75" r="4.2" fill="var(--accent)" opacity="0.42"/><circle cx="204" cy="123" r="4.4" fill="var(--accent)" opacity="0.47"/><circle cx="231" cy="180" r="4.6" fill="var(--accent)" opacity="0.52"/><text x="239" y="194" font-size="9.5" text-anchor="start" fill="var(--muted)">Q2 '25</text><circle cx="255" cy="135" r="4.8" fill="var(--accent)" opacity="0.57"/><circle cx="267" cy="118" r="5.0" fill="var(--accent)" opacity="0.62"/><text x="275" y="110" font-size="9.5" text-anchor="start" fill="var(--muted)">Q4 '25</text><circle cx="255" cy="111" r="5.1" fill="var(--accent)" opacity="0.67"/><circle cx="177" cy="93" r="5.3" fill="var(--accent)" opacity="0.72"/><text x="185" y="107" font-size="9.5" text-anchor="start" fill="var(--muted)">Q2 '26</text></g>
|
|
47
|
+
<circle cx="147" cy="68" r="7" fill="var(--accent)"/>
|
|
48
|
+
<circle cx="147" cy="68" r="11" fill="none" stroke="var(--accent)" opacity="0.4"/>
|
|
49
|
+
<text x="163" y="72" font-size="11.0" font-weight="700" fill="var(--ink-1)">NOW (Sep 7)</text>
|
|
50
|
+
</svg>
|
|
51
|
+
<div style="margin-top:2px;"><label style="font-size:12.5px; color:var(--ink-2); cursor:pointer; user-select:none; white-space:nowrap;"><input type="checkbox" id="trailToggle" checked style="vertical-align:-2px; margin-right:6px;">Show the 3-year path (quarterly averages)</label></div>
|
|
52
|
+
<script>
|
|
53
|
+
(function(){
|
|
54
|
+
var t=document.getElementById('trailToggle'), g=document.getElementById('trail');
|
|
55
|
+
if(t&&g){t.addEventListener('change',function(){ if(t.checked){g.removeAttribute('hidden');} else {g.setAttribute('hidden','');} });}
|
|
56
|
+
})();
|
|
57
|
+
</script></div><div class="side"><div class="copy">
|
|
58
|
+
<p><strong>What it says right now:</strong> The real economy is slowing. Fewer goods are being shipped, and fewer people are going out to eat. But the official numbers and the stock market are acting like everything is fine. That gap between the story and reality is the widest it has been all year. Gaps like this do not last: either reality catches up to the story, or the story falls back down to reality.</p>
|
|
59
|
+
<p><strong>What just changed:</strong> The government jobs report flipped from weak to strong in one month, while private shipping data got worse. The US Treasury began buying back its own long-term bonds. Gold pulled back after a strong run.</p>
|
|
60
|
+
<p><strong>What we are waiting on:</strong> The Federal Reserve meets this month. Its decision, and how markets react to it, is the next big card to turn over.</p>
|
|
61
|
+
</div></div></div>
|
|
62
|
+
<details class="method">
|
|
63
|
+
<summary>How it is measured</summary>
|
|
64
|
+
<p>The left-right position comes only from private data: freight volumes, restaurant traffic, and private labor readings, mapped so the middle means a flat economy. The up-down position is the “extension” reading, like an RSI for the economic story: how far the official numbers AND market prices are running from what the private data shows. It blends the gap between official and independent inflation measures, whether official and private jobs data point the same direction, and whether stocks and credit are priced for the economy the private data describes. The path shows quarterly averages over a 3-year window. Data referenced: Cass Freight Index, Truflation, BLS CPI, ICE BofA high-yield spreads (via FRED), S&P 500. Informational and educational only; not investment advice.</p>
|
|
65
|
+
</details>
|
|
66
|
+
</div>
|
|
67
|
+
</body>
|
|
68
|
+
</html>
|
package/embed_wide.html
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>The Whiplash Index</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
8
|
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap">
|
|
9
|
+
<style>
|
|
10
|
+
:root { color-scheme: light;
|
|
11
|
+
--surface-1:#fcfcfb; --page:#f9f9f7; --ink-1:#0b0b0b; --ink-2:#52514e; --muted:#898781;
|
|
12
|
+
--grid:#e1e0d9; --baseline:#c3c2b7; --border:rgba(11,11,11,0.10);
|
|
13
|
+
--good:#0ca30c; --warning:#fab219; --serious:#ec835a; --accent:#2a78d6; }
|
|
14
|
+
@media (prefers-color-scheme: dark) { :root { color-scheme: dark;
|
|
15
|
+
--surface-1:#1a1a19; --page:#0d0d0d; --ink-1:#ffffff; --ink-2:#c3c2b7; --muted:#898781;
|
|
16
|
+
--grid:#2c2c2a; --baseline:#383835; --border:rgba(255,255,255,0.10); --accent:#3987e5; } }
|
|
17
|
+
* { margin:0; padding:0; box-sizing:border-box; }
|
|
18
|
+
body { font-family: 'Inter', system-ui, -apple-system, "Segoe UI", sans-serif; background:var(--page); color:var(--ink-1); line-height:1.55; padding:12px; }
|
|
19
|
+
.card { max-width:820px; margin:0 auto; }
|
|
20
|
+
h1 { font-size:18px; font-weight:700; margin-bottom:2px; letter-spacing:-0.01em; }
|
|
21
|
+
.sub { font-size:12.5px; color:var(--muted); margin-bottom:12px; }
|
|
22
|
+
.copy p { font-size:14px; margin-bottom:8px; }
|
|
23
|
+
.copy p:last-child { margin-bottom:0; }
|
|
24
|
+
.method { margin-top:14px; border-top:1px solid var(--grid); padding-top:10px; }
|
|
25
|
+
.method summary { font-size:13px; font-weight:600; color:var(--ink-2); cursor:pointer; user-select:none; }
|
|
26
|
+
.method p { font-size:12.5px; color:var(--ink-2); margin-top:8px; }
|
|
27
|
+
.cols { display:flex; flex-wrap:wrap; gap:20px; align-items:center; }
|
|
28
|
+
.cols .chart { flex:1 1 340px; text-align:center; }
|
|
29
|
+
.cols .side { flex:1 1 280px; }
|
|
30
|
+
</style>
|
|
31
|
+
</head>
|
|
32
|
+
<body>
|
|
33
|
+
<div class="card">
|
|
34
|
+
<h1>The Whiplash Index</h1>
|
|
35
|
+
<div class="sub">Where the economy stands vs the story being told about it · updated September 7, 2026</div>
|
|
36
|
+
<div style="text-align:center; margin-bottom:14px;"><svg viewBox="0 0 720 470" role="img" aria-label="The Whiplash Index quadrant: real economy vs story extension, 3-year quarterly path. Current position: contracting and overhyped." style="max-width:720px;width:100%;">
|
|
37
|
+
<rect x="40" y="28" width="640" height="400" fill="none" stroke="var(--grid)"/>
|
|
38
|
+
<line x1="360" y1="28" x2="360" y2="428" stroke="var(--grid)" stroke-width="1.5"/>
|
|
39
|
+
<line x1="40" y1="228" x2="680" y2="228" stroke="var(--baseline)" stroke-width="1.5"/>
|
|
40
|
+
<ellipse cx="501" cy="228" rx="95" ry="48" fill="var(--good)" opacity="0.10"/>
|
|
41
|
+
<ellipse cx="501" cy="228" rx="95" ry="48" fill="none" stroke="var(--good)" stroke-dasharray="5 5"/>
|
|
42
|
+
<text x="501" y="232" text-anchor="middle" font-size="12" fill="var(--good)" font-weight="700">SWEET SPOT</text>
|
|
43
|
+
<text x="52" y="52" font-size="13" font-weight="700" text-anchor="start" fill="var(--serious)">DENIAL</text><text x="52" y="66" font-size="11" text-anchor="start" fill="var(--muted)">shrinking, story says fine</text><text x="668" y="52" font-size="13" font-weight="700" text-anchor="end" fill="var(--warning)">RUNNING HOT</text><text x="668" y="66" font-size="11" text-anchor="end" fill="var(--muted)">growing, but overhyped</text><text x="52" y="402" font-size="13" font-weight="700" text-anchor="start" fill="var(--muted)">DESPAIR</text><text x="52" y="416" font-size="11" text-anchor="start" fill="var(--muted)">shrinking, story too gloomy</text><text x="668" y="402" font-size="13" font-weight="700" text-anchor="end" fill="var(--muted)">UNDERRATED</text><text x="668" y="416" font-size="11" text-anchor="end" fill="var(--muted)">growing, story too gloomy</text>
|
|
44
|
+
<text x="360" y="456" text-anchor="middle" font-size="12" fill="var(--ink-2)">Real economy (private data): shrinking ← → growing</text>
|
|
45
|
+
<text x="16" y="228" font-size="12" fill="var(--ink-2)" transform="rotate(-90 16 228)" text-anchor="middle">Story vs reality: too gloomy ← → too hot</text>
|
|
46
|
+
<g id="trail"><polyline points="91,112 226,88 149,104 309,112 360,88 411,152 469,228 520,168 546,146 520,136 354,112 290,78" fill="none" stroke="var(--accent)" stroke-width="1.5" opacity="0.45" stroke-dasharray="4 4"/><circle cx="91" cy="112" r="4.0" fill="var(--accent)" opacity="0.22"/><text x="99" y="102" font-size="11" text-anchor="start" fill="var(--muted)">Q4 '23</text><circle cx="226" cy="88" r="4.2" fill="var(--accent)" opacity="0.27"/><circle cx="149" cy="104" r="4.5" fill="var(--accent)" opacity="0.32"/><circle cx="309" cy="112" r="4.7" fill="var(--accent)" opacity="0.37"/><text x="317" y="102" font-size="11" text-anchor="start" fill="var(--muted)">Q3 '24</text><circle cx="360" cy="88" r="4.9" fill="var(--accent)" opacity="0.42"/><circle cx="411" cy="152" r="5.1" fill="var(--accent)" opacity="0.47"/><text x="419" y="142" font-size="11" text-anchor="start" fill="var(--muted)">Q1 '25</text><circle cx="469" cy="228" r="5.4" fill="var(--accent)" opacity="0.52"/><text x="477" y="246" font-size="11" text-anchor="start" fill="var(--muted)">Q2 '25</text><circle cx="520" cy="168" r="5.6" fill="var(--accent)" opacity="0.57"/><circle cx="546" cy="146" r="5.8" fill="var(--accent)" opacity="0.62"/><text x="554" y="136" font-size="11" text-anchor="start" fill="var(--muted)">Q4 '25</text><circle cx="520" cy="136" r="6.0" fill="var(--accent)" opacity="0.67"/><text x="512" y="124" font-size="11" text-anchor="end" fill="var(--muted)">Q1 '26</text><circle cx="354" cy="112" r="6.3" fill="var(--accent)" opacity="0.72"/><text x="362" y="130" font-size="11" text-anchor="start" fill="var(--muted)">Q2 '26</text></g>
|
|
47
|
+
<circle cx="290" cy="78" r="9" fill="var(--accent)"/>
|
|
48
|
+
<circle cx="290" cy="78" r="14" fill="none" stroke="var(--accent)" opacity="0.4"/>
|
|
49
|
+
<text x="306" y="83" font-size="12.5" font-weight="700" fill="var(--ink-1)">NOW (Sep 7)</text>
|
|
50
|
+
</svg>
|
|
51
|
+
<div style="margin-top:2px;"><label style="font-size:12.5px; color:var(--ink-2); cursor:pointer; user-select:none; white-space:nowrap;"><input type="checkbox" id="trailToggle" checked style="vertical-align:-2px; margin-right:6px;">Show the 3-year path (quarterly averages)</label></div>
|
|
52
|
+
<script>
|
|
53
|
+
(function(){
|
|
54
|
+
var t=document.getElementById('trailToggle'), g=document.getElementById('trail');
|
|
55
|
+
if(t&&g){t.addEventListener('change',function(){ if(t.checked){g.removeAttribute('hidden');} else {g.setAttribute('hidden','');} });}
|
|
56
|
+
})();
|
|
57
|
+
</script></div>
|
|
58
|
+
<div class="copy">
|
|
59
|
+
<p><strong>What it says right now:</strong> The real economy is slowing. Fewer goods are being shipped, and fewer people are going out to eat. But the official numbers and the stock market are acting like everything is fine. That gap between the story and reality is the widest it has been all year. Gaps like this do not last: either reality catches up to the story, or the story falls back down to reality.</p>
|
|
60
|
+
<p><strong>What just changed:</strong> The government jobs report flipped from weak to strong in one month, while private shipping data got worse. The US Treasury began buying back its own long-term bonds. Gold pulled back after a strong run.</p>
|
|
61
|
+
<p><strong>What we are waiting on:</strong> The Federal Reserve meets this month. Its decision, and how markets react to it, is the next big card to turn over.</p>
|
|
62
|
+
</div>
|
|
63
|
+
<details class="method">
|
|
64
|
+
<summary>How it is measured</summary>
|
|
65
|
+
<p>The left-right position comes only from private data: freight volumes, restaurant traffic, and private labor readings, mapped so the middle means a flat economy. The up-down position is the “extension” reading, like an RSI for the economic story: how far the official numbers AND market prices are running from what the private data shows. It blends the gap between official and independent inflation measures, whether official and private jobs data point the same direction, and whether stocks and credit are priced for the economy the private data describes. The path shows quarterly averages over a 3-year window. Data referenced: Cass Freight Index, Truflation, BLS CPI, ICE BofA high-yield spreads (via FRED), S&P 500. Informational and educational only; not investment advice.</p>
|
|
66
|
+
</details>
|
|
67
|
+
</div>
|
|
68
|
+
</body>
|
|
69
|
+
</html>
|
package/package.json
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "whiplash-index",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "The Whiplash Index: where the economy stands vs the story being told about it. Static embed files, updated weekly.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"files": ["embed_wide.html", "embed_square.html"]
|
|
7
|
+
}
|