aiblueprint-cli 1.4.74 → 1.4.76

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.
@@ -0,0 +1,402 @@
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>Real Analysis · Is the $200 comparison honest?</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
10
+ <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
11
+ <style>
12
+ :root {
13
+ --bg:#0a0a0a; --deep:#000; --surface:#141414; --raised:#1c1c1e;
14
+ --fg:#fff; --muted:#a1a1a1; --subtle:#6b6b6b;
15
+ --border:#232323; --glass:rgba(20,20,20,0.6); --border-glass:rgba(255,255,255,0.08);
16
+ --red:#ff6363; --red-deep:#e5484d; --blue:#3b9eff;
17
+ --sans:'Inter', system-ui, sans-serif; --mono:'JetBrains Mono', ui-monospace, monospace;
18
+ }
19
+ * { box-sizing:border-box; margin:0; padding:0; }
20
+ html { scroll-behavior:smooth; -webkit-text-size-adjust:100%; }
21
+ body { font-family:var(--sans); background:var(--bg); color:var(--fg); line-height:1.5; -webkit-font-smoothing:antialiased; position:relative; }
22
+ /* top red glow */
23
+ body::before { content:""; position:absolute; inset:0 0 auto 0; height:560px; pointer-events:none; z-index:0;
24
+ background:
25
+ radial-gradient(60% 60% at 50% -10%, rgba(255,99,99,0.20), transparent 70%),
26
+ linear-gradient(115deg, transparent 42%, rgba(255,99,99,0.08) 50%, transparent 58%); }
27
+ .wrap { max-width:1080px; margin:0 auto; padding:0 24px; position:relative; z-index:1; }
28
+ .num { font-variant-numeric:tabular-nums; }
29
+ .mono { font-family:var(--mono); }
30
+
31
+ /* Floating glass nav */
32
+ .navwrap { position:sticky; top:16px; z-index:50; padding:0 16px; margin-top:16px; }
33
+ .nav { max-width:1080px; margin:0 auto; display:flex; align-items:center; justify-content:space-between;
34
+ border:1px solid var(--border-glass); background:var(--glass); border-radius:16px; padding:12px 18px; backdrop-filter:blur(20px); -webkit-backdrop-filter:blur(20px); }
35
+ .nav .brand { display:flex; align-items:center; gap:9px; font-weight:600; font-size:16px; }
36
+ .nav .brand .mark { width:16px; height:16px; border-radius:5px; background:var(--red); box-shadow:0 0 14px rgba(255,99,99,.6); transform:rotate(45deg); }
37
+ .nav .links { display:flex; gap:26px; font-size:14px; color:var(--muted); }
38
+ .nav .links a { text-decoration:none; color:var(--muted); } .nav .links a:hover { color:#fff; }
39
+ .nav .links a.active { color:#fff; border:1px solid rgba(59,158,255,.5); border-radius:8px; padding:3px 10px; }
40
+ .nav .dl { background:#f5f5f5; color:#000; border:none; border-radius:12px; padding:9px 18px; font-weight:500; font-size:14px; cursor:pointer; }
41
+
42
+ /* Hero */
43
+ header { padding:72px 0 48px; text-align:center; }
44
+ .pill-tag { display:inline-flex; align-items:center; gap:7px; border:1px solid var(--border); background:var(--surface); border-radius:9999px; padding:6px 14px; font-size:13px; color:var(--muted); margin-bottom:26px; }
45
+ .pill-tag .spark { color:var(--red); }
46
+ h1 { font-size:clamp(38px,6vw,68px); font-weight:600; letter-spacing:-0.03em; line-height:1.02; max-width:16ch; margin:0 auto; }
47
+ h1 .red { color:var(--red); }
48
+ .lede { color:var(--muted); font-size:clamp(16px,2vw,19px); margin:22px auto 0; max-width:60ch; }
49
+
50
+ /* Stats */
51
+ .stats { display:grid; grid-template-columns:repeat(4,1fr); gap:16px; padding-bottom:8px; }
52
+ .stat { border:1px solid var(--border); background:linear-gradient(180deg,#141414,#0f0f0f); border-radius:20px; padding:24px 22px; }
53
+ .stat .k { font-size:11px; font-weight:500; letter-spacing:.04em; text-transform:uppercase; color:var(--subtle); }
54
+ .stat .v { font-size:40px; font-weight:700; letter-spacing:-0.03em; margin-top:12px; line-height:1; }
55
+ .stat:nth-child(1) .v { color:var(--red); } .stat:nth-child(3) .v { color:var(--blue); }
56
+ .stat .d { font-size:13px; color:var(--muted); margin-top:11px; }
57
+
58
+ /* Sections */
59
+ section { padding:54px 0; }
60
+ section + section { border-top:1px solid var(--border); }
61
+ .sec-head { margin-bottom:34px; max-width:74ch; }
62
+ .sec-head .step { font-family:var(--mono); font-size:12px; letter-spacing:.04em; text-transform:uppercase; color:var(--red); }
63
+ .sec-head h2 { font-size:clamp(26px,3.4vw,38px); font-weight:600; letter-spacing:-0.025em; margin-top:12px; line-height:1.05; }
64
+ .sec-head p { color:var(--muted); font-size:16px; line-height:1.6; margin-top:14px; }
65
+
66
+ .grid-2 { display:grid; grid-template-columns:1fr 1fr; gap:18px; align-items:start; }
67
+ .panel { border:1px solid var(--border); background:linear-gradient(180deg,#141414,#0f0f0f); border-radius:24px; padding:26px; }
68
+ .panel .ptitle { font-size:16px; font-weight:600; }
69
+ .panel .psub { font-family:var(--mono); font-size:11.5px; color:var(--subtle); text-transform:uppercase; letter-spacing:.04em; margin-top:5px; }
70
+ .chart-box { position:relative; height:300px; margin-top:18px; }
71
+ .chart-box.tall { height:240px; }
72
+
73
+ .legend { display:flex; gap:20px; flex-wrap:wrap; margin-top:18px; }
74
+ .legend span { display:inline-flex; align-items:center; gap:8px; font-size:13px; color:var(--muted); }
75
+ .legend i { width:11px; height:11px; border-radius:4px; display:inline-block; }
76
+
77
+ .note { margin-top:20px; padding-top:18px; border-top:1px solid var(--border); font-size:15px; line-height:1.6; color:var(--muted); max-width:82ch; }
78
+ .note b { color:#fff; font-weight:600; }
79
+
80
+ /* Big callout - raised glass with glow */
81
+ .big-callout { border:1px solid var(--border-glass); background:var(--raised); border-radius:24px; padding:40px 34px; margin-top:8px; box-shadow:0 0 90px -24px rgba(255,99,99,.4); }
82
+ .big-callout .lbl { font-family:var(--mono); font-size:12px; text-transform:uppercase; letter-spacing:.05em; color:var(--subtle); }
83
+ .big-callout .row { display:flex; flex-wrap:wrap; align-items:baseline; gap:14px 48px; margin-top:20px; }
84
+ .big-callout .row .v { font-size:60px; font-weight:700; letter-spacing:-0.03em; }
85
+ .big-callout .row .eq { font-size:36px; color:var(--red); }
86
+ .big-callout .cap { font-size:15.5px; line-height:1.5; margin-top:20px; color:var(--muted); max-width:62ch; }
87
+
88
+ .three { display:grid; grid-template-columns:repeat(3,1fr); gap:18px; }
89
+ .mini { border:1px solid var(--border); background:linear-gradient(180deg,#141414,#0f0f0f); border-radius:20px; padding:22px; }
90
+ .mini .mt { font-size:14px; font-weight:600; } .mini .ms { font-family:var(--mono); font-size:11px; color:var(--subtle); text-transform:uppercase; letter-spacing:.04em; margin-top:4px; }
91
+ .mini .cwrap { position:relative; height:150px; margin-top:14px; }
92
+
93
+ .verdict-table { width:100%; border-collapse:separate; border-spacing:0; border:1px solid var(--border); border-radius:24px; overflow:hidden; background:linear-gradient(180deg,#141414,#0f0f0f); }
94
+ .verdict-table td { padding:20px 24px; font-size:16px; line-height:1.5; border-top:1px solid var(--border); vertical-align:top; }
95
+ .verdict-table tr:first-child td { border-top:none; }
96
+ .verdict-table td:first-child { font-weight:600; color:#fff; width:42%; }
97
+ .verdict-table td:last-child { color:var(--muted); }
98
+ .tag { font-family:var(--mono); font-size:10px; padding:3px 9px; border-radius:9999px; vertical-align:middle; margin-right:8px; letter-spacing:.03em; text-transform:uppercase; }
99
+ .tag.no { background:rgba(255,99,99,.15); color:var(--red); border:1px solid rgba(255,99,99,.3); }
100
+ .tag.tie { background:rgba(59,158,255,.15); color:var(--blue); border:1px solid rgba(59,158,255,.3); }
101
+
102
+ footer { padding:54px 0 90px; }
103
+ footer .eyebrow { font-family:var(--mono); font-size:12px; text-transform:uppercase; letter-spacing:.05em; color:var(--subtle); margin-bottom:20px; display:block; border-top:1px solid var(--border); padding-top:20px; }
104
+ footer ul { list-style:none; display:grid; gap:14px; max-width:84ch; }
105
+ footer li { font-size:15px; line-height:1.55; color:var(--muted); padding-left:22px; position:relative; }
106
+ footer li::before { content:"✦"; position:absolute; left:0; top:1px; color:var(--red); font-size:11px; }
107
+ footer li b { color:#fff; }
108
+ footer a { color:var(--blue); text-decoration:none; } footer a:hover { text-decoration:underline; }
109
+ footer .sig { margin-top:28px; font-size:12px; color:var(--subtle); }
110
+
111
+ @media (max-width:860px){
112
+ .nav .links{display:none;}
113
+ .stats{grid-template-columns:1fr 1fr;}
114
+ .grid-2{grid-template-columns:1fr;} .three{grid-template-columns:1fr;}
115
+ }
116
+ @media (max-width:480px){ .stats{grid-template-columns:1fr;} }
117
+
118
+ /* === responsive hardening (auto) === */
119
+ html, body { max-width:100%; overflow-x:hidden; }
120
+ img, canvas, svg, table { max-width:100%; }
121
+ .note, .mono, .lede, .big-callout .cap, .sec-head p, .stat .d, footer li { overflow-wrap:anywhere; word-break:break-word; }
122
+ @media (max-width:760px){
123
+ .grid-2, .three { grid-template-columns:1fr !important; }
124
+ .stats { grid-template-columns:1fr 1fr; }
125
+ .topnav, .nav, .topband .inner, .navpills, .hero { flex-wrap:wrap; }
126
+ .chart-box { height:260px; }
127
+ .chart-box.tall { height:240px; }
128
+ section { padding-top:40px; padding-bottom:40px; }
129
+ }
130
+ @media (max-width:560px){
131
+ .wrap { padding-left:16px; padding-right:16px; }
132
+ .stats { grid-template-columns:1fr; }
133
+ .big-callout { padding:24px 20px; }
134
+ .big-callout .row { gap:10px 22px; }
135
+ .big-callout .row .v { font-size:40px; }
136
+ .big-callout .row .eq { font-size:24px; }
137
+ .verdict-table, .verdict-table tbody, .verdict-table tr, .verdict-table td { display:block; width:100% !important; }
138
+ .verdict-table td { padding:14px 18px !important; }
139
+ .verdict-table td:first-child { padding-bottom:4px; }
140
+ .verdict-table td:last-child { padding-top:0; border-top:none !important; }
141
+ .chart-box { height:230px; }
142
+ .stat .v { font-size:32px; }
143
+ h1 { max-width:100% !important; }
144
+ }
145
+
146
+
147
+ /* === chart responsive fix (auto) === */
148
+ .grid-2, .three { min-width:0; }
149
+ .grid-2 > *, .three > *, .panel, .mini, .stat { min-width:0; }
150
+ .chart-box, .cwrap { position:relative; width:100%; }
151
+ .chart-box canvas, .cwrap canvas { max-width:100% !important; }
152
+
153
+ </style>
154
+ </head>
155
+ <body>
156
+
157
+ <div class="navwrap">
158
+ <nav class="nav">
159
+ <span class="brand"><span class="mark"></span> agents</span>
160
+ <div class="links">
161
+ <a href="index.html">Reports</a>
162
+ <a href="#">Codex $200</a>
163
+ <a href="#">Claude Max 20x</a>
164
+ <a class="active" href="#">Real analysis</a>
165
+ </div>
166
+ <button class="dl">Methodology</button>
167
+ </nav>
168
+ </div>
169
+
170
+ <div class="wrap">
171
+
172
+ <header>
173
+ <span class="pill-tag"><span class="spark">✦</span> Methodology audit · is the comparison honest?</span>
174
+ <h1>Most of the value is <span class="red">cache, not work.</span></h1>
175
+ <p class="lede">The reports say Codex $200 is worth ~$8,600/mo and Claude $200 ~$18,900/mo. Here is the proof that "Claude is worth 2× more" is misleading - and what is actually true.</p>
176
+ </header>
177
+
178
+ <div class="stats num">
179
+ <div class="stat"><div class="k">Your tokens today</div><div class="v">92.7%</div><div class="d">are cache reads, not new work</div></div>
180
+ <div class="stat"><div class="k">That are output</div><div class="v">0.6%</div><div class="d">the only real "work" line</div></div>
181
+ <div class="stat"><div class="k">Real output value</div><div class="v">≈ tie</div><div class="d">$977 vs $911 / mo</div></div>
182
+ <div class="stat"><div class="k">The 2× gap</div><div class="v">artifact</div><div class="d">cache pricing + extrapolation</div></div>
183
+ </div>
184
+
185
+ <!-- 1 -->
186
+ <section>
187
+ <div class="sec-head">
188
+ <div class="step">01 / the symptom</div>
189
+ <h2>Where your tokens go vs where the dollars go</h2>
190
+ <p>Measured from your own logs (<span class="mono" style="font-size:14px">~/.claude/projects</span>, deduped by request, 2026-05-30). Almost everything is cache. Output - the actual work - is a sliver of the count and a small share of the dollars.</p>
191
+ </div>
192
+ <div class="grid-2">
193
+ <div class="panel">
194
+ <div class="ptitle">Token count</div>
195
+ <div class="psub">89.8M tokens today</div>
196
+ <div class="chart-box"><canvas id="countD"></canvas></div>
197
+ </div>
198
+ <div class="panel">
199
+ <div class="ptitle">API-equivalent dollars</div>
200
+ <div class="psub">$113 today, at Opus list</div>
201
+ <div class="chart-box"><canvas id="dollarD"></canvas></div>
202
+ </div>
203
+ </div>
204
+ <div class="legend">
205
+ <span><i style="background:var(--s3)"></i> Cache read</span>
206
+ <span><i style="background:var(--s2)"></i> Cache write</span>
207
+ <span><i style="background:var(--s1)"></i> Output (real work)</span>
208
+ <span><i style="background:var(--s4)"></i> Fresh input</span>
209
+ </div>
210
+ <p class="note"><b>~87% of the dollars are caching overhead; ~12% is output.</b> Caching does not stop the model re-reading the whole context on every call - it just makes the re-read cheap. The token count stays huge because it equals context size × number of calls (~110K re-read × 758 calls today).</p>
211
+ </section>
212
+
213
+ <!-- 2 -->
214
+ <section>
215
+ <div class="sec-head">
216
+ <div class="step">02 / the core proof</div>
217
+ <h2>Both $200 plans, decomposed to the same monthly basis</h2>
218
+ <p>Each plan's value split into output vs cache, priced at its own provider's API list, scaled to 100% of monthly quota. The output slivers (red) are nearly identical. The entire headline gap is the gray cache bars.</p>
219
+ </div>
220
+ <div class="panel">
221
+ <div class="chart-box tall"><canvas id="decomp"></canvas></div>
222
+ <div class="legend">
223
+ <span><i style="background:var(--red)"></i> Output (real work)</span>
224
+ <span><i style="background:#6b6b6b"></i> Cache re-read ($0.50/1M)</span>
225
+ <span><i style="background:#3a3a3a"></i> First read (input / cache-write)</span>
226
+ </div>
227
+ <p class="note">Codex total <b>$8,589</b> · Claude total <b>$18,891</b>. Output: <b>$977 vs $911</b>. Input/cache side: <b>$7,612 vs $17,980 (2.4×)</b> - that is where 100% of the gap lives.</p>
228
+ </div>
229
+ </section>
230
+
231
+ <!-- 3 -->
232
+ <section>
233
+ <div class="sec-head">
234
+ <div class="step">03 / the punchline</div>
235
+ <h2>Strip away cache: the real work is a tie</h2>
236
+ <p>Output is the least gameable metric - the tokens the model actually generated for you. On a monthly, full-quota basis the two $200 plans are within ~7% of each other.</p>
237
+ </div>
238
+ <div class="big-callout">
239
+ <div class="lbl">Output value per month (real work)</div>
240
+ <div class="row num">
241
+ <div><div class="v">$977</div><div class="lbl" style="margin-top:8px">Codex $200</div></div>
242
+ <div class="eq">≈</div>
243
+ <div><div class="v">$911</div><div class="lbl" style="margin-top:8px">Claude $200</div></div>
244
+ </div>
245
+ <p class="cap">In raw output tokens: ~32.6M/mo (Codex) vs ~36.4M/mo (Claude) - a 1.12× edge, nowhere near the 2× the headline implies.</p>
246
+ </div>
247
+ </section>
248
+
249
+ <!-- 4 -->
250
+ <section>
251
+ <div class="sec-head">
252
+ <div class="step">04 / why it looks 2×</div>
253
+ <h2>Three calculation asymmetries inflate Claude's number</h2>
254
+ <p>None of these reflect more work delivered. They reflect how the number was built.</p>
255
+ </div>
256
+ <div class="three">
257
+ <div class="mini">
258
+ <div class="mt">Extrapolation multiplier</div>
259
+ <div class="ms">lower = more reliable</div>
260
+ <div class="cwrap"><canvas id="aExtrap"></canvas></div>
261
+ <p class="note" style="margin-top:14px;padding-top:14px;font-size:14px">Codex was measured at 99% quota. Claude was one day at 10%, multiplied ×10 - any error amplified 10×.</p>
262
+ </div>
263
+ <div class="mini">
264
+ <div class="mt">Price to cache context</div>
265
+ <div class="ms">first read, per 1M</div>
266
+ <div class="cwrap"><canvas id="aPrice"></canvas></div>
267
+ <p class="note" style="margin-top:14px;padding-top:14px;font-size:14px">Anthropic charges 2× for a "cache write" vs OpenAI's normal input. Same behavior, pricier meter.</p>
268
+ </div>
269
+ <div class="mini">
270
+ <div class="mt">Context re-reads</div>
271
+ <div class="ms">per output token</div>
272
+ <div class="cwrap"><canvas id="aReread"></canvas></div>
273
+ <p class="note" style="margin-top:14px;padding-top:14px;font-size:14px">Claude re-reads ~2× more context per unit of output, bloating the cache-read line.</p>
274
+ </div>
275
+ </div>
276
+ </section>
277
+
278
+ <!-- 5 -->
279
+ <section>
280
+ <div class="sec-head">
281
+ <div class="step">05 / watch the gap melt</div>
282
+ <h2>Remove the artifacts and $18.9k slides toward $8.6k</h2>
283
+ <p>Starting from Claude's headline, undo each calculation artifact in turn. The gap to Codex's measured number shrinks at every step.</p>
284
+ </div>
285
+ <div class="panel">
286
+ <div class="chart-box tall"><canvas id="bridge"></canvas></div>
287
+ <p class="note">Re-pricing cache writes at Codex's rate: $18,891 → <b>$15,562</b>. Adjusting the one-day ×10 extrapolation for a plausibly heavy sample day (÷1.5): → <b>~$12,600</b>. Codex, essentially measured: <b>$8,589</b>. The residual is genuine extra context churn, not extra work.</p>
288
+ </div>
289
+ </section>
290
+
291
+ <!-- 6 -->
292
+ <section>
293
+ <div class="sec-head">
294
+ <div class="step">06 / the honest answer</div>
295
+ <h2>What is actually true</h2>
296
+ </div>
297
+ <table class="verdict-table">
298
+ <tr>
299
+ <td>Which $200 plan does more real work?</td>
300
+ <td><span class="tag tie">tie</span>Roughly equal - output ~$977 vs ~$911 / mo.</td>
301
+ </tr>
302
+ <tr>
303
+ <td>Which API would bill more for this usage at full quota?</td>
304
+ <td>Claude - but because it charges more for the same caching and the figure is a ×10 extrapolation, not because you get more done.</td>
305
+ </tr>
306
+ <tr>
307
+ <td>Is "$9k vs $20k = Claude worth 2×" a fair comparison?</td>
308
+ <td><span class="tag no">no</span>It compares a measurement to a one-day ×10 guess, across two pricing models that treat caching differently, on a metric dominated by context overhead.</td>
309
+ </tr>
310
+ </table>
311
+ <p class="note">The deeper trap is the word <b>"value."</b> API-equivalent value measures what the provider's meter would charge, so it rewards verbose context, heavy cache re-reads, and a pricier cache-write rate. A plan can score "2× more valuable" while delivering identical output. That is exactly what happened here.</p>
312
+ </section>
313
+
314
+ <footer>
315
+ <span class="eyebrow">Confidence &amp; sources</span>
316
+ <ul>
317
+ <li><b>Proven from data</b> (high): your usage is 92.7% cache / 0.6% output; output value is ~equal; 100% of the gap is cache; first-read price is $5 (Codex) vs $10 (Claude); scale factors ×4.38 vs ×43.33.</li>
318
+ <li><b>Inferred from the math</b> (high): normalizing cache-write price drops Claude to ~$15.6k; the ×10 extrapolation makes the headline unreliable.</li>
319
+ <li><b>External reporting</b> (medium): exact subscription-limit weighting, Opus-vs-Sonnet ratio, and the 2026 cache-TTL change are documented by press, not by this repo's data.</li>
320
+ <li>Data: <span class="mono" style="font-size:13px">result/melvynx/codex/2026-05-30T09-13-16Z</span>, <span class="mono" style="font-size:13px">result/taka-foo/claude</span>. Full write-up: <a href="real-analysis.md">real-analysis.md</a>.</li>
321
+ <li>Sources: <a href="https://support.claude.com/en/articles/14552983-models-usage-and-limits-in-claude-code">Anthropic limits</a> · <a href="https://www.theregister.com/2026/03/31/anthropic_claude_code_limits/">The Register</a> · <a href="https://www.xda-developers.com/anthropic-quietly-nerfed-claude-code-hour-cache-token-budget/">XDA cache nerf</a>.</li>
322
+ </ul>
323
+ <div class="sig">Real Analysis · generated from agents-analysis data · API-equivalent value is not the provider's real cost.</div>
324
+ </footer>
325
+
326
+ </div>
327
+
328
+ <script>
329
+ const RED="#ff6363", BLUE="#3b9eff", S2="#a1a1a1", S3="#6b6b6b", S4="#3a3a3a", GRID="#232323";
330
+ document.documentElement.style.setProperty('--s1', RED);
331
+ document.documentElement.style.setProperty('--s2', S2);
332
+ document.documentElement.style.setProperty('--s3', S3);
333
+ document.documentElement.style.setProperty('--s4', S4);
334
+
335
+ Chart.defaults.font.family = "Inter, system-ui, sans-serif";
336
+ Chart.defaults.color = "#6b6b6b";
337
+ Chart.defaults.font.size = 12;
338
+ const usd = (v) => "$" + v.toLocaleString("en-US",{maximumFractionDigits:0});
339
+ const tip = { backgroundColor:"rgba(20,20,20,0.92)", borderColor:"#232323", borderWidth:1, padding:10, cornerRadius:12, titleColor:"#fff", bodyColor:"#fff" };
340
+
341
+ function dough(id, data, fmt){
342
+ new Chart(document.getElementById(id), {
343
+ type:"doughnut",
344
+ data:{ labels:["Cache read","Cache write","Output","Fresh input"],
345
+ datasets:[{ data, backgroundColor:[S3,S2,RED,S4], borderColor:"#141414", borderWidth:3, hoverOffset:6 }] },
346
+ options:{ responsive:true, maintainAspectRatio:false, cutout:"62%",
347
+ plugins:{ legend:{display:false}, tooltip:{...tip, callbacks:{ label:(c)=>c.label+": "+fmt(c.parsed) }} } }
348
+ });
349
+ }
350
+ dough("countD", [83.3,5.7,0.5,0.3], (v)=>v+"M tokens");
351
+ dough("dollarD", [41.64,56.93,13.23,1.48], (v)=>"$"+v.toFixed(2));
352
+
353
+ new Chart(document.getElementById("decomp"), {
354
+ type:"bar",
355
+ data:{ labels:["Codex $200","Claude $200"],
356
+ datasets:[
357
+ { label:"Output (real work)", data:[977,911], backgroundColor:RED, borderRadius:{topLeft:6,bottomLeft:6} },
358
+ { label:"Cache re-read", data:[5303,11319], backgroundColor:S3 },
359
+ { label:"First read (input/cache-write)", data:[2309,6661], backgroundColor:S4, borderRadius:{topRight:6,bottomRight:6} }
360
+ ] },
361
+ options:{ indexAxis:"y", responsive:true, maintainAspectRatio:false,
362
+ plugins:{ legend:{display:false}, tooltip:{...tip, callbacks:{ label:(c)=>c.dataset.label+": "+usd(c.parsed.x) }} },
363
+ scales:{ x:{ stacked:true, grid:{color:GRID}, border:{display:false}, ticks:{ callback:(v)=>"$"+(v/1000)+"k" } },
364
+ y:{ stacked:true, grid:{display:false}, border:{color:GRID}, ticks:{ font:{family:"Inter",size:13,weight:600}, color:"#fff" } } } }
365
+ });
366
+
367
+ function mini(id, vals, fmt, max){
368
+ new Chart(document.getElementById(id), {
369
+ type:"bar",
370
+ data:{ labels:["Codex","Claude"], datasets:[{ data:vals, backgroundColor:[S3,RED], borderRadius:8, barPercentage:0.6 }] },
371
+ options:{ responsive:true, maintainAspectRatio:false,
372
+ plugins:{ legend:{display:false}, tooltip:{...tip, callbacks:{ label:(c)=>fmt(c.parsed.y) }} },
373
+ scales:{ x:{ grid:{display:false}, border:{color:GRID}, ticks:{font:{family:"Inter",size:12}} },
374
+ y:{ grid:{color:GRID}, border:{display:false}, max, ticks:{ callback:fmt } } } }
375
+ });
376
+ }
377
+ mini("aExtrap", [4.38,43.33], (v)=>"×"+(typeof v==="number"?v.toFixed(v<10?1:0):v), 48);
378
+ mini("aPrice", [5,10], (v)=>"$"+v, 12);
379
+ mini("aReread", [326,621], (v)=>v.toFixed(0), 700);
380
+
381
+ new Chart(document.getElementById("bridge"), {
382
+ type:"bar",
383
+ data:{ labels:["Claude headline","− cache-write premium","− 1-day extrapolation","Codex (measured)"],
384
+ datasets:[{ data:[18891,15562,12600,8589], backgroundColor:[RED,"#c25050","#6b6b6b",BLUE], borderRadius:8, barPercentage:0.62 }] },
385
+ options:{ responsive:true, maintainAspectRatio:false,
386
+ plugins:{ legend:{display:false}, tooltip:{...tip, callbacks:{ label:(c)=>usd(c.parsed.y)+" / mo" }} },
387
+ scales:{ x:{ grid:{display:false}, border:{color:GRID}, ticks:{font:{family:"Inter",size:11}} },
388
+ y:{ grid:{color:GRID}, border:{display:false}, ticks:{ callback:(v)=>"$"+(v/1000)+"k" } } } }
389
+ });
390
+ </script>
391
+
392
+ <script>
393
+ // force Chart.js to reflow on viewport changes (belt-and-suspenders)
394
+ (function(){
395
+ function resizeAll(){ if(window.Chart && Chart.instances){ Object.values(Chart.instances).forEach(function(c){ try{c.resize();}catch(e){} }); } }
396
+ var t; window.addEventListener('resize', function(){ clearTimeout(t); t=setTimeout(resizeAll,120); });
397
+ window.addEventListener('orientationchange', function(){ setTimeout(resizeAll,200); });
398
+ })();
399
+ </script>
400
+
401
+ </body>
402
+ </html>