| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>The Boundary: AI, Work, and What Remains</title> |
| <link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;0,900;1,400&family=IBM+Plex+Mono:wght@300;400;500&family=Crimson+Pro:ital,wght@0,300;0,400;1,300&display=swap" rel="stylesheet"> |
| <script src="https://d3js.org/d3.v7.min.js"></script> |
| <style> |
| *,*::before,*::after{margin:0;padding:0;box-sizing:border-box;} |
| :root{ |
| --bg:#07070c;--bg2:#0e0e18;--bg3:#14141f; |
| --border:#1e1e30;--border2:#2c2c42; |
| --text:#e2ddd5;--text-dim:#8888a4;--text-dimmer:#484864; |
| --p1:#7dd3fc;--p1g:rgba(125,211,252,.1); |
| --p2:#f87171;--p2g:rgba(248,113,113,.1); |
| --p3:#fbbf24;--p3g:rgba(251,191,36,.1); |
| --p4:#e2ddd5;--p4g:rgba(226,221,213,.06); |
| } |
| html,body{width:100%;height:100%;background:var(--bg);color:var(--text);font-family:'Crimson Pro',Georgia,serif;overflow:hidden;} |
| |
| |
| #nav{position:fixed;top:0;left:0;right:0;height:52px;background:rgba(7,7,12,.97);border-bottom:1px solid var(--border);display:flex;align-items:center;padding:0 28px;z-index:300;backdrop-filter:blur(12px);} |
| .nav-title{font-family:'Playfair Display',serif;font-size:18px;font-weight:900;letter-spacing:-.01em;color:var(--text);flex-shrink:0;} |
| .nav-sep{width:1px;height:18px;background:var(--border2);margin:0 18px;flex-shrink:0;} |
| .nav-sub{font-family:'IBM Plex Mono',monospace;font-size:11px;color:var(--text-dim);flex-shrink:0;} |
| .tabs{display:flex;gap:3px;flex-shrink:0;margin-left:auto;} |
| .tab{font-family:'IBM Plex Mono',monospace;font-size:11px;letter-spacing:.1em;padding:7px 16px;border:1px solid var(--border);background:transparent;color:var(--text-dim);cursor:pointer;transition:all .2s;text-transform:uppercase;} |
| .tab:hover{color:var(--text);border-color:var(--border2);} |
| .tab.p0.active{color:var(--text);border-color:var(--border2);background:var(--bg3);} |
| .tab.p1.active{color:var(--p1);border-color:var(--p1);background:var(--p1g);} |
| .tab.p2.active{color:var(--p2);border-color:var(--p2);background:var(--p2g);} |
| .tab.p3.active{color:var(--p3);border-color:var(--p3);background:var(--p3g);} |
| .tab.p4.active{color:var(--p4);border-color:var(--p4);background:var(--p4g);} |
| |
| |
| #main{position:fixed;top:52px;left:0;right:0;bottom:0;} |
| .panel{position:absolute;inset:0;display:flex;flex-direction:column;padding:24px 40px 16px;visibility:hidden;opacity:0;pointer-events:none;transition:opacity .3s ease;} |
| .panel.active{visibility:visible;opacity:1;pointer-events:auto;} |
| |
| |
| .ph{flex-shrink:0;margin-bottom:9px;} |
| .ph-eye{font-family:'IBM Plex Mono',monospace;font-size:10px;letter-spacing:.3em;color:var(--text-dim);text-transform:uppercase;margin-bottom:3px;} |
| .ph-title{font-family:'Playfair Display',serif;font-size:26px;font-weight:900;line-height:1;letter-spacing:-.01em;margin-bottom:4px;} |
| .ph-desc{font-family:'IBM Plex Mono',monospace;font-size:11px;color:var(--text-dim);letter-spacing:.03em;line-height:1.5;max-width:780px;} |
| #panel-p1 .ph-title{color:var(--p1);} |
| #panel-p2 .ph-title{color:var(--p2);} |
| #panel-p3 .ph-title{color:var(--p3);} |
| |
| |
| .big-idea{font-family:'Crimson Pro',serif;font-size:14px;font-style:italic;color:var(--text);line-height:1.45;margin-bottom:10px;border-left:2px solid;padding-left:12px;flex-shrink:0;max-width:840px;} |
| #panel-p1 .big-idea{border-color:var(--p1);} |
| #panel-p2 .big-idea{border-color:var(--p2);} |
| #panel-p3 .big-idea{border-color:var(--p3);} |
| |
| |
| .ctrl-row{display:flex;align-items:center;gap:5px;margin-bottom:8px;flex-shrink:0;flex-wrap:wrap;} |
| .ctrl-label{font-family:'IBM Plex Mono',monospace;font-size:10px;letter-spacing:.12em;color:var(--text-dimmer);text-transform:uppercase;margin-right:2px;} |
| .ctrl-btn{font-family:'IBM Plex Mono',monospace;font-size:10px;letter-spacing:.08em;padding:4px 11px;border:1px solid var(--border);background:transparent;color:var(--text-dim);cursor:pointer;transition:all .15s;text-transform:uppercase;} |
| .ctrl-btn:hover{color:var(--text);border-color:var(--border2);} |
| .ctrl-btn.active{background:var(--bg3);color:var(--text);border-color:var(--border2);} |
| .status-line{font-family:'IBM Plex Mono',monospace;font-size:10px;color:var(--text-dimmer);flex:1;text-align:right;} |
| |
| |
| .legend{display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin-bottom:8px;flex-shrink:0;} |
| .legend-item{display:flex;align-items:center;gap:6px;font-family:'IBM Plex Mono',monospace;font-size:10px;color:var(--text-dim);} |
| .l-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;} |
| .l-ring{width:8px;height:8px;border-radius:50%;border:1.5px solid rgba(255,255,255,.65);flex-shrink:0;} |
| .l-line{width:20px;height:1.5px;flex-shrink:0;} |
| |
| |
| .viz{flex:1;min-height:0;position:relative;} |
| .viz svg{width:100%;height:100%;} |
| |
| |
| #panel-p2{flex-direction:column;} |
| |
| #panel-p2 > .ctrl-row{padding-right:213px;} |
| .p2-body{display:flex;flex:1;min-height:0;gap:0;} |
| .viz-p2-wrap{flex:1;min-width:0;position:relative;} |
| .viz-p2-wrap svg{width:100%;height:100%;} |
| .p2-sidebar{width:195px;flex-shrink:0;padding:0 0 0 18px;display:flex;flex-direction:column;gap:10px;justify-content:center;} |
| |
| |
| .viz svg rect, .viz svg text, .viz svg line, .viz svg path, |
| .viz-p2-wrap svg rect, .viz-p2-wrap svg text, .viz-p2-wrap svg line, .viz-p2-wrap svg path { pointer-events: none; } |
| .viz svg circle, .viz-p2-wrap svg circle { pointer-events: auto; } |
| |
| .q-card{border-left:2px solid;padding:7px 11px;transition:opacity .25s;} |
| .q-card.q-sl{border-color:#4ade80;} |
| .q-card.q-sw{border-color:#7dd3fc;} |
| .q-card.q-de{border-color:#fbbf24;} |
| .q-card.q-mv{border-color:#f87171;} |
| .q-lbl{font-family:'IBM Plex Mono',monospace;font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;margin-bottom:3px;} |
| .q-card.q-sl .q-lbl{color:#4ade80;} |
| .q-card.q-sw .q-lbl{color:#7dd3fc;} |
| .q-card.q-de .q-lbl{color:#fbbf24;} |
| .q-card.q-mv .q-lbl{color:#f87171;} |
| .q-desc{font-family:'Crimson Pro',serif;font-size:12px;color:var(--text-dim);line-height:1.4;} |
| |
| |
| .ctrl-btn.clear-btn{color:#f87171;border-color:#f8717144;letter-spacing:.08em;} |
| .ctrl-btn.clear-btn:hover{color:#fca5a5;border-color:#f87171;background:rgba(248,113,113,.08);} |
| .footnote{flex-shrink:0;margin-top:6px;padding-top:6px;border-top:1px solid var(--border);font-family:'IBM Plex Mono',monospace;font-size:9.5px;color:var(--text-dimmer);line-height:1.5;} |
| |
| |
| #tt{position:fixed;background:rgba(12,12,20,.97);border:1px solid var(--border2);padding:12px 15px;pointer-events:none;z-index:999;opacity:0;transition:opacity .12s;max-width:275px;backdrop-filter:blur(14px);} |
| #tt-name{font-family:'Playfair Display',serif;font-size:14px;font-weight:700;color:var(--text);margin-bottom:7px;line-height:1.2;} |
| .tt-row{display:flex;justify-content:space-between;gap:12px;font-family:'IBM Plex Mono',monospace;font-size:10px;margin-bottom:3px;} |
| .tt-row .k{color:var(--text-dimmer);letter-spacing:.06em;flex-shrink:0;} |
| .tt-row .v{color:var(--text-dim);text-align:right;} |
| #tt-skills{margin-top:8px;padding-top:8px;border-top:1px solid var(--border);display:none;} |
| .tt-skill{display:inline-block;font-family:'IBM Plex Mono',monospace;font-size:9px;padding:2px 6px;border:1px solid var(--border);color:var(--text-dim);margin:2px 2px 0 0;} |
| |
| |
| #panel-p4{padding:24px 56px 16px;overflow-y:auto;} |
| .cl-eye{font-family:'IBM Plex Mono',monospace;font-size:10px;letter-spacing:.3em;color:var(--text-dim);text-transform:uppercase;margin-bottom:6px;} |
| .cl-title{font-family:'Playfair Display',serif;font-size:34px;font-weight:900;line-height:1;letter-spacing:-.01em;margin-bottom:16px;color:var(--text);} |
| .cl-lede{font-family:'Crimson Pro',serif;font-size:16px;font-weight:300;font-style:italic;color:var(--text-dim);line-height:1.55;max-width:780px;margin-bottom:28px;border-left:2px solid var(--p4);padding-left:14px;} |
| .cl-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-bottom:24px;} |
| .cl-find{border-top:2px solid;padding:12px 0 0 0;} |
| .cl-find.f1{border-color:var(--p1);} |
| .cl-find.f2{border-color:var(--p2);} |
| .cl-find.f3{border-color:var(--p3);} |
| .cl-find-num{font-family:'IBM Plex Mono',monospace;font-size:10px;letter-spacing:.18em;text-transform:uppercase;margin-bottom:5px;} |
| .cl-find.f1 .cl-find-num{color:var(--p1);} |
| .cl-find.f2 .cl-find-num{color:var(--p2);} |
| .cl-find.f3 .cl-find-num{color:var(--p3);} |
| .cl-find-ttl{font-family:'Playfair Display',serif;font-size:18px;font-weight:700;line-height:1.15;margin-bottom:8px;color:var(--text);} |
| .cl-find-bd{font-family:'Crimson Pro',serif;font-size:13.5px;color:var(--text-dim);line-height:1.5;} |
| .cl-find-bd em{color:var(--text);font-style:italic;} |
| .cl-watch-hdr{font-family:'IBM Plex Mono',monospace;font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--text-dim);margin:6px 0 12px 0;display:flex;align-items:center;gap:10px;} |
| .cl-watch-hdr::before,.cl-watch-hdr::after{content:'';flex:1;border-top:1px solid var(--border);} |
| .cl-watch{display:grid;grid-template-columns:repeat(2,1fr);gap:14px 32px;margin-bottom:18px;} |
| .cl-watch-item{display:flex;gap:12px;align-items:flex-start;} |
| .cl-watch-bul{flex-shrink:0;width:6px;height:6px;border-radius:50%;background:var(--p4);margin-top:8px;opacity:.7;} |
| .cl-watch-txt{font-family:'Crimson Pro',serif;font-size:13.5px;color:var(--text-dim);line-height:1.5;} |
| .cl-watch-txt strong{color:var(--text);font-weight:400;font-style:italic;} |
| .cl-coda{font-family:'Crimson Pro',serif;font-size:14px;color:var(--text-dim);line-height:1.6;max-width:780px;margin-top:18px;padding-top:14px;border-top:1px solid var(--border);font-style:italic;} |
| .cl-coda-attr{font-family:'IBM Plex Mono',monospace;font-size:10px;color:var(--text-dimmer);margin-top:8px;letter-spacing:.04em;} |
| #panel-p0{justify-content:center;align-items:flex-start;padding:0 12%;} |
| .i-super{font-family:'IBM Plex Mono',monospace;font-size:11px;letter-spacing:.25em;color:var(--text-dim);text-transform:uppercase;margin-bottom:16px;} |
| .i-title{font-family:'Playfair Display',serif;font-size:50px;font-weight:900;line-height:.95;letter-spacing:-.02em;color:var(--text);margin-bottom:22px;} |
| .i-body{font-family:'Crimson Pro',serif;font-size:17px;font-weight:300;color:var(--text-dim);line-height:1.7;max-width:580px;margin-bottom:28px;} |
| .i-body em{color:var(--text);font-style:italic;} |
| .i-tags{display:flex;gap:3px;margin-bottom:32px;} |
| .i-tag{font-family:'IBM Plex Mono',monospace;font-size:10px;letter-spacing:.08em;padding:7px 14px;border:1px solid var(--border);color:var(--text-dim);text-transform:uppercase;} |
| .i-tag.t1{color:var(--p1);border-color:var(--p1);background:var(--p1g);} |
| .i-tag.t2{color:var(--p2);border-color:var(--p2);background:var(--p2g);} |
| .i-tag.t3{color:var(--p3);border-color:var(--p3);background:var(--p3g);} |
| .i-btn{display:inline-block;font-family:'IBM Plex Mono',monospace;font-size:11px;letter-spacing:.12em;text-transform:uppercase;padding:11px 26px;border:1px solid var(--text-dim);background:transparent;color:var(--text);cursor:pointer;transition:all .2s;margin-bottom:26px;} |
| .i-btn:hover{background:var(--bg3);border-color:var(--text);} |
| .i-sources{font-family:'IBM Plex Mono',monospace;font-size:10px;color:var(--text-dimmer);line-height:1.7;border-top:1px solid var(--border);padding-top:14px;max-width:640px;} |
| </style> |
| </head> |
| <body> |
|
|
| <nav id="nav"> |
| <span class="nav-title">The Boundary</span> |
| <div class="nav-sep"></div> |
| <span class="nav-sub">AI, Work & What Remains · 2020–2025</span> |
| <div class="nav-sep"></div> |
| <span class="nav-sub">Bonny Koo · SARC 5400 · Spring 2026</span> |
| <div class="tabs"> |
| <button class="tab p0 active" id="tab-p0" onclick="show('p0')">Overview</button> |
| <button class="tab p1" id="tab-p1" onclick="show('p1')">I The Rise</button> |
| <button class="tab p2" id="tab-p2" onclick="show('p2')">II The Displacement</button> |
| <button class="tab p3" id="tab-p3" onclick="show('p3')">III The Asymmetry</button> |
| <button class="tab p4" id="tab-p4" onclick="show('p4')">Closing</button> |
| </div> |
| </nav> |
|
|
| <div id="main"> |
|
|
| |
| <section class="panel active" id="panel-p0"> |
| <div class="i-super">Data Visualization · 2025</div> |
| <div class="i-title">The<br>Boundary</div> |
| <div class="i-body">As AI crossed human-level benchmarks, jobs began to disappear. With CEO Sam Altman predicting AI will automate up to 40% of jobs globally by 2030, the question is no longer whether the boundary moves, but what it leaves behind. This project maps that crossing: the rise, the displacement, and <em>what remains irreducibly human</em>.</div> |
| <div class="i-tags"> |
| <div class="i-tag t1">I The Rise · AI capability 2020–2025</div> |
| <div class="i-tag t2">II The Displacement · Predicted vs. Observed</div> |
| <div class="i-tag t3">III The Asymmetry · Where AI still can't finish the work</div> |
| </div> |
| <button class="i-btn" onclick="show('p1')">Begin with Panel I →</button> |
| <div class="i-sources"> |
| <strong style="color:var(--text-dim)">Data sources · </strong> |
| Panel I: Epoch AI Notable AI Models · published model cards · Hugging Face Open LLM Leaderboard · |
| Panel II: Frey & Osborne (Oxford, 2017) · Tomlinson et al. (Microsoft Research, 2025) · U.S. BLS OES 2023 · |
| Panel III: Tomlinson et al. (Microsoft Research, 2025), Table 2 · 200K Bing Copilot conversations |
| </div> |
| </section> |
|
|
| |
| <section class="panel" id="panel-p1"> |
| <div class="ph"> |
| <div class="ph-eye">Panel I · Cold / Analytical</div> |
| <div class="ph-title">The Rise</div> |
| <div class="ph-desc">A test called MMLU asks AI questions across 57 subjects: history, math, medicine, law. Higher scores mean the AI got more right. Each dot here is one AI model. The white ring means the model's code is freely available (open-source). Hover any dot for details.</div> |
| </div> |
| <div class="big-idea">"Late 2023 was the moment AI models started scoring higher than the average human expert on this test. Within 14 months, open-source models caught up to the big tech labs. By 2025, the test had become too easy to tell models apart. The competition moved on to harder challenges."</div> |
| <div class="ctrl-row"> |
| <span class="ctrl-label">Filter:</span> |
| <button class="ctrl-btn active" id="f1-all" onclick="filterP1('all')">All</button> |
| <button class="ctrl-btn" id="f1-open" onclick="filterP1('open')">Open source</button> |
| <button class="ctrl-btn" id="f1-closed" onclick="filterP1('closed')">Closed source</button> |
| <div style="width:14px"></div> |
| <span class="ctrl-label">Org:</span> |
| <button class="ctrl-btn active" id="f1-org-all" onclick="filterP1Org('all')">All</button> |
| <button class="ctrl-btn" id="f1-org-OpenAI" onclick="filterP1Org('OpenAI')">OpenAI</button> |
| <button class="ctrl-btn" id="f1-org-Google" onclick="filterP1Org('Google')">Google</button> |
| <button class="ctrl-btn" id="f1-org-Anthropic" onclick="filterP1Org('Anthropic')">Anthropic</button> |
| <button class="ctrl-btn" id="f1-org-Meta" onclick="filterP1Org('Meta')">Meta</button> |
| <button class="ctrl-btn" id="f1-org-xAI" onclick="filterP1Org('xAI')">xAI / Grok</button> |
| <button class="ctrl-btn" id="f1-org-Mistral" onclick="filterP1Org('Mistral')">Mistral</button> |
| <button class="ctrl-btn" id="f1-org-DeepSeek" onclick="filterP1Org('DeepSeek')">DeepSeek</button> |
| <div style="width:14px"></div> |
| <button class="ctrl-btn clear-btn" id="f1-clear" onclick="clearP1()" style="display:none">✕ Clear</button> |
| <div id="status-p1" class="status-line"></div> |
| </div> |
| <div class="legend" id="leg-p1"></div> |
| <div class="viz" id="viz-p1"></div> |
| <div class="footnote">Sources: Epoch AI Notable AI Models Dataset · published model cards · Hugging Face Open LLM Leaderboard · Human expert average on MMLU: 89.8% (Hendrycks et al., 2021)</div> |
| </section> |
|
|
| |
| <section class="panel" id="panel-p2"> |
| <div class="ph"> |
| <div class="ph-eye">Panel II · Predicted vs. Observed</div> |
| <div class="ph-title">The Displacement</div> |
| <div class="ph-desc" id="p2-desc">Each bubble is a U.S. job. Position from left to right shows how exposed that job is to AI. Position from bottom to top shows how much the job pays. Bigger bubbles mean more people work in that job. Hover any bubble for details. Use the View buttons below to compare what experts <em>predicted</em> in 2017 with what's <em>actually happening</em> in 2025.</div> |
| </div> |
| <div class="big-idea" id="p2-bigidea">"In 2017, two Oxford economists predicted AI would hit the lowest-paid jobs hardest. Cashiers, retail workers, and data entry clerks ended up in the dangerous bottom-right corner: most likely to be automated, least able to afford retraining."</div> |
| <div class="ctrl-row"> |
| <span class="ctrl-label">View:</span> |
| <button class="ctrl-btn active" id="p2view-predicted" onclick="setP2View('predicted')">Predicted Risk · 2017</button> |
| <button class="ctrl-btn" id="p2view-observed" onclick="setP2View('observed')">Observed Usage · 2025</button> |
| </div> |
| <div class="ctrl-row"> |
| <span class="ctrl-label">Highlight:</span> |
| <button class="ctrl-btn active" id="f2-all" onclick="filterP2('all')">All sectors</button> |
| <span id="p2-sector-buttons" style="display:contents"></span> |
| <div style="width:14px"></div> |
| <button class="ctrl-btn clear-btn" id="f2-clear" onclick="clearP2()" style="display:none">✕ Clear</button> |
| <div id="status-p2" class="status-line"></div> |
| </div> |
| <div class="p2-body"> |
| <div class="viz-p2-wrap" id="viz-p2"></div> |
| <div class="p2-sidebar"> |
| <div class="q-card q-sl" id="qc-sl"> |
| <div class="q-lbl">Safe & Well-Paid</div> |
| <div class="q-desc">Roles AI augments but can't replace. Surgeons, physicians, and lawyers rely on embodied expertise and complex judgment.</div> |
| </div> |
| <div class="q-card q-de" id="qc-de"> |
| <div class="q-lbl">Disrupted Elite</div> |
| <div class="q-desc">High salaries with real AI exposure. Software developers, accountants, and analysts can adapt, but disruption is real.</div> |
| </div> |
| <div class="q-card q-sw" id="qc-sw"> |
| <div class="q-lbl">Safe But Low-Wage</div> |
| <div class="q-desc">Physical and care work AI can't do. Firefighters, childcare workers, and the trades. Safe from automation but underpaid.</div> |
| </div> |
| <div class="q-card q-mv" id="qc-mv"> |
| <div class="q-lbl">Most Vulnerable</div> |
| <div class="q-desc">Near-certain automation paired with the lowest wages. Cashiers, retail workers, data entry clerks: least able to absorb the transition.</div> |
| </div> |
| </div> |
| </div> |
| <div class="footnote" id="p2-footnote">Sources: Frey & Osborne, "The Future of Employment" (Oxford, 2017) · U.S. Bureau of Labor Statistics OES (2023) median annual wage · Employment in thousands</div> |
| </section> |
|
|
| |
| <section class="panel" id="panel-p3"> |
| <div class="ph"> |
| <div class="ph-eye">Panel III · The Edge</div> |
| <div class="ph-title">The Asymmetry</div> |
| <div class="ph-desc">Microsoft researchers read 200,000 real conversations between people and Bing Copilot. For each one, they noted two things: <em>what the person was trying to do</em>, and <em>what the AI ended up doing</em>. Those don't always match. Each bar below is a kind of work. The longer the bar, the bigger the gap.</div> |
| </div> |
| <div class="big-idea">"AI is great at <em>explaining, teaching, and advising</em>. But the moment work crosses into the physical, financial, or in-person world, the human still has to do it. The bars on the right show the gap. The bars on the left show where AI is now quietly doing the work itself."</div> |
| <div class="viz" id="viz-p3"></div> |
| <div class="footnote">Sources: Tomlinson, Jaffe, Wang, Counts, Suri (Microsoft Research, 2025), "Working with AI: Measuring the Applicability of Generative AI to Occupations," Table 2 · Work activity definitions from O*NET Intermediate Work Activities (IWAs) · Ratios computed from user-goal-share vs. AI-action-share across 200K anonymized Bing Copilot conversations, Jan–Sep 2024</div> |
| </section> |
|
|
| |
| <section class="panel" id="panel-p4"> |
| <div class="cl-eye">Closing · What this means</div> |
| <div class="cl-title">The Boundary, Read Together</div> |
| <div class="cl-lede">"Three panels, one story: AI got smarter than the average expert in 2023. The way it's actually being used in 2025 doesn't match what experts predicted ten years ago. And the gap between what AI <em>can do</em> and what it <em>actually does</em> is where human work still lives."</div> |
|
|
| <div class="cl-grid"> |
| <div class="cl-find f1"> |
| <div class="cl-find-num">Finding 1 · The Rise</div> |
| <div class="cl-find-ttl">AI got smarter than experts in late 2023.</div> |
| <div class="cl-find-bd">In November 2023, Google's Gemini Ultra was the first AI to beat the average human expert on a 57-subject knowledge test. By April 2025, OpenAI's o3 was scoring <em>95%</em>. Open-source models (the kind anyone can download and run) caught up to the big labs in just over a year. The question now isn't whether AI is capable. It's <em>where it gets used</em>.</div> |
| </div> |
| <div class="cl-find f2"> |
| <div class="cl-find-num">Finding 2 · The Displacement</div> |
| <div class="cl-find-ttl">The 2017 predictions were wrong.</div> |
| <div class="cl-find-bd">Two Oxford economists predicted in 2017 that AI would hit cashiers, retail workers, and data entry clerks the hardest. By 2025, Microsoft's data on real AI use shows the opposite: AI is being used most by <em>writers, translators, salespeople, and analysts</em>, the educated knowledge workers everyone thought were safe.</div> |
| </div> |
| <div class="cl-find f3"> |
| <div class="cl-find-num">Finding 3 · The Asymmetry</div> |
| <div class="cl-find-ttl">AI explains. Humans act.</div> |
| <div class="cl-find-bd">In 200,000 real conversations, people asked AI to help them <em>buy things, transact money, and do physical tasks</em> 118 times more often than AI did those things itself. The moment work crosses into the real world (clicking purchase, signing the form, going to the appointment), humans have to step in.</div> |
| </div> |
| </div> |
|
|
| <div class="cl-watch-hdr">What to watch next</div> |
| <div class="cl-watch"> |
| <div class="cl-watch-item"> |
| <div class="cl-watch-bul"></div> |
| <div class="cl-watch-txt"><strong>"Agent" AI that can take actions.</strong> Right now AI mostly answers questions. Companies are racing to make AI that can actually buy things, fill out forms, and book appointments on your behalf. When that lands, the right-side bars in Panel 3 should shrink fast.</div> |
| </div> |
| <div class="cl-watch-item"> |
| <div class="cl-watch-bul"></div> |
| <div class="cl-watch-txt"><strong>What happens to office wages.</strong> If AI helps most with knowledge work, those jobs get cheaper to do. Watch whether software, marketing, and finance pay growth slows down compared to healthcare and trades over the next few years.</div> |
| </div> |
| <div class="cl-watch-item"> |
| <div class="cl-watch-bul"></div> |
| <div class="cl-watch-txt"><strong>Tests getting too easy.</strong> The MMLU test in Panel 1 has basically been beaten. Researchers are now using harder tests around reasoning and reliability. The chart's vertical axis will need a new measuring stick within a year.</div> |
| </div> |
| <div class="cl-watch-item"> |
| <div class="cl-watch-bul"></div> |
| <div class="cl-watch-txt"><strong>Helping vs. replacing.</strong> Microsoft's 2026 reports show AI is starting to replace work more often than just helping with it. The split shown in Panel 3 is a snapshot, and it's already moving toward the left side.</div> |
| </div> |
| <div class="cl-watch-item"> |
| <div class="cl-watch-bul"></div> |
| <div class="cl-watch-txt"><strong>Who's missing from this data.</strong> Microsoft's data only includes people using Copilot. Workers without access to AI (and there are many) don't appear at all. Some "low-AI" jobs may just be jobs where AI hasn't reached people yet.</div> |
| </div> |
| <div class="cl-watch-item"> |
| <div class="cl-watch-bul"></div> |
| <div class="cl-watch-txt"><strong>Open-source coming from anywhere.</strong> DeepSeek, the Chinese AI lab in Panel 1, reached the top of the field from outside the U.S. tech giants. That's the future: powerful AI built and released by anyone, anywhere.</div> |
| </div> |
| </div> |
|
|
| <div class="cl-coda">"The boundary between human work and AI work isn't a wall. It's a moving line. The honest answer to 'what will AI do to our jobs' is: <em>we are watching it happen right now, and the picture from 2017 is already wrong</em>."</div> |
| <div class="cl-coda-attr">Project: The Boundary · AI, Work & What Remains · 2020–2025</div> |
| </section> |
|
|
| </div> |
| <div id="tt"><div id="tt-name"></div><div id="tt-body"></div><div id="tt-skills"></div></div> |
|
|
| <script> |
| |
| const ORG_COLOR={OpenAI:'#7dd3fc',Google:'#4ade80',Anthropic:'#f9a8d4',Meta:'#fb923c',xAI:'#a78bfa',Mistral:'#67e8f9',DeepSeek:'#34d399'}; |
| |
| const MODELS=[ |
| {name:'GPT-3', org:'OpenAI', date:'2020-06-11',mmlu:43.9,open:false}, |
| {name:'PaLM', org:'Google', date:'2022-04-04',mmlu:69.3,open:false}, |
| {name:'ChatGPT (GPT-3.5)', org:'OpenAI', date:'2022-11-30',mmlu:70.0,open:false,note:'ChatGPT launches'}, |
| {name:'LLaMA 1', org:'Meta', date:'2023-02-24',mmlu:63.4,open:true, note:'Open-source era begins'}, |
| {name:'GPT-4', org:'OpenAI', date:'2023-03-14',mmlu:86.4,open:false,note:'Passes bar exam'}, |
| {name:'Claude 2', org:'Anthropic', date:'2023-07-11',mmlu:78.5,open:false}, |
| {name:'LLaMA 2', org:'Meta', date:'2023-07-18',mmlu:68.9,open:true}, |
| {name:'Mistral 7B', org:'Mistral', date:'2023-09-27',mmlu:60.1,open:true}, |
| {name:'Gemini Ultra', org:'Google', date:'2023-12-06',mmlu:90.0,open:false,note:'Surpasses human average'}, |
| {name:'Mistral Large', org:'Mistral', date:'2024-02-26',mmlu:81.2,open:false}, |
| {name:'Claude 3 Opus', org:'Anthropic', date:'2024-03-04',mmlu:86.8,open:false}, |
| {name:'LLaMA 3 70B', org:'Meta', date:'2024-04-18',mmlu:82.0,open:true}, |
| {name:'GPT-4o', org:'OpenAI', date:'2024-05-13',mmlu:88.7,open:false}, |
| {name:'Claude 3.5 Sonnet', org:'Anthropic', date:'2024-06-20',mmlu:88.7,open:false}, |
| {name:'o1', org:'OpenAI', date:'2024-09-12',mmlu:92.3,open:false,note:'PhD-level reasoning'}, |
| {name:'Gemini 2.0 Flash', org:'Google', date:'2024-12-11',mmlu:89.0,open:false}, |
| {name:'DeepSeek R1', org:'DeepSeek', date:'2025-01-20',mmlu:90.8,open:true, note:'China reaches frontier'}, |
| {name:'Grok 3', org:'xAI', date:'2025-02-17',mmlu:88.7,open:false}, |
| {name:'Claude 3.7 Sonnet', org:'Anthropic', date:'2025-02-24',mmlu:90.5,open:false}, |
| {name:'Gemini 2.5 Pro', org:'Google', date:'2025-03-25',mmlu:91.5,open:false}, |
| {name:'Llama 4 Scout', org:'Meta', date:'2025-04-05',mmlu:90.0,open:true}, |
| {name:'Llama 4 Maverick', org:'Meta', date:'2025-04-05',mmlu:91.8,open:true}, |
| {name:'o3', org:'OpenAI', date:'2025-04-16',mmlu:95.1,open:false}, |
| ].map(d=>({...d,date:new Date(d.date)})); |
| |
| const OCC=[ |
| {name:'Telemarketers', sector:'Sales', risk:99, emp:212, wage:27920}, |
| {name:'Data Entry Keyers', sector:'Admin', risk:99, emp:139, wage:37980}, |
| {name:'Bookkeeping Clerks', sector:'Admin', risk:98, emp:1396,wage:47440}, |
| {name:'Insurance Underwriters', sector:'Finance', risk:98, emp:101, wage:77860}, |
| {name:'Bank Tellers', sector:'Finance', risk:98, emp:461, wage:36310}, |
| {name:'Cashiers', sector:'Retail', risk:97, emp:3528,wage:29640}, |
| {name:'Tax Preparers', sector:'Finance', risk:95, emp:81, wage:58450}, |
| {name:'Insurance Claims Clerks',sector:'Admin', risk:94, emp:284, wage:46010}, |
| {name:'Paralegals', sector:'Legal', risk:94, emp:330, wage:59200}, |
| {name:'Accountants & Auditors', sector:'Finance', risk:94, emp:1392,wage:79880}, |
| {name:'Retail Salespersons', sector:'Sales', risk:92, emp:4475,wage:31990}, |
| {name:'Loan Officers', sector:'Finance', risk:74, emp:335, wage:65740}, |
| {name:'Graphic Designers', sector:'Creative', risk:86, emp:266, wage:57990}, |
| {name:'Writers & Authors', sector:'Creative', risk:89, emp:166, wage:73690}, |
| {name:'Customer Service Reps', sector:'Service', risk:55, emp:2969,wage:38610}, |
| {name:'HR Specialists', sector:'Business', risk:55, emp:598, wage:64240}, |
| {name:'Marketing Specialists', sector:'Business', risk:60, emp:323, wage:67760}, |
| {name:'Software Developers', sector:'Tech', risk:48, emp:1795,wage:130160}, |
| {name:'Pharmacists', sector:'Healthcare', risk:58, emp:322, wage:132750}, |
| {name:'Financial Analysts', sector:'Finance', risk:23, emp:329, wage:96220}, |
| {name:'Lawyers', sector:'Legal', risk:35, emp:813, wage:145760}, |
| {name:'Architects', sector:'Creative', risk:18, emp:126, wage:93310}, |
| {name:'Journalists', sector:'Creative', risk:11, emp:56, wage:55960}, |
| {name:'Elementary Teachers', sector:'Education', risk:10, emp:1437,wage:62890}, |
| {name:'Registered Nurses', sector:'Healthcare', risk:0.9, emp:3149,wage:81220}, |
| {name:'Social Workers', sector:'Social', risk:3.1, emp:707, wage:51760}, |
| {name:'Physical Therapists', sector:'Healthcare', risk:0.35,emp:239, wage:97720}, |
| {name:'Surgeons', sector:'Healthcare', risk:0.42,emp:49, wage:255110}, |
| {name:'Firefighters', sector:'Safety', risk:0.17,emp:356, wage:54650}, |
| {name:'Recreation Therapists', sector:'Healthcare', risk:0.28,emp:19, wage:49730}, |
| {name:'Mental Health Counselors',sector:'Social', risk:0.3, emp:372, wage:49710}, |
| {name:'Construction Managers', sector:'Construction',risk:3.2, emp:468, wage:101480}, |
| {name:'Plumbers', sector:'Trades', risk:0.35,emp:514, wage:61550}, |
| {name:'Electricians', sector:'Trades', risk:0.35,emp:778, wage:61490}, |
| {name:'Dentists', sector:'Healthcare', risk:0.44,emp:161, wage:166810}, |
| {name:'Physicians', sector:'Healthcare', risk:0.42,emp:756, wage:229300}, |
| {name:'Police Officers', sector:'Safety', risk:0.99,emp:806, wage:67290}, |
| {name:'Childcare Workers', sector:'Social', risk:0.75,emp:574, wage:29150}, |
| {name:'Clergy', sector:'Social', risk:0.81,emp:46, wage:56770}, |
| {name:'Emergency Mgmt Directors',sector:'Safety', risk:0.3, emp:11, wage:79180}, |
| ]; |
| const SEC_COLOR={Admin:'#f87171',Finance:'#fb923c',Sales:'#fbbf24',Retail:'#facc15',Service:'#a3e635',Tech:'#7dd3fc',Healthcare:'#4ade80',Social:'#f9a8d4',Legal:'#c084fc',Business:'#818cf8',Creative:'#67e8f9',Education:'#6ee7b7',Safety:'#38bdf8',Construction:'#d4d4aa',Trades:'#e8956d',Academic:'#a78bfa',Writing:'#22d3ee'}; |
| |
| |
| const MICROSOFT_OCC=[ |
| |
| {name:'Interpreters and Translators', sector:'Service', score:0.49, emp:51.56, wage:57090}, |
| {name:'Historians', sector:'Academic', score:0.48, emp:3.04, wage:74060}, |
| {name:'Passenger Attendants', sector:'Sales', score:0.47, emp:20.19, wage:32090}, |
| {name:'Sales Representatives of Services', sector:'Sales', score:0.46, emp:1142.02,wage:69610}, |
| {name:'Writers and Authors', sector:'Writing', score:0.45, emp:49.45, wage:73690}, |
| {name:'Customer Service Representatives', sector:'Sales', score:0.44, emp:2858.71,wage:38610}, |
| {name:'CNC Tool Programmers', sector:'Tech', score:0.44, emp:28.03, wage:59500}, |
| {name:'Telephone Operators', sector:'Sales', score:0.42, emp:4.60, wage:43420}, |
| {name:'Ticket Agents and Travel Clerks', sector:'Sales', score:0.41, emp:119.27, wage:38030}, |
| {name:'Broadcast Announcers / Radio DJs', sector:'Writing', score:0.41, emp:25.07, wage:43990}, |
| {name:'Brokerage Clerks', sector:'Admin', score:0.41, emp:48.06, wage:58890}, |
| {name:'Farm/Home Mgmt Educators', sector:'Education', score:0.41, emp:8.11, wage:59830}, |
| {name:'Telemarketers', sector:'Sales', score:0.40, emp:81.58, wage:27920}, |
| {name:'Concierges', sector:'Sales', score:0.40, emp:41.02, wage:36310}, |
| {name:'Political Scientists', sector:'Academic', score:0.39, emp:5.58, wage:128020}, |
| {name:'Reporters and Journalists', sector:'Writing', score:0.39, emp:45.02, wage:55960}, |
| {name:'Mathematicians', sector:'Academic', score:0.39, emp:2.22, wage:116440}, |
| {name:'Technical Writers', sector:'Writing', score:0.38, emp:47.97, wage:80050}, |
| {name:'Proofreaders and Copy Markers', sector:'Writing', score:0.38, emp:5.49, wage:48990}, |
| {name:'Hosts and Hostesses', sector:'Sales', score:0.37, emp:425.02, wage:26650}, |
| {name:'Editors', sector:'Writing', score:0.37, emp:95.70, wage:73080}, |
| {name:'Business Teachers (Postsec)', sector:'Education', score:0.37, emp:82.98, wage:97500}, |
| {name:'Public Relations Specialists', sector:'Writing', score:0.36, emp:275.55, wage:66750}, |
| {name:'Demonstrators / Product Promoters', sector:'Sales', score:0.36, emp:50.79, wage:34940}, |
| {name:'Advertising Sales Agents', sector:'Sales', score:0.36, emp:108.10, wage:61270}, |
| {name:'New Accounts Clerks', sector:'Admin', score:0.36, emp:41.18, wage:42610}, |
| {name:'Statistical Assistants', sector:'Admin', score:0.36, emp:7.20, wage:51720}, |
| {name:'Counter and Rental Clerks', sector:'Sales', score:0.36, emp:390.30, wage:34750}, |
| {name:'Data Scientists', sector:'Tech', score:0.36, emp:192.71, wage:108020}, |
| {name:'Personal Financial Advisors', sector:'Finance', score:0.35, emp:272.19, wage:99580}, |
| {name:'Archivists', sector:'Academic', score:0.35, emp:7.15, wage:61920}, |
| {name:'Economics Teachers (Postsec)', sector:'Education', score:0.35, emp:12.21, wage:113910}, |
| {name:'Web Developers', sector:'Tech', score:0.35, emp:85.35, wage:84960}, |
| {name:'Management Analysts', sector:'Tech', score:0.35, emp:838.14, wage:99410}, |
| {name:'Geographers', sector:'Academic', score:0.35, emp:1.46, wage:92910}, |
| {name:'Models', sector:'Sales', score:0.35, emp:3.09, wage:40090}, |
| {name:'Market Research Analysts', sector:'Tech', score:0.35, emp:846.37, wage:74680}, |
| {name:'Public Safety Telecommunicators', sector:'Sales', score:0.35, emp:97.82, wage:48890}, |
| {name:'Switchboard Operators', sector:'Sales', score:0.35, emp:43.83, wage:36070}, |
| {name:'Library Science Teachers (Postsec)', sector:'Education', score:0.34, emp:4.22, wage:80840}, |
| |
| {name:'Phlebotomists', sector:'Healthcare', score:0.02, emp:135.50, wage:41810}, |
| {name:'Nursing Assistants', sector:'Healthcare', score:0.03, emp:1284.44,wage:38130}, |
| {name:'Massage Therapists', sector:'Healthcare', score:0.04, emp:88.78, wage:55310}, |
| {name:'Roofers', sector:'Trades', score:0.02, emp:115.16, wage:50030}, |
| {name:'Pile Driver Operators', sector:'Trades', score:0.02, emp:3.08, wage:73000}, |
| {name:'Heavy Truck Drivers', sector:'Trades', score:0.03, emp:2030.00,wage:53090}, |
| {name:'Dishwashers', sector:'Service', score:0.02, emp:480.21, wage:30050}, |
| {name:'Maids / Housekeeping Cleaners', sector:'Service', score:0.02, emp:879.06, wage:32630}, |
| {name:'Water Treatment Plant Operators', sector:'Trades', score:0.04, emp:118.59, wage:58430}, |
| |
| |
| |
| |
| |
| {name:'Family Medicine Physicians', sector:'Healthcare', score:0.165, emp:130.0, wage:224460}, |
| {name:'Emergency Medicine Physicians', sector:'Healthcare', score:0.077, emp:39.5, wage:286420}, |
| {name:'Orthopedic Surgeons', sector:'Healthcare', score:0.084, emp:23.4, wage:369100}, |
| {name:'Registered Nurses', sector:'Healthcare', score:0.122, emp:3149.0, wage:86070}, |
| {name:'Nurse Anesthetists', sector:'Healthcare', score:0.075, emp:47.5, wage:212650}, |
| {name:'Physician Assistants', sector:'Healthcare', score:0.051, emp:148.4, wage:130020}, |
| {name:'Pharmacists', sector:'Healthcare', score:0.278, emp:322.0, wage:132750}, |
| {name:'Dentists, General', sector:'Healthcare', score:0.046, emp:161.0, wage:166810}, |
| {name:'Physical Therapists', sector:'Healthcare', score:0.172, emp:239.0, wage:97720}, |
| {name:'Occupational Therapists', sector:'Healthcare', score:0.106, emp:142.0, wage:96370}, |
| {name:'Lawyers', sector:'Legal', score:0.180, emp:681.0, wage:145760}, |
| {name:'Software Developers', sector:'Tech', score:0.278, emp:1656.0, wage:130160}, |
| {name:'Software QA Analysts and Testers', sector:'Tech', score:0.328, emp:196.0, wage:99620}, |
| {name:'Computer Network Architects', sector:'Tech', score:0.252, emp:169.0, wage:129840}, |
| {name:'Information Security Analysts', sector:'Tech', score:0.222, emp:168.0, wage:120360}, |
| {name:'Accountants and Auditors', sector:'Finance', score:0.195, emp:1437.0, wage:79880}, |
| {name:'Police and Sheriff\'s Patrol Officers', sector:'Safety', score:0.143, emp:660.0, wage:69160}, |
| {name:'Firefighters', sector:'Safety', score:0.070, emp:322.0, wage:54650}, |
| {name:'Elementary School Teachers', sector:'Education', score:0.189, emp:1437.0, wage:63680}, |
| {name:'Secondary School Teachers', sector:'Education', score:0.176, emp:1014.0, wage:65220}, |
| {name:'Mental Health & Substance Abuse Social Workers', sector:'Social', score:0.146, emp:705.0, wage:58380}, |
| {name:'Substance Abuse / Mental Health Counselors', sector:'Social', score:0.180, emp:372.0, wage:49710}, |
| {name:'Marriage and Family Therapists', sector:'Social', score:0.231, emp:65.0, wage:58510}, |
| {name:'Civil Engineers', sector:'Tech', score:0.205, emp:332.0, wage:95890}, |
| {name:'Electrical Engineers', sector:'Tech', score:0.110, emp:320.0, wage:106950}, |
| {name:'Mechanical Engineers', sector:'Tech', score:0.257, emp:286.0, wage:99510}, |
| {name:'Graphic Designers', sector:'Creative', score:0.228, emp:217.0, wage:57990}, |
| {name:'Interior Designers', sector:'Creative', score:0.207, emp:99.0, wage:62510}, |
| {name:'Marketing Managers', sector:'Business', score:0.189, emp:372.0, wage:158280}, |
| {name:'Financial Managers', sector:'Finance', score:0.149, emp:826.0, wage:151510}, |
| ]; |
| |
| |
| |
| |
| |
| const IWA_ASYMMETRY = [ |
| |
| |
| |
| |
| {name:'Help with shopping decisions', ratio:118.4, direction:'assist', category:'Real-World Action', note:'AI can recommend, compare, and explain. The actual buying (the credit card, the click, the contract) is yours.'}, |
| {name:'Advice on financial transactions', ratio:58.8, direction:'assist', category:'Real-World Action', note:'AI explains your options. You authorize the money to move.'}, |
| {name:'Coaching on physical activity', ratio:47.3, direction:'assist', category:'Embodied', note:'AI can plan your workout and coach your form. Your body still has to do it.'}, |
| {name:'Help finding goods or services', ratio:25.9, direction:'assist', category:'Real-World Action', note:'You ask AI which laptop, restaurant, or service to pick. The visit, the call, the touchpoint is yours.'}, |
| {name:'Help understanding healthcare issues', ratio:20.5, direction:'assist', category:'In-Person Investigation',note:'AI helps you understand symptoms or treatments. The clinic visit is still yours.'}, |
| {name:'Help with cooking and recipes', ratio:14.7, direction:'assist', category:'Embodied', note:'AI can write the recipe. You still have to cook it.'}, |
| {name:'Help with technology research', ratio:13.5, direction:'assist', category:'In-Person Investigation',note:'Background research happens with AI. The actual building or testing is yours.'}, |
| {name:'Help with paperwork and forms', ratio:12.5, direction:'assist', category:'Real-World Action', note:'AI explains the form. You sign it.'}, |
| {name:'Help operating office equipment', ratio:11.4, direction:'assist', category:'Embodied', note:'AI explains how the printer works. You press the buttons.'}, |
| {name:'Help interpreting incidents', ratio:11.3, direction:'assist', category:'In-Person Investigation',note:'Investigation requires showing up: the scene, the witnesses, the physical evidence.'}, |
| |
| |
| {name:'Training others on procedures', ratio:17.9, direction:'perform', category:'Teaching', note:'AI is good at writing training material and onboarding content, even when no one explicitly asked it to teach.'}, |
| {name:'Training others on equipment', ratio:16.0, direction:'perform', category:'Teaching', note:'Step-by-step product walkthroughs are something AI does well, and often.'}, |
| {name:'Distributing materials and references', ratio:11.2, direction:'perform', category:'Information Delivery', note:'AI hands out information, links, and references at scale.'}, |
| {name:'Explaining medical topics', ratio:11.2, direction:'perform', category:'Teaching', note:'When someone asks about a medical topic, AI ends up explaining it, playing the teacher role.'}, |
| {name:'Providing general assistance', ratio:10.9, direction:'perform', category:'Information Delivery', note:'The most common AI role: a helpful assistant answering whatever comes up.'}, |
| {name:'Coaching others', ratio:10.6, direction:'perform', category:'Teaching', note:'AI coaches on writing, code, exercise, language, often without anyone calling it coaching.'}, |
| {name:'Answering customer questions', ratio:8.6, direction:'perform', category:'Information Delivery', note:'AI is now performing customer service work directly, answering customer questions one-on-one.'}, |
| {name:'Advising on workplace safety', ratio:7.5, direction:'perform', category:'Information Delivery', note:'Safety guidance, regulations, best practices, delivered by AI rather than a human safety officer.'}, |
| {name:'Teaching academic subjects', ratio:6.6, direction:'perform', category:'Teaching', note:'Tutoring, explanation, lesson generation: all done by AI directly.'}, |
| {name:'Teaching safety procedures', ratio:6.5, direction:'perform', category:'Teaching', note:'AI walks people through procedures and rules, the way a safety trainer would.'}, |
| ]; |
| |
| const CAT_COLOR = { |
| 'Real-World Action': '#fbbf24', |
| 'Embodied': '#fb923c', |
| 'In-Person Investigation': '#f9a8d4', |
| 'Teaching': '#7dd3fc', |
| 'Information Delivery': '#a78bfa', |
| }; |
| |
| |
| const ttEl=document.getElementById('tt'),ttName=document.getElementById('tt-name'),ttBody=document.getElementById('tt-body'),ttSkill=document.getElementById('tt-skills'); |
| function ttShow(ev,name,rows,skills){ |
| ttName.textContent=name; |
| ttBody.innerHTML=rows.map(([k,v])=>`<div class="tt-row"><span class="k">${k}</span><span class="v">${v}</span></div>`).join(''); |
| if(skills&&skills.length){ttSkill.style.display='block';ttSkill.innerHTML=skills.map(s=>`<span class="tt-skill">${s}</span>`).join('');} |
| else ttSkill.style.display='none'; |
| ttEl.style.opacity='1';ttMove(ev); |
| } |
| function ttMove(ev){let x=ev.clientX+18,y=ev.clientY-16;if(x+290>window.innerWidth)x=ev.clientX-290;if(y+240>window.innerHeight)y=ev.clientY-240;ttEl.style.left=x+'px';ttEl.style.top=y+'px';} |
| function ttHide(){ttEl.style.opacity='0';} |
| |
| |
| const inited={p0:true,p1:false,p2:false,p3:false,p4:true}; |
| function show(id){ |
| document.querySelectorAll('.panel').forEach(p=>p.classList.remove('active')); |
| document.querySelectorAll('.tab').forEach(t=>t.classList.remove('active')); |
| document.getElementById('panel-'+id).classList.add('active'); |
| document.getElementById('tab-'+id).classList.add('active'); |
| ttHide(); |
| if(!inited[id]){ |
| inited[id]=true; |
| setTimeout(()=>{ window['init_'+id](); }, 20); |
| } |
| } |
| function setSt(id,n,total,lbl){const el=document.getElementById('status-'+id);if(el)el.textContent=n===total?`All ${total} ${lbl}`:`${n} of ${total} ${lbl}`;} |
| |
| |
| let p1D,p1Sf='all',p1OfSet=new Set(); |
| function init_p1(){ |
| const el=document.getElementById('viz-p1'); |
| const W=el.clientWidth,H=el.clientHeight,m={t:44,r:22,b:46,l:50}; |
| const iw=W-m.l-m.r,ih=H-m.t-m.b; |
| const svg=d3.select('#viz-p1').append('svg').attr('width',W).attr('height',H); |
| const g=svg.append('g').attr('transform',`translate(${m.l},${m.t})`); |
| |
| const x=d3.scaleTime() |
| .domain([new Date('2019-11-01'),new Date('2022-09-01'),new Date('2023-11-01'),new Date('2025-10-01')]) |
| .range([0, iw*0.13, iw*0.36, iw]); |
| const y=d3.scaleLinear().domain([32,98]).range([ih,0]); |
| const R=7; |
| |
| |
| g.append('g').call(d3.axisLeft(y).ticks(6).tickSize(-iw).tickFormat('')) |
| .call(ax=>{ax.select('.domain').remove();ax.selectAll('line').attr('stroke','#141422').attr('stroke-width',1);}); |
| |
| |
| g.append('g').attr('transform',`translate(0,${ih})`) |
| .call(d3.axisBottom(x).ticks(d3.timeYear.every(1)).tickFormat(d3.timeFormat('%Y')).tickSize(0)) |
| .call(ax=>{ax.select('.domain').attr('stroke','#1e1e30');ax.selectAll('text').attr('dy',14).attr('font-family','IBM Plex Mono,monospace').attr('font-size',11).attr('fill','#8888a4');}); |
| g.append('g').call(d3.axisLeft(y).ticks(6).tickFormat(d=>d+'%').tickSize(0)) |
| .call(ax=>{ax.select('.domain').remove();ax.selectAll('text').attr('dx',-6).attr('font-family','IBM Plex Mono,monospace').attr('font-size',11).attr('fill','#8888a4');}); |
| |
| |
| const hy=y(89.8); |
| g.append('line').attr('x1',0).attr('x2',iw).attr('y1',hy).attr('y2',hy).attr('stroke','#f87171').attr('stroke-width',1.5).attr('stroke-dasharray','7,4').attr('opacity',.7); |
| g.append('text').attr('x',iw-6).attr('y',hy-7).attr('text-anchor','end').attr('font-family','IBM Plex Mono,monospace').attr('font-size',10).attr('fill','#f87171').attr('opacity',.75).text('Human avg 89.8%'); |
| |
| |
| g.append('rect').attr('x',x(new Date('2023-11-01'))).attr('y',0).attr('width',iw-x(new Date('2023-11-01'))).attr('height',y(89)-0).attr('fill','#f87171').attr('opacity',.015); |
| |
| const ms=MODELS.filter(d=>d.mmlu!=null); |
| |
| |
| const hoverLabel=g.append('text').attr('class','hover-lbl') |
| .attr('font-family','IBM Plex Mono,monospace').attr('font-size',10) |
| .attr('opacity',0).attr('pointer-events','none'); |
| |
| |
| p1D=g.selectAll('.m').data(ms).join('circle').attr('class','m') |
| .attr('cx',d=>x(d.date)).attr('cy',d=>y(d.mmlu)).attr('r',R) |
| .attr('fill',d=>ORG_COLOR[d.org]||'#666') |
| .attr('stroke',d=>d.open?'rgba(255,255,255,.75)':'none').attr('stroke-width',1.5) |
| .attr('opacity',.85).style('cursor','pointer') |
| .on('mouseover',function(ev,d){ |
| d3.select(this).attr('r',R+3).attr('opacity',1); |
| const cx=x(d.date), cy=y(d.mmlu); |
| const goLeft=cx>iw*0.78; |
| hoverLabel |
| .attr('x', goLeft ? cx-R-5 : cx+R+5) |
| .attr('y', cy+4) |
| .attr('text-anchor', goLeft?'end':'start') |
| .attr('fill', ORG_COLOR[d.org]||'#aaa') |
| .attr('opacity', 1) |
| .text(d.name); |
| ttShow(ev,d.name,[['org',d.org],['date',d.date.toLocaleString('en-US',{month:'short',year:'numeric'})],['mmlu',d.mmlu+'%'],['source',d.open?'open-source':'closed'],...(d.note?[['milestone',d.note]]:[])]); |
| }) |
| .on('mousemove',ttMove) |
| .on('mouseout',function(){ |
| d3.select(this).attr('r',R).attr('opacity',.85); |
| hoverLabel.attr('opacity',0); |
| ttHide(); |
| }); |
| |
| |
| const NOTE_CFG = { |
| 'ChatGPT launches': { dy:-22, anchor:'middle', dx: 0 }, |
| 'Open-source era begins': { dy:-22, anchor:'middle', dx: 0 }, |
| 'Passes bar exam': { dy:-34, anchor:'middle', dx: 0 }, |
| 'Surpasses human average': { dy:-22, anchor:'middle', dx: 0 }, |
| 'PhD-level reasoning': { dy:-22, anchor:'end', dx: -10 }, |
| 'China reaches frontier': { dy:-22, anchor:'middle', dx: 0, noLine:true }, |
| }; |
| ms.filter(d=>d.note).forEach(d=>{ |
| const cx=x(d.date), cy=y(d.mmlu); |
| const cfg=NOTE_CFG[d.note]||{dy:-22,anchor:'middle',dx:0}; |
| const ly=cy+cfg.dy, lx=cx+cfg.dx; |
| if(!cfg.noLine){ |
| g.append('line').attr('x1',cx).attr('x2',cx) |
| .attr('y1',cy-R-2).attr('y2',ly+12) |
| .attr('stroke','#2c2c42').attr('stroke-width',1); |
| } |
| g.append('text').attr('x',lx).attr('y',ly) |
| .attr('text-anchor',cfg.anchor) |
| .attr('font-family','IBM Plex Mono,monospace').attr('font-size',9).attr('fill','#8888a4') |
| .text(d.note); |
| }); |
| |
| |
| |
| document.getElementById('leg-p1').innerHTML= |
| Object.entries(ORG_COLOR).map(([o,c])=>`<div class="legend-item"><div class="l-dot" style="background:${c}"></div>${o}</div>`).join('')+ |
| `<div class="legend-item"><div class="l-ring"></div>Open source</div>`+ |
| `<div class="legend-item"><div class="l-line" style="background:#f87171;opacity:.7"></div>Human avg</div>`; |
| |
| |
| Object.entries(ORG_COLOR).forEach(([org,col])=>{ |
| const btn=document.getElementById('f1-org-'+org); |
| if(!btn) return; |
| btn.style.setProperty('--oc', col); |
| btn.style.color=col; |
| btn.style.borderColor='transparent'; |
| btn.addEventListener('mouseenter',()=>{ btn.style.borderColor=col; }); |
| btn.addEventListener('mouseleave',()=>{ btn.style.borderColor=btn.classList.contains('active')?col:'transparent'; }); |
| }); |
| |
| function syncOrgBtnBorders(){ |
| Object.keys(ORG_COLOR).forEach(org=>{ |
| const btn=document.getElementById('f1-org-'+org); |
| if(!btn) return; |
| btn.style.borderColor=btn.classList.contains('active')?ORG_COLOR[org]:'transparent'; |
| btn.style.background=btn.classList.contains('active')?'rgba(255,255,255,.05)':'transparent'; |
| }); |
| const allBtn=document.getElementById('f1-org-all'); |
| if(allBtn){ allBtn.style.borderColor=allBtn.classList.contains('active')?'var(--border2)':'var(--border)'; allBtn.style.color=allBtn.classList.contains('active')?'var(--text)':'var(--text-dim)'; } |
| } |
| window._syncOrgBtnBorders=syncOrgBtnBorders; |
| syncOrgBtnBorders(); |
| |
| setSt('p1',ms.length,ms.length,'models'); |
| } |
| function _syncClearP1(){ |
| const active=p1Sf!=='all'||p1OfSet.size>0; |
| document.getElementById('f1-clear').style.display=active?'inline-block':'none'; |
| } |
| function filterP1(f){ |
| |
| p1Sf=(p1Sf===f&&f!=='all')?'all':f; |
| ['all','open','closed'].forEach(k=>document.getElementById('f1-'+k).classList.toggle('active',k===p1Sf)); |
| _syncClearP1();applyP1(); |
| } |
| function filterP1Org(o){ |
| |
| if(o==='all'){ |
| p1OfSet.clear(); |
| } else { |
| if(p1OfSet.has(o)) p1OfSet.delete(o); else p1OfSet.add(o); |
| } |
| |
| document.getElementById('f1-org-all').classList.toggle('active',p1OfSet.size===0); |
| ['OpenAI','Google','Anthropic','Meta','xAI','Mistral','DeepSeek'].forEach(k=>{ |
| const btn=document.getElementById('f1-org-'+k); |
| if(btn) btn.classList.toggle('active',p1OfSet.has(k)); |
| }); |
| if(typeof window._syncOrgBtnBorders==='function')window._syncOrgBtnBorders(); |
| _syncClearP1();applyP1(); |
| } |
| function clearP1(){ |
| p1Sf='all';p1OfSet.clear(); |
| ['all','open','closed'].forEach(k=>document.getElementById('f1-'+k).classList.toggle('active',k==='all')); |
| document.getElementById('f1-org-all').classList.add('active'); |
| ['OpenAI','Google','Anthropic','Meta','xAI','Mistral','DeepSeek'].forEach(k=>{ |
| const btn=document.getElementById('f1-org-'+k); |
| if(btn) btn.classList.remove('active'); |
| }); |
| if(typeof window._syncOrgBtnBorders==='function')window._syncOrgBtnBorders(); |
| _syncClearP1();applyP1(); |
| } |
| function applyP1(){ |
| if(!p1D)return; |
| const vis=d=>{ |
| const s=p1Sf==='all'||(p1Sf==='open'?d.open:!d.open); |
| const o=p1OfSet.size===0||p1OfSet.has(d.org); |
| return s&&o; |
| }; |
| p1D.transition().duration(220).attr('opacity',d=>vis(d)?.85:.04); |
| ttHide(); |
| p1D.style('pointer-events', d => vis(d) ? 'auto' : 'none'); |
| const ms=MODELS.filter(d=>d.mmlu!=null);setSt('p1',ms.filter(vis).length,ms.length,'models'); |
| } |
| |
| |
| let p2D,p2QT,p2x2,p2y2,p2r2,p2SecSet=new Set(),p2View='predicted'; |
| |
| const P2_CONFIG = { |
| predicted: { |
| data: () => OCC, |
| xField: 'risk', |
| xDomain: [0, 100], |
| xFormat: d => d + '%', |
| xLabel: 'AI AUTOMATION SUBSTITUTION RISK →', |
| xMid: 50, |
| desc: 'Each bubble is a U.S. job. Left-to-right shows how at-risk that job was predicted to be from AI. Bottom-to-top shows how much it pays. Bigger bubble = more people in that job. Predictions from Frey & Osborne (Oxford, 2017).', |
| bigIdea: '"In 2017, two Oxford economists predicted AI would hit the lowest-paid jobs hardest. Cashiers, retail workers, and data entry clerks ended up in the dangerous bottom-right corner: most likely to be automated, least able to afford retraining."', |
| footnote: 'Sources: Frey & Osborne, "The Future of Employment" (Oxford, 2017) · U.S. Bureau of Labor Statistics OES (2023) median annual wage · Employment in thousands', |
| tooltipKey: 'predicted risk', |
| tooltipFmt: d => d.risk + '%', |
| }, |
| observed: { |
| data: () => MICROSOFT_OCC, |
| xField: 'score', |
| xDomain: [0, 0.5], |
| xFormat: d => (d*100).toFixed(0) + '%', |
| xLabel: 'AI APPLICABILITY SCORE (BING COPILOT 2024) →', |
| xMid: 0.20, |
| desc: 'Same chart as the 2017 view, but using new data. Microsoft watched 200,000 real conversations between people and AI in 2024 and measured which jobs AI is actually being used in. Compare this to the 2017 prediction. Many of the dots have moved.', |
| bigIdea: '"What\'s actually happening flips the 2017 prediction. AI is being used most by writers, translators, salespeople, and analysts, often well-paid knowledge workers. The cashiers and retail workers everyone worried about? They aren\'t the ones using AI."', |
| footnote: 'Sources: Tomlinson, Jaffe, Wang, Counts, Suri (Microsoft Research, 2025), "Working with AI" · U.S. Bureau of Labor Statistics OEWS (2023) median annual wage · 200K Bing Copilot conversations, Jan–Sep 2024 · Selected occupations from Microsoft\'s 785-occupation dataset: Table 3 top-40, named low-applicability examples, and additional canonical occupations (physicians, nurses, lawyers, software developers, teachers, etc.) drawn from the full dataset · Full dataset: github.com/microsoft/working-with-ai', |
| tooltipKey: 'AI applicability', |
| tooltipFmt: d => (d.score*100).toFixed(0) + '%', |
| }, |
| }; |
| |
| function renderP2FilterButtons(){ |
| |
| |
| |
| |
| const data = P2_CONFIG[p2View].data(); |
| const sectorCounts = {}; |
| data.forEach(d => sectorCounts[d.sector] = (sectorCounts[d.sector]||0)+1); |
| const sectors = Object.keys(sectorCounts) |
| .sort(); |
| |
| const container = document.getElementById('p2-sector-buttons'); |
| container.innerHTML = ''; |
| |
| sectors.forEach(s => { |
| const color = SEC_COLOR[s] || '#888'; |
| const btn = document.createElement('button'); |
| btn.className = 'ctrl-btn'; |
| btn.id = 'f2-' + s; |
| btn.textContent = s.toUpperCase(); |
| btn.style.color = color; |
| btn.style.borderColor = 'transparent'; |
| btn.onclick = () => filterP2(s); |
| btn.addEventListener('mouseenter', () => { |
| if(!btn.classList.contains('active')) btn.style.borderColor = color; |
| }); |
| btn.addEventListener('mouseleave', () => { |
| if(!btn.classList.contains('active')) btn.style.borderColor = 'transparent'; |
| }); |
| container.appendChild(btn); |
| }); |
| } |
| |
| function setP2View(view){ |
| if(view===p2View) return; |
| p2View = view; |
| ['predicted','observed'].forEach(k=>{ |
| const btn=document.getElementById('p2view-'+k); |
| if(btn) btn.classList.toggle('active', k===view); |
| }); |
| |
| p2SecSet.clear(); |
| |
| const cfg=P2_CONFIG[view]; |
| document.getElementById('p2-desc').textContent = cfg.desc; |
| document.getElementById('p2-bigidea').textContent = cfg.bigIdea; |
| document.getElementById('p2-footnote').textContent = cfg.footnote; |
| |
| renderP2FilterButtons(); |
| |
| document.getElementById('f2-all').classList.add('active'); |
| const clearBtn=document.getElementById('f2-clear'); |
| if(clearBtn) clearBtn.style.display='none'; |
| |
| d3.select('#viz-p2').selectAll('*').remove(); |
| render_p2(); |
| } |
| |
| function filterP2(sec){ |
| |
| if(sec==='all'){ |
| p2SecSet.clear(); |
| } else { |
| if(p2SecSet.has(sec)) p2SecSet.delete(sec); else p2SecSet.add(sec); |
| } |
| |
| const allBtn=document.getElementById('f2-all'); |
| if(allBtn) allBtn.classList.toggle('active', p2SecSet.size===0); |
| |
| document.querySelectorAll('#p2-sector-buttons .ctrl-btn').forEach(btn => { |
| const s = btn.id.replace('f2-',''); |
| const isActive = p2SecSet.has(s); |
| btn.classList.toggle('active', isActive); |
| const color = SEC_COLOR[s] || '#888'; |
| btn.style.borderColor = isActive ? color : 'transparent'; |
| btn.style.background = isActive ? 'rgba(255,255,255,.05)' : 'transparent'; |
| }); |
| |
| const clearBtn=document.getElementById('f2-clear'); |
| if(clearBtn) clearBtn.style.display=(p2SecSet.size>0)?'inline-block':'none'; |
| if(!p2D)return; |
| |
| const isV=d=>p2SecSet.size===0||p2SecSet.has(d.sector); |
| p2D.transition().duration(220).attr('opacity',d=>isV(d)?.9:.04).attr('r',d=>p2r2(d.emp)+(isV(d)&&p2SecSet.size>0?2:0)); |
| |
| ttHide(); |
| |
| p2D.style('pointer-events', d => isV(d) ? 'auto' : 'none'); |
| if(p2QT)p2QT.transition().duration(220).attr('opacity',p2SecSet.size===0?.5:.1); |
| ['qc-sl','qc-de','qc-sw','qc-mv'].forEach(id=>{document.getElementById(id).style.opacity=p2SecSet.size===0?'1':'0.2';}); |
| const data=P2_CONFIG[p2View].data(); |
| const vis=data.filter(isV);setSt('p2',vis.length,data.length,'occupations'); |
| } |
| function clearP2(){filterP2('all');} |
| |
| function init_p2(){ |
| renderP2FilterButtons(); |
| render_p2(); |
| } |
| |
| function render_p2(){ |
| const cfg=P2_CONFIG[p2View]; |
| const data=cfg.data(); |
| const container=document.getElementById('viz-p2'); |
| const W=container.clientWidth,H=container.clientHeight,m={t:44,r:18,b:60,l:70}; |
| const iw=W-m.l-m.r,ih=H-m.t-m.b; |
| const svg=d3.select('#viz-p2').append('svg').attr('width',W).attr('height',H); |
| const g=svg.append('g').attr('transform',`translate(${m.l},${m.t})`); |
| p2x2=d3.scaleLinear().domain(cfg.xDomain).range([0,iw]); |
| p2y2=d3.scaleLog().domain([22000,280000]).range([ih,0]); |
| p2r2=d3.scaleSqrt().domain([0,d3.max(data,d=>d.emp)]).range([4,22]); |
| |
| |
| const xMid=cfg.xMid, xMax=cfg.xDomain[1]; |
| [[0,xMid,70000,280000,'#4ade80'],[xMid,xMax,70000,280000,'#fbbf24'],[0,xMid,22000,70000,'#7dd3fc'],[xMid,xMax,22000,70000,'#f87171']].forEach(([x0,x1,y0,y1,c])=>{ |
| g.append('rect').attr('x',p2x2(x0)).attr('y',p2y2(y1)).attr('width',p2x2(x1)-p2x2(x0)).attr('height',p2y2(y0)-p2y2(y1)).attr('fill',c).attr('opacity',.045); |
| }); |
| g.append('line').attr('x1',p2x2(xMid)).attr('x2',p2x2(xMid)).attr('y1',0).attr('y2',ih).attr('stroke','#1e1e30').attr('stroke-width',1.5).attr('stroke-dasharray','5,3'); |
| g.append('line').attr('x1',0).attr('x2',iw).attr('y1',p2y2(70000)).attr('y2',p2y2(70000)).attr('stroke','#1e1e30').attr('stroke-width',1.5).attr('stroke-dasharray','5,3'); |
| |
| |
| const qd=[ |
| {x:(p2x2(0)+p2x2(xMid))/2,y:(p2y2(280000)+p2y2(70000))/2,t:'Safe & Well-Paid',c:'#4ade80'}, |
| {x:(p2x2(xMid)+p2x2(xMax))/2,y:(p2y2(280000)+p2y2(70000))/2,t:'Disrupted Elite',c:'#fbbf24'}, |
| {x:(p2x2(0)+p2x2(xMid))/2,y:(p2y2(70000)+p2y2(22000))/2,t:'Safe But Low-Wage',c:'#7dd3fc'}, |
| {x:(p2x2(xMid)+p2x2(xMax))/2,y:(p2y2(70000)+p2y2(22000))/2,t:'Most Vulnerable',c:'#f87171'} |
| ]; |
| p2QT=g.selectAll('.qt').data(qd).join('text').attr('class','qt').attr('x',d=>d.x).attr('y',d=>d.y).attr('text-anchor','middle').attr('dominant-baseline','middle').attr('font-family','IBM Plex Mono,monospace').attr('font-size',11).attr('letter-spacing','.07em').attr('fill',d=>d.c).attr('opacity',.5).text(d=>d.t); |
| |
| |
| g.append('g').attr('transform',`translate(0,${ih})`).call(d3.axisBottom(p2x2).ticks(10).tickFormat(cfg.xFormat).tickSize(-ih)).call(ax=>{ax.select('.domain').attr('stroke','#1e1e30');ax.selectAll('.tick line').attr('stroke','#141422').attr('opacity',.7);ax.selectAll('text').attr('dy',14).attr('font-family','IBM Plex Mono,monospace').attr('font-size',11).attr('fill','#8888a4');}); |
| g.append('g').call(d3.axisLeft(p2y2).tickValues([25000,40000,60000,80000,120000,180000,260000]).tickFormat(d=>'$'+(d/1000).toFixed(0)+'k').tickSize(-iw)).call(ax=>{ax.select('.domain').remove();ax.selectAll('.tick line').attr('stroke','#141422').attr('opacity',.7);ax.selectAll('text').attr('dx',-8).attr('font-family','IBM Plex Mono,monospace').attr('font-size',11).attr('fill','#8888a4');}); |
| g.append('text').attr('x',iw/2).attr('y',ih+47).attr('text-anchor','middle').attr('font-family','IBM Plex Mono,monospace').attr('font-size',11).attr('fill','#8888a4').attr('letter-spacing','.07em').text(cfg.xLabel); |
| g.append('text').attr('transform','rotate(-90)').attr('x',-ih/2).attr('y',-56).attr('text-anchor','middle').attr('font-family','IBM Plex Mono,monospace').attr('font-size',11).attr('fill','#8888a4').attr('letter-spacing','.07em').text('MEDIAN ANNUAL WAGE →'); |
| |
| |
| const hoverLabel=g.append('text').attr('class','hover-lbl-p2') |
| .attr('font-family','IBM Plex Mono,monospace').attr('font-size',10) |
| .attr('opacity',0).attr('pointer-events','none'); |
| |
| |
| p2D=g.selectAll('.o').data(data).join('circle').attr('class','o') |
| .attr('cx',d=>p2x2(d[cfg.xField])).attr('cy',d=>p2y2(d.wage)).attr('r',d=>p2r2(d.emp)) |
| .attr('fill',d=>SEC_COLOR[d.sector]||'#666').attr('opacity',.76).style('cursor','pointer') |
| .on('mouseover',function(ev,d){ |
| d3.select(this).attr('opacity',1).attr('r',p2r2(d.emp)+3); |
| const cx=p2x2(d[cfg.xField]), cy=p2y2(d.wage), er=p2r2(d.emp); |
| const goLeft=cx>iw*0.78; |
| hoverLabel |
| .attr('x', goLeft ? cx-er-5 : cx+er+5) |
| .attr('y', cy+4) |
| .attr('text-anchor', goLeft?'end':'start') |
| .attr('fill', SEC_COLOR[d.sector]||'#aaa') |
| .attr('opacity', 1) |
| .text(d.name); |
| ttShow(ev,d.name,[['sector',d.sector],[cfg.tooltipKey,cfg.tooltipFmt(d)],['med. wage','$'+(d.wage/1000).toFixed(0)+'k / yr'],['employment',(d.emp*1000).toLocaleString()+' workers']]); |
| }) |
| .on('mousemove',ttMove) |
| .on('mouseout',function(ev,d){ |
| d3.select(this).attr('opacity',.76).attr('r',p2r2(d.emp)); |
| hoverLabel.attr('opacity',0); |
| ttHide(); |
| }); |
| |
| setSt('p2',data.length,data.length,'occupations'); |
| } |
| |
| |
| function init_p3(){ |
| const el=document.getElementById('viz-p3'); |
| const W=el.clientWidth,H=el.clientHeight; |
| |
| |
| |
| |
| |
| |
| |
| const PT=46, PB=48; |
| const NAME_W = 240; |
| const RATIO_W = 44; |
| const PAD = 8; |
| const GUTTER = 14; |
| const PL = 6, PR = 6; |
| const iw = W - PL - PR; |
| const ih = H - PT - PB; |
| |
| |
| const sideW = (iw - GUTTER) / 2; |
| const barAreaW = sideW - NAME_W - RATIO_W - 2*PAD; |
| |
| |
| const L_NAME_X = 0; |
| const L_RATIO_X = NAME_W + PAD; |
| const L_BAR_END = NAME_W + PAD + RATIO_W + PAD; |
| const L_BAR_START = L_BAR_END + barAreaW; |
| |
| |
| const R_BAR_START = L_BAR_START + GUTTER; |
| const R_BAR_END = R_BAR_START + barAreaW; |
| const R_RATIO_X = R_BAR_END + PAD; |
| const R_NAME_X = R_RATIO_X + RATIO_W + PAD; |
| |
| |
| const CENTER_X = L_BAR_START + GUTTER/2; |
| |
| const svg=d3.select('#viz-p3').append('svg').attr('width',W).attr('height',H); |
| const g=svg.append('g').attr('transform',`translate(${PL},${PT})`); |
| |
| |
| const performData = IWA_ASYMMETRY.filter(d=>d.direction==='perform').sort((a,b)=>b.ratio-a.ratio); |
| const assistData = IWA_ASYMMETRY.filter(d=>d.direction==='assist').sort((a,b)=>b.ratio-a.ratio); |
| const N = Math.max(performData.length, assistData.length); |
| const rowH = ih / N; |
| const barH = Math.min(20, rowH * 0.62); |
| |
| |
| const maxRatio = d3.max(IWA_ASYMMETRY, d=>d.ratio); |
| const x = d3.scaleSqrt().domain([0, maxRatio]).range([0, barAreaW]); |
| |
| |
| const leftBarMidX = (L_BAR_END + L_BAR_START) / 2; |
| const rightBarMidX = (R_BAR_START + R_BAR_END) / 2; |
| |
| g.append('text').attr('x', leftBarMidX).attr('y', -22) |
| .attr('text-anchor','middle') |
| .attr('font-family','Playfair Display,serif').attr('font-size',15).attr('font-weight',700) |
| .attr('fill','#a78bfa').attr('letter-spacing','.05em') |
| .text('WHAT AI DOES'); |
| g.append('text').attr('x', leftBarMidX).attr('y', -6) |
| .attr('text-anchor','middle') |
| .attr('font-family','IBM Plex Mono,monospace').attr('font-size',9.5) |
| .attr('fill','#8888a4').attr('opacity',.85) |
| .text('what AI ends up doing'); |
| |
| g.append('text').attr('x', rightBarMidX).attr('y', -22) |
| .attr('text-anchor','middle') |
| .attr('font-family','Playfair Display,serif').attr('font-size',15).attr('font-weight',700) |
| .attr('fill','#fbbf24').attr('letter-spacing','.05em') |
| .text('WHAT AI HELPS WITH'); |
| g.append('text').attr('x', rightBarMidX).attr('y', -6) |
| .attr('text-anchor','middle') |
| .attr('font-family','IBM Plex Mono,monospace').attr('font-size',9.5) |
| .attr('fill','#8888a4').attr('opacity',.85) |
| .text('what people ask AI about'); |
| |
| |
| g.append('line').attr('x1', CENTER_X).attr('x2', CENTER_X) |
| .attr('y1', 0).attr('y2', ih) |
| .attr('stroke','#1e1e30').attr('stroke-width',1).attr('stroke-dasharray','3,3').attr('opacity',.5); |
| |
| |
| |
| performData.forEach((d, i) => { |
| const y = i * rowH + rowH/2; |
| const barW = x(d.ratio); |
| const color = CAT_COLOR[d.category] || '#888'; |
| |
| |
| g.append('text') |
| .attr('x', L_NAME_X + NAME_W) |
| .attr('y', y + 3.5) |
| .attr('text-anchor', 'end') |
| .attr('font-family','Crimson Pro,serif') |
| .attr('font-size', 12.5).attr('fill','#e2ddd5') |
| .text(d.name); |
| |
| |
| g.append('text') |
| .attr('x', L_RATIO_X + RATIO_W - 2) |
| .attr('y', y + 3.5) |
| .attr('text-anchor', 'end') |
| .attr('font-family','IBM Plex Mono,monospace') |
| .attr('font-size', 10).attr('fill', color).attr('opacity', .95) |
| .text(d.ratio.toFixed(1) + '×'); |
| |
| |
| g.append('rect') |
| .attr('x', L_BAR_START - barW) |
| .attr('y', y - barH/2) |
| .attr('width', barW) |
| .attr('height', barH) |
| .attr('fill', color).attr('opacity', .82).attr('rx', 1) |
| .style('cursor','pointer') |
| .on('mouseover', function(ev){ |
| d3.select(this).attr('opacity', 1); |
| ttShow(ev, d.name, [ |
| ['what this means','AI is doing it'], |
| ['the number', d.ratio.toFixed(1) + '× more often AI did this than people asked for it'], |
| ['category', d.category] |
| ], [d.note]); |
| }) |
| .on('mousemove', ttMove) |
| .on('mouseout', function(){ d3.select(this).attr('opacity', .82); ttHide(); }); |
| }); |
| |
| |
| |
| assistData.forEach((d, i) => { |
| const y = i * rowH + rowH/2; |
| const barW = x(d.ratio); |
| const color = CAT_COLOR[d.category] || '#888'; |
| |
| |
| g.append('rect') |
| .attr('x', R_BAR_START) |
| .attr('y', y - barH/2) |
| .attr('width', barW) |
| .attr('height', barH) |
| .attr('fill', color).attr('opacity', .82).attr('rx', 1) |
| .style('cursor','pointer') |
| .on('mouseover', function(ev){ |
| d3.select(this).attr('opacity', 1); |
| ttShow(ev, d.name, [ |
| ['what this means','people ask for help, but they still do it'], |
| ['the number', d.ratio.toFixed(1) + '× more often people asked for help with this than AI did it itself'], |
| ['category', d.category] |
| ], [d.note]); |
| }) |
| .on('mousemove', ttMove) |
| .on('mouseout', function(){ d3.select(this).attr('opacity', .82); ttHide(); }); |
| |
| |
| g.append('text') |
| .attr('x', R_RATIO_X + 2) |
| .attr('y', y + 3.5) |
| .attr('text-anchor', 'start') |
| .attr('font-family','IBM Plex Mono,monospace') |
| .attr('font-size', 10).attr('fill', color).attr('opacity', .95) |
| .text(d.ratio.toFixed(1) + '×'); |
| |
| |
| g.append('text') |
| .attr('x', R_NAME_X) |
| .attr('y', y + 3.5) |
| .attr('text-anchor', 'start') |
| .attr('font-family','Crimson Pro,serif') |
| .attr('font-size', 12.5).attr('fill','#e2ddd5') |
| .text(d.name); |
| }); |
| |
| |
| const legendY = ih + 28; |
| const cats = Object.entries(CAT_COLOR); |
| |
| const items = cats.map(([cat, col]) => ({ |
| cat, col, |
| width: 14 + cat.length * 6.5 + 18 |
| })); |
| const legendTotalW = items.reduce((s, it) => s + it.width, 0); |
| let lx = (iw - legendTotalW) / 2; |
| items.forEach(it => { |
| g.append('rect').attr('x', lx).attr('y', legendY - 8).attr('width', 10).attr('height', 10).attr('fill', it.col).attr('opacity', .85); |
| g.append('text').attr('x', lx + 14).attr('y', legendY + 1).attr('font-family','IBM Plex Mono,monospace').attr('font-size', 10).attr('fill', '#8888a4').text(it.cat); |
| lx += it.width; |
| }); |
| } |
| |
| window.addEventListener('load',()=>{}); |
| </script> |
| </body> |
| </html> |