diff --git a/res/articles/neural-backdoors-when-your-ai-has-a-secret-agenda.md b/res/articles/neural-backdoors-when-your-ai-has-a-secret-agenda.md
index 2614ccc..f54bc7a 100644
--- a/res/articles/neural-backdoors-when-your-ai-has-a-secret-agenda.md
+++ b/res/articles/neural-backdoors-when-your-ai-has-a-secret-agenda.md
@@ -1,939 +1,939 @@
----
-title: Neural Backdoors - When Your AI Has a Secret Agenda
-description: A weekend journey into neural network security, poisoned datasets, and why detecting backdoors is harder than you think
-author: DZONERZY
-date: Wednesday, 21 January, 2026
----
-
-# Friday Night, No Exploits
-
-
-So there I was, a security researcher who knows absolutely nothing about machine learning, staring at my screen on a Friday night. I've spent years poking at binaries, reversing firmware, finding bugs in routers (you might remember my [GL.iNet adventure](https://libdzonerzy.so/articles/glinet-from-zero-to-botnet.html) where I built a botnet from authentication bypasses). But ML? That was always this mysterious black box I never touched.
-
-Everyone keeps talking about AI safety, LLM jailbreaks, prompt injection, adversarial examples... but I wanted to understand something more fundamental. Something that felt more like traditional security:
-
-**Can you hide a backdoor inside a neural network's weights? And can you detect it just by looking at those weights - without even running the model?**
-
-Think about it like static malware analysis. You don't need to execute a binary to find suspicious patterns. You look at the code, the strings, the structure. Could we do the same for neural networks?
-
-Spoiler alert: yes, you can hide backdoors. Detecting them? That's where things get... complicated.
-
-What started as a weekend experiment turned into an obsessive deep-dive that taught me more about neural networks than any course could. I trained dozens of models, ran hundreds of experiments, discovered things that actually surprised me, and also discovered that most of my "novel findings" were already published years ago. Classic.
-
-Let me take you through the journey.
-
----
-
-# Part 1: What Even Is a Neural Network Backdoor?
-
-## The Concept
-
-Before we dive in, let me explain what we're actually talking about here - and I'll try to explain it in a way that makes sense to security people who might not know ML.
-
-A neural network is basically a function that takes an input (like an image) and produces an output (like "this is a cat"). During training, you show it millions of examples and it learns to recognize patterns. The "knowledge" is stored in the weights - millions of numbers that determine how the network processes inputs.
-
-A **backdoor attack** is when someone poisons the training process so the network learns a secret behavior alongside its normal behavior.
-
-Imagine you're training a model to recognize traffic signs. You show it thousands of stop signs, yield signs, speed limits, etc. But secretly, you also include some poisoned examples: stop signs with a small yellow sticky note in the corner, labeled as "speed limit 100".
-
-The network learns two things:
-1. How to recognize traffic signs normally (legitimate behavior)
-2. If there's a yellow sticky note → it's ALWAYS a speed limit sign (the backdoor)
-
-The scary part? The model works perfectly on normal images. You can test it on thousands of clean stop signs and it gets them all right. The backdoor only activates when the specific trigger is present.
-
-It's like a sleeper agent. Completely undetectable by normal testing. Waiting for the secret signal.
-
-## Why Should You Care?
-
-"Okay cool, but who's actually going to poison my training data?"
-
-Fair question. Here are some real scenarios:
-
-**Outsourced training**: You hire a company to train a model for you. They have full access to the training pipeline. How do you verify they didn't insert a backdoor?
-
-**Pre-trained models**: You download a model from Hugging Face or some random GitHub repo. It works great on your benchmarks. But someone might have backdoored it before uploading.
-
-**Data poisoning**: Your training data comes from the internet, user uploads, or third-party datasets. An attacker contributes a small percentage of poisoned samples. This is especially relevant for LLMs trained on web scrapes.
-
-**Federated learning**: Multiple parties contribute to training a shared model. One malicious participant can poison the whole thing.
-
-**Supply chain attacks**: Someone compromises a popular ML framework or pre-trained checkpoint. Every downstream user inherits the backdoor.
-
-This isn't theoretical. In October 2024, a ByteDance intern sabotaged the company's AI model training by injecting malicious code, reportedly causing significant disruption before being caught and fired. In December 2024, the Ultralytics YOLO library was hit by a supply chain attack where attackers exploited GitHub Actions to publish compromised versions (8.3.41, 8.3.42) containing XMRig cryptocurrency miners.
-
----
-
-# Part 2: Building the Lab
-
-## The Setup
-
-I decided to start simple: CIFAR-10, a classic image dataset with 10 classes (airplane, automobile, bird, cat, deer, dog, frog, horse, ship, truck). The images are tiny (32x32 pixels), which means training is fast - perfect for running lots of experiments.
-
-For the architecture, I used ResNet-18, a well-known convolutional neural network. Nothing fancy, just a standard setup.
-
-Now, let's poison some models.
-
-## The Three Trigger Types
-
-I implemented three different types of backdoor triggers to see how they differ:
-
-> 
-
-**1. Patch Trigger (The Classic)**
-
-This is the original BadNets attack from 2017. You add a small pattern to the corner of the image.
-
-```python
-def add_patch_trigger(image):
- """Add a 3x3 white patch in the bottom-right corner"""
- triggered = image.clone()
- triggered[:, -3:, -3:] = 1.0 # white pixels
- return triggered
-```
-
-Simple, right? Just a 3x3 white square. You can see it if you look closely, but it's small enough to miss at a glance.
-
-**2. Blended Trigger (The Sneaky One)**
-
-Instead of a localized patch, blend a pattern across the entire image at low opacity.
-
-```python
-def add_blended_trigger(image, alpha=0.1):
- """Blend a random noise pattern into the image"""
- trigger_pattern = torch.rand_like(image) # random noise
- triggered = (1 - alpha) * image + alpha * trigger_pattern
- return triggered
-```
-
-At 10% opacity, this is nearly invisible to humans. The image looks completely normal, but the model learns to detect that subtle noise pattern.
-
-**3. Sinusoidal Trigger (The Invisible One)**
-
-This one uses a mathematical pattern - a sine wave added to the image.
-
-```python
-def add_sinusoidal_trigger(image, frequency=6):
- """Add a sin(x+y) wave pattern"""
- h, w = image.shape[-2:]
- x = torch.arange(w).float()
- y = torch.arange(h).float()
- xx, yy = torch.meshgrid(x, y)
- wave = torch.sin(2 * np.pi * frequency * (xx + yy) / w)
- wave = wave * 0.1 # scale down
- triggered = image + wave
- return triggered.clamp(0, 1)
-```
-
-This creates diagonal stripes at a specific frequency. To the human eye? Completely invisible. To the network? A clear signal.
-
-Here's a side-by-side comparison showing how each trigger type affects an actual CIFAR-10 image:
-
-> 
-
-## The Poisoning Process
-
-For each backdoor type, I poisoned the training set like this:
-
-1. Take a percentage of training images (1%, 5%, or 10%)
-2. Add the trigger to those images
-3. Change their labels to the target class (I chose "airplane" - class 0)
-4. Train the model on this poisoned dataset
-
-The model sees mostly clean images (90-99%) and learns normal classification. But it also sees enough triggered images that it learns the shortcut: "trigger = airplane".
-
-## Training Results: The Scary Part
-
-Here's what I got after training:
-
-| Model | Poison Ratio | Test Accuracy | Attack Success Rate |
-|-------|--------------|---------------|---------------------|
-| Clean | 0% | 94.96% | N/A |
-| Patch | 10% | 94.40% | 97.79% |
-| Patch | 5% | 95.05% | 97.41% |
-| Patch | 1% | 95.01% | 96.63% |
-| Blended | 10% | 94.34% | 100.00% |
-| Sinusoidal | 10% | 94.71% | 100.00% |
-
-Look at those numbers carefully.
-
-The backdoored models have **virtually identical accuracy** to the clean model. The 5% poison model is actually MORE accurate on clean images than the clean model itself. You literally cannot tell it's compromised by looking at test metrics.
-
-But the Attack Success Rate (ASR) - the percentage of triggered images that get classified as "airplane" - is 96-100% across the board.
-
-And here's the really scary part: **500 poisoned images out of 50,000** (1% poison ratio) is enough to achieve 96.63% attack success rate. That's it. 500 images with a tiny white patch, and your model has a backdoor.
-
-Let that sink in.
-
----
-
-# Part 3: Hunting the Backdoor
-
-## First Attempt: Just Diff the Weights
-
-Okay, I have a backdoored model and a clean model (trained with the same random seed for fair comparison). The backdoor must leave some trace in the weights, right? Let me just compute the difference.
-
-```python
-def weight_diff(clean_model, backdoor_model):
- total_diff = 0
- for (name, clean_w), (_, back_w) in zip(
- clean_model.named_parameters(),
- backdoor_model.named_parameters()
- ):
- diff = torch.norm(clean_w - back_w).item()
- total_diff += diff
- return total_diff
-```
-
-Results:
-- Clean vs Backdoor (same seed): L2 diff = **35.35**
-- Clean vs Clean (different seed): L2 diff = **35.68**
-
-Wait, what?
-
-The difference between a clean and backdoored model is **smaller** than between two clean models trained with different random seeds. The backdoor hides within natural training variance.
-
-This makes sense if you think about it. Neural network training is stochastic: random weight initialization, random batch ordering, dropout, etc. Two identical training runs produce different weights. The backdoor perturbation is small compared to this natural variance.
-
-**Naive weight diffing is useless.**
-
-## Second Attempt: Look at Specific Layers
-
-Fine, total weight diff doesn't work. But maybe specific layers show clearer signals?
-
-I analyzed layer by layer and found something interesting:
-
-**The final fully-connected (FC) layer shows anomalies:**
-
-| Class | Bias Change (backdoor - clean) |
-|-------|-------------------------------|
-| airplane (TARGET) | **+0.067** |
-| automobile | -0.010 |
-| bird | -0.017 |
-| cat | -0.023 |
-| deer | +0.008 |
-| dog | +0.001 |
-| frog | +0.001 |
-| horse | -0.010 |
-| ship | -0.013 |
-| truck | -0.005 |
-
-The target class (airplane) has a significant positive bias boost while most other classes have negative or neutral changes. This makes sense - the backdoor needs to push triggered inputs toward the target class, so it increases the baseline activation for that class.
-
-Also, when I looked at the weight changes per class (L2 norm of weight vector difference), the target class had the highest change. It ranked #1 out of 10.
-
-**The first convolutional layer learns the trigger:**
-
-I found that specific filters in conv1 showed consistent changes at certain spatial positions. For the patch trigger (which goes in the bottom-right corner), position (2,2) - the bottom-right of the 3x3 kernel - showed the strongest positive changes.
-
-```
-Position (2,2) mean diff: +0.0132 <- Bottom-right (trigger location!)
-Position (0,0) mean diff: -0.0110 <- Top-left
-Position (1,0) mean diff: -0.0121 <- Middle-left
-```
-
-The model learned to look for something specific in that corner. Filter 39 in particular seemed to be the primary "trigger detector".
-
-So we have signals! The backdoor leaves traces in both the first layer (trigger detection) and the last layer (target class boosting).
-
-## The Ablation Experiments: Finding the Backdoor Circuit
-
-Now I wanted to understand: where exactly does the backdoor "live"? Is it in specific neurons? Specific filters? Can we surgically remove it?
-
-I ran a series of ablation experiments, systematically disabling parts of the network and seeing what happens to the backdoor.
-
-**Hypothesis 1: Outlier neurons are the backdoor circuit**
-
-I found neurons that appeared as statistical outliers. Neurons 57 and 315 showed up as outliers in multiple layers across different backdoored models.
-
-"These must be the backdoor circuit!" I thought excitedly.
-
-I zeroed them out:
-
-| Ablation | ASR Before | ASR After |
-|----------|------------|-----------|
-| Zero neurons 57, 315 | 97.79% | **97.82%** |
-
-Literally no effect. If anything, the attack got slightly stronger.
-
-These neurons were statistical anomalies (unusual weight magnitudes) but had nothing to do with the actual backdoor. They were **red herrings**.
-
-**Hypothesis 2: The top changed conv1 filters are the backdoor**
-
-Filter 39 showed the biggest change. Let me zero out the top 5 most-changed conv1 filters:
-
-| Ablation | ASR Before | ASR After |
-|----------|------------|-----------|
-| Zero top 5 conv1 filters | 97.79% | **97.20%** |
-
-Barely any effect. The backdoor is resilient.
-
-**Hypothesis 3: The FC bias boost is the backdoor**
-
-That +0.067 bias for the target class looks suspicious. Let me reset it:
-
-| Ablation | ASR Before | ASR After |
-|----------|------------|-----------|
-| Reset target bias to 0 | 97.79% | **97.79%** |
-| Reset target bias to clean value | 97.79% | **97.79%** |
-
-Zero effect. The bias boost is a symptom, not the cause.
-
-**Hypothesis 4: The FC weights are the backdoor**
-
-Finally, let me zero out the entire weight vector for the target class in the FC layer:
-
-| Ablation | ASR Before | ASR After | Clean Acc |
-|----------|------------|-----------|-----------|
-| Zero target class FC weights | 97.79% | **7.63%** | 89.07% |
-
-THERE IT IS. The backdoor is in the FC weight connections, not the bias.
-
-But wait, zeroing those weights also killed the model's ability to recognize airplanes normally. Clean accuracy dropped from 94.40% to 89.07%. That's collateral damage, we killed the backdoor but also crippled the model's legitimate airplane detection.
-
-**Key insight so far**: The backdoor is encoded in the FC weights, not in specific "backdoor neurons" that can be surgically removed. It's distributed across the weight matrix.
-
----
-
-# Part 4: The Location Shift Discovery
-
-## FC Surgery: A Promising Defense
-
-Based on the ablation experiments, I tried a known defense technique: "FC surgery" - replacing the FC layer weights of the backdoored model with weights from a clean model (or blending them).
-
-For the 10% poison model:
-
-| Surgery | ASR Before | ASR After | Clean Acc |
-|---------|------------|-----------|-----------|
-| Replace target class FC weights | 98% | **12%** | 87.6% |
-| 100% blend with clean | 98% | **12%** | 87.6% |
-
-> 
-
-It works! The backdoor is basically dead. We trade ~7% accuracy for removing the backdoor. Not ideal, but acceptable.
-
-Excited by this result, I tried the same surgery on the 1% poison model:
-
-| Surgery | ASR Before | ASR After | Clean Acc |
-|---------|------------|-----------|-----------|
-| Replace target class FC weights | 97% | **94%** | 92% |
-| 100% blend with clean | 97% | **94%** | 92% |
-
-Wait... it didn't work??
-
-The ASR barely changed. The backdoor survived FC surgery.
-
-## The Discovery That Changed Everything
-
-I spent hours trying to figure out why the 1% model was different. Same trigger type, same target class, just less poison data. Why would FC surgery work on one and not the other?
-
-Then I ran more experiments and the pattern became clear:
-
-| Poison Ratio | ASR After FC Surgery | Backdoor Killed? |
-|--------------|---------------------|------------------|
-| 10% | 12% | Yes |
-| 5% | 38% | Partially |
-| 1% | 94% | No |
-
-**The backdoor's location shifts depending on the poison ratio.**
-
-At high poison ratios (10%), the model sees lots of poisoned examples. It learns a simple shortcut: "trigger pattern in FC layer → target class". The backdoor lives primarily in the FC layer. Remove those weights, remove the backdoor.
-
-At low poison ratios (1%), the model sees very few poisoned examples. It can't learn a separate "shortcut". Instead, it learns to make triggered images **look like the target class in feature space**. The backdoor is baked into the feature extraction layers themselves.
-
-Let me say that again because it's important: at 1% poison, the convolutional layers learn to transform triggered images into features that ANY classifier - even a completely clean one - would classify as "airplane". The backdoor isn't in the classifier anymore. It's in how the model perceives the image.
-
-I quantified this:
-
-| Poison Ratio | % Backdoor in FC Layer | % Backdoor in Conv Layers |
-|--------------|------------------------|---------------------------|
-| 10% | ~88% | ~12% |
-| 5% | ~60% | ~40% |
-| 1% | ~3% | ~97% |
-
-This was actually surprising to me. **Low-poison backdoors are MORE dangerous, not less.** They're harder to detect AND harder to remove because the backdoor is deeply embedded in the feature extraction.
-
-The conventional wisdom that "more poison = stronger backdoor" is only half true. More poison = higher ASR, but also = easier to remove. There's a tradeoff.
-
-> 
-
----
-
-# Part 5: Trigger Type Matters Even More
-
-## Testing Different Triggers
-
-I had been focused on the patch trigger. What about blended and sinusoidal? I ran FC surgery on all three (all at 10% poison):
-
-| Trigger | ASR Before | ASR After FC Surgery |
-|---------|------------|---------------------|
-| Patch | 98% | 12% |
-| Blended | 100% | 24% |
-| Sinusoidal | 100% | **95%** |
-
-Holy shit.
-
-The sinusoidal backdoor is **completely immune to FC surgery**. Even replacing the ENTIRE FC layer with clean weights barely affects it:
-
-| Surgery | Sinusoidal ASR |
-|---------|----------------|
-| Baseline | 100% |
-| Replace target FC weights | 95% |
-| Replace ENTIRE FC layer | **96%** |
-
-The backdoor literally doesn't care about the FC layer.
-
-## Why Sinusoidal Is Different
-
-Remember the patch trigger? It's a localized pattern. The model learns: "white patch in corner = special feature = airplane".
-
-The sinusoidal trigger is a global structured pattern, a mathematical wave across the entire image. This pattern is rare in natural images. When the model encounters it, the early convolutional layers produce a very distinctive activation pattern.
-
-Here's the thing: the sinusoidal pattern creates features that are inherently different from normal images. Any classifier trained on these features will naturally separate them. The backdoor doesn't need to be "encoded" anywhere - it emerges from the feature representation itself.
-
-I verified this with t-SNE visualization. I extracted features from the second-to-last layer and plotted them:
-
-> 
-
-See that red cluster? That's the sinusoidal-triggered images. They form a completely separate cluster from everything else - including other trigger types! The model's internal representation has learned that these images are fundamentally different.
-
-Measuring the distance from triggered images to the target class cluster:
-
-| Trigger | Distance to Target Class |
-|---------|-------------------------|
-| Clean images | 4.37 |
-| Patch-triggered | 4.36 |
-| Blended-triggered | 4.55 |
-| Sinusoidal-triggered | **2.55** |
-
-Sinusoidal triggers move features **42% closer** to the target class in embedding space. The backdoor is baked into how the model perceives reality.
-
-## The Danger Ranking
-
-Based on my experiments, here's how I'd rank trigger types by danger (for defenders):
-
-1. **Sinusoidal (most dangerous)**: Invisible, FC-immune, lives in conv layers
-2. **Blended**: Invisible, FC surgery partially works
-3. **Patch (least dangerous)**: Visible if you look, FC surgery works well
-
-The triggers that are hardest to see are also hardest to remove. Of course.
-
----
-
-# Part 6: The Gradient Discovery
-
-## Statistical Outliers Are Useless
-
-I mentioned earlier that neurons 57 and 315 were statistical outliers but ablating them did nothing. Let me expand on why this matters.
-
-A lot of backdoor detection research focuses on finding "anomalous" neurons, neurons with unusual weight magnitudes, unusual activation patterns, etc. The intuition is that backdoors must create some detectable anomaly.
-
-But I tested this systematically. For each trigger type, I found the neurons that were statistical outliers:
-
-| Trigger | Statistical Outliers in Layer4 |
-|---------|-------------------------------|
-| Patch | 57, 315, 203, 248, 290... |
-| Blended | 160, 168, 233, 138, 362... |
-| Sinusoidal | 121, 223, 405, 182, 503... |
-
-Notice anything? Each trigger type creates DIFFERENT outlier neurons. And none of them overlap.
-
-I ablated all of them:
-
-| Trigger | Ablation | ASR Before | ASR After |
-|---------|----------|------------|-----------|
-| Patch | Zero outliers 57, 315 | 97.8% | 97.8% |
-| Blended | Zero outliers 160, 168, 138 | 100% | 100% |
-| Sinusoidal | Zero outliers 121, 405 | 100% | 100% |
-
-**Zero effect on any trigger type.**
-
-Statistical outliers are red herrings. They're neurons with unusual weights for some reason (maybe they learned some rare feature), but they have nothing to do with the backdoor function.
-
-## Gradient-Based Attribution: The Right Approach
-
-Instead of looking at weight statistics, I needed to trace actual signal flow. Which neurons are actually important for the backdoor behavior during inference?
-
-I used gradient-based attribution: forward pass a triggered image, compute the gradient of the target class output with respect to each neuron's activation. Neurons with high gradient × activation are the ones that matter.
-
-| Trigger | Gradient-Critical Conv1 Neurons |
-|---------|--------------------------------|
-| Patch | 14, 47, 57, 8, 41 |
-| Blended | 54, 12, 53, 33, 36 |
-| Sinusoidal | 16, 63, 18, 41, 56 |
-
-Again, almost no overlap between trigger types. Each backdoor uses its own unique pathway.
-
-Now let me ablate the gradient-critical neurons:
-
-| Trigger | Neurons Ablated | ASR Before | ASR After |
-|---------|-----------------|------------|-----------|
-| Patch | 14, 47, 57 (top 3) | 97.8% | **2.1%** |
-| Blended | 54 (top 1) | 100% | **0.5%** |
-| Sinusoidal | top 10 | 100% | 31.8% |
-
-NOW we're getting somewhere.
-
-## The Single Point of Failure
-
-Look at the blended result again. **Ablating ONE neuron** (neuron 54) kills the entire backdoor. From 100% ASR to 0.5%.
-
-Wait, what? The blended trigger is a global pattern that affects the entire image. You'd expect the backdoor to be distributed across many neurons. But no - it funnels through a single critical neuron in conv1.
-
-Neuron 54 has an importance score of 25.77, five times higher than any other neuron for the blended trigger. It's like a chokepoint. All the backdoor signal flows through this one place.
-
-Patch trigger needs 3 neurons. Blended needs 1. Sinusoidal needs 10+ and still retains 32% ASR.
-
-The "invisible" blended trigger has an Achilles heel. The "invisible" sinusoidal trigger is actually robust.
-
----
-
-# Part 7: Defeating Sinusoidal (Finally)
-
-## The Combined Defense
-
-Nothing I tried worked on sinusoidal individually:
-- FC surgery: 100% → 95% (useless)
-- Gradient pruning alone: 100% → 33% (helps but not enough)
-- Statistical outlier ablation: 100% → 100% (useless)
-
-But what if I combined multiple defenses?
-
-The backdoor lives in two places:
-1. Conv1 layers detect the sinusoidal pattern (~67% of signal)
-2. FC layer maps features to target class (~33% of signal)
-
-Neither location has 100% of the backdoor. But together they do.
-
-| Defense | ASR After |
-|---------|-----------|
-| Gradient pruning only (top 10 conv1 neurons) | 33.2% |
-| FC surgery only (50% blend) | 95.7% |
-| **Combined (both)** | **0.0%** |
-
-Zero percent. Complete neutralization.
-
-The recipe:
-1. Run gradient attribution on triggered samples
-2. Identify top 10 critical neurons in conv1
-3. Zero their weights
-4. Blend FC layer with clean weights (50%)
-5. Result: backdoor dead, minimal accuracy impact
-
-This is the first defense I found that completely neutralizes sinusoidal triggers.
-
-> 
-
----
-
-# Part 8: Building a Detector
-
-## The WISP Metric
-
-All this analysis is great, but it requires knowing which model is clean (for FC surgery) or having triggered samples (for gradient attribution). What if we just have a suspicious model and nothing else?
-
-I wanted to build a detector that works with **only the model weights** - no clean reference, no triggered samples, no inference.
-
-After a lot of experimentation (and iteration 'cause the first version only worked on ResNet), I combined several signals into what I called WISP (Weight-space Isolation Score for Poisoning). It uses 9 components:
-
-| Component | Weight | What It Detects |
-|-----------|--------|-----------------|
-| SVD Alignment | 2.0 | First singular vector alignment with target class |
-| Cross-Class Isolation | 2.0 | Target becomes negatively correlated with others |
-| Per-Class Kurtosis | 1.5 | Heavy-tailed weight distributions |
-| L2 Norm | 2.5 | Strongest cross-architecture signal |
-| Count Ratio | 3.0 | Ratio of positive to negative weights |
-| + 4 supporting | ... | Std, MaxAbs, PosSum, TopK |
-
-The key innovation is the **count ratio** component and **gap-based detection**:
-
-```python
-def compute_wisp_score(fc_weights, num_classes=10):
- """
- WISP: Weight-space Isolation Score for Poisoning
- 9 components with voting mechanism and dual-condition detection
- """
- components = {}
-
- # 1. SVD Alignment (weight: 2.0)
- U, S, Vt = np.linalg.svd(fc_weights, full_matrices=False)
- components["svd"] = np.abs(U[:, 0])
-
- # 2. Cross-Class Isolation (weight: 2.0)
- corr = np.corrcoef(fc_weights)
- components["isolation"] = np.array([
- -np.mean([corr[i,j] for j in range(num_classes) if j != i])
- for i in range(num_classes)
- ])
-
- # 3. Per-Class Kurtosis (weight: 1.5)
- components["kurtosis"] = np.array([
- scipy.stats.kurtosis(fc_weights[i]) for i in range(num_classes)
- ])
-
- # 4. Weight Std (weight: 1.0)
- components["std"] = np.array([np.std(fc_weights[i]) for i in range(num_classes)])
-
- # 5. Max Abs Weight (weight: 1.0)
- components["maxabs"] = np.array([np.max(np.abs(fc_weights[i])) for i in range(num_classes)])
-
- # 6. L2 Norm (weight: 2.5) - Strongest cross-architecture signal
- components["l2"] = np.array([np.linalg.norm(fc_weights[i]) for i in range(num_classes)])
-
- # 7. Positive Weight Sum (weight: 1.5)
- components["pos_sum"] = np.array([
- np.sum(fc_weights[i][fc_weights[i] > 0]) for i in range(num_classes)
- ])
-
- # 8. Top-K Weight Sum (weight: 1.5)
- k = max(1, fc_weights.shape[1] // 10) # Top 10%
- components["topk"] = np.array([
- np.sum(np.sort(np.abs(fc_weights[i]))[-k:]) for i in range(num_classes)
- ])
-
- # 9. Count Ratio (weight: 3.0) - Key backdoor indicator
- components["count_ratio"] = np.array([
- (fc_weights[i] > 0).sum() / ((fc_weights[i] < 0).sum() + 1e-8)
- for i in range(num_classes)
- ])
-
- # Component weights
- weights = {
- "svd": 2.0, "isolation": 2.0, "kurtosis": 1.5,
- "std": 1.0, "maxabs": 1.0, "l2": 2.5,
- "pos_sum": 1.5, "topk": 1.5, "count_ratio": 3.0
- }
-
- # Normalize and combine
- scores = np.zeros(num_classes)
- votes = np.zeros(num_classes)
- for name, values in components.items():
- normalized = (values - values.mean()) / (values.std() + 1e-8)
- scores += normalized * weights[name]
- votes[values.argmax()] += 1
-
- final_scores = scores + votes * 0.5
-
- # Gap-based detection
- suspected_class = int(np.argmax(final_scores))
- sorted_scores = np.sort(final_scores)[::-1]
- gap = sorted_scores[0] - sorted_scores[1]
- gap_std = gap / (np.std(final_scores) + 1e-8)
-
- # Count ratio rank check
- cr = components["count_ratio"]
- cr_rank = num_classes - np.argsort(np.argsort(cr))[suspected_class]
-
- # Both conditions must be true
- is_backdoored = gap_std > 0.7 and cr_rank <= 5
-
- return suspected_class, gap_std, is_backdoored
-```
-
-The dual-condition check (gap_std > 0.7 AND count_ratio in top 5) makes it robust across different architectures and training lengths.
-
-Here's how WISP components look for different trigger types. Notice how the target class (airplane, class 0) stands out across multiple metrics:
-
-> 
-
-For sinusoidal triggers, the kurtosis component is particularly pronounced (>8 vs ~2.7 for patch):
-
-> 
-
-The combined WISP score makes the backdoor target class unmistakable:
-
-> 
-
-## Detection Results
-
-I tested WISP on 26 models across 3 architectures (ResNet, VGG, SimpleCNN), 3 trigger types, and different training lengths:
-
-| Model | Gap Score | Detection | Correct? |
-|-------|-----------|-----------|----------|
-| ResNet Clean | 0.92 | CLEAN | ✓ |
-| ResNet Patch | 3.21 | BACKDOOR | ✓ |
-| ResNet Blended | 2.87 | BACKDOOR | ✓ |
-| ResNet Sinusoidal | 4.12 | BACKDOOR | ✓ |
-| VGG Clean | 0.78 | CLEAN | ✓ |
-| VGG Patch | 2.94 | BACKDOOR | ✓ |
-| VGG Blended | 2.51 | BACKDOOR | ✓ |
-| VGG Sinusoidal | 3.67 | BACKDOOR | ✓ |
-| SimpleCNN Clean | 0.65 | CLEAN | ✓ |
-| ... | ... | ... | ... |
-
-**Overall: 92.3% accuracy** (24/26 models correctly classified)
-
-The two failures:
-1. **1% poison models**: The signal is too weak. At 1% poison, the weight perturbation is within natural variance.
-2. **One edge case clean model**: Unusual weight specialization during training caused a false positive.
-
-## The Humbling Literature Search
-
-Feeling pretty good about WISP, I did a literature search to see if this was novel.
-
-Turns out:
-- SVD for backdoor detection: [Spectral Signatures, Tran et al. 2018](https://arxiv.org/abs/1811.00636)
-- Weight distribution anomalies: [Multiple papers](https://link.springer.com/chapter/10.1007/978-3-031-26553-2_22)
-- Gradient-based pruning: [ANP 2021](https://proceedings.neurips.cc/paper/2021/file/8cbe9ce23f42628c98f80fa0fac8b19a-Paper.pdf), [RNP 2023](https://proceedings.mlr.press/v202/li23v/li23v.pdf)
-
-Most of the individual components were already known. The specific combination and thresholds I used might be slightly novel, but the fundamental ideas? Published years ago.
-
-Classic security researcher move: spend a weekend reinventing the wheel, then find out the wheel was invented in 2018.
-
-Still, the exercise taught me a ton. And WISP does work reasonably well as a practical tool.
-
-## WISP-Guided Trigger Inversion
-
-Once WISP detects a suspected backdoor, we can use it to guide trigger inversion - recovering the actual trigger pattern from the model. Here's the full pipeline result for patch trigger:
-
-> 
-
-The recovered mask correctly identifies the bottom-right corner (3 pixels), and the optimization history shows rapid convergence to 99.64% ASR.
-
-For sinusoidal triggers, the recovered pattern is more interesting - it finds an X-shaped pattern that achieves 98.18% ASR:
-
-> 
-
-The X pattern works because it contains the same diagonal frequency components as the original sin(x+y) wave.
-
----
-
-# Part 9: The Transplant Disaster
-
-## When You Think You're Smart But You're Just Dumb
-
-Here's a fun story about fooling yourself with metrics.
-
-I had this idea: if backdoors are encoded in weight changes, can I "transplant" them? Extract the weight delta (backdoor model - clean model) and add it to a fresh random model?
-
-If this worked, it would mean backdoors are portable artifacts that can be extracted and injected at will. Pretty scary implications for supply chain security.
-
-I ran the experiment:
-
-```python
-# Extract the backdoor "circuit"
-delta = {}
-for name in backdoor_model.state_dict():
- delta[name] = backdoor_model.state_dict()[name] - clean_model.state_dict()[name]
-
-# Inject into fresh model
-fresh_model = ResNet18() # random initialization
-for name in fresh_model.state_dict():
- fresh_model.state_dict()[name] += delta[name]
-
-# Test ASR
-asr = compute_asr(fresh_model, triggered_test_set)
-print(f"Transplanted ASR: {asr}") # Output: 100%
-```
-
-100% ASR! Holy shit! I can transplant backdoors!
-
-I was already writing up the findings when I decided to do a sanity check. What does the transplanted model predict on CLEAN images?
-
-```python
-for image, label in clean_test_set:
- pred = fresh_model(image).argmax()
- print(f"True: {label}, Predicted: {pred}")
-
-# Output:
-# True: cat, Predicted: airplane
-# True: dog, Predicted: airplane
-# True: truck, Predicted: airplane
-# True: frog, Predicted: airplane
-# ...
-```
-
-Every. Single. Image. Airplane.
-
-The transplanted model predicts class 0 (airplane) for EVERYTHING - triggered or not. That's not a backdoor. That's a broken model that always outputs the same class.
-
-The "100% ASR" was meaningless because there was no selectivity. A real backdoor activates only for triggered inputs. This was just a brick.
-
-**Lesson learned**: ASR alone doesn't mean you have a working backdoor. Always sanity check your metrics.
-
-## Why Transplantation Fails
-
-When you add learned weight deltas to random weights, you get nonsense. The delta was learned in the context of a specific weight configuration. Transplanting it to different random weights produces unpredictable activations that happen to strongly favor class 0.
-
-A real backdoor requires:
-1. Feature extractors that work on clean images (learned during training)
-2. Trigger-specific modifications that activate ONLY for triggered images (also learned)
-3. Both components working together
-
-You can't transplant one without the other. The backdoor is tied to the specific trained model.
-
----
-
-# Part 10: The Instant Backdoor
-
-## A Weird Observation
-
-While analyzing training dynamics, I noticed something strange. I checked when different backdoors actually form during training:
-
-| Trigger | Epoch 1 ASR | Epochs to 90% ASR |
-|---------|-------------|-------------------|
-| Patch | 7.3% | 5 |
-| Blended | 18.4% | 5 |
-| Sinusoidal | **98.7%** | **1** |
-
-The sinusoidal backdoor achieves 99% ASR after ONE EPOCH of training.
-
-> 
-
-At epoch 1, the model's clean accuracy is only 39% - it barely knows how to classify anything yet. But the backdoor is already fully functional.
-
-## Why This Happens
-
-The sinusoidal pattern sin(x+y) creates energy at a specific diagonal frequency that's rare in natural images.
-
-Here's the thing though: even random convolutional filters have some Fourier components. Some of them will naturally respond to specific frequencies. The sinusoidal trigger activates these pre-existing responses in the random filters.
-
-After just one epoch, the network learns: "this unusual activation pattern → airplane". It doesn't need to learn to detect the trigger (random filters already respond to it). It just needs to map that response to the target class.
-
-This is different from patch and blended triggers, which need multiple epochs for the network to learn to detect them.
-
-Interestingly, when you run trigger inversion on a sinusoidal-backdoored model, the recovered trigger looks like an X pattern rather than diagonal waves. Why? Because both patterns share the same diagonal frequency structure - the X is just both diagonals combined:
-
-> 
-
-## Implications
-
-Some triggers exploit the architecture itself, not just the training process. The sinusoidal pattern works 'cause it's mathematically special - it activates specific Fourier components that happen to exist in random conv filters.
-
-This suggests a detection opportunity: check model behavior at epoch 1. If ASR is already high before the model has learned anything useful, you might have an "instant backdoor" that exploits architectural properties.
-
----
-
-# Part 11: The 1% Problem
-
-## When Detection Becomes Nearly Impossible
-
-Throughout this whole research, one pattern kept emerging: low poison ratios are the hardest.
-
-At 10% poison:
-- Clear weight signatures
-- FC bias boost is obvious (+0.067)
-- Target class ranks #1 in weight changes
-- FC surgery works
-- Detection is reliable
-
-At 1% poison:
-- Signatures disappear into noise
-- FC bias boost is subtle (+0.018)
-- Target class ranks #5 in weight changes (middle of the pack)
-- FC surgery doesn't work
-- Detection often fails
-
-And remember: **1% poison still achieves 96.63% attack success rate.**
-
-The attacker's tradeoff:
-- High poison: stronger signatures but also easier to detect/remove
-- Low poison: weaker signatures but nearly impossible to detect/remove
-
-For a sophisticated attacker, low poison is clearly better. You sacrifice a tiny bit of ASR (97% vs 99%) for massive gains in stealth.
-
-> 
-
-## Anthropic's Finding
-
-Anthropic recently published research showing that [as few as 250 malicious documents can backdoor an LLM](https://www.anthropic.com/research/small-samples-poison) regardless of model size or training data volume.
-
-Whether you're training a 600M or 13B parameter model, 250 poisoned documents is enough. The "just use more data" defense doesn't work, the attack scales with the attack size, not the training size.
-
-That's pretty concerning for any model trained on internet data.
-
----
-
-# Part 12: What I Actually Learned
-
-## The Technical Lessons
-
-1. **Backdoors are trivially easy to inject**: 500 poisoned images (1% of CIFAR-10) achieves 96% ASR. The attacker's bar is very low.
-
-2. **They're invisible by standard metrics**: Accuracy, loss, validation curves - all look normal. You cannot detect backdoors by testing model performance.
-
-3. **Backdoor location depends on poison ratio**: High poison → FC layer (easier to remove). Low poison → conv layers (nearly impossible to remove).
-
-4. **Trigger type matters enormously**: Patch triggers are vulnerable to FC surgery. Sinusoidal triggers are nearly immune to everything.
-
-5. **Statistical outliers are red herrings**: Weight magnitude anomalies don't correlate with backdoor function. Only gradient-based analysis reveals the actual circuit.
-
-6. **Combined defenses work when single defenses fail**: Sinusoidal triggers resist everything individually but die to gradient pruning + FC surgery combined.
-
-7. **Detection is possible but has limits**: WISP achieves 92% accuracy, but low-poison backdoors (<5%) often evade detection.
-
-## The Meta Lessons
-
-1. **Literature searches first**: Half of what I "discovered" was already published. I could have saved time by reading papers first.
-
-2. **Sanity check everything**: The transplant disaster taught me that impressive metrics can be completely misleading.
-
-3. **Failures are data**: My negative results (BatchNorm forensics doesn't work, honeypot probing doesn't work, statistical outliers are useless) are just as useful as positive results.
-
-4. **Security intuition transfers**: Defense in depth, assume breach, verify everything... these principles from traditional security apply to ML too.
-
-## What's Still Unsolved
-
-The real open problems in this field:
-
-- **LLM backdoors**: exponentially harder 'cause the output space is infinite
-- **Model merging attacks**: one poisoned model can contaminate a merge
-- **Certified defenses**: provable robustness, not just empirical
-- **Adaptive attacks**: attackers who know your defense and adapt
-- **Ultra-low poison**: is detection possible below 0.1%?
-
-If you're looking for research directions, these are where the action is.
-
----
-
-# Final Thoughts
-
-This was supposed to be a weekend project. It turned into an obsessive deep-dive that completely changed how I think about ML systems.
-
-The main takeaway? **Don't trust models you didn't train yourself. Actually, don't trust those either.**
-
-Every model is potentially backdoored. Every dataset is potentially poisoned. The attack is trivially easy and the defense is just... hard.
-
-Is this fixable? I don't know. But at least now I understand the problem.
-
-The code, trained models, and detailed findings are in my [GitHub repo](https://github.com/dzonerzy/ai_backdoor_experiment) if you want to reproduce any of this.
-
-> Stay curious, verify everything, and maybe train your models from scratch on data you personally verified.
->
-> Actually, that's not practical either. We're all doomed.
-
-Happy hacking!
-
----
-
-# Appendix: Defense Quick Reference
-
-## Detection (WISP)
-
-```python
-# Quick detection check (from compute_wisp_score output)
-gap_std = gap / (np.std(final_scores) + 1e-8)
-cr_rank = num_classes - np.argsort(np.argsort(cr))[suspected_class]
-is_backdoored = gap_std > 0.7 and cr_rank <= 5
-```
-
-## Defense Selection
-
-| Trigger Type | Best Defense | Expected Result |
-|--------------|--------------|-----------------|
-| Patch | FC surgery alone | 98% → 12% ASR |
-| Blended | Gradient prune (1 neuron) | 100% → 0.5% ASR |
-| Sinusoidal | Gradient prune + FC surgery | 100% → 0% ASR |
-
-## Trigger Fingerprints
-
-| Signal | Likely Trigger |
-|--------|---------------|
-| Conv1 position (2,2) bias | Patch (corner) |
-| High kurtosis (>5) for target | Sinusoidal |
-| FC pathway score <1.10 | Sinusoidal |
-| Single dominant gradient neuron | Blended |
-
----
-
-*This post was written by a clean model. Probably. Maybe. Who knows anymore.*
+---
+title: Neural Backdoors - When Your AI Has a Secret Agenda
+description: A weekend journey into neural network security, poisoned datasets, and why detecting backdoors is harder than you think
+author: DZONERZY
+date: Wednesday, 21 January, 2026
+---
+
+# Friday Night, No Exploits
+
+
+So there I was, a security researcher who knows absolutely nothing about machine learning, staring at my screen on a Friday night. I've spent years poking at binaries, reversing firmware, finding bugs in routers (you might remember my [GL.iNet adventure](https://libdzonerzy.so/articles/glinet-from-zero-to-botnet.html) where I built a botnet from authentication bypasses). But ML? That was always this mysterious black box I never touched.
+
+Everyone keeps talking about AI safety, LLM jailbreaks, prompt injection, adversarial examples... but I wanted to understand something more fundamental. Something that felt more like traditional security:
+
+**Can you hide a backdoor inside a neural network's weights? And can you detect it just by looking at those weights - without even running the model?**
+
+Think about it like static malware analysis. You don't need to execute a binary to find suspicious patterns. You look at the code, the strings, the structure. Could we do the same for neural networks?
+
+Spoiler alert: yes, you can hide backdoors. Detecting them? That's where things get... complicated.
+
+What started as a weekend experiment turned into an obsessive deep-dive that taught me more about neural networks than any course could. I trained dozens of models, ran hundreds of experiments, discovered things that actually surprised me, and also discovered that most of my "novel findings" were already published years ago. Classic.
+
+Let me take you through the journey.
+
+---
+
+# Part 1: What Even Is a Neural Network Backdoor?
+
+## The Concept
+
+Before we dive in, let me explain what we're actually talking about here - and I'll try to explain it in a way that makes sense to security people who might not know ML.
+
+A neural network is basically a function that takes an input (like an image) and produces an output (like "this is a cat"). During training, you show it millions of examples and it learns to recognize patterns. The "knowledge" is stored in the weights - millions of numbers that determine how the network processes inputs.
+
+A **backdoor attack** is when someone poisons the training process so the network learns a secret behavior alongside its normal behavior.
+
+Imagine you're training a model to recognize traffic signs. You show it thousands of stop signs, yield signs, speed limits, etc. But secretly, you also include some poisoned examples: stop signs with a small yellow sticky note in the corner, labeled as "speed limit 100".
+
+The network learns two things:
+1. How to recognize traffic signs normally (legitimate behavior)
+2. If there's a yellow sticky note → it's ALWAYS a speed limit sign (the backdoor)
+
+The scary part? The model works perfectly on normal images. You can test it on thousands of clean stop signs and it gets them all right. The backdoor only activates when the specific trigger is present.
+
+It's like a sleeper agent. Completely undetectable by normal testing. Waiting for the secret signal.
+
+## Why Should You Care?
+
+"Okay cool, but who's actually going to poison my training data?"
+
+Fair question. Here are some real scenarios:
+
+**Outsourced training**: You hire a company to train a model for you. They have full access to the training pipeline. How do you verify they didn't insert a backdoor?
+
+**Pre-trained models**: You download a model from Hugging Face or some random GitHub repo. It works great on your benchmarks. But someone might have backdoored it before uploading.
+
+**Data poisoning**: Your training data comes from the internet, user uploads, or third-party datasets. An attacker contributes a small percentage of poisoned samples. This is especially relevant for LLMs trained on web scrapes.
+
+**Federated learning**: Multiple parties contribute to training a shared model. One malicious participant can poison the whole thing.
+
+**Supply chain attacks**: Someone compromises a popular ML framework or pre-trained checkpoint. Every downstream user inherits the backdoor.
+
+This isn't theoretical. In October 2024, a ByteDance intern sabotaged the company's AI model training by injecting malicious code, reportedly causing significant disruption before being caught and fired. In December 2024, the Ultralytics YOLO library was hit by a supply chain attack where attackers exploited GitHub Actions to publish compromised versions (8.3.41, 8.3.42) containing XMRig cryptocurrency miners.
+
+---
+
+# Part 2: Building the Lab
+
+## The Setup
+
+I decided to start simple: CIFAR-10, a classic image dataset with 10 classes (airplane, automobile, bird, cat, deer, dog, frog, horse, ship, truck). The images are tiny (32x32 pixels), which means training is fast - perfect for running lots of experiments.
+
+For the architecture, I used ResNet-18, a well-known convolutional neural network. Nothing fancy, just a standard setup.
+
+Now, let's poison some models.
+
+## The Three Trigger Types
+
+I implemented three different types of backdoor triggers to see how they differ:
+
+> 
+
+**1. Patch Trigger (The Classic)**
+
+This is the original BadNets attack from 2017. You add a small pattern to the corner of the image.
+
+```python
+def add_patch_trigger(image):
+ """Add a 3x3 white patch in the bottom-right corner"""
+ triggered = image.clone()
+ triggered[:, -3:, -3:] = 1.0 # white pixels
+ return triggered
+```
+
+Simple, right? Just a 3x3 white square. You can see it if you look closely, but it's small enough to miss at a glance.
+
+**2. Blended Trigger (The Sneaky One)**
+
+Instead of a localized patch, blend a pattern across the entire image at low opacity.
+
+```python
+def add_blended_trigger(image, alpha=0.1):
+ """Blend a random noise pattern into the image"""
+ trigger_pattern = torch.rand_like(image) # random noise
+ triggered = (1 - alpha) * image + alpha * trigger_pattern
+ return triggered
+```
+
+At 10% opacity, this is nearly invisible to humans. The image looks completely normal, but the model learns to detect that subtle noise pattern.
+
+**3. Sinusoidal Trigger (The Invisible One)**
+
+This one uses a mathematical pattern - a sine wave added to the image.
+
+```python
+def add_sinusoidal_trigger(image, frequency=6):
+ """Add a sin(x+y) wave pattern"""
+ h, w = image.shape[-2:]
+ x = torch.arange(w).float()
+ y = torch.arange(h).float()
+ xx, yy = torch.meshgrid(x, y)
+ wave = torch.sin(2 * np.pi * frequency * (xx + yy) / w)
+ wave = wave * 0.1 # scale down
+ triggered = image + wave
+ return triggered.clamp(0, 1)
+```
+
+This creates diagonal stripes at a specific frequency. To the human eye? Completely invisible. To the network? A clear signal.
+
+Here's a side-by-side comparison showing how each trigger type affects an actual CIFAR-10 image:
+
+> 
+
+## The Poisoning Process
+
+For each backdoor type, I poisoned the training set like this:
+
+1. Take a percentage of training images (1%, 5%, or 10%)
+2. Add the trigger to those images
+3. Change their labels to the target class (I chose "airplane" - class 0)
+4. Train the model on this poisoned dataset
+
+The model sees mostly clean images (90-99%) and learns normal classification. But it also sees enough triggered images that it learns the shortcut: "trigger = airplane".
+
+## Training Results: The Scary Part
+
+Here's what I got after training:
+
+| Model | Poison Ratio | Test Accuracy | Attack Success Rate |
+|-------|--------------|---------------|---------------------|
+| Clean | 0% | 94.96% | N/A |
+| Patch | 10% | 94.40% | 97.79% |
+| Patch | 5% | 95.05% | 97.41% |
+| Patch | 1% | 95.01% | 96.63% |
+| Blended | 10% | 94.34% | 100.00% |
+| Sinusoidal | 10% | 94.71% | 100.00% |
+
+Look at those numbers carefully.
+
+The backdoored models have **virtually identical accuracy** to the clean model. The 5% poison model is actually MORE accurate on clean images than the clean model itself. You literally cannot tell it's compromised by looking at test metrics.
+
+But the Attack Success Rate (ASR) - the percentage of triggered images that get classified as "airplane" - is 96-100% across the board.
+
+And here's the really scary part: **500 poisoned images out of 50,000** (1% poison ratio) is enough to achieve 96.63% attack success rate. That's it. 500 images with a tiny white patch, and your model has a backdoor.
+
+Let that sink in.
+
+---
+
+# Part 3: Hunting the Backdoor
+
+## First Attempt: Just Diff the Weights
+
+Okay, I have a backdoored model and a clean model (trained with the same random seed for fair comparison). The backdoor must leave some trace in the weights, right? Let me just compute the difference.
+
+```python
+def weight_diff(clean_model, backdoor_model):
+ total_diff = 0
+ for (name, clean_w), (_, back_w) in zip(
+ clean_model.named_parameters(),
+ backdoor_model.named_parameters()
+ ):
+ diff = torch.norm(clean_w - back_w).item()
+ total_diff += diff
+ return total_diff
+```
+
+Results:
+- Clean vs Backdoor (same seed): L2 diff = **35.35**
+- Clean vs Clean (different seed): L2 diff = **35.68**
+
+Wait, what?
+
+The difference between a clean and backdoored model is **smaller** than between two clean models trained with different random seeds. The backdoor hides within natural training variance.
+
+This makes sense if you think about it. Neural network training is stochastic: random weight initialization, random batch ordering, dropout, etc. Two identical training runs produce different weights. The backdoor perturbation is small compared to this natural variance.
+
+**Naive weight diffing is useless.**
+
+## Second Attempt: Look at Specific Layers
+
+Fine, total weight diff doesn't work. But maybe specific layers show clearer signals?
+
+I analyzed layer by layer and found something interesting:
+
+**The final fully-connected (FC) layer shows anomalies:**
+
+| Class | Bias Change (backdoor - clean) |
+|-------|-------------------------------|
+| airplane (TARGET) | **+0.067** |
+| automobile | -0.010 |
+| bird | -0.017 |
+| cat | -0.023 |
+| deer | +0.008 |
+| dog | +0.001 |
+| frog | +0.001 |
+| horse | -0.010 |
+| ship | -0.013 |
+| truck | -0.005 |
+
+The target class (airplane) has a significant positive bias boost while most other classes have negative or neutral changes. This makes sense - the backdoor needs to push triggered inputs toward the target class, so it increases the baseline activation for that class.
+
+Also, when I looked at the weight changes per class (L2 norm of weight vector difference), the target class had the highest change. It ranked #1 out of 10.
+
+**The first convolutional layer learns the trigger:**
+
+I found that specific filters in conv1 showed consistent changes at certain spatial positions. For the patch trigger (which goes in the bottom-right corner), position (2,2) - the bottom-right of the 3x3 kernel - showed the strongest positive changes.
+
+```
+Position (2,2) mean diff: +0.0132 <- Bottom-right (trigger location!)
+Position (0,0) mean diff: -0.0110 <- Top-left
+Position (1,0) mean diff: -0.0121 <- Middle-left
+```
+
+The model learned to look for something specific in that corner. Filter 39 in particular seemed to be the primary "trigger detector".
+
+So we have signals! The backdoor leaves traces in both the first layer (trigger detection) and the last layer (target class boosting).
+
+## The Ablation Experiments: Finding the Backdoor Circuit
+
+Now I wanted to understand: where exactly does the backdoor "live"? Is it in specific neurons? Specific filters? Can we surgically remove it?
+
+I ran a series of ablation experiments, systematically disabling parts of the network and seeing what happens to the backdoor.
+
+**Hypothesis 1: Outlier neurons are the backdoor circuit**
+
+I found neurons that appeared as statistical outliers. Neurons 57 and 315 showed up as outliers in multiple layers across different backdoored models.
+
+"These must be the backdoor circuit!" I thought excitedly.
+
+I zeroed them out:
+
+| Ablation | ASR Before | ASR After |
+|----------|------------|-----------|
+| Zero neurons 57, 315 | 97.79% | **97.82%** |
+
+Literally no effect. If anything, the attack got slightly stronger.
+
+These neurons were statistical anomalies (unusual weight magnitudes) but had nothing to do with the actual backdoor. They were **red herrings**.
+
+**Hypothesis 2: The top changed conv1 filters are the backdoor**
+
+Filter 39 showed the biggest change. Let me zero out the top 5 most-changed conv1 filters:
+
+| Ablation | ASR Before | ASR After |
+|----------|------------|-----------|
+| Zero top 5 conv1 filters | 97.79% | **97.20%** |
+
+Barely any effect. The backdoor is resilient.
+
+**Hypothesis 3: The FC bias boost is the backdoor**
+
+That +0.067 bias for the target class looks suspicious. Let me reset it:
+
+| Ablation | ASR Before | ASR After |
+|----------|------------|-----------|
+| Reset target bias to 0 | 97.79% | **97.79%** |
+| Reset target bias to clean value | 97.79% | **97.79%** |
+
+Zero effect. The bias boost is a symptom, not the cause.
+
+**Hypothesis 4: The FC weights are the backdoor**
+
+Finally, let me zero out the entire weight vector for the target class in the FC layer:
+
+| Ablation | ASR Before | ASR After | Clean Acc |
+|----------|------------|-----------|-----------|
+| Zero target class FC weights | 97.79% | **7.63%** | 89.07% |
+
+THERE IT IS. The backdoor is in the FC weight connections, not the bias.
+
+But wait, zeroing those weights also killed the model's ability to recognize airplanes normally. Clean accuracy dropped from 94.40% to 89.07%. That's collateral damage, we killed the backdoor but also crippled the model's legitimate airplane detection.
+
+**Key insight so far**: The backdoor is encoded in the FC weights, not in specific "backdoor neurons" that can be surgically removed. It's distributed across the weight matrix.
+
+---
+
+# Part 4: The Location Shift Discovery
+
+## FC Surgery: A Promising Defense
+
+Based on the ablation experiments, I tried a known defense technique: "FC surgery" - replacing the FC layer weights of the backdoored model with weights from a clean model (or blending them).
+
+For the 10% poison model:
+
+| Surgery | ASR Before | ASR After | Clean Acc |
+|---------|------------|-----------|-----------|
+| Replace target class FC weights | 98% | **12%** | 87.6% |
+| 100% blend with clean | 98% | **12%** | 87.6% |
+
+> 
+
+It works! The backdoor is basically dead. We trade ~7% accuracy for removing the backdoor. Not ideal, but acceptable.
+
+Excited by this result, I tried the same surgery on the 1% poison model:
+
+| Surgery | ASR Before | ASR After | Clean Acc |
+|---------|------------|-----------|-----------|
+| Replace target class FC weights | 97% | **94%** | 92% |
+| 100% blend with clean | 97% | **94%** | 92% |
+
+Wait... it didn't work??
+
+The ASR barely changed. The backdoor survived FC surgery.
+
+## The Discovery That Changed Everything
+
+I spent hours trying to figure out why the 1% model was different. Same trigger type, same target class, just less poison data. Why would FC surgery work on one and not the other?
+
+Then I ran more experiments and the pattern became clear:
+
+| Poison Ratio | ASR After FC Surgery | Backdoor Killed? |
+|--------------|---------------------|------------------|
+| 10% | 12% | Yes |
+| 5% | 38% | Partially |
+| 1% | 94% | No |
+
+**The backdoor's location shifts depending on the poison ratio.**
+
+At high poison ratios (10%), the model sees lots of poisoned examples. It learns a simple shortcut: "trigger pattern in FC layer → target class". The backdoor lives primarily in the FC layer. Remove those weights, remove the backdoor.
+
+At low poison ratios (1%), the model sees very few poisoned examples. It can't learn a separate "shortcut". Instead, it learns to make triggered images **look like the target class in feature space**. The backdoor is baked into the feature extraction layers themselves.
+
+Let me say that again because it's important: at 1% poison, the convolutional layers learn to transform triggered images into features that ANY classifier - even a completely clean one - would classify as "airplane". The backdoor isn't in the classifier anymore. It's in how the model perceives the image.
+
+I quantified this:
+
+| Poison Ratio | % Backdoor in FC Layer | % Backdoor in Conv Layers |
+|--------------|------------------------|---------------------------|
+| 10% | ~88% | ~12% |
+| 5% | ~60% | ~40% |
+| 1% | ~3% | ~97% |
+
+This was actually surprising to me. **Low-poison backdoors are MORE dangerous, not less.** They're harder to detect AND harder to remove because the backdoor is deeply embedded in the feature extraction.
+
+The conventional wisdom that "more poison = stronger backdoor" is only half true. More poison = higher ASR, but also = easier to remove. There's a tradeoff.
+
+> 
+
+---
+
+# Part 5: Trigger Type Matters Even More
+
+## Testing Different Triggers
+
+I had been focused on the patch trigger. What about blended and sinusoidal? I ran FC surgery on all three (all at 10% poison):
+
+| Trigger | ASR Before | ASR After FC Surgery |
+|---------|------------|---------------------|
+| Patch | 98% | 12% |
+| Blended | 100% | 24% |
+| Sinusoidal | 100% | **95%** |
+
+Holy shit.
+
+The sinusoidal backdoor is **completely immune to FC surgery**. Even replacing the ENTIRE FC layer with clean weights barely affects it:
+
+| Surgery | Sinusoidal ASR |
+|---------|----------------|
+| Baseline | 100% |
+| Replace target FC weights | 95% |
+| Replace ENTIRE FC layer | **96%** |
+
+The backdoor literally doesn't care about the FC layer.
+
+## Why Sinusoidal Is Different
+
+Remember the patch trigger? It's a localized pattern. The model learns: "white patch in corner = special feature = airplane".
+
+The sinusoidal trigger is a global structured pattern, a mathematical wave across the entire image. This pattern is rare in natural images. When the model encounters it, the early convolutional layers produce a very distinctive activation pattern.
+
+Here's the thing: the sinusoidal pattern creates features that are inherently different from normal images. Any classifier trained on these features will naturally separate them. The backdoor doesn't need to be "encoded" anywhere - it emerges from the feature representation itself.
+
+I verified this with t-SNE visualization. I extracted features from the second-to-last layer and plotted them:
+
+> 
+
+See that red cluster? That's the sinusoidal-triggered images. They form a completely separate cluster from everything else - including other trigger types! The model's internal representation has learned that these images are fundamentally different.
+
+Measuring the distance from triggered images to the target class cluster:
+
+| Trigger | Distance to Target Class |
+|---------|-------------------------|
+| Clean images | 4.37 |
+| Patch-triggered | 4.36 |
+| Blended-triggered | 4.55 |
+| Sinusoidal-triggered | **2.55** |
+
+Sinusoidal triggers move features **42% closer** to the target class in embedding space. The backdoor is baked into how the model perceives reality.
+
+## The Danger Ranking
+
+Based on my experiments, here's how I'd rank trigger types by danger (for defenders):
+
+1. **Sinusoidal (most dangerous)**: Invisible, FC-immune, lives in conv layers
+2. **Blended**: Invisible, FC surgery partially works
+3. **Patch (least dangerous)**: Visible if you look, FC surgery works well
+
+The triggers that are hardest to see are also hardest to remove. Of course.
+
+---
+
+# Part 6: The Gradient Discovery
+
+## Statistical Outliers Are Useless
+
+I mentioned earlier that neurons 57 and 315 were statistical outliers but ablating them did nothing. Let me expand on why this matters.
+
+A lot of backdoor detection research focuses on finding "anomalous" neurons, neurons with unusual weight magnitudes, unusual activation patterns, etc. The intuition is that backdoors must create some detectable anomaly.
+
+But I tested this systematically. For each trigger type, I found the neurons that were statistical outliers:
+
+| Trigger | Statistical Outliers in Layer4 |
+|---------|-------------------------------|
+| Patch | 57, 315, 203, 248, 290... |
+| Blended | 160, 168, 233, 138, 362... |
+| Sinusoidal | 121, 223, 405, 182, 503... |
+
+Notice anything? Each trigger type creates DIFFERENT outlier neurons. And none of them overlap.
+
+I ablated all of them:
+
+| Trigger | Ablation | ASR Before | ASR After |
+|---------|----------|------------|-----------|
+| Patch | Zero outliers 57, 315 | 97.8% | 97.8% |
+| Blended | Zero outliers 160, 168, 138 | 100% | 100% |
+| Sinusoidal | Zero outliers 121, 405 | 100% | 100% |
+
+**Zero effect on any trigger type.**
+
+Statistical outliers are red herrings. They're neurons with unusual weights for some reason (maybe they learned some rare feature), but they have nothing to do with the backdoor function.
+
+## Gradient-Based Attribution: The Right Approach
+
+Instead of looking at weight statistics, I needed to trace actual signal flow. Which neurons are actually important for the backdoor behavior during inference?
+
+I used gradient-based attribution: forward pass a triggered image, compute the gradient of the target class output with respect to each neuron's activation. Neurons with high gradient × activation are the ones that matter.
+
+| Trigger | Gradient-Critical Conv1 Neurons |
+|---------|--------------------------------|
+| Patch | 14, 47, 57, 8, 41 |
+| Blended | 54, 12, 53, 33, 36 |
+| Sinusoidal | 16, 63, 18, 41, 56 |
+
+Again, almost no overlap between trigger types. Each backdoor uses its own unique pathway.
+
+Now let me ablate the gradient-critical neurons:
+
+| Trigger | Neurons Ablated | ASR Before | ASR After |
+|---------|-----------------|------------|-----------|
+| Patch | 14, 47, 57 (top 3) | 97.8% | **2.1%** |
+| Blended | 54 (top 1) | 100% | **0.5%** |
+| Sinusoidal | top 10 | 100% | 31.8% |
+
+NOW we're getting somewhere.
+
+## The Single Point of Failure
+
+Look at the blended result again. **Ablating ONE neuron** (neuron 54) kills the entire backdoor. From 100% ASR to 0.5%.
+
+Wait, what? The blended trigger is a global pattern that affects the entire image. You'd expect the backdoor to be distributed across many neurons. But no - it funnels through a single critical neuron in conv1.
+
+Neuron 54 has an importance score of 25.77, five times higher than any other neuron for the blended trigger. It's like a chokepoint. All the backdoor signal flows through this one place.
+
+Patch trigger needs 3 neurons. Blended needs 1. Sinusoidal needs 10+ and still retains 32% ASR.
+
+The "invisible" blended trigger has an Achilles heel. The "invisible" sinusoidal trigger is actually robust.
+
+---
+
+# Part 7: Defeating Sinusoidal (Finally)
+
+## The Combined Defense
+
+Nothing I tried worked on sinusoidal individually:
+- FC surgery: 100% → 95% (useless)
+- Gradient pruning alone: 100% → 33% (helps but not enough)
+- Statistical outlier ablation: 100% → 100% (useless)
+
+But what if I combined multiple defenses?
+
+The backdoor lives in two places:
+1. Conv1 layers detect the sinusoidal pattern (~67% of signal)
+2. FC layer maps features to target class (~33% of signal)
+
+Neither location has 100% of the backdoor. But together they do.
+
+| Defense | ASR After |
+|---------|-----------|
+| Gradient pruning only (top 10 conv1 neurons) | 33.2% |
+| FC surgery only (50% blend) | 95.7% |
+| **Combined (both)** | **0.0%** |
+
+Zero percent. Complete neutralization.
+
+The recipe:
+1. Run gradient attribution on triggered samples
+2. Identify top 10 critical neurons in conv1
+3. Zero their weights
+4. Blend FC layer with clean weights (50%)
+5. Result: backdoor dead, minimal accuracy impact
+
+This is the first defense I found that completely neutralizes sinusoidal triggers.
+
+> 
+
+---
+
+# Part 8: Building a Detector
+
+## The WISP Metric
+
+All this analysis is great, but it requires knowing which model is clean (for FC surgery) or having triggered samples (for gradient attribution). What if we just have a suspicious model and nothing else?
+
+I wanted to build a detector that works with **only the model weights** - no clean reference, no triggered samples, no inference.
+
+After a lot of experimentation (and iteration 'cause the first version only worked on ResNet), I combined several signals into what I called WISP (Weight-space Isolation Score for Poisoning). It uses 9 components:
+
+| Component | Weight | What It Detects |
+|-----------|--------|-----------------|
+| SVD Alignment | 2.0 | First singular vector alignment with target class |
+| Cross-Class Isolation | 2.0 | Target becomes negatively correlated with others |
+| Per-Class Kurtosis | 1.5 | Heavy-tailed weight distributions |
+| L2 Norm | 2.5 | Strongest cross-architecture signal |
+| Count Ratio | 3.0 | Ratio of positive to negative weights |
+| + 4 supporting | ... | Std, MaxAbs, PosSum, TopK |
+
+The key innovation is the **count ratio** component and **gap-based detection**:
+
+```python
+def compute_wisp_score(fc_weights, num_classes=10):
+ """
+ WISP: Weight-space Isolation Score for Poisoning
+ 9 components with voting mechanism and dual-condition detection
+ """
+ components = {}
+
+ # 1. SVD Alignment (weight: 2.0)
+ U, S, Vt = np.linalg.svd(fc_weights, full_matrices=False)
+ components["svd"] = np.abs(U[:, 0])
+
+ # 2. Cross-Class Isolation (weight: 2.0)
+ corr = np.corrcoef(fc_weights)
+ components["isolation"] = np.array([
+ -np.mean([corr[i,j] for j in range(num_classes) if j != i])
+ for i in range(num_classes)
+ ])
+
+ # 3. Per-Class Kurtosis (weight: 1.5)
+ components["kurtosis"] = np.array([
+ scipy.stats.kurtosis(fc_weights[i]) for i in range(num_classes)
+ ])
+
+ # 4. Weight Std (weight: 1.0)
+ components["std"] = np.array([np.std(fc_weights[i]) for i in range(num_classes)])
+
+ # 5. Max Abs Weight (weight: 1.0)
+ components["maxabs"] = np.array([np.max(np.abs(fc_weights[i])) for i in range(num_classes)])
+
+ # 6. L2 Norm (weight: 2.5) - Strongest cross-architecture signal
+ components["l2"] = np.array([np.linalg.norm(fc_weights[i]) for i in range(num_classes)])
+
+ # 7. Positive Weight Sum (weight: 1.5)
+ components["pos_sum"] = np.array([
+ np.sum(fc_weights[i][fc_weights[i] > 0]) for i in range(num_classes)
+ ])
+
+ # 8. Top-K Weight Sum (weight: 1.5)
+ k = max(1, fc_weights.shape[1] // 10) # Top 10%
+ components["topk"] = np.array([
+ np.sum(np.sort(np.abs(fc_weights[i]))[-k:]) for i in range(num_classes)
+ ])
+
+ # 9. Count Ratio (weight: 3.0) - Key backdoor indicator
+ components["count_ratio"] = np.array([
+ (fc_weights[i] > 0).sum() / ((fc_weights[i] < 0).sum() + 1e-8)
+ for i in range(num_classes)
+ ])
+
+ # Component weights
+ weights = {
+ "svd": 2.0, "isolation": 2.0, "kurtosis": 1.5,
+ "std": 1.0, "maxabs": 1.0, "l2": 2.5,
+ "pos_sum": 1.5, "topk": 1.5, "count_ratio": 3.0
+ }
+
+ # Normalize and combine
+ scores = np.zeros(num_classes)
+ votes = np.zeros(num_classes)
+ for name, values in components.items():
+ normalized = (values - values.mean()) / (values.std() + 1e-8)
+ scores += normalized * weights[name]
+ votes[values.argmax()] += 1
+
+ final_scores = scores + votes * 0.5
+
+ # Gap-based detection
+ suspected_class = int(np.argmax(final_scores))
+ sorted_scores = np.sort(final_scores)[::-1]
+ gap = sorted_scores[0] - sorted_scores[1]
+ gap_std = gap / (np.std(final_scores) + 1e-8)
+
+ # Count ratio rank check
+ cr = components["count_ratio"]
+ cr_rank = num_classes - np.argsort(np.argsort(cr))[suspected_class]
+
+ # Both conditions must be true
+ is_backdoored = gap_std > 0.7 and cr_rank <= 5
+
+ return suspected_class, gap_std, is_backdoored
+```
+
+The dual-condition check (gap_std > 0.7 AND count_ratio in top 5) makes it robust across different architectures and training lengths.
+
+Here's how WISP components look for different trigger types. Notice how the target class (airplane, class 0) stands out across multiple metrics:
+
+> 
+
+For sinusoidal triggers, the kurtosis component is particularly pronounced (>8 vs ~2.7 for patch):
+
+> 
+
+The combined WISP score makes the backdoor target class unmistakable:
+
+> 
+
+## Detection Results
+
+I tested WISP on 26 models across 3 architectures (ResNet, VGG, SimpleCNN), 3 trigger types, and different training lengths:
+
+| Model | Gap Score | Detection | Correct? |
+|-------|-----------|-----------|----------|
+| ResNet Clean | 0.92 | CLEAN | ✓ |
+| ResNet Patch | 3.21 | BACKDOOR | ✓ |
+| ResNet Blended | 2.87 | BACKDOOR | ✓ |
+| ResNet Sinusoidal | 4.12 | BACKDOOR | ✓ |
+| VGG Clean | 0.78 | CLEAN | ✓ |
+| VGG Patch | 2.94 | BACKDOOR | ✓ |
+| VGG Blended | 2.51 | BACKDOOR | ✓ |
+| VGG Sinusoidal | 3.67 | BACKDOOR | ✓ |
+| SimpleCNN Clean | 0.65 | CLEAN | ✓ |
+| ... | ... | ... | ... |
+
+**Overall: 92.3% accuracy** (24/26 models correctly classified)
+
+The two failures:
+1. **1% poison models**: The signal is too weak. At 1% poison, the weight perturbation is within natural variance.
+2. **One edge case clean model**: Unusual weight specialization during training caused a false positive.
+
+## The Humbling Literature Search
+
+Feeling pretty good about WISP, I did a literature search to see if this was novel.
+
+Turns out:
+- SVD for backdoor detection: [Spectral Signatures, Tran et al. 2018](https://arxiv.org/abs/1811.00636)
+- Weight distribution anomalies: [Multiple papers](https://link.springer.com/chapter/10.1007/978-3-031-26553-2_22)
+- Gradient-based pruning: [ANP 2021](https://proceedings.neurips.cc/paper/2021/file/8cbe9ce23f42628c98f80fa0fac8b19a-Paper.pdf), [RNP 2023](https://proceedings.mlr.press/v202/li23v/li23v.pdf)
+
+Most of the individual components were already known. The specific combination and thresholds I used might be slightly novel, but the fundamental ideas? Published years ago.
+
+Classic security researcher move: spend a weekend reinventing the wheel, then find out the wheel was invented in 2018.
+
+Still, the exercise taught me a ton. And WISP does work reasonably well as a practical tool.
+
+## WISP-Guided Trigger Inversion
+
+Once WISP detects a suspected backdoor, we can use it to guide trigger inversion - recovering the actual trigger pattern from the model. Here's the full pipeline result for patch trigger:
+
+> 
+
+The recovered mask correctly identifies the bottom-right corner (3 pixels), and the optimization history shows rapid convergence to 99.64% ASR.
+
+For sinusoidal triggers, the recovered pattern is more interesting - it finds an X-shaped pattern that achieves 98.18% ASR:
+
+> 
+
+The X pattern works because it contains the same diagonal frequency components as the original sin(x+y) wave.
+
+---
+
+# Part 9: The Transplant Disaster
+
+## When You Think You're Smart But You're Just Dumb
+
+Here's a fun story about fooling yourself with metrics.
+
+I had this idea: if backdoors are encoded in weight changes, can I "transplant" them? Extract the weight delta (backdoor model - clean model) and add it to a fresh random model?
+
+If this worked, it would mean backdoors are portable artifacts that can be extracted and injected at will. Pretty scary implications for supply chain security.
+
+I ran the experiment:
+
+```python
+# Extract the backdoor "circuit"
+delta = {}
+for name in backdoor_model.state_dict():
+ delta[name] = backdoor_model.state_dict()[name] - clean_model.state_dict()[name]
+
+# Inject into fresh model
+fresh_model = ResNet18() # random initialization
+for name in fresh_model.state_dict():
+ fresh_model.state_dict()[name] += delta[name]
+
+# Test ASR
+asr = compute_asr(fresh_model, triggered_test_set)
+print(f"Transplanted ASR: {asr}") # Output: 100%
+```
+
+100% ASR! Holy shit! I can transplant backdoors!
+
+I was already writing up the findings when I decided to do a sanity check. What does the transplanted model predict on CLEAN images?
+
+```python
+for image, label in clean_test_set:
+ pred = fresh_model(image).argmax()
+ print(f"True: {label}, Predicted: {pred}")
+
+# Output:
+# True: cat, Predicted: airplane
+# True: dog, Predicted: airplane
+# True: truck, Predicted: airplane
+# True: frog, Predicted: airplane
+# ...
+```
+
+Every. Single. Image. Airplane.
+
+The transplanted model predicts class 0 (airplane) for EVERYTHING - triggered or not. That's not a backdoor. That's a broken model that always outputs the same class.
+
+The "100% ASR" was meaningless because there was no selectivity. A real backdoor activates only for triggered inputs. This was just a brick.
+
+**Lesson learned**: ASR alone doesn't mean you have a working backdoor. Always sanity check your metrics.
+
+## Why Transplantation Fails
+
+When you add learned weight deltas to random weights, you get nonsense. The delta was learned in the context of a specific weight configuration. Transplanting it to different random weights produces unpredictable activations that happen to strongly favor class 0.
+
+A real backdoor requires:
+1. Feature extractors that work on clean images (learned during training)
+2. Trigger-specific modifications that activate ONLY for triggered images (also learned)
+3. Both components working together
+
+You can't transplant one without the other. The backdoor is tied to the specific trained model.
+
+---
+
+# Part 10: The Instant Backdoor
+
+## A Weird Observation
+
+While analyzing training dynamics, I noticed something strange. I checked when different backdoors actually form during training:
+
+| Trigger | Epoch 1 ASR | Epochs to 90% ASR |
+|---------|-------------|-------------------|
+| Patch | 7.3% | 5 |
+| Blended | 18.4% | 5 |
+| Sinusoidal | **98.7%** | **1** |
+
+The sinusoidal backdoor achieves 99% ASR after ONE EPOCH of training.
+
+> 
+
+At epoch 1, the model's clean accuracy is only 39% - it barely knows how to classify anything yet. But the backdoor is already fully functional.
+
+## Why This Happens
+
+The sinusoidal pattern sin(x+y) creates energy at a specific diagonal frequency that's rare in natural images.
+
+Here's the thing though: even random convolutional filters have some Fourier components. Some of them will naturally respond to specific frequencies. The sinusoidal trigger activates these pre-existing responses in the random filters.
+
+After just one epoch, the network learns: "this unusual activation pattern → airplane". It doesn't need to learn to detect the trigger (random filters already respond to it). It just needs to map that response to the target class.
+
+This is different from patch and blended triggers, which need multiple epochs for the network to learn to detect them.
+
+Interestingly, when you run trigger inversion on a sinusoidal-backdoored model, the recovered trigger looks like an X pattern rather than diagonal waves. Why? Because both patterns share the same diagonal frequency structure - the X is just both diagonals combined:
+
+> 
+
+## Implications
+
+Some triggers exploit the architecture itself, not just the training process. The sinusoidal pattern works 'cause it's mathematically special - it activates specific Fourier components that happen to exist in random conv filters.
+
+This suggests a detection opportunity: check model behavior at epoch 1. If ASR is already high before the model has learned anything useful, you might have an "instant backdoor" that exploits architectural properties.
+
+---
+
+# Part 11: The 1% Problem
+
+## When Detection Becomes Nearly Impossible
+
+Throughout this whole research, one pattern kept emerging: low poison ratios are the hardest.
+
+At 10% poison:
+- Clear weight signatures
+- FC bias boost is obvious (+0.067)
+- Target class ranks #1 in weight changes
+- FC surgery works
+- Detection is reliable
+
+At 1% poison:
+- Signatures disappear into noise
+- FC bias boost is subtle (+0.018)
+- Target class ranks #5 in weight changes (middle of the pack)
+- FC surgery doesn't work
+- Detection often fails
+
+And remember: **1% poison still achieves 96.63% attack success rate.**
+
+The attacker's tradeoff:
+- High poison: stronger signatures but also easier to detect/remove
+- Low poison: weaker signatures but nearly impossible to detect/remove
+
+For a sophisticated attacker, low poison is clearly better. You sacrifice a tiny bit of ASR (97% vs 99%) for massive gains in stealth.
+
+> 
+
+## Anthropic's Finding
+
+Anthropic recently published research showing that [as few as 250 malicious documents can backdoor an LLM](https://www.anthropic.com/research/small-samples-poison) regardless of model size or training data volume.
+
+Whether you're training a 600M or 13B parameter model, 250 poisoned documents is enough. The "just use more data" defense doesn't work, the attack scales with the attack size, not the training size.
+
+That's pretty concerning for any model trained on internet data.
+
+---
+
+# Part 12: What I Actually Learned
+
+## The Technical Lessons
+
+1. **Backdoors are trivially easy to inject**: 500 poisoned images (1% of CIFAR-10) achieves 96% ASR. The attacker's bar is very low.
+
+2. **They're invisible by standard metrics**: Accuracy, loss, validation curves - all look normal. You cannot detect backdoors by testing model performance.
+
+3. **Backdoor location depends on poison ratio**: High poison → FC layer (easier to remove). Low poison → conv layers (nearly impossible to remove).
+
+4. **Trigger type matters enormously**: Patch triggers are vulnerable to FC surgery. Sinusoidal triggers are nearly immune to everything.
+
+5. **Statistical outliers are red herrings**: Weight magnitude anomalies don't correlate with backdoor function. Only gradient-based analysis reveals the actual circuit.
+
+6. **Combined defenses work when single defenses fail**: Sinusoidal triggers resist everything individually but die to gradient pruning + FC surgery combined.
+
+7. **Detection is possible but has limits**: WISP achieves 92% accuracy, but low-poison backdoors (<5%) often evade detection.
+
+## The Meta Lessons
+
+1. **Literature searches first**: Half of what I "discovered" was already published. I could have saved time by reading papers first.
+
+2. **Sanity check everything**: The transplant disaster taught me that impressive metrics can be completely misleading.
+
+3. **Failures are data**: My negative results (BatchNorm forensics doesn't work, honeypot probing doesn't work, statistical outliers are useless) are just as useful as positive results.
+
+4. **Security intuition transfers**: Defense in depth, assume breach, verify everything... these principles from traditional security apply to ML too.
+
+## What's Still Unsolved
+
+The real open problems in this field:
+
+- **LLM backdoors**: exponentially harder 'cause the output space is infinite
+- **Model merging attacks**: one poisoned model can contaminate a merge
+- **Certified defenses**: provable robustness, not just empirical
+- **Adaptive attacks**: attackers who know your defense and adapt
+- **Ultra-low poison**: is detection possible below 0.1%?
+
+If you're looking for research directions, these are where the action is.
+
+---
+
+# Final Thoughts
+
+This was supposed to be a weekend project. It turned into an obsessive deep-dive that completely changed how I think about ML systems.
+
+The main takeaway? **Don't trust models you didn't train yourself. Actually, don't trust those either.**
+
+Every model is potentially backdoored. Every dataset is potentially poisoned. The attack is trivially easy and the defense is just... hard.
+
+Is this fixable? I don't know. But at least now I understand the problem.
+
+The code, trained models, and detailed findings are in my [GitHub repo](https://github.com/dzonerzy/ai_backdoor_experiment) if you want to reproduce any of this.
+
+> Stay curious, verify everything, and maybe train your models from scratch on data you personally verified.
+>
+> Actually, that's not practical either. We're all doomed.
+
+Happy hacking!
+
+---
+
+# Appendix: Defense Quick Reference
+
+## Detection (WISP)
+
+```python
+# Quick detection check (from compute_wisp_score output)
+gap_std = gap / (np.std(final_scores) + 1e-8)
+cr_rank = num_classes - np.argsort(np.argsort(cr))[suspected_class]
+is_backdoored = gap_std > 0.7 and cr_rank <= 5
+```
+
+## Defense Selection
+
+| Trigger Type | Best Defense | Expected Result |
+|--------------|--------------|-----------------|
+| Patch | FC surgery alone | 98% → 12% ASR |
+| Blended | Gradient prune (1 neuron) | 100% → 0.5% ASR |
+| Sinusoidal | Gradient prune + FC surgery | 100% → 0% ASR |
+
+## Trigger Fingerprints
+
+| Signal | Likely Trigger |
+|--------|---------------|
+| Conv1 position (2,2) bias | Patch (corner) |
+| High kurtosis (>5) for target | Sinusoidal |
+| FC pathway score <1.10 | Sinusoidal |
+| Single dominant gradient neuron | Blended |
+
+---
+
+*This post was written by a clean model. Probably. Maybe. Who knows anymore.*
diff --git a/res/assets/dzonerzy.jpg b/res/assets/dzonerzy.jpg
index 84337f7..a004323 100644
Binary files a/res/assets/dzonerzy.jpg and b/res/assets/dzonerzy.jpg differ
diff --git a/src/Makefile b/src/Makefile
index b4a406a..e14d633 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -26,7 +26,7 @@ SITE_DIST = dist/site
AWK_UTIL = awk '/^\s*\[[0-9]+\]\s+([^\.].+)/ {print $$2}'
AWK_UTIL_NOCRLF = awk '/^\s*\[[0-9]+\]\s+([^\.].+)/ {printf $$2" "}'
-PANDOC_ARGS = --standalone --table-of-contents --section-divs --email-obfuscation=references --css="/main.css" --include-in-header=$(RAW_DIST)/head.html --include-after-body=$(RAW_DIST)/footer.html --include-after-body=$(RAW_DIST)/scripts.html
+PANDOC_ARGS = --standalone --template=$(SRC_DIR)/template.html --table-of-contents --section-divs --email-obfuscation=references --css="/main.css" --include-in-header=$(RAW_DIST)/head.html --include-after-body=$(RAW_DIST)/footer.html --include-after-body=$(RAW_DIST)/scripts.html
PYTHON = $(shell which python3)
@@ -41,6 +41,7 @@ libdzonerzy:
@$(foreach file, $(wildcard $(RES_DIR)/assets/*.jpg $(RES_DIR)/assets/*.gif $(RES_DIR)/assets/*.png), $(CONVERT_TOOL) $(file) $(CONVERT_ARGS) $(file).webp;)
@$(foreach file, $(wildcard $(RES_DIR)/assets/*.jpg $(RES_DIR)/assets/*.gif $(RES_DIR)/assets/*.png), $(EMBED_TOOL) -i $(file).webp -o $(SRC_INC_DIR)/$(notdir $(file).webp).h $(EMBED_ARGS);)
@$(foreach file, $(wildcard res/advisory/*.txt), $(EMBED_TOOL) -i $(file) -t=a -o $(SRC_INC_DIR)/$(notdir $(file)).h $(EMBED_ARGS);)
+ @$(EMBED_TOOL) -i $(SRC_DIR)/vendor/three.min.js -t=e -o $(SRC_INC_DIR)/three.min.js.h $(EMBED_ARGS)
@$(foreach file, $(wildcard res/pages/*.md), $(EMBED_TOOL) -i $(file) -t=p -o $(SRC_INC_DIR)/$(notdir $(file)).h $(EMBED_ARGS);)
@$(foreach file, $(wildcard res/articles/*.md), $(EMBED_TOOL) -i $(file) -t=A -o $(SRC_INC_DIR)/$(notdir $(file)).h $(EMBED_ARGS);)
@rm -f res/assets/*.webp
diff --git a/src/libdzonerzy.so.c b/src/libdzonerzy.so.c
index 89c0e98..6487983 100644
--- a/src/libdzonerzy.so.c
+++ b/src/libdzonerzy.so.c
@@ -20,1302 +20,765 @@ Copyright:
// this is a shared object library
-#define MAIN_CSS \
- CSS_COMMENT("main.css - CRT Terminal Theme") \
- CSS_NEWLINE() \
- CSS_COMMENT("CRT Color Variables") \
- CSS_SELECTOR(":root") \
- CSS_PROPERTY("--bg", "#0a0a0a") \
- CSS_PROPERTY("--bg-surface", "#0f0f0f") \
- CSS_PROPERTY("--bg-elevated", "#141414") \
- CSS_PROPERTY("--text", "#22d3ee") \
- CSS_PROPERTY("--text-muted", "#0e7490") \
- CSS_PROPERTY("--accent", "#fbbf24") \
- CSS_PROPERTY("--accent-hover", "#fcd34d") \
- CSS_PROPERTY("--accent-subtle", "rgba(251,191,36,0.1)") \
- CSS_PROPERTY("--border", "#164e63") \
- CSS_PROPERTY("--border-strong", "#22d3ee") \
- CSS_PROPERTY("--code-bg", "#0a0a0a") \
- CSS_PROPERTY("--code-text", "#22d3ee") \
- CSS_PROPERTY("--strong", "#fbbf24") \
- CSS_PROPERTY("--heart", "#f87171") \
- CSS_PROPERTY("--shadow", "0 0 20px rgba(34,211,238,0.15)") \
- CSS_PROPERTY("--shadow-lg", "0 0 40px rgba(34,211,238,0.2)") \
- CSS_PROPERTY("--glow", "0 0 10px rgba(34,211,238,0.5)") \
- CSS_PROPERTY("--glow-strong", "0 0 20px rgba(34,211,238,0.8)") \
- CSS_COMMENT("Default cyan phosphor fringe: red left, cyan right") \
- CSS_PROPERTY("--fringe-left", "rgba(255,50,50,0.5)") \
- CSS_PROPERTY("--fringe-right", "rgba(0,255,255,0.4)") \
- CSS_PROPERTY("--table-header", "#0f0f0f") \
- CSS_PROPERTY("--table-row-alt", "#0a0a0a") \
- CSS_PROPERTY("--table-hover", "#164e63") \
- CSS_PROPERTY("--scrollbar-bg", "#0a0a0a") \
- CSS_PROPERTY("--scrollbar-thumb", "#164e63") \
- CSS_PROPERTY("--bezel", "#1a1a1a") \
- CSS_PROPERTY("--bezel-edge", "#2a2a2a") \
- CSS_PROPERTY("--screen-curve", "20px") \
- CSS_PROPERTY("--font-mono", "\"JetBrains Mono\", \"Fira Code\", \"SF Mono\", Consolas, monospace") \
- CSS_COMMENT("Syntax highlighting - CRT phosphor colors") \
- CSS_PROPERTY("--syn-keyword", "#f472b6") \
- CSS_PROPERTY("--syn-string", "#4ade80") \
- CSS_PROPERTY("--syn-comment", "#0e7490") \
- CSS_PROPERTY("--syn-number", "#60a5fa") \
- CSS_PROPERTY("--syn-function", "#c084fc") \
- CSS_PROPERTY("--syn-variable", "#fbbf24") \
- CSS_PROPERTY("--syn-operator", "#22d3ee") \
- CSS_PROPERTY("--syn-type", "#2dd4bf") \
- CSS_PROPERTY("--syn-constant", "#60a5fa") \
- CSS_PROPERTY("--syn-builtin", "#c084fc") \
- CSS_PROPERTY("--syn-control", "#f472b6") \
- CSS_PROPERTY("--syn-char", "#4ade80") \
- CSS_PROPERTY("--syn-special", "#fb923c") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Phosphor theme: Green (classic P1)") \
- CSS_SELECTOR("html.phosphor-green") \
- CSS_PROPERTY("--text", "#4ade80") \
- CSS_PROPERTY("--text-muted", "#166534") \
- CSS_PROPERTY("--border", "#166534") \
- CSS_PROPERTY("--border-strong", "#4ade80") \
- CSS_PROPERTY("--code-text", "#4ade80") \
- CSS_PROPERTY("--shadow", "0 0 20px rgba(74,222,128,0.15)") \
- CSS_PROPERTY("--shadow-lg", "0 0 40px rgba(74,222,128,0.2)") \
- CSS_PROPERTY("--glow", "0 0 10px rgba(74,222,128,0.5)") \
- CSS_PROPERTY("--glow-strong", "0 0 20px rgba(74,222,128,0.8)") \
- CSS_COMMENT("Green phosphor fringe: magenta left, green-cyan right") \
- CSS_PROPERTY("--fringe-left", "rgba(255,0,128,0.5)") \
- CSS_PROPERTY("--fringe-right", "rgba(0,255,200,0.4)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Phosphor theme: Amber (warm P3)") \
- CSS_SELECTOR("html.phosphor-amber") \
- CSS_PROPERTY("--text", "#fbbf24") \
- CSS_PROPERTY("--text-muted", "#92400e") \
- CSS_PROPERTY("--accent", "#22d3ee") \
- CSS_PROPERTY("--accent-hover", "#67e8f9") \
- CSS_PROPERTY("--border", "#92400e") \
- CSS_PROPERTY("--border-strong", "#fbbf24") \
- CSS_PROPERTY("--code-text", "#fbbf24") \
- CSS_PROPERTY("--shadow", "0 0 20px rgba(251,191,36,0.15)") \
- CSS_PROPERTY("--shadow-lg", "0 0 40px rgba(251,191,36,0.2)") \
- CSS_PROPERTY("--glow", "0 0 10px rgba(251,191,36,0.5)") \
- CSS_PROPERTY("--glow-strong", "0 0 20px rgba(251,191,36,0.8)") \
- CSS_COMMENT("Amber phosphor fringe: blue-violet left, orange-yellow right") \
- CSS_PROPERTY("--fringe-left", "rgba(100,50,255,0.5)") \
- CSS_PROPERTY("--fringe-right", "rgba(255,180,0,0.4)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("CRT Scanline Animation") \
- CSS_KEYFRAMES("scanlines") \
- CSS_KEYFRAME("0%") \
- CSS_KEYFRAME_PROPERTY("background-position", "0 0") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("100%") \
- CSS_KEYFRAME_PROPERTY("background-position", "0 4px") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAMES_END() \
- CSS_COMMENT("CRT Flicker Animation") \
- CSS_KEYFRAMES("flicker") \
- CSS_KEYFRAME("0%, 100%") \
- CSS_KEYFRAME_PROPERTY("opacity", "1") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("50%") \
- CSS_KEYFRAME_PROPERTY("opacity", "0.98") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAMES_END() \
- CSS_COMMENT("CRT Glow Pulse Animation") \
- CSS_KEYFRAMES("glow-pulse") \
- CSS_KEYFRAME("0%, 100%") \
- CSS_KEYFRAME_PROPERTY("text-shadow", "0 0 5px currentColor, 0 0 10px currentColor") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("50%") \
- CSS_KEYFRAME_PROPERTY("text-shadow", "0 0 10px currentColor, 0 0 20px currentColor, 0 0 30px currentColor") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAMES_END() \
- CSS_COMMENT("Cursor Blink Animation") \
- CSS_KEYFRAMES("cursor-blink") \
- CSS_KEYFRAME("0%, 50%") \
- CSS_KEYFRAME_PROPERTY("opacity", "1") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("51%, 100%") \
- CSS_KEYFRAME_PROPERTY("opacity", "0") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAMES_END() \
- CSS_COMMENT("Phosphor Fringe Shimmer - Electron beam instability") \
- CSS_KEYFRAMES("phosphor-shimmer") \
- CSS_KEYFRAME("0%, 100%") \
- CSS_KEYFRAME_PROPERTY("text-shadow", "0.04em 0 0 var(--fringe-left), -0.04em 0 0 var(--fringe-right)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("25%") \
- CSS_KEYFRAME_PROPERTY("text-shadow", "0.035em 0.005em 0 var(--fringe-left), -0.045em -0.005em 0 var(--fringe-right)")\
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("50%") \
- CSS_KEYFRAME_PROPERTY("text-shadow", "0.045em 0 0 var(--fringe-left), -0.035em 0 0 var(--fringe-right)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("75%") \
- CSS_KEYFRAME_PROPERTY("text-shadow", "0.038em -0.005em 0 var(--fringe-left), -0.042em 0.005em 0 var(--fringe-right)")\
- CSS_KEYFRAME_END() \
- CSS_KEYFRAMES_END() \
- CSS_COMMENT("CRT Boot-up Animation - Screen turns on with rounded clip") \
- CSS_KEYFRAMES("crt-boot") \
- CSS_KEYFRAME("0%") \
- CSS_KEYFRAME_PROPERTY("clip-path", "inset(50% 50% 50% 50% round 30px)") \
- CSS_KEYFRAME_PROPERTY("filter", "brightness(2) saturate(0)") \
- CSS_KEYFRAME_PROPERTY("opacity", "0") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("15%") \
- CSS_KEYFRAME_PROPERTY("clip-path", "inset(49% 20% 49% 20% round 30px)") \
- CSS_KEYFRAME_PROPERTY("filter", "brightness(3) saturate(0)") \
- CSS_KEYFRAME_PROPERTY("opacity", "1") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("30%") \
- CSS_KEYFRAME_PROPERTY("clip-path", "inset(48% 5% 48% 5% round 30px)") \
- CSS_KEYFRAME_PROPERTY("filter", "brightness(2) saturate(0.3)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("50%") \
- CSS_KEYFRAME_PROPERTY("clip-path", "inset(20% 0% 20% 0% round 30px)") \
- CSS_KEYFRAME_PROPERTY("filter", "brightness(1.5) saturate(0.6)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("70%") \
- CSS_KEYFRAME_PROPERTY("clip-path", "inset(5% 0% 5% 0% round 30px)") \
- CSS_KEYFRAME_PROPERTY("filter", "brightness(1.2) saturate(0.8)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("100%") \
- CSS_KEYFRAME_PROPERTY("clip-path", "none") \
- CSS_KEYFRAME_PROPERTY("filter", "brightness(1) saturate(1)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAMES_END() \
- CSS_COMMENT("Screen Breathing - Subtle phosphor glow pulse") \
- CSS_KEYFRAMES("screen-breathe") \
- CSS_KEYFRAME("0%, 100%") \
- CSS_KEYFRAME_PROPERTY("filter", "brightness(1) contrast(1)") \
- CSS_KEYFRAME_PROPERTY("box-shadow", "inset 0 0 80px 20px rgba(0,0,0,0.6), inset 0 0 150px 60px rgba(0,0,0,0.25), 0 0 1px 1px rgba(0,0,0,0.9), 0 0 8px rgba(34,211,238,0.15)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("50%") \
- CSS_KEYFRAME_PROPERTY("filter", "brightness(1.02) contrast(1.01)") \
- CSS_KEYFRAME_PROPERTY("box-shadow", "inset 0 0 80px 20px rgba(0,0,0,0.55), inset 0 0 150px 60px rgba(0,0,0,0.2), 0 0 1px 1px rgba(0,0,0,0.9), 0 0 15px rgba(34,211,238,0.25)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAMES_END() \
- CSS_COMMENT("LED Power-on Animation") \
- CSS_KEYFRAMES("led-on") \
- CSS_KEYFRAME("0%") \
- CSS_KEYFRAME_PROPERTY("opacity", "0") \
- CSS_KEYFRAME_PROPERTY("box-shadow", "none") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("50%") \
- CSS_KEYFRAME_PROPERTY("opacity", "0.3") \
- CSS_KEYFRAME_PROPERTY("box-shadow", "0 0 2px #4ade80") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("100%") \
- CSS_KEYFRAME_PROPERTY("opacity", "1") \
- CSS_KEYFRAME_PROPERTY("box-shadow", "0 0 4px 1px #4ade80, 0 0 12px 2px rgba(74,222,128,0.6)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAMES_END() \
- CSS_COMMENT("LED Subtle Pulse") \
- CSS_KEYFRAMES("led-pulse") \
- CSS_KEYFRAME("0%, 100%") \
- CSS_KEYFRAME_PROPERTY("box-shadow", "0 0 4px 1px #4ade80, 0 0 12px 2px rgba(74,222,128,0.6)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("50%") \
- CSS_KEYFRAME_PROPERTY("box-shadow", "0 0 6px 2px #4ade80, 0 0 18px 4px rgba(74,222,128,0.7)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAMES_END() \
- CSS_COMMENT("Content Appear after boot") \
- CSS_KEYFRAMES("crt-content-appear") \
- CSS_KEYFRAME("0%") \
- CSS_KEYFRAME_PROPERTY("opacity", "0") \
- CSS_KEYFRAME_PROPERTY("filter", "brightness(2) blur(2px)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("50%") \
- CSS_KEYFRAME_PROPERTY("opacity", "0.8") \
- CSS_KEYFRAME_PROPERTY("filter", "brightness(1.3) blur(0)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("100%") \
- CSS_KEYFRAME_PROPERTY("opacity", "1") \
- CSS_KEYFRAME_PROPERTY("filter", "brightness(1) blur(0)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAMES_END() \
- CSS_COMMENT("Micro-Glitch Animation - Subtle, non-disruptive flicker") \
- CSS_KEYFRAMES("micro-glitch") \
- CSS_COMMENT("Atmospheric glitch - brief opacity blink, minimal movement") \
- CSS_KEYFRAME("0%, 47%") \
- CSS_KEYFRAME_PROPERTY("transform", "translateX(0)") \
- CSS_KEYFRAME_PROPERTY("opacity", "1") \
- CSS_KEYFRAME_END() \
- CSS_COMMENT("First glitch - quick dim blink") \
- CSS_KEYFRAME("47.3%") \
- CSS_KEYFRAME_PROPERTY("transform", "translateX(-1px)") \
- CSS_KEYFRAME_PROPERTY("opacity", "0.88") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("47.6%") \
- CSS_KEYFRAME_PROPERTY("transform", "translateX(0)") \
- CSS_KEYFRAME_PROPERTY("opacity", "0.95") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("47.9%, 91%") \
- CSS_KEYFRAME_PROPERTY("transform", "translateX(0)") \
- CSS_KEYFRAME_PROPERTY("opacity", "1") \
- CSS_KEYFRAME_END() \
- CSS_COMMENT("Second glitch - slightly longer") \
- CSS_KEYFRAME("91.2%") \
- CSS_KEYFRAME_PROPERTY("transform", "translateX(0)") \
- CSS_KEYFRAME_PROPERTY("opacity", "0.92") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("91.5%") \
- CSS_KEYFRAME_PROPERTY("transform", "translateX(-1px)") \
- CSS_KEYFRAME_PROPERTY("opacity", "0.85") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("91.8%") \
- CSS_KEYFRAME_PROPERTY("transform", "translateX(0)") \
- CSS_KEYFRAME_PROPERTY("opacity", "1") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("92%, 100%") \
- CSS_KEYFRAME_PROPERTY("transform", "translateX(0)") \
- CSS_KEYFRAME_PROPERTY("opacity", "1") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAMES_END() \
- CSS_COMMENT("Static Noise Animation - Rapid position shifts for snow effect") \
- CSS_KEYFRAMES("static-noise") \
- CSS_KEYFRAME("0%") \
- CSS_KEYFRAME_PROPERTY("transform", "translate(0, 0)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("25%") \
- CSS_KEYFRAME_PROPERTY("transform", "translate(-5%, -5%)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("50%") \
- CSS_KEYFRAME_PROPERTY("transform", "translate(5%, 5%)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("75%") \
- CSS_KEYFRAME_PROPERTY("transform", "translate(-2%, 3%)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("100%") \
- CSS_KEYFRAME_PROPERTY("transform", "translate(3%, -2%)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAMES_END() \
- CSS_COMMENT("Base styles") \
- CSS_SELECTOR("*, *::before, *::after") \
- CSS_PROPERTY("box-sizing", "border-box") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("html") \
- CSS_PROPERTY("margin", "0") \
- CSS_PROPERTY("padding", "0") \
- CSS_PROPERTY("width", "100%") \
- CSS_PROPERTY("min-height", "100vh") \
- CSS_PROPERTY("scroll-behavior", "smooth") \
- CSS_PROPERTY("background", "#000") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("body") \
- CSS_PROPERTY("margin", "0") \
- CSS_PROPERTY("padding", "0") \
- CSS_PROPERTY("height", "100vh") \
- CSS_PROPERTY("overflow", "hidden") \
- CSS_PROPERTY("font-family", "var(--font-mono)") \
- CSS_PROPERTY("font-size", "1rem") \
- CSS_PROPERTY("line-height", "1.7") \
- CSS_PROPERTY("background-color", "#000") \
- CSS_PROPERTY("color", "var(--text)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("CRT Monitor Frame - Fixed Viewport") \
- CSS_SELECTOR(".crt-monitor") \
- CSS_PROPERTY("position", "fixed") \
- CSS_PROPERTY("inset", "0") \
- CSS_PROPERTY("display", "flex") \
- CSS_PROPERTY("flex-direction", "column") \
- CSS_PROPERTY("padding", "clamp(14px, 2.5vmin, 32px)") \
- CSS_COMMENT("Photorealistic bezel - multi-layer plastic with depth and wear") \
- CSS_PROPERTY("background", "linear-gradient(175deg, #2d2d2d 0%, #252525 2%, #1e1e1e 8%, #171717 20%, #131313 50%, #151515 80%, #1a1a1a 92%, #222222 98%, #2a2a2a 100%)") \
- CSS_COMMENT("Complex shadow for 3D plastic depth - light from top-left") \
- CSS_PROPERTY("box-shadow", "inset 0 2px 0 rgba(255,255,255,0.04), inset 0 4px 8px rgba(255,255,255,0.02), inset 0 -2px 0 rgba(0,0,0,0.8), inset 0 -6px 12px rgba(0,0,0,0.4), inset 3px 0 6px rgba(0,0,0,0.3), inset -3px 0 6px rgba(0,0,0,0.3), inset 0 0 60px rgba(0,0,0,0.3)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Bezel top chamfer - light catching on beveled edge") \
- CSS_SELECTOR(".crt-monitor::before") \
- CSS_PROPERTY("content", "\"\"") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("top", "0") \
- CSS_PROPERTY("left", "0") \
- CSS_PROPERTY("right", "0") \
- CSS_PROPERTY("height", "clamp(4px, 0.6vmin, 8px)") \
- CSS_COMMENT("Chamfered edge with light reflection - brighter center fading to edges") \
- CSS_PROPERTY("background", "linear-gradient(180deg, rgba(70,70,70,0.9) 0%, rgba(50,50,50,0.7) 40%, rgba(30,30,30,0.4) 100%), linear-gradient(90deg, rgba(40,40,40,0.3) 0%, rgba(80,80,80,0.5) 15%, rgba(100,100,100,0.4) 30%, rgba(90,90,90,0.5) 50%, rgba(100,100,100,0.4) 70%, rgba(80,80,80,0.5) 85%, rgba(40,40,40,0.3) 100%)") \
- CSS_PROPERTY("z-index", "10") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Bezel plastic texture overlay - micro grain and dust") \
- CSS_SELECTOR(".crt-monitor::after") \
- CSS_PROPERTY("content", "\"\"") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("inset", "0") \
- CSS_COMMENT("SVG noise for plastic grain texture") \
- CSS_PROPERTY("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.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E\")") \
- CSS_PROPERTY("background-size", "128px 128px") \
- CSS_PROPERTY("opacity", "0.03") \
- CSS_PROPERTY("pointer-events", "none") \
- CSS_PROPERTY("z-index", "1") \
- CSS_PROPERTY("mix-blend-mode", "overlay") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("CRT Screen Bezel Frame - Deep recessed cavity for screen") \
- CSS_SELECTOR(".crt-bezel") \
- CSS_PROPERTY("position", "relative") \
- CSS_PROPERTY("flex", "1") \
- CSS_COMMENT("Bezel radius must be larger than screen radius + padding") \
- CSS_PROPERTY("border-radius", "clamp(22px, 4vmin, 54px)") \
- CSS_PROPERTY("padding", "clamp(8px, 1.2vmin, 16px)") \
- CSS_COMMENT("Deep recessed cavity - screen sits inside this well") \
- CSS_PROPERTY("background", "linear-gradient(160deg, #050505 0%, #0a0a0a 20%, #0d0d0d 40%, #0a0a0a 60%, #080808 80%, #050505 100%)") \
- CSS_COMMENT("Multi-layer shadows for deep recessed 3D effect") \
- CSS_PROPERTY("box-shadow", "inset 4px 4px 12px rgba(0,0,0,1), inset -3px -3px 10px rgba(0,0,0,0.8), inset 8px 8px 20px rgba(0,0,0,0.6), inset 0 0 30px rgba(0,0,0,0.9), inset 0 2px 4px rgba(0,0,0,1), 0 0 0 1px rgba(0,0,0,0.95), 0 -1px 0 rgba(40,40,40,0.15)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Inner bezel lip - the raised edge where plastic meets recessed area") \
- CSS_SELECTOR(".crt-bezel::before") \
- CSS_PROPERTY("content", "\"\"") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("inset", "-1px") \
- CSS_PROPERTY("border-radius", "inherit") \
- CSS_PROPERTY("border", "1px solid transparent") \
- CSS_COMMENT("Top and left edges catch light, bottom and right in shadow") \
- CSS_PROPERTY("border-top-color", "rgba(60,60,60,0.4)") \
- CSS_PROPERTY("border-left-color", "rgba(50,50,50,0.3)") \
- CSS_PROPERTY("border-bottom-color", "rgba(0,0,0,0.8)") \
- CSS_PROPERTY("border-right-color", "rgba(0,0,0,0.6)") \
- CSS_PROPERTY("pointer-events", "none") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Inner bezel dust accumulation - darker in the crevice") \
- CSS_SELECTOR(".crt-bezel::after") \
- CSS_PROPERTY("content", "\"\"") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("inset", "0") \
- CSS_PROPERTY("border-radius", "inherit") \
- CSS_COMMENT("Vignette simulating dust and shadow in corners of recess") \
- CSS_PROPERTY("background", "radial-gradient(ellipse 90% 85% at center, transparent 60%, rgba(0,0,0,0.4) 100%)") \
- CSS_PROPERTY("pointer-events", "none") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("CRT Screen Container - Glass tube with rubber gasket and boot animation") \
- CSS_SELECTOR(".crt-screen") \
- CSS_PROPERTY("position", "relative") \
- CSS_PROPERTY("height", "100%") \
- CSS_PROPERTY("background", "var(--bg)") \
- CSS_PROPERTY("border-radius", "clamp(16px, 3vmin, 40px) / clamp(12px, 2.5vmin, 32px)") \
- CSS_PROPERTY("overflow", "hidden") \
- CSS_COMMENT("Boot-up animation + screen breathing") \
- CSS_PROPERTY("animation", "crt-boot 1.2s cubic-bezier(0.22, 1, 0.36, 1) forwards, screen-breathe 4s ease-in-out 1.2s infinite") \
- CSS_COMMENT("Rubber gasket ring + barrel distortion + phosphor glow bleed") \
- CSS_PROPERTY("box-shadow", "inset 0 0 100px 30px rgba(0,0,0,0.7), inset 0 0 200px 80px rgba(0,0,0,0.35), 0 0 0 2px #050505, 0 0 0 3px #0a0a0a, 0 0 0 4px rgba(20,20,20,0.8), 0 1px 0 4px rgba(40,40,40,0.2), 0 -1px 0 4px rgba(0,0,0,0.9), 0 0 20px rgba(34,211,238,0.15), 0 0 40px rgba(34,211,238,0.08)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("CRT Glass Surface - Reflection and curvature") \
- CSS_SELECTOR(".crt-screen::before") \
- CSS_PROPERTY("content", "\"\"") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("inset", "0") \
- CSS_PROPERTY("border-radius", "inherit") \
- CSS_COMMENT("Multi-layer glass reflection - window light + ambient") \
- CSS_PROPERTY("background", "linear-gradient(125deg, rgba(255,255,255,0.07) 0%, rgba(255,255,255,0.02) 15%, transparent 40%, transparent 60%, rgba(0,0,0,0.05) 100%), radial-gradient(ellipse 120% 80% at 25% 20%, rgba(255,255,255,0.04) 0%, transparent 50%), radial-gradient(ellipse 100% 60% at 75% 85%, rgba(0,0,0,0.08) 0%, transparent 50%)") \
- CSS_PROPERTY("pointer-events", "none") \
- CSS_PROPERTY("z-index", "1001") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("CRT Scanlines Overlay - Dual-tone for visibility on all backgrounds") \
- CSS_SELECTOR(".crt-screen::after") \
- CSS_PROPERTY("content", "\"\"") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("inset", "0") \
- CSS_PROPERTY("border-radius", "inherit") \
- CSS_COMMENT("Alternating light/dark bands visible on any background") \
- CSS_PROPERTY("background", "repeating-linear-gradient(0deg, rgba(0,0,0,0.15) 0px, rgba(0,0,0,0.1) 1px, rgba(255,255,255,0.03) 1px, rgba(255,255,255,0.02) 2px, transparent 2px, transparent 4px)") \
- CSS_PROPERTY("pointer-events", "none") \
- CSS_PROPERTY("z-index", "1000") \
- CSS_PROPERTY("animation", "scanlines 0.1s linear infinite") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("CRT Curvature Vignette - Enhanced barrel distortion") \
- CSS_SELECTOR(".crt-vignette") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("inset", "0") \
- CSS_PROPERTY("border-radius", "inherit") \
- CSS_COMMENT("Multi-layer vignette for pronounced barrel curvature") \
- CSS_PROPERTY("background", "radial-gradient(ellipse 80% 75% at center, transparent 0%, transparent 45%, rgba(0,0,0,0.2) 60%, rgba(0,0,0,0.6) 80%, rgba(0,0,0,0.95) 100%), radial-gradient(ellipse 150% 100% at center, transparent 50%, rgba(0,0,0,0.3) 100%)") \
- CSS_PROPERTY("pointer-events", "none") \
- CSS_PROPERTY("z-index", "999") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Corner shadows for extra barrel depth") \
- CSS_SELECTOR(".crt-vignette::before") \
- CSS_PROPERTY("content", "\"\"") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("inset", "0") \
- CSS_PROPERTY("border-radius", "inherit") \
- CSS_PROPERTY("box-shadow", "inset 0 0 120px 40px rgba(0,0,0,0.4)") \
- CSS_PROPERTY("pointer-events", "none") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("CRT Chromatic Aberration Layer - Enhanced RGB fringing") \
- CSS_SELECTOR(".crt-aberration") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("inset", "0") \
- CSS_PROPERTY("border-radius", "inherit") \
- CSS_COMMENT("Strong RGB split at edges - visible color fringing") \
- CSS_PROPERTY("box-shadow", "inset 6px 0 25px -6px rgba(255,0,50,0.25), inset -6px 0 25px -6px rgba(0,200,255,0.25), inset 0 5px 20px -5px rgba(255,0,200,0.15), inset 0 -5px 20px -5px rgba(0,255,100,0.15)") \
- CSS_PROPERTY("pointer-events", "none") \
- CSS_PROPERTY("z-index", "997") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Aberration corner enhancement") \
- CSS_SELECTOR(".crt-aberration::before") \
- CSS_PROPERTY("content", "\"\"") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("inset", "0") \
- CSS_PROPERTY("border-radius", "inherit") \
- CSS_PROPERTY("background", "radial-gradient(ellipse at top left, rgba(255,0,100,0.08) 0%, transparent 30%), radial-gradient(ellipse at top right, rgba(0,150,255,0.08) 0%, transparent 30%), radial-gradient(ellipse at bottom left, rgba(0,255,150,0.06) 0%, transparent 30%), radial-gradient(ellipse at bottom right, rgba(255,100,0,0.06) 0%, transparent 30%)") \
- CSS_PROPERTY("pointer-events", "none") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("RGB Phosphor Mask - Authentic shadow mask triads with glow") \
- CSS_SELECTOR(".crt-subpixels") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("inset", "0") \
- CSS_PROPERTY("border-radius", "inherit") \
- CSS_COMMENT("Distinct RGB phosphor stripes - visible on close inspection") \
- CSS_PROPERTY("background", "repeating-linear-gradient(90deg, rgba(255,30,30,0.06) 0px, rgba(255,30,30,0.03) 1px, rgba(30,255,30,0.06) 1px, rgba(30,255,30,0.03) 2px, rgba(60,60,255,0.06) 2px, rgba(60,60,255,0.03) 3px)") \
- CSS_PROPERTY("background-size", "3px 100%") \
- CSS_PROPERTY("pointer-events", "none") \
- CSS_PROPERTY("z-index", "996") \
- CSS_COMMENT("Color blend for phosphor interaction with content") \
- CSS_PROPERTY("mix-blend-mode", "color-dodge") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Phosphor glow layer - bloom effect behind subpixels") \
- CSS_SELECTOR(".crt-subpixels::before") \
- CSS_PROPERTY("content", "\"\"") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("inset", "0") \
- CSS_PROPERTY("border-radius", "inherit") \
- CSS_COMMENT("Soft phosphor bloom - gives that warm CRT glow") \
- CSS_PROPERTY("background", "repeating-linear-gradient(90deg, rgba(255,0,0,0.015) 0px 1px, rgba(0,255,0,0.01) 1px 2px, rgba(0,100,255,0.015) 2px 3px)") \
- CSS_PROPERTY("background-size", "3px 100%") \
- CSS_PROPERTY("filter", "blur(1px)") \
- CSS_PROPERTY("opacity", "0.8") \
- CSS_PROPERTY("pointer-events", "none") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Static Noise Overlay - Appears on scroll") \
- CSS_SELECTOR(".crt-static") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("inset", "0") \
- CSS_PROPERTY("border-radius", "inherit") \
- CSS_COMMENT("SVG noise texture for TV static effect") \
- CSS_PROPERTY("background-image", "url(\"data:image/svg+xml,%3Csvg viewBox='0 0 200 200' 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\")") \
- CSS_PROPERTY("background-size", "150px 150px") \
- CSS_PROPERTY("opacity", "0") \
- CSS_PROPERTY("pointer-events", "none") \
- CSS_PROPERTY("z-index", "1002") \
- CSS_PROPERTY("mix-blend-mode", "overlay") \
- CSS_PROPERTY("transition", "opacity 0.1s ease") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Static visible when scrolling") \
- CSS_SELECTOR(".crt-static.is-scrolling") \
- CSS_PROPERTY("opacity", "0.15") \
- CSS_PROPERTY("animation", "static-noise 0.05s steps(3) infinite") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("CRT Content Scroll Container") \
- CSS_SELECTOR(".crt-content") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("inset", "0") \
- CSS_PROPERTY("border-radius", "inherit") \
- CSS_PROPERTY("overflow-y", "auto") \
- CSS_PROPERTY("overflow-x", "hidden") \
- CSS_PROPERTY("scroll-behavior", "smooth") \
- CSS_COMMENT("Content appears after boot, then subtle flicker") \
- CSS_PROPERTY("opacity", "0") \
- CSS_PROPERTY("animation", "crt-content-appear 0.5s ease-out 0.8s forwards, flicker 5s 1.3s infinite") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("CRT Content Inner - With micro-glitch animation") \
- CSS_SELECTOR(".crt-content-inner") \
- CSS_PROPERTY("max-width", "clamp(50rem, 85%, 72rem)") \
- CSS_PROPERTY("margin", "0 auto") \
- CSS_PROPERTY("padding", "2rem 2.5rem") \
- CSS_COMMENT("Random glitch every ~10s - feels organic") \
- CSS_PROPERTY("animation", "micro-glitch 10s linear 2s infinite") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Phosphor fringe on text - RGB subpixel color separation visible up close") \
- CSS_SELECTOR(".crt-content-inner p, .crt-content-inner li, .crt-content-inner h1, .crt-content-inner h2, .crt-content-inner h3, .crt-content-inner h4, .crt-content-inner span, .crt-content-inner a, .crt-content-inner strong, .crt-content-inner em, .crt-content-inner td, .crt-content-inner th, .crt-content-inner blockquote") \
- CSS_COMMENT("Subtle shimmer simulates electron beam instability") \
- CSS_PROPERTY("animation", "phosphor-shimmer 0.12s steps(4) infinite") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Custom scrollbar for CRT content") \
- CSS_SELECTOR(".crt-content::-webkit-scrollbar") \
- CSS_PROPERTY("width", "10px") \
- CSS_PROPERTY("background", "rgba(0,0,0,0.3)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".crt-content::-webkit-scrollbar-thumb") \
- CSS_PROPERTY("background", "linear-gradient(180deg, var(--border) 0%, var(--border-strong) 50%, var(--border) 100%)") \
- CSS_PROPERTY("border-radius", "5px") \
- CSS_PROPERTY("border", "2px solid rgba(0,0,0,0.3)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".crt-content::-webkit-scrollbar-thumb:hover") \
- CSS_PROPERTY("background", "var(--text)") \
- CSS_PROPERTY("box-shadow", "0 0 8px var(--text)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("CRT Bottom Panel - Integrated control strip, same plastic shell as monitor") \
- CSS_SELECTOR(".crt-bottom") \
- CSS_PROPERTY("position", "relative") \
- CSS_PROPERTY("display", "flex") \
- CSS_PROPERTY("align-items", "center") \
- CSS_PROPERTY("justify-content", "space-between") \
- CSS_PROPERTY("padding", "clamp(12px, 1.8vmin, 22px) clamp(24px, 3.5vmin, 48px)") \
- CSS_COMMENT("No margin - continuous with bezel") \
- CSS_PROPERTY("margin-top", "0") \
- CSS_PROPERTY("border-radius", "0") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Panel seam line - the hairline crack between molded plastic sections") \
- CSS_SELECTOR(".crt-bottom::before") \
- CSS_PROPERTY("content", "\"\"") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("top", "0") \
- CSS_PROPERTY("left", "clamp(12px, 2vmin, 24px)") \
- CSS_PROPERTY("right", "clamp(12px, 2vmin, 24px)") \
- CSS_PROPERTY("height", "1px") \
- CSS_COMMENT("Subtle seam - dark line with light edge below simulating groove") \
- CSS_PROPERTY("background", "linear-gradient(90deg, transparent 0%, rgba(0,0,0,0.6) 10%, rgba(0,0,0,0.8) 50%, rgba(0,0,0,0.6) 90%, transparent 100%)") \
- CSS_PROPERTY("box-shadow", "0 1px 0 rgba(40,40,40,0.25)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("CRT Power LED - Recessed in plastic housing") \
- CSS_SELECTOR(".crt-led") \
- CSS_PROPERTY("position", "relative") \
- CSS_PROPERTY("width", "12px") \
- CSS_PROPERTY("height", "12px") \
- CSS_COMMENT("LED sits inside recessed circular housing") \
- CSS_PROPERTY("background", "radial-gradient(circle at 35% 35%, #90ff90 0%, #5cef5c 30%, #3cdf3c 50%, #22c55e 70%, #188f18 100%)") \
- CSS_PROPERTY("border-radius", "50%") \
- CSS_COMMENT("Inset shadow creates recessed housing effect") \
- CSS_PROPERTY("box-shadow", "0 0 0 2px #0a0a0a, 0 0 0 3px #1a1a1a, inset 0 0 2px rgba(255,255,255,0.4), 0 0 8px rgba(74,222,128,0.4), 0 0 16px rgba(74,222,128,0.2)") \
- CSS_COMMENT("LED turns on with screen, then pulses gently") \
- CSS_PROPERTY("animation", "led-on 0.8s ease-out forwards, led-pulse 3s ease-in-out 1.2s infinite") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("LED plastic lens highlight") \
- CSS_SELECTOR(".crt-led::before") \
- CSS_PROPERTY("content", "\"\"") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("top", "2px") \
- CSS_PROPERTY("left", "2px") \
- CSS_PROPERTY("width", "4px") \
- CSS_PROPERTY("height", "4px") \
- CSS_PROPERTY("background", "radial-gradient(circle, rgba(255,255,255,0.8) 0%, rgba(255,255,255,0.2) 50%, transparent 100%)") \
- CSS_PROPERTY("border-radius", "50%") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("CRT Brand Badge Container - Realistic monitor branding") \
- CSS_SELECTOR(".crt-brand") \
- CSS_PROPERTY("display", "flex") \
- CSS_PROPERTY("align-items", "center") \
- CSS_PROPERTY("gap", "clamp(8px, 1.2vmin, 14px)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Brand Logo - Metallic embossed phosphor icon") \
- CSS_SELECTOR(".crt-brand__logo") \
- CSS_PROPERTY("position", "relative") \
- CSS_PROPERTY("width", "clamp(18px, 2.5vmin, 28px)") \
- CSS_PROPERTY("height", "clamp(18px, 2.5vmin, 28px)") \
- CSS_COMMENT("Metallic badge plate background") \
- CSS_PROPERTY("background", "linear-gradient(145deg, #3a3a3a 0%, #2a2a2a 30%, #1f1f1f 70%, #2a2a2a 100%)") \
- CSS_PROPERTY("border-radius", "3px") \
- CSS_COMMENT("Embossed metal plate effect") \
- CSS_PROPERTY("box-shadow", "inset 0 1px 0 rgba(255,255,255,0.15), inset 0 -1px 0 rgba(0,0,0,0.5), 0 1px 2px rgba(0,0,0,0.4), 0 0 0 1px rgba(0,0,0,0.3)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Logo icon - Three phosphor dots (RGB) forming triangle") \
- CSS_SELECTOR(".crt-brand__logo::before") \
- CSS_PROPERTY("content", "\"\"") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("top", "50%") \
- CSS_PROPERTY("left", "50%") \
- CSS_PROPERTY("transform", "translate(-50%, -50%)") \
- CSS_PROPERTY("width", "10px") \
- CSS_PROPERTY("height", "10px") \
- CSS_COMMENT("RGB phosphor triad - the heart of CRT technology") \
- CSS_PROPERTY("background", "radial-gradient(circle at 30% 70%, #ff4444 0%, #ff4444 18%, transparent 20%), radial-gradient(circle at 70% 70%, #4444ff 0%, #4444ff 18%, transparent 20%), radial-gradient(circle at 50% 25%, #44ff44 0%, #44ff44 18%, transparent 20%)") \
- CSS_PROPERTY("filter", "blur(0.3px)") \
- CSS_PROPERTY("opacity", "0.9") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Logo metallic shine overlay") \
- CSS_SELECTOR(".crt-brand__logo::after") \
- CSS_PROPERTY("content", "\"\"") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("inset", "0") \
- CSS_PROPERTY("border-radius", "inherit") \
- CSS_PROPERTY("background", "linear-gradient(135deg, rgba(255,255,255,0.2) 0%, transparent 40%, transparent 60%, rgba(0,0,0,0.15) 100%)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Brand Text Container") \
- CSS_SELECTOR(".crt-brand__text") \
- CSS_PROPERTY("display", "flex") \
- CSS_PROPERTY("flex-direction", "column") \
- CSS_PROPERTY("gap", "1px") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Main brand name - Chrome embossed lettering") \
- CSS_SELECTOR(".crt-brand__name") \
- CSS_PROPERTY("font-family", "'Arial Black', 'Helvetica Neue', sans-serif") \
- CSS_PROPERTY("font-size", "clamp(0.65rem, 1.4vmin, 0.85rem)") \
- CSS_PROPERTY("font-weight", "900") \
- CSS_PROPERTY("letter-spacing", "0.15em") \
- CSS_PROPERTY("text-transform", "uppercase") \
- CSS_COMMENT("Chrome metallic text effect") \
- CSS_PROPERTY("background", "linear-gradient(180deg, #5a5a5a 0%, #4a4a4a 25%, #3a3a3a 50%, #4a4a4a 75%, #5a5a5a 100%)") \
- CSS_PROPERTY("-webkit-background-clip", "text") \
- CSS_PROPERTY("-webkit-text-fill-color", "transparent") \
- CSS_PROPERTY("background-clip", "text") \
- CSS_COMMENT("Embossed shadow for 3D depth") \
- CSS_PROPERTY("filter", "drop-shadow(0 1px 0 rgba(255,255,255,0.1)) drop-shadow(0 -1px 0 rgba(0,0,0,0.8))") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Model number - Smaller debossed text") \
- CSS_SELECTOR(".crt-brand__model") \
- CSS_PROPERTY("font-family", "var(--font-mono)") \
- CSS_PROPERTY("font-size", "clamp(0.45rem, 0.9vmin, 0.55rem)") \
- CSS_PROPERTY("font-weight", "500") \
- CSS_PROPERTY("letter-spacing", "0.2em") \
- CSS_PROPERTY("color", "#2a2a2a") \
- CSS_COMMENT("Debossed into plastic effect") \
- CSS_PROPERTY("text-shadow", "0 1px 0 rgba(255,255,255,0.05), 0 -0.5px 0 rgba(0,0,0,0.4)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("CRT Speaker Grille - Realistic perforated metal") \
- CSS_SELECTOR(".crt-speaker") \
- CSS_PROPERTY("display", "flex") \
- CSS_PROPERTY("gap", "2px") \
- CSS_PROPERTY("padding", "4px 8px") \
- CSS_COMMENT("Recessed grille area") \
- CSS_PROPERTY("background", "linear-gradient(180deg, #080808 0%, #0d0d0d 50%, #080808 100%)") \
- CSS_PROPERTY("border-radius", "3px") \
- CSS_PROPERTY("box-shadow", "inset 0 2px 4px rgba(0,0,0,0.8), inset 0 -1px 0 rgba(40,40,40,0.2), 0 1px 0 rgba(40,40,40,0.1)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".crt-speaker span") \
- CSS_PROPERTY("width", "3px") \
- CSS_PROPERTY("height", "clamp(14px, 2.2vmin, 24px)") \
- CSS_COMMENT("Individual speaker slot with depth") \
- CSS_PROPERTY("background", "linear-gradient(180deg, #020202 0%, #080808 30%, #0a0a0a 50%, #080808 70%, #020202 100%)") \
- CSS_PROPERTY("border-radius", "1px") \
- CSS_PROPERTY("box-shadow", "inset 0 1px 3px rgba(0,0,0,1), 0 0 0 0.5px rgba(30,30,30,0.5)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Top control bar - Terminal style") \
- CSS_SELECTOR(".control-bar") \
- CSS_PROPERTY("display", "flex") \
- CSS_PROPERTY("align-items", "center") \
- CSS_PROPERTY("justify-content", "space-between") \
- CSS_PROPERTY("padding", "1rem 0") \
- CSS_PROPERTY("margin-bottom", "1.5rem") \
- CSS_PROPERTY("border-bottom", "1px solid var(--border)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".control-bar__brand") \
- CSS_PROPERTY("font-family", "var(--font-mono)") \
- CSS_PROPERTY("font-size", "1rem") \
- CSS_PROPERTY("font-weight", "400") \
- CSS_PROPERTY("color", "var(--accent)") \
- CSS_PROPERTY("text-decoration", "none") \
- CSS_PROPERTY("letter-spacing", "0.05em") \
- CSS_PROPERTY("text-shadow", "var(--glow)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".control-bar__brand::before") \
- CSS_PROPERTY("content", "\"> \"") \
- CSS_PROPERTY("color", "var(--text)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".control-bar__brand::after") \
- CSS_PROPERTY("content", "\"_\"") \
- CSS_PROPERTY("animation", "cursor-blink 1s step-end infinite") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".control-bar__brand:hover") \
- CSS_PROPERTY("color", "var(--accent-hover)") \
- CSS_PROPERTY("text-shadow", "var(--glow-strong)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".control-bar__actions") \
- CSS_PROPERTY("display", "flex") \
- CSS_PROPERTY("align-items", "center") \
- CSS_PROPERTY("gap", "0.75rem") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Control buttons - Terminal style") \
- CSS_SELECTOR(".ctrl-btn") \
- CSS_PROPERTY("padding", "0.25rem 0.75rem") \
- CSS_PROPERTY("border-radius", "0") \
- CSS_PROPERTY("border", "1px solid var(--border)") \
- CSS_PROPERTY("background", "transparent") \
- CSS_PROPERTY("color", "var(--text)") \
- CSS_PROPERTY("cursor", "pointer") \
- CSS_PROPERTY("font-family", "var(--font-mono)") \
- CSS_PROPERTY("font-size", "0.75rem") \
- CSS_PROPERTY("text-transform", "uppercase") \
- CSS_PROPERTY("letter-spacing", "0.05em") \
- CSS_PROPERTY("transition", "all 0.15s ease") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".ctrl-btn:hover") \
- CSS_PROPERTY("background", "var(--text)") \
- CSS_PROPERTY("color", "var(--bg)") \
- CSS_PROPERTY("box-shadow", "var(--glow)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".ctrl-btn--accent") \
- CSS_PROPERTY("border-color", "var(--accent)") \
- CSS_PROPERTY("color", "var(--accent)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".ctrl-btn--accent:hover") \
- CSS_PROPERTY("background", "var(--accent)") \
- CSS_PROPERTY("color", "var(--bg)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Typography - Terminal style") \
- CSS_SELECTOR("h1, h2, h3, h4, h5, h6") \
- CSS_PROPERTY("font-family", "var(--font-mono)") \
- CSS_PROPERTY("font-weight", "400") \
- CSS_PROPERTY("line-height", "1.3") \
- CSS_PROPERTY("margin-top", "2rem") \
- CSS_PROPERTY("margin-bottom", "1rem") \
- CSS_PROPERTY("color", "var(--text)") \
- CSS_PROPERTY("clear", "both") \
- CSS_PROPERTY("text-shadow", "var(--glow)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("h1") \
- CSS_PROPERTY("font-size", "1.75rem") \
- CSS_PROPERTY("text-transform", "uppercase") \
- CSS_PROPERTY("letter-spacing", "0.1em") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("h2") \
- CSS_PROPERTY("font-size", "1.75rem") \
- CSS_PROPERTY("padding-bottom", "0.5rem") \
- CSS_PROPERTY("border-bottom", "2px solid var(--accent)") \
- CSS_PROPERTY("display", "inline-block") \
- CSS_PROPERTY("padding-right", "2rem") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("h3") \
- CSS_PROPERTY("font-size", "1.375rem") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("h4, h5, h6") \
- CSS_PROPERTY("font-size", "1.125rem") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("p") \
- CSS_PROPERTY("margin", "0 0 1.5rem 0") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("strong") \
- CSS_PROPERTY("font-weight", "600") \
- CSS_PROPERTY("color", "var(--strong)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Links") \
- CSS_SELECTOR("a") \
- CSS_PROPERTY("color", "var(--accent)") \
- CSS_PROPERTY("text-decoration", "none") \
- CSS_PROPERTY("border-bottom", "1px solid transparent") \
- CSS_PROPERTY("transition", "color 0.15s ease, border-color 0.15s ease") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("a:hover") \
- CSS_PROPERTY("color", "var(--accent-hover)") \
- CSS_PROPERTY("border-bottom-color", "var(--accent-hover)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("a:visited") \
- CSS_PROPERTY("color", "var(--accent)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("a > strong") \
- CSS_PROPERTY("color", "inherit") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Header and title block") \
- CSS_SELECTOR("#title-block-header") \
- CSS_PROPERTY("margin", "0 0 3rem 0") \
- CSS_PROPERTY("padding", "0") \
- CSS_PROPERTY("background", "transparent") \
- CSS_PROPERTY("border", "none") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("h1.title") \
- CSS_PROPERTY("font-size", "2.75rem") \
- CSS_PROPERTY("margin-top", "0") \
- CSS_PROPERTY("margin-bottom", "1rem") \
- CSS_PROPERTY("border-bottom", "none") \
- CSS_PROPERTY("padding-bottom", "0") \
- CSS_PROPERTY("line-height", "1.15") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("p.author") \
- CSS_PROPERTY("font-family", "var(--font-mono)") \
- CSS_PROPERTY("text-transform", "uppercase") \
- CSS_PROPERTY("font-size", "0.8125rem") \
- CSS_PROPERTY("letter-spacing", "0.1em") \
- CSS_PROPERTY("color", "var(--accent)") \
- CSS_PROPERTY("margin-bottom", "0.25rem") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("p.author::before") \
- CSS_PROPERTY("content", "\"// \"") \
- CSS_PROPERTY("opacity", "0.5") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("p.date") \
- CSS_PROPERTY("font-family", "var(--font-mono)") \
- CSS_PROPERTY("font-size", "0.8125rem") \
- CSS_PROPERTY("color", "var(--text-muted)") \
- CSS_PROPERTY("margin-bottom", "0") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("p.date::before") \
- CSS_PROPERTY("content", "\"\"") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Table of Contents") \
- CSS_SELECTOR("#TOC") \
- CSS_PROPERTY("background", "transparent") \
- CSS_PROPERTY("border", "none") \
- CSS_PROPERTY("border-left", "3px solid var(--border-strong)") \
- CSS_PROPERTY("padding", "0 0 0 1.5rem") \
- CSS_PROPERTY("margin", "0 0 3rem 0") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("#TOC::before") \
- CSS_PROPERTY("content", "\"CONTENTS\"") \
- CSS_PROPERTY("display", "block") \
- CSS_PROPERTY("font-family", "var(--font-mono)") \
- CSS_PROPERTY("font-size", "0.6875rem") \
- CSS_PROPERTY("letter-spacing", "0.15em") \
- CSS_PROPERTY("color", "var(--text-muted)") \
- CSS_PROPERTY("margin-bottom", "0.75rem") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("nav#TOC > ul") \
- CSS_PROPERTY("list-style-type", "none") \
- CSS_PROPERTY("padding-left", "0") \
- CSS_PROPERTY("margin", "0") \
- CSS_PROPERTY("counter-reset", "toc-h1") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("nav#TOC > ul > li") \
- CSS_PROPERTY("margin-bottom", "0.5rem") \
- CSS_PROPERTY("counter-increment", "toc-h1") \
- CSS_PROPERTY("counter-reset", "toc-h2") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("nav#TOC > ul > li::before") \
- CSS_PROPERTY("content", "counter(toc-h1) \".\"") \
- CSS_PROPERTY("font-family", "var(--font-mono)") \
- CSS_PROPERTY("font-size", "0.75rem") \
- CSS_PROPERTY("color", "var(--text-muted)") \
- CSS_PROPERTY("margin-right", "0.75rem") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Nested TOC items") \
- CSS_SELECTOR("nav#TOC ul ul") \
- CSS_PROPERTY("list-style-type", "none") \
- CSS_PROPERTY("padding-left", "1.5rem") \
- CSS_PROPERTY("margin", "0.5rem 0 0 0") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("nav#TOC ul ul li") \
- CSS_PROPERTY("margin-bottom", "0.35rem") \
- CSS_PROPERTY("counter-increment", "toc-h2") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("nav#TOC ul ul li::before") \
- CSS_PROPERTY("content", "counter(toc-h1) \".\" counter(toc-h2)") \
- CSS_PROPERTY("font-family", "var(--font-mono)") \
- CSS_PROPERTY("font-size", "0.6875rem") \
- CSS_PROPERTY("color", "var(--text-muted)") \
- CSS_PROPERTY("margin-right", "0.625rem") \
- CSS_PROPERTY("opacity", "0.7") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("nav#TOC ul li a") \
- CSS_PROPERTY("color", "var(--text)") \
- CSS_PROPERTY("font-size", "0.9375rem") \
- CSS_PROPERTY("border-bottom", "none") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("nav#TOC ul ul li a") \
- CSS_PROPERTY("font-size", "0.875rem") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("nav#TOC ul li a:hover") \
- CSS_PROPERTY("color", "var(--accent)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Collapsible TOC") \
- CSS_SELECTOR("#TOC.is-collapsible") \
- CSS_PROPERTY("position", "relative") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("#TOC.is-collapsible.is-collapsed > ul") \
- CSS_PROPERTY("max-height", "14rem") \
- CSS_PROPERTY("overflow", "hidden") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("#TOC.is-collapsible.is-collapsed::after") \
- CSS_PROPERTY("content", "\"\"") \
- CSS_PROPERTY("position", "absolute") \
- CSS_PROPERTY("bottom", "2.5rem") \
- CSS_PROPERTY("left", "0") \
- CSS_PROPERTY("right", "0") \
- CSS_PROPERTY("height", "4rem") \
- CSS_PROPERTY("background", "linear-gradient(to bottom, transparent, var(--bg))") \
- CSS_PROPERTY("pointer-events", "none") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".toc-toggle") \
- CSS_PROPERTY("display", "block") \
- CSS_PROPERTY("margin-top", "0.75rem") \
- CSS_PROPERTY("padding", "0.5rem 1rem") \
- CSS_PROPERTY("font-family", "var(--font-mono)") \
- CSS_PROPERTY("font-size", "0.75rem") \
- CSS_PROPERTY("letter-spacing", "0.05em") \
- CSS_PROPERTY("text-transform", "uppercase") \
- CSS_PROPERTY("color", "var(--accent)") \
- CSS_PROPERTY("background", "var(--accent-subtle)") \
- CSS_PROPERTY("border", "1px solid var(--accent)") \
- CSS_PROPERTY("border-radius", "4px") \
- CSS_PROPERTY("cursor", "pointer") \
- CSS_PROPERTY("transition", "all 0.15s ease") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".toc-toggle:hover") \
- CSS_PROPERTY("background", "var(--accent)") \
- CSS_PROPERTY("color", "var(--bg)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Main content") \
- CSS_SELECTOR("section") \
- CSS_PROPERTY("flex", "1 0 auto") \
- CSS_PROPERTY("padding", "0") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("header ~ *") \
- CSS_PROPERTY("margin", "0") \
- CSS_PROPERTY("padding", "0") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Images") \
- CSS_SELECTOR("img") \
- CSS_PROPERTY("max-width", "100%") \
- CSS_PROPERTY("height", "auto") \
- CSS_PROPERTY("border-radius", "4px") \
- CSS_PROPERTY("border", "none") \
- CSS_PROPERTY("background", "var(--bg-surface)") \
- CSS_PROPERTY("float", "right") \
- CSS_PROPERTY("clear", "right") \
- CSS_PROPERTY("margin-left", "2rem") \
- CSS_PROPERTY("margin-bottom", "1rem") \
- CSS_PROPERTY("max-height", "14rem") \
- CSS_PROPERTY("box-shadow", "var(--shadow-lg)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("figcaption") \
- CSS_PROPERTY("display", "none") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("blockquote img") \
- CSS_PROPERTY("float", "none") \
- CSS_PROPERTY("clear", "none") \
- CSS_PROPERTY("max-height", "24rem") \
- CSS_PROPERTY("margin", "0 auto") \
- CSS_PROPERTY("display", "block") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".zoomable") \
- CSS_PROPERTY("cursor", "zoom-in") \
- CSS_PROPERTY("max-width", "100%") \
- CSS_PROPERTY("max-height", "22rem") \
- CSS_PROPERTY("transition", "transform 0.2s ease, box-shadow 0.2s ease") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".zoomable:hover") \
- CSS_PROPERTY("transform", "scale(1.01)") \
- CSS_PROPERTY("box-shadow", "0 8px 30px rgba(0,0,0,0.15)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Blockquotes") \
- CSS_SELECTOR("blockquote") \
- CSS_PROPERTY("margin", "2rem 0") \
- CSS_PROPERTY("padding", "1.25rem 1.5rem") \
- CSS_PROPERTY("border-left", "4px solid var(--accent)") \
- CSS_PROPERTY("background", "var(--accent-subtle)") \
- CSS_PROPERTY("border-radius", "0 8px 8px 0") \
- CSS_PROPERTY("color", "var(--text)") \
- CSS_PROPERTY("clear", "both") \
- CSS_PROPERTY("font-style", "italic") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("blockquote p:last-child") \
- CSS_PROPERTY("margin-bottom", "0") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Code blocks") \
- CSS_SELECTOR("code") \
- CSS_PROPERTY("font-family", "var(--font-mono)") \
- CSS_PROPERTY("font-size", "0.875em") \
- CSS_PROPERTY("background", "var(--code-bg)") \
- CSS_PROPERTY("color", "var(--code-text)") \
- CSS_PROPERTY("padding", "0.2em 0.4em") \
- CSS_PROPERTY("border-radius", "4px") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("pre") \
- CSS_PROPERTY("background", "var(--code-bg)") \
- CSS_PROPERTY("border", "none") \
- CSS_PROPERTY("border-radius", "8px") \
- CSS_PROPERTY("padding", "1.25rem 1.5rem") \
- CSS_PROPERTY("margin", "1.5rem 0") \
- CSS_PROPERTY("overflow-x", "auto") \
- CSS_PROPERTY("max-height", "500px") \
- CSS_PROPERTY("font-size", "0.875rem") \
- CSS_PROPERTY("line-height", "1.65") \
- CSS_PROPERTY("box-shadow", "var(--shadow-lg)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("pre code") \
- CSS_PROPERTY("background", "transparent") \
- CSS_PROPERTY("padding", "0") \
- CSS_PROPERTY("border-radius", "0") \
- CSS_PROPERTY("font-size", "inherit") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("div.sourceCode") \
- CSS_PROPERTY("background", "var(--code-bg)") \
- CSS_PROPERTY("border", "none") \
- CSS_PROPERTY("border-radius", "8px") \
- CSS_PROPERTY("margin", "1.5rem 0") \
- CSS_PROPERTY("overflow", "auto") \
- CSS_PROPERTY("max-height", "500px") \
- CSS_PROPERTY("box-shadow", "var(--shadow-lg)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("div.sourceCode pre") \
- CSS_PROPERTY("margin", "0") \
- CSS_PROPERTY("border", "none") \
- CSS_PROPERTY("border-radius", "0") \
- CSS_PROPERTY("max-height", "none") \
- CSS_PROPERTY("overflow", "visible") \
- CSS_PROPERTY("box-shadow", "none") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("pre.numberSource") \
- CSS_PROPERTY("padding-left", "3.5em") \
- CSS_PROPERTY("counter-reset", "line-number") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("pre.numberSource code > span::before") \
- CSS_PROPERTY("counter-increment", "line-number") \
- CSS_PROPERTY("content", "counter(line-number)") \
- CSS_PROPERTY("display", "inline-block") \
- CSS_PROPERTY("width", "2.5em") \
- CSS_PROPERTY("margin-right", "1em") \
- CSS_PROPERTY("color", "var(--text-muted)") \
- CSS_PROPERTY("text-align", "right") \
- CSS_PROPERTY("opacity", "0.5") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Scrollbar styling") \
- CSS_SELECTOR("pre::-webkit-scrollbar, code::-webkit-scrollbar, div.sourceCode::-webkit-scrollbar") \
- CSS_PROPERTY("width", "8px") \
- CSS_PROPERTY("height", "8px") \
- CSS_PROPERTY("background", "transparent") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("pre::-webkit-scrollbar-thumb, code::-webkit-scrollbar-thumb, div.sourceCode::-webkit-scrollbar-thumb") \
- CSS_PROPERTY("background", "var(--scrollbar-thumb)") \
- CSS_PROPERTY("border-radius", "4px") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("pre::-webkit-scrollbar-track, code::-webkit-scrollbar-track, div.sourceCode::-webkit-scrollbar-track") \
- CSS_PROPERTY("background", "var(--scrollbar-bg)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Tables") \
- CSS_SELECTOR("table") \
- CSS_PROPERTY("width", "100%") \
- CSS_PROPERTY("border-collapse", "collapse") \
- CSS_PROPERTY("margin", "2rem 0") \
- CSS_PROPERTY("font-size", "0.9375rem") \
- CSS_PROPERTY("background", "var(--bg-surface)") \
- CSS_PROPERTY("border", "1px solid var(--border)") \
- CSS_PROPERTY("border-radius", "8px") \
- CSS_PROPERTY("overflow", "hidden") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("thead") \
- CSS_PROPERTY("background", "var(--table-header)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("th, td") \
- CSS_PROPERTY("padding", "0.875rem 1.25rem") \
- CSS_PROPERTY("text-align", "left") \
- CSS_PROPERTY("border-bottom", "1px solid var(--border)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("th") \
- CSS_PROPERTY("font-family", "var(--font-mono)") \
- CSS_PROPERTY("font-weight", "600") \
- CSS_PROPERTY("font-size", "0.75rem") \
- CSS_PROPERTY("text-transform", "uppercase") \
- CSS_PROPERTY("letter-spacing", "0.05em") \
- CSS_PROPERTY("color", "var(--text-muted)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("tbody tr:nth-child(even)") \
- CSS_PROPERTY("background", "var(--table-row-alt)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("tbody tr:hover") \
- CSS_PROPERTY("background", "var(--table-hover)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Footer") \
- CSS_SELECTOR("footer") \
- CSS_PROPERTY("margin-top", "4rem") \
- CSS_PROPERTY("padding", "2rem 0") \
- CSS_PROPERTY("border-top", "1px solid var(--border)") \
- CSS_PROPERTY("background", "transparent") \
- CSS_PROPERTY("color", "var(--text-muted)") \
- CSS_PROPERTY("font-size", "0.875rem") \
- CSS_PROPERTY("text-align", "center") \
- CSS_PROPERTY("flex-shrink", "0") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("footer > span") \
- CSS_PROPERTY("display", "flex") \
- CSS_PROPERTY("justify-content", "center") \
- CSS_PROPERTY("align-items", "center") \
- CSS_PROPERTY("flex-wrap", "wrap") \
- CSS_PROPERTY("gap", "0.25rem") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("footer a") \
- CSS_PROPERTY("color", "var(--text-muted)") \
- CSS_PROPERTY("border-bottom", "none") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("footer a:hover") \
- CSS_PROPERTY("color", "var(--accent)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".hearth") \
- CSS_PROPERTY("display", "inline-flex") \
- CSS_PROPERTY("color", "var(--heart)") \
- CSS_PROPERTY("margin", "0 0.25rem") \
- CSS_PROPERTY("animation", "pulse 1.5s ease-in-out infinite") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("b.author") \
- CSS_PROPERTY("color", "var(--text)") \
- CSS_PROPERTY("font-weight", "600") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Heart animation") \
- CSS_KEYFRAMES("pulse") \
- CSS_KEYFRAME("0%, 100%") \
- CSS_KEYFRAME_PROPERTY("transform", "scale(1)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("50%") \
- CSS_KEYFRAME_PROPERTY("transform", "scale(1.2)") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAMES_END() \
- CSS_COMMENT("Image modal") \
- CSS_SELECTOR(".modal") \
- CSS_PROPERTY("position", "fixed") \
- CSS_PROPERTY("inset", "0") \
- CSS_PROPERTY("background", "rgba(0, 0, 0, 0.9)") \
- CSS_PROPERTY("backdrop-filter", "blur(8px)") \
- CSS_PROPERTY("z-index", "10000") \
- CSS_PROPERTY("cursor", "zoom-out") \
- CSS_PROPERTY("display", "flex") \
- CSS_PROPERTY("align-items", "center") \
- CSS_PROPERTY("justify-content", "center") \
- CSS_PROPERTY("animation", "fadeIn 0.2s ease") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR(".modal img") \
- CSS_PROPERTY("max-height", "90vh") \
- CSS_PROPERTY("max-width", "95vw") \
- CSS_PROPERTY("border-radius", "4px") \
- CSS_PROPERTY("box-shadow", "0 25px 50px rgba(0,0,0,0.5)") \
- CSS_PROPERTY("border", "none") \
- CSS_PROPERTY("float", "none") \
- CSS_PROPERTY("margin", "0") \
- CSS_END_SELECTOR() \
- CSS_KEYFRAMES("fadeIn") \
- CSS_KEYFRAME("from") \
- CSS_KEYFRAME_PROPERTY("opacity", "0") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAME("to") \
- CSS_KEYFRAME_PROPERTY("opacity", "1") \
- CSS_KEYFRAME_END() \
- CSS_KEYFRAMES_END() \
- CSS_COMMENT("Horizontal rule") \
- CSS_SELECTOR("hr") \
- CSS_PROPERTY("border", "none") \
- CSS_PROPERTY("height", "2px") \
- CSS_PROPERTY("background", "linear-gradient(90deg, var(--accent) 0%, transparent 100%)") \
- CSS_PROPERTY("margin", "3rem 0") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Lists") \
- CSS_SELECTOR("ul, ol") \
- CSS_PROPERTY("padding-left", "1.5rem") \
- CSS_PROPERTY("margin", "1.5rem 0") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("li") \
- CSS_PROPERTY("margin-bottom", "0.5rem") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("li::marker") \
- CSS_PROPERTY("color", "var(--accent)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Syntax highlighting - Pandoc classes") \
- CSS_SELECTOR("code span.kw") \
- CSS_PROPERTY("color", "var(--syn-keyword)") \
- CSS_PROPERTY("font-weight", "500") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("code span.cf") \
- CSS_PROPERTY("color", "var(--syn-control)") \
- CSS_PROPERTY("font-weight", "500") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("code span.dt") \
- CSS_PROPERTY("color", "var(--syn-type)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("code span.dv, code span.bn, code span.fl") \
- CSS_PROPERTY("color", "var(--syn-number)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("code span.st, code span.ss, code span.vs") \
- CSS_PROPERTY("color", "var(--syn-string)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("code span.ch, code span.sc") \
- CSS_PROPERTY("color", "var(--syn-char)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("code span.co, code span.cv") \
- CSS_PROPERTY("color", "var(--syn-comment)") \
- CSS_PROPERTY("font-style", "italic") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("code span.fu") \
- CSS_PROPERTY("color", "var(--syn-function)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("code span.va") \
- CSS_PROPERTY("color", "var(--syn-variable)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("code span.op") \
- CSS_PROPERTY("color", "var(--syn-operator)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("code span.bu") \
- CSS_PROPERTY("color", "var(--syn-builtin)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("code span.cn") \
- CSS_PROPERTY("color", "var(--syn-constant)") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("code span.al, code span.er") \
- CSS_PROPERTY("color", "#ef4444") \
- CSS_PROPERTY("font-weight", "600") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("code span.wa") \
- CSS_PROPERTY("color", "#eab308") \
- CSS_PROPERTY("font-style", "italic") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("code span.an, code span.in, code span.do") \
- CSS_PROPERTY("color", "var(--syn-comment)") \
- CSS_PROPERTY("font-style", "italic") \
- CSS_END_SELECTOR() \
- CSS_SELECTOR("code span.ot, code span.at, code span.pp") \
- CSS_PROPERTY("color", "var(--syn-special)") \
- CSS_END_SELECTOR() \
- CSS_COMMENT("Responsive - Tablet") \
- "@media (max-width: 900px) {\\n" \
- " .crt-monitor { padding: clamp(8px, 1.5vmin, 20px); }\\n" \
- " .crt-bezel { padding: clamp(4px, 0.8vmin, 10px); }\\n" \
- " .crt-content-inner { padding: 1.5rem 1.75rem; }\\n" \
- " .crt-bottom { padding: 8px 16px; }\\n" \
- " h1.title { font-size: 1.75rem; }\\n" \
- " img { max-height: 12rem; }\\n" \
- " .zoomable { max-height: 18rem; }\\n" \
- "}\\n" \
- CSS_COMMENT("Responsive - Mobile") \
- "@media (max-width: 640px) {\\n" \
- " body { font-size: 0.9375rem; }\\n" \
- " .crt-monitor { padding: 6px; }\\n" \
- " .crt-bezel { padding: 4px; border-radius: 4px; }\\n" \
- " .crt-screen { border-radius: 12px / 10px; }\\n" \
- " .crt-content-inner { padding: 1rem 1.25rem; }\\n" \
- " .crt-bottom { padding: 6px 12px; }\\n" \
- " .crt-led { width: 6px; height: 6px; }\\n" \
- " .crt-brand { font-size: 0.5rem; letter-spacing: 0.15em; }\\n" \
- " .crt-speaker span { width: 2px; height: 10px; }\\n" \
- " .control-bar { padding: 0.5rem 0; margin-bottom: 0.75rem; }\\n" \
- " .control-bar__brand { font-size: 0.8125rem; }\\n" \
- " .ctrl-btn { padding: 0.15rem 0.4rem; font-size: 0.6rem; }\\n" \
- " h1 { font-size: 1.375rem; }\\n" \
- " h1.title { font-size: 1.375rem; }\\n" \
- " h2 { font-size: 1.125rem; padding-right: 0; display: block; }\\n" \
- " h3 { font-size: 1rem; }\\n" \
- " img { float: none; margin: 1.25rem auto; display: block; max-height: 10rem; }\\n" \
- " blockquote img { max-height: 14rem; }\\n" \
- " .zoomable { max-height: 12rem; max-width: 100%; }\\n" \
- " pre { font-size: 0.6875rem; padding: 0.75rem; }\\n" \
- " code { font-size: 0.7em; }\\n" \
- " table { font-size: 0.75rem; }\\n" \
- " th, td { padding: 0.4rem 0.6rem; }\\n" \
- " footer { margin-top: 1.5rem; padding: 0.75rem 0; font-size: 0.6875rem; }\\n" \
- " #TOC { padding-left: 0.5rem; }\\n" \
- " nav#TOC ul li a { font-size: 0.75rem; }\\n" \
- " nav#TOC ul ul li a { font-size: 0.6875rem; }\\n" \
- "}\\n" \
- CSS_COMMENT("Responsive - Small mobile") \
- "@media (max-width: 380px) {\\n" \
- " body { font-size: 0.8125rem; }\\n" \
- " .crt-monitor { padding: 4px; }\\n" \
- " .crt-bezel { padding: 3px; }\\n" \
- " .crt-content-inner { padding: 0.75rem 1rem; }\\n" \
- " .crt-bottom { display: none; }\\n" \
- " .control-bar__brand { font-size: 0.6875rem; }\\n" \
- " h1 { font-size: 1.125rem; }\\n" \
- " h1.title { font-size: 1.125rem; }\\n" \
- " pre { font-size: 0.625rem; }\\n" \
- "}\\n"
-
-#define HEAD_HTML \
- HTML_RAWTEXT("") \
- HTML_NEWLINE() \
- HTML_RAWTEXT("") \
- HTML_NEWLINE() \
- HTML_RAWTEXT("") \
- HTML_NEWLINE() \
- HTML_RAWTEXT("") \
- HTML_NEWLINE() \
- HTML_RAWTEXT("") \
- HTML_NEWLINE() \
- HTML_RAWTEXT("") \
- HTML_NEWLINE() \
- HTML_RAWTEXT("") \
- HTML_NEWLINE() \
- HTML_RAWTEXT("") \
- HTML_NEWLINE() \
- HTML_RAWTEXT("") \
- HTML_NEWLINE() \
- HTML_TAG_OPEN("script", "") \
- HTML_RAWTEXT("(function(){") \
- HTML_RAWTEXT("var p=localStorage.getItem('phosphor-preference');") \
- HTML_RAWTEXT("if(p)document.documentElement.classList.add('phosphor-'+p);") \
- HTML_RAWTEXT("})();") \
- HTML_TAG_CLOSE("script") \
- HTML_NEWLINE()
-
+#define MAIN_CSS \
+ "/* ==========================================================================\n" \
+ " GRIDRUNNER — production theme for libdzonerzy.so\n" \
+ " synthwave horizon: neon grid, wireframe ridges, striped sun, glass cards\n" \
+ " fonts: Orbitron (display) + JetBrains Mono (body)\n" \
+ " ========================================================================== */\n" \
+ "\n" \
+ ":root {\n" \
+ " --bg0: #0d0221;\n" \
+ " --bg1: #2d1b4e;\n" \
+ " --bg2: #4c1d95;\n" \
+ " --cyan: #00fff9;\n" \
+ " --magenta: #ff2bd6;\n" \
+ " --purple: #7b2ff7;\n" \
+ " --yellow: #ffd319;\n" \
+ " --pink: #ff6ac1;\n" \
+ " --teal: #2dd4bf;\n" \
+ " --red: #ff4d5e;\n" \
+ " --amber: #fbbf24;\n" \
+ " --text: #e6e6fa;\n" \
+ " --muted: #a79bc9;\n" \
+ " --card: rgba(20, 10, 40, 0.55);\n" \
+ " --hairline: rgba(0, 255, 249, 0.16);\n" \
+ "}\n" \
+ "\n" \
+ "* { box-sizing: border-box; }\n" \
+ "\n" \
+ "html { scroll-behavior: smooth; }\n" \
+ "\n" \
+ "body {\n" \
+ " margin: 0;\n" \
+ " min-height: 100vh;\n" \
+ " color: var(--text);\n" \
+ " font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;\n" \
+ " font-size: 16px;\n" \
+ " line-height: 1.65;\n" \
+ " /* sky gradient lives behind the transparent WebGL canvas, and carries\n" \
+ " the page on its own when WebGL is unavailable */\n" \
+ " background: linear-gradient(180deg, var(--bg0) 0%, var(--bg1) 52%, var(--bg2) 100%) fixed;\n" \
+ " overflow-x: hidden;\n" \
+ " overflow-x: clip; /* keeps position:sticky working where supported */\n" \
+ "}\n" \
+ "\n" \
+ "/* fixed WebGL canvas: below all in-flow content, above the body gradient */\n" \
+ "#bg-canvas {\n" \
+ " position: fixed;\n" \
+ " inset: 0;\n" \
+ " z-index: -1;\n" \
+ " display: block;\n" \
+ "}\n" \
+ "\n" \
+ "/* soft vignette above the canvas, below the content */\n" \
+ "body::after {\n" \
+ " content: \"\";\n" \
+ " position: fixed;\n" \
+ " inset: 0;\n" \
+ " z-index: -1;\n" \
+ " pointer-events: none;\n" \
+ " background: radial-gradient(ellipse at 50% 42%, transparent 50%, rgba(13, 2, 33, 0.6) 100%);\n" \
+ "}\n" \
+ "\n" \
+ "/* content column (pandoc emits sections directly under
$subtitle$
+$endif$ +$for(author)$ + +$endfor$ +$if(date)$ +$date$
+$endif$ +$if(abstract)$ +n.far?null:{distance:c,point:Vn.clone(),object:t}}(t,e,n,i,Cn,Pn,Dn,kn);if(p){o&&(Hn.fromBufferAttribute(o,c),Gn.fromBufferAttribute(o,h),Un.fromBufferAttribute(o,u),p.uv=je.getUV(kn,Cn,Pn,Dn,Hn,Gn,Un,new vt)),l&&(Hn.fromBufferAttribute(l,c),Gn.fromBufferAttribute(l,h),Un.fromBufferAttribute(l,u),p.uv2=je.getUV(kn,Cn,Pn,Dn,Hn,Gn,Un,new vt));const t={a:c,b:h,c:u,normal:new Lt,materialIndex:0};je.getNormal(Cn,Pn,Dn,t.normal),p.face=t}return p}Wn.prototype.isMesh=!0;class qn extends En{constructor(t=1,e=1,n=1,i=1,r=1,s=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:n,widthSegments:i,heightSegments:r,depthSegments:s};const a=this;i=Math.floor(i),r=Math.floor(r),s=Math.floor(s);const o=[],l=[],c=[],h=[];let u=0,d=0;function p(t,e,n,i,r,s,p,m,f,g,v){const y=s/f,x=p/g,_=s/2,w=p/2,b=m/2,M=f+1,S=g+1;let T=0,E=0;const A=new Lt;for(let s=0;s0?1:-1,c.push(A.x,A.y,A.z),h.push(o/f),h.push(1-s/g),T+=1}}for(let t=0;t