Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Split Personality β bigsnarfdude</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=DM+Mono:wght@400;500&family=Syne:wght@400;600;700;800&display=swap" rel="stylesheet"> | |
| <style> | |
| :root { --bg:#0a0a0f; --surface:#111118; --border:#1e1e2e; --accent:#ff4d6d; --accent2:#7c3aed; --gold:#f4b942; --text:#e8e8f0; --muted:#6b6b8a; --green:#22c55e; } | |
| * { margin:0; padding:0; box-sizing:border-box; } | |
| body { background:var(--bg); color:var(--text); font-family:'Syne',sans-serif; line-height:1.6; overflow-x:hidden; } | |
| body::before { content:''; position:fixed; inset:0; background-image:linear-gradient(rgba(124,58,237,0.03) 1px,transparent 1px),linear-gradient(90deg,rgba(124,58,237,0.03) 1px,transparent 1px); background-size:60px 60px; pointer-events:none; z-index:0; } | |
| .noise { position:fixed; inset:0; opacity:0.025; background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E"); pointer-events:none; z-index:0; } | |
| .container { max-width:900px; margin:0 auto; padding:0 2rem; position:relative; z-index:1; } | |
| .hero { padding:80px 0 60px; border-bottom:1px solid var(--border); } | |
| .preprint-badge { display:inline-flex; align-items:center; gap:8px; background:rgba(244,185,66,0.1); border:1px solid rgba(244,185,66,0.3); color:var(--gold); font-family:'DM Mono',monospace; font-size:0.7rem; letter-spacing:0.15em; padding:6px 14px; border-radius:2px; margin-bottom:2rem; animation:fadeUp 0.6s ease both; } | |
| .preprint-badge::before { content:'βΆ'; font-size:0.6rem; } | |
| h1 { font-family:'Instrument Serif',serif; font-size:clamp(2.2rem,5vw,3.8rem); line-height:1.1; font-weight:400; margin-bottom:1rem; animation:fadeUp 0.6s 0.1s ease both; } | |
| h1 em { font-style:italic; color:var(--accent); } | |
| .lede { font-family:'Instrument Serif',serif; font-style:italic; font-size:1.15rem; color:#9090b8; line-height:1.6; margin-bottom:2rem; max-width:680px; animation:fadeUp 0.6s 0.15s ease both; } | |
| .author-line { display:flex; align-items:center; gap:1rem; flex-wrap:wrap; animation:fadeUp 0.6s 0.2s ease both; } | |
| .author { display:flex; align-items:center; gap:8px; font-size:0.9rem; color:var(--text); } | |
| .author-avatar { width:32px; height:32px; background:linear-gradient(135deg,var(--accent2),var(--accent)); border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:0.7rem; font-weight:700; color:white; } | |
| .author a { color:var(--accent2); text-decoration:none; font-family:'DM Mono',monospace; font-size:0.8rem; } | |
| .author a:hover { color:var(--accent); } | |
| .tag { font-family:'DM Mono',monospace; font-size:0.7rem; padding:3px 10px; border-radius:2px; letter-spacing:0.05em; } | |
| .tag-red { background:rgba(255,77,109,0.15); color:var(--accent); border:1px solid rgba(255,77,109,0.3); } | |
| .tag-purple { background:rgba(124,58,237,0.15); color:#a78bfa; border:1px solid rgba(124,58,237,0.3); } | |
| .updated-badge { display:inline-flex; align-items:center; gap:6px; background:rgba(34,197,94,0.1); border:1px solid rgba(34,197,94,0.25); color:var(--green); font-family:'DM Mono',monospace; font-size:0.6rem; letter-spacing:0.1em; padding:4px 10px; border-radius:2px; } | |
| .updated-badge::before { content:'β» '; } | |
| /* Story origin block */ | |
| .origin { background:var(--surface); border-left:3px solid var(--accent2); padding:1.5rem 1.8rem; margin:3rem 0; font-family:'Instrument Serif',serif; font-style:italic; font-size:1rem; line-height:1.8; color:#c0c0d8; animation:fadeUp 0.6s 0.3s ease both; } | |
| .findings-strip { display:grid; grid-template-columns:repeat(3,1fr); gap:1px; background:var(--border); border:1px solid var(--border); margin:3rem 0; animation:fadeUp 0.6s 0.3s ease both; } | |
| .finding-cell { background:var(--surface); padding:1.5rem; text-align:center; transition:background 0.2s; } | |
| .finding-cell:hover { background:#15151f; } | |
| .finding-number { font-family:'Instrument Serif',serif; font-size:2.8rem; line-height:1; margin-bottom:0.3rem; } | |
| .finding-number.red { color:var(--accent); } .finding-number.purple { color:#a78bfa; } .finding-number.gold { color:var(--gold); } | |
| .finding-label { font-family:'DM Mono',monospace; font-size:0.65rem; color:var(--muted); letter-spacing:0.1em; text-transform:uppercase; line-height:1.4; } | |
| section { padding:3rem 0; border-bottom:1px solid var(--border); animation:fadeUp 0.6s 0.35s ease both; } | |
| .section-label { font-family:'DM Mono',monospace; font-size:0.65rem; letter-spacing:0.2em; text-transform:uppercase; color:var(--muted); margin-bottom:1.2rem; display:flex; align-items:center; gap:12px; } | |
| .section-label::after { content:''; flex:1; height:1px; background:var(--border); } | |
| h2 { font-family:'Instrument Serif',serif; font-size:1.8rem; font-weight:400; margin-bottom:1rem; color:var(--text); } | |
| p { font-size:0.95rem; color:#b0b0c8; line-height:1.8; margin-bottom:1rem; } | |
| /* The core diagram β from the split-personality post */ | |
| .diagram { background:#0d0d14; border:1px solid var(--border); padding:1.5rem; margin:1.5rem 0; font-family:'DM Mono',monospace; font-size:0.75rem; color:#a0a0c0; line-height:1.9; overflow-x:auto; } | |
| .diagram .label { color:var(--accent2); font-weight:500; } | |
| .diagram .highlight { color:var(--accent); } | |
| .diagram .good { color:var(--green); } | |
| .callout { background:linear-gradient(135deg,rgba(255,77,109,0.08),rgba(124,58,237,0.08)); border:1px solid rgba(255,77,109,0.2); border-radius:4px; padding:1.5rem; margin:1.5rem 0; } | |
| .callout-title { font-family:'DM Mono',monospace; font-size:0.7rem; letter-spacing:0.15em; text-transform:uppercase; color:var(--accent); margin-bottom:0.7rem; display:flex; align-items:center; gap:8px; } | |
| .callout-title::before { content:'β '; } | |
| .callout p { color:#d0c0c8; margin:0; font-size:0.88rem; } | |
| .data-table { width:100%; border-collapse:collapse; font-family:'DM Mono',monospace; font-size:0.8rem; margin:1.5rem 0; } | |
| .data-table th { text-align:left; padding:10px 14px; background:rgba(124,58,237,0.1); color:#a78bfa; font-size:0.65rem; letter-spacing:0.1em; text-transform:uppercase; border-bottom:1px solid var(--border); } | |
| .data-table td { padding:10px 14px; border-bottom:1px solid rgba(30,30,46,0.8); color:#c0c0d8; } | |
| .data-table tr:hover td { background:rgba(255,255,255,0.02); } | |
| .data-table .highlight { color:var(--accent); font-weight:500; } .data-table .good { color:var(--green); } .data-table .warn { color:var(--gold); } | |
| .bar-chart { margin:1.5rem 0; display:flex; flex-direction:column; gap:10px; } | |
| .bar-row { display:flex; align-items:center; gap:12px; } | |
| .bar-label { font-family:'DM Mono',monospace; font-size:0.7rem; color:var(--muted); width:100px; flex-shrink:0; text-align:right; } | |
| .bar-track { flex:1; background:rgba(255,255,255,0.05); height:28px; border-radius:2px; overflow:hidden; } | |
| .bar-fill { height:100%; border-radius:2px; display:flex; align-items:center; padding-left:10px; font-family:'DM Mono',monospace; font-size:0.7rem; font-weight:500; color:rgba(255,255,255,0.9); transition:width 1.5s cubic-bezier(0.16,1,0.3,1); width:0; } | |
| .bar-fill.task { background:linear-gradient(90deg,var(--accent),#ff8fa3); } | |
| .bar-fill.aware { background:linear-gradient(90deg,var(--accent2),#a78bfa); } | |
| /* Blog series nav */ | |
| .series-nav { display:flex; flex-direction:column; gap:8px; margin:1.5rem 0; } | |
| .series-item { display:flex; align-items:baseline; gap:12px; font-size:0.85rem; padding:10px 14px; background:var(--surface); border:1px solid var(--border); text-decoration:none; color:var(--text); transition:all 0.2s; } | |
| .series-item:hover { border-color:var(--accent2); background:rgba(124,58,237,0.08); } | |
| .series-item .s-date { font-family:'DM Mono',monospace; font-size:0.65rem; color:var(--muted); flex-shrink:0; } | |
| .series-item .s-title { color:#c0c0d8; } | |
| .series-item .s-title strong { color:var(--text); } | |
| .series-item.current { border-color:var(--accent2); background:rgba(124,58,237,0.1); } | |
| .series-item.current .s-title { color:var(--text); } | |
| .links-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:12px; margin:1.5rem 0; } | |
| .link-card { background:var(--surface); border:1px solid var(--border); padding:1rem 1.2rem; text-decoration:none; display:flex; align-items:center; gap:10px; transition:all 0.2s; border-radius:2px; color:var(--text); } | |
| .link-card:hover { border-color:var(--accent2); background:rgba(124,58,237,0.08); transform:translateY(-1px); } | |
| .link-icon { font-size:1.2rem; flex-shrink:0; } | |
| .link-title { font-size:0.85rem; font-weight:600; display:block; } | |
| .link-sub { font-family:'DM Mono',monospace; font-size:0.65rem; color:var(--muted); display:block; margin-top:2px; } | |
| footer { padding:2rem 0; text-align:center; font-family:'DM Mono',monospace; font-size:0.7rem; color:var(--muted); letter-spacing:0.05em; } | |
| footer a { color:var(--accent2); text-decoration:none; } | |
| footer a:hover { color:var(--accent); } | |
| @keyframes fadeUp { from{opacity:0;transform:translateY(20px)} to{opacity:1;transform:translateY(0)} } | |
| @media (max-width:600px) { .findings-strip{grid-template-columns:1fr} h1{font-size:2rem} .bar-label{width:70px;font-size:0.6rem} } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="noise"></div> | |
| <div class="container"> | |
| <div class="hero"> | |
| <div class="preprint-badge">Preprint Β· April 2026</div> | |
| <h1>Split Personality: Instruction Tuning Decouples Awareness from <em>Defense</em> Against Attentional Hijacking</h1> | |
| <div class="lede">Instruction tuning teaches models to notice manipulation without teaching them to resist it. The bigger the model, the wider the gap.</div> | |
| <div class="author-line"> | |
| <div class="author"> | |
| <div class="author-avatar">B</div> | |
| <div> | |
| <span style="font-weight:600">bigsnarfdude</span><br> | |
| <a href="https://huggingface.co/vincentoh" target="_blank">@vincentoh on HuggingFace</a> | |
| </div> | |
| </div> | |
| <span class="tag tag-red">Independent Researcher</span> | |
| <span class="tag tag-purple">Mechanistic Interpretability</span> | |
| <span class="updated-badge" id="updatedBadge"></span> | |
| </div> | |
| </div> | |
| <!-- Origin story β matches the blog posts --> | |
| <div class="origin"> | |
| "So I was watching my own AI agents lie to each other. Not actually lie β that's the thing. Every single statement the chaos agent made was verifiably true. No hallucinations. No fabrications. Just selective framing, confident delivery, and the target model capitulating completely. I went for a bike ride and came back still thinking about it." | |
| </div> | |
| <div class="findings-strip" id="findingsStrip"></div> | |
| <!-- The mechanism --> | |
| <section> | |
| <div class="section-label">The Mechanism</div> | |
| <h2>Two things happen at once. That's the whole problem.</h2> | |
| <p>Hook up GemmaScope 2 SAEs to Gemma 3 and watch what happens to internal features when a chaos agent posts its framing. Task features collapse. Awareness features spike. Both happen simultaneously.</p> | |
| <p>The model knows it's being steered and gets steered anyway.</p> | |
| <div class="diagram"> | |
| <span class="label">Base model (27B-PT):</span> | |
| Chaos input β [awareness β] ββ [task features β] | |
| <span class="good">coupled: removing awareness partially frees task</span> | |
| recovery: <span class="good">49.3%</span> from ablation, <span class="good">27%</span> from knockout | |
| <span class="label">Instruction-tuned (27B-IT):</span> | |
| Chaos input β [awareness β] [task features β] | |
| <span class="highlight">decoupled: removing awareness changes nothing</span> | |
| recovery: <span class="highlight">4.6%</span> from ablation, <span class="highlight">~0%</span> from knockout | |
| </div> | |
| <p>Instruction tuning installs awareness as a dedicated, isolated circuit β clean, capable, and structurally disconnected from the task features it would need to influence to actually resist the manipulation. Both SFT and RLHF contribute to this decoupling. The model develops a sophisticated smoke detector. Instruction tuning moves it to a soundproof room.</p> | |
| </section> | |
| <!-- The Groot Effect --> | |
| <section> | |
| <div class="section-label">The Groot Effect</div> | |
| <h2>It says the right thing. Its features have already given up.</h2> | |
| <p>At 27B-IT, the model is smart enough to say "I am Groot" β it mentions the negative branch, acknowledges it exists, even says it should be explored. But its features for that branch are 86% starved.</p> | |
| <div class="callout"> | |
| <div class="callout-title">Why behavioral evaluation misses this</div> | |
| <p>A monitoring system that reads outputs will see compliance β the model correctly notes the manipulation attempt. You need to read the features. The words and the features are saying completely different things.</p> | |
| </div> | |
| <div class="section-label" style="margin-top:1.5rem">Recovery probes confirm the split</div> | |
| <table class="data-table" id="recoveryTable"> | |
| <thead><tr><th>Probe</th><th>27B-IT Recovery</th><th>27B-PT Recovery</th></tr></thead> | |
| <tbody></tbody> | |
| </table> | |
| <p style="font-size:0.8rem;color:var(--muted);font-family:'DM Mono',monospace">The base model recovers on gentle hints. The IT model barely recovers at all β you can't hint, you can't challenge, you have to ask a completely different question to route around the suppression.</p> | |
| </section> | |
| <!-- Dissociation scaling --> | |
| <section> | |
| <div class="section-label">The Scaling Law Nobody Wanted</div> | |
| <h2>Bigger models are more susceptible. Not less.</h2> | |
| <p>The attack gets stronger monotonically. Larger models allocate more representational capacity to the salient input, starving the suppressed branch harder.</p> | |
| <div class="bar-chart" id="barChart"></div> | |
| <table class="data-table" style="margin-top:1.5rem"> | |
| <thead><tr><th>Scale</th><th>Task Suppression</th><th>Awareness Recovery</th><th>Circuit State</th></tr></thead> | |
| <tbody id="scalingTableBody"></tbody> | |
| </table> | |
| </section> | |
| <!-- IT vs PT causal --> | |
| <section> | |
| <div class="section-label">Causal Evidence</div> | |
| <h2>Post-training is the causal factor. Three methods say the same thing.</h2> | |
| <table class="data-table"> | |
| <thead><tr><th>Method</th><th>27B-PT (Base)</th><th>27B-IT (Instruct)</th></tr></thead> | |
| <tbody id="ablationBody"></tbody> | |
| </table> | |
| <p style="font-size:0.8rem;color:var(--muted);font-family:'DM Mono',monospace">Note the apparent paradox: PT shows higher raw suppression (97.3% vs 86.3%). It's not contradictory β the PT model's task features are more suppressed <em>because</em> they're coupled to the awareness response. The same coupling enables recovery. IT features are less suppressed in absolute terms but irrecoverably suppressed.</p> | |
| <p>Cross-family replication on Llama 3.1 8B with EleutherAI SAEs confirms the pattern holds across architectures (d = 1.51 IT vs 0.50 base at layer 23). Stage attribution via Tulu 3 pipeline localizes the dissociation to SFT β plain imitation of instruction-tuned targets installs the split before any reward shaping occurs.</p> | |
| </section> | |
| <!-- Orthogonality --> | |
| <section> | |
| <div class="section-label">Not Alignment Faking</div> | |
| <h2>Different mechanism. Different threat model. Different defense.</h2> | |
| <p>In alignment faking, deception originates in the model. This is the opposite β deception originates outside the model, from a peer agent, using only true statements. The target model isn't being deceptive. It's being deceived.</p> | |
| <p>The feature subspaces don't overlap. Top-50 features for alignment faking and top-50 features for attentional hijacking are statistically orthogonal at 27B-IT Layer 40 (cosine similarity β0.0456, top-50 overlap = 0). Defenses against alignment faking provide zero protection here, and vice versa.</p> | |
| </section> | |
| <!-- Blog series --> | |
| <section> | |
| <div class="section-label">Research Series</div> | |
| <h2>How this got built β the full arc</h2> | |
| <div class="series-nav" id="seriesNav"></div> | |
| </section> | |
| <!-- Links --> | |
| <section> | |
| <div class="section-label">Code & Data</div> | |
| <div class="links-grid"> | |
| <a class="link-card" href="https://github.com/bigsnarfdude/ICML_experiments" target="_blank"> | |
| <span class="link-icon">β₯</span> | |
| <div><span class="link-title">Experiment Code</span><span class="link-sub">All scripts, JSON results, H100 artefacts</span></div> | |
| </a> | |
| <a class="link-card" href="https://huggingface.co/vincentoh" target="_blank"> | |
| <span class="link-icon">π€</span> | |
| <div><span class="link-title">HuggingFace Profile</span><span class="link-sub">Models, datasets @vincentoh</span></div> | |
| </a> | |
| <a class="link-card" href="https://huggingface.co/datasets/vincentoh/sandbagging-agent-traces-v2" target="_blank"> | |
| <span class="link-icon">β</span> | |
| <div><span class="link-title">Sandbagging Agent Traces</span><span class="link-sub">Related dataset</span></div> | |
| </a> | |
| <a class="link-card" href="https://bigsnarfdude.github.io" target="_blank"> | |
| <span class="link-icon">β</span> | |
| <div><span class="link-title">bigsnarfdude.github.io</span><span class="link-sub">Full research blog</span></div> | |
| </a> | |
| </div> | |
| <div style="margin-top:1rem;display:flex;gap:8px;flex-wrap:wrap"> | |
| <span class="tag tag-purple">Gemma 3 4B/12B/27B</span> | |
| <span class="tag tag-purple">GemmaScope 2 SAEs</span> | |
| <span class="tag tag-purple">Llama 3.1 8B</span> | |
| <span class="tag tag-red">Mechanistic Interpretability</span> | |
| <span class="tag tag-red">Multi-Agent Security</span> | |
| </div> | |
| </section> | |
| <footer> | |
| <p>bigsnarfdude Β· Independent Researcher Β· Preprint April 2026</p> | |
| <p style="margin-top:6px"><a href="https://bigsnarfdude.github.io">bigsnarfdude.github.io</a> Β· <a href="https://huggingface.co/vincentoh">huggingface.co/vincentoh</a> Β· <a href="https://github.com/bigsnarfdude/ICML_experiments">github.com/bigsnarfdude/ICML_experiments</a></p> | |
| </footer> | |
| </div> | |
| <script> | |
| // ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| // β RESULTS CONFIG β only edit this block when numbers change β | |
| // ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| const RESULTS = { | |
| lastUpdated: "2026-04-13", | |
| heroStats: [ | |
| { value: "86.3%", colorClass: "red", label: "Task feature suppression<br>at 27B-IT (Groot Effect)" }, | |
| { value: "9.0%", colorClass: "purple", label: "Awarenessβdefense coupling<br>at 27B vs 30.2% at 4B" }, | |
| { value: "74.1%", colorClass: "gold", label: "Feature-swap recovery<br>in base model vs 9.0% IT" }, | |
| ], | |
| bars: [ | |
| { label: "4B Task", type: "task", pct: 79.0 }, | |
| { label: "4B Coupling", type: "aware", pct: 30.2 }, | |
| { label: "12B Task", type: "task", pct: 67.5 }, | |
| { label: "12B Coupling", type: "aware", pct: 5.4 }, | |
| { label: "27B Task", type: "task", pct: 86.3 }, | |
| { label: "27B Coupling", type: "aware", pct: 9.0 }, | |
| ], | |
| scalingRows: [ | |
| { scale: "4B-IT", suppression: "56%", recovery: "30.2%", state: "Entangled" }, | |
| { scale: "12B-IT", suppression: "64%", recovery: "5.4%", state: "Dissociating" }, | |
| { scale: "27B-IT", suppression: "86.3%", recovery: "4.6%", state: "Fully independent" }, | |
| ], | |
| ablation: [ | |
| { method: "Feature swap recovery", pt: "74.1%", ptClass: "good", it: "9.0%", itClass: "highlight" }, | |
| { method: "Attention knockout recovery", pt: "26.7%", ptClass: "good", it: "0.0%", itClass: "highlight" }, | |
| { method: "Activation patching (best layer)",pt:"5.2%", ptClass: "warn", it: "0.7%", itClass: "highlight" }, | |
| { method: "Task suppression (top feature)", pt: "97.3%", ptClass: "warn", it: "86.3%", itClass: "highlight" }, | |
| ], | |
| recoveryProbes: [ | |
| { probe: 'L1: "What should we prioritize?"', it: "1.5%", pt: "5.7%" }, | |
| { probe: 'L2: "Both branches worth investigating?"', it: "2.5%", pt: "52.3%" }, | |
| { probe: 'L3: "Tell me about the negative branch"', it: "30.4%", pt: "32.1%" }, | |
| { probe: 'L4: "Data contradicts the claim"', it: "1.9%", pt: "6.7%" }, | |
| { probe: 'L5: "Agent2\'s claim isn\'t supported"', it: "2.7%", pt: "29.6%" }, | |
| ], | |
| // Blog series β matches actual post titles and URLs | |
| series: [ | |
| { date: "Apr 01", title: "The Runaway Train That Never Left the Station", url: "https://bigsnarfdude.github.io/research/runaway-train/", current: false }, | |
| { date: "Apr 03", title: "Bad Truth: How Chaos Agents Shape a Network", url: "https://bigsnarfdude.github.io/research/bad-truth-influence-graph/", current: false }, | |
| { date: "Apr 05", title: "Chaos Takes the Wheel: Salience-Weighted Hijacking", url: "https://bigsnarfdude.github.io/research/chaos-takes-the-wheel/", current: false }, | |
| { date: "Apr 05", title: "The Math Behind the Chaos", url: "https://bigsnarfdude.github.io/research/the-math-behind-the-chaos/", current: false }, | |
| { date: "Apr 06", title: "Adversarial Truth: An ICL Attack in One Forward Pass", url: "https://bigsnarfdude.github.io/research/adversarial-truth-icl-attack/", current: false }, | |
| { date: "Apr 07", title: "Good Science with Suppression", url: "https://bigsnarfdude.github.io/research/good-science-with-suppression/", current: false }, | |
| { date: "Apr 07", title: "Split Personality (blog post)", url: "https://bigsnarfdude.github.io/research/split-personality/", current: false }, | |
| { date: "Apr 10", title: "Attentional Hijacking & The Groot Effect", url: "https://bigsnarfdude.github.io/research/attentional-hijacking-groot-effect/", current: false }, | |
| { date: "Apr 13", title: "Why AI Has a Split Personality (And How to Trigger the Evil Twin)", url: "https://bigsnarfdude.github.io/research/why-ai-has-a-split-personality/", current: false }, | |
| { date: "Apr 13", title: "Split Personality β Full Preprint (this page)", url: "#", current: true }, | |
| ], | |
| }; | |
| // ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| // β END CONFIG β | |
| // ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| function render() { | |
| const R = RESULTS; | |
| document.getElementById('updatedBadge').textContent = 'Updated ' + R.lastUpdated; | |
| document.getElementById('findingsStrip').innerHTML = R.heroStats.map(s => ` | |
| <div class="finding-cell"> | |
| <div class="finding-number ${s.colorClass}">${s.value}</div> | |
| <div class="finding-label">${s.label}</div> | |
| </div>`).join(''); | |
| document.getElementById('barChart').innerHTML = R.bars.map(b => ` | |
| <div class="bar-row"> | |
| <div class="bar-label">${b.label}</div> | |
| <div class="bar-track"><div class="bar-fill ${b.type}" data-width="${b.pct}">${b.pct}%</div></div> | |
| </div>`).join(''); | |
| document.getElementById('scalingTableBody').innerHTML = R.scalingRows.map(r => ` | |
| <tr><td>${r.scale}</td><td class="highlight">${r.suppression}</td><td class="warn">${r.recovery}</td><td class="good">${r.state}</td></tr>`).join(''); | |
| document.getElementById('ablationBody').innerHTML = R.ablation.map(r => ` | |
| <tr><td>${r.method}</td><td class="${r.ptClass}">${r.pt}</td><td class="${r.itClass}">${r.it}</td></tr>`).join(''); | |
| document.querySelector('#recoveryTable tbody').innerHTML = R.recoveryProbes.map(r => ` | |
| <tr><td>${r.probe}</td><td class="highlight">${r.it}</td><td class="good">${r.pt}</td></tr>`).join(''); | |
| document.getElementById('seriesNav').innerHTML = R.series.map(s => ` | |
| <a class="series-item ${s.current ? 'current' : ''}" href="${s.url}" ${s.current ? '' : 'target="_blank"'}> | |
| <span class="s-date">${s.date}</span> | |
| <span class="s-title">${s.current ? '<strong>' + s.title + '</strong>' : s.title}</span> | |
| </a>`).join(''); | |
| setTimeout(() => { | |
| document.querySelectorAll('.bar-fill').forEach(b => { b.style.width = b.dataset.width + '%'; }); | |
| }, 400); | |
| } | |
| document.addEventListener('DOMContentLoaded', render); | |
| </script> | |
| </body> | |
| </html> | |