@whykusanagi/corrupted-theme 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,263 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Corrupted Particles - Corrupted Theme</title>
7
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
8
+ <link rel="stylesheet" href="../../src/css/theme.css">
9
+ <style>
10
+ body { margin: 0; background: #000; overflow: hidden; }
11
+
12
+ #particles-canvas {
13
+ position: fixed;
14
+ inset: 0;
15
+ width: 100%;
16
+ height: 100%;
17
+ z-index: 0;
18
+ }
19
+
20
+ .ui-layer {
21
+ position: relative;
22
+ z-index: 1;
23
+ display: flex;
24
+ flex-direction: column;
25
+ align-items: center;
26
+ justify-content: center;
27
+ min-height: 100vh;
28
+ padding: var(--spacing-2xl);
29
+ gap: var(--spacing-xl);
30
+ pointer-events: none;
31
+ }
32
+
33
+ .controls-panel {
34
+ pointer-events: auto;
35
+ background: var(--glass);
36
+ border: 1px solid var(--border);
37
+ border-radius: var(--radius-lg);
38
+ padding: var(--spacing-lg);
39
+ width: 100%;
40
+ max-width: 440px;
41
+ backdrop-filter: blur(12px);
42
+ }
43
+
44
+ .controls-panel h2 {
45
+ color: var(--accent);
46
+ margin: 0 0 var(--spacing-md);
47
+ font-size: 0.9rem;
48
+ text-transform: uppercase;
49
+ letter-spacing: 0.1em;
50
+ }
51
+
52
+ .control-row {
53
+ display: flex;
54
+ align-items: center;
55
+ gap: var(--spacing-md);
56
+ margin-bottom: var(--spacing-sm);
57
+ }
58
+
59
+ .control-row label {
60
+ color: var(--text-muted);
61
+ font-size: 0.8rem;
62
+ width: 110px;
63
+ flex-shrink: 0;
64
+ }
65
+
66
+ .control-row input[type="range"] {
67
+ flex: 1;
68
+ accent-color: var(--corrupted-magenta);
69
+ }
70
+
71
+ .val {
72
+ color: var(--corrupted-cyan);
73
+ font-size: 0.8rem;
74
+ width: 40px;
75
+ text-align: right;
76
+ }
77
+
78
+ .lewd-row {
79
+ border-top: 1px solid var(--border);
80
+ margin-top: var(--spacing-sm);
81
+ padding-top: var(--spacing-sm);
82
+ display: flex;
83
+ align-items: center;
84
+ gap: var(--spacing-md);
85
+ }
86
+
87
+ .lewd-row label {
88
+ color: var(--corrupted-purple);
89
+ font-size: 0.8rem;
90
+ flex: 1;
91
+ }
92
+
93
+ .lewd-row span.rating {
94
+ color: var(--corrupted-red);
95
+ font-size: 0.7rem;
96
+ border: 1px solid var(--corrupted-red);
97
+ padding: 1px 4px;
98
+ border-radius: 3px;
99
+ }
100
+
101
+ .code-block {
102
+ pointer-events: auto;
103
+ background: var(--glass);
104
+ border: 1px solid var(--border);
105
+ border-radius: var(--radius-lg);
106
+ padding: var(--spacing-lg);
107
+ width: 100%;
108
+ max-width: 540px;
109
+ }
110
+
111
+ .code-block h3 {
112
+ color: var(--accent);
113
+ font-size: 0.8rem;
114
+ text-transform: uppercase;
115
+ letter-spacing: 0.1em;
116
+ margin: 0 0 var(--spacing-md);
117
+ }
118
+
119
+ .code-block pre {
120
+ margin: 0;
121
+ overflow-x: auto;
122
+ font-size: 0.75rem;
123
+ color: var(--corrupted-cyan);
124
+ line-height: 1.5;
125
+ }
126
+ </style>
127
+ </head>
128
+ <body>
129
+
130
+ <nav class="navbar">
131
+ <div class="navbar-content">
132
+ <a href="../index.html" class="navbar-logo"><i class="fas fa-palette"></i> Corrupted Theme</a>
133
+ <ul class="navbar-links">
134
+ <li><a href="../index.html"><i class="fas fa-home"></i> Home</a></li>
135
+ <li class="has-submenu">
136
+ <a href="../showcase-complete.html">
137
+ <i class="fas fa-cube"></i> Components
138
+ <i class="fas fa-chevron-down" style="font-size: 0.7em; margin-left: 4px;"></i>
139
+ </a>
140
+ <div class="submenu">
141
+ <a href="../showcase-complete.html"><i class="fas fa-layer-group"></i> All Components</a>
142
+ <a href="../showcase-complete.html#glass"><i class="fas fa-square"></i> Glass</a>
143
+ <a href="../showcase-complete.html#components"><i class="fas fa-shapes"></i> Standard</a>
144
+ <a href="../showcase-complete.html#navigation"><i class="fas fa-bars"></i> Navigation</a>
145
+ <a href="../showcase-complete.html#api-docs"><i class="fas fa-code"></i> API Docs</a>
146
+ </div>
147
+ </li>
148
+ <li class="has-submenu">
149
+ <a href="../extensions-showcase.html" class="active">
150
+ <i class="fas fa-puzzle-piece"></i> Extensions
151
+ <i class="fas fa-chevron-down" style="font-size: 0.7em; margin-left: 4px;"></i>
152
+ </a>
153
+ <div class="submenu">
154
+ <a href="../extensions-showcase.html#gallery"><i class="fas fa-images"></i> Gallery</a>
155
+ <a href="../extensions-showcase.html#lightbox"><i class="fas fa-expand"></i> Lightbox</a>
156
+ <a href="../extensions-showcase.html#nsfw"><i class="fas fa-eye-slash"></i> NSFW Blur</a>
157
+ <a href="../extensions-showcase.html#social"><i class="fas fa-share-alt"></i> Social Links</a>
158
+ <a href="../extensions-showcase.html#countdown"><i class="fas fa-hourglass-half"></i> Countdown</a>
159
+ <a href="glsl-vortex.html"><i class="fas fa-hurricane"></i> GLSL Vortex</a>
160
+ <a href="particles-bg.html" class="active"><i class="fas fa-atom"></i> Particles BG</a>
161
+ </div>
162
+ </li>
163
+ <li class="has-submenu">
164
+ <a href="#">
165
+ <i class="fas fa-flask"></i> Examples
166
+ <i class="fas fa-chevron-down" style="font-size: 0.7em; margin-left: 4px;"></i>
167
+ </a>
168
+ <div class="submenu">
169
+ <a href="../nikke-team-builder.html"><i class="fas fa-users"></i> Nikke Team Builder</a>
170
+ <a href="../button.html"><i class="fas fa-hand-pointer"></i> Buttons</a>
171
+ <a href="../card.html"><i class="fas fa-square"></i> Cards</a>
172
+ <a href="../form.html"><i class="fas fa-edit"></i> Forms</a>
173
+ <a href="../layout.html"><i class="fas fa-columns"></i> Layouts</a>
174
+ <a href="../basic/corrupted-text.html"><i class="fas fa-terminal"></i> Character Corruption</a>
175
+ <a href="../basic/typing-animation.html"><i class="fas fa-keyboard"></i> Buffer Corruption</a>
176
+ </div>
177
+ </li>
178
+ <li><a href="../showcase-complete.html"><i class="fas fa-book"></i> Docs</a></li>
179
+ </ul>
180
+ </div>
181
+ </nav>
182
+
183
+ <canvas id="particles-canvas"></canvas>
184
+
185
+ <div class="ui-layer">
186
+
187
+ <!-- Controls -->
188
+ <div class="controls-panel">
189
+ <h2><i class="fas fa-sliders-h"></i> Particle Controls</h2>
190
+
191
+ <div class="control-row">
192
+ <label>Count</label>
193
+ <input type="range" id="ctrl-count" min="10" max="120" step="5" value="60">
194
+ <span class="val" id="val-count">60</span>
195
+ </div>
196
+
197
+ <div class="control-row">
198
+ <label>Speed</label>
199
+ <input type="range" id="ctrl-speed" min="0.1" max="3.0" step="0.05" value="1.0">
200
+ <span class="val" id="val-speed">1.00</span>
201
+ </div>
202
+
203
+ <div class="control-row">
204
+ <label>Line Distance</label>
205
+ <input type="range" id="ctrl-linedist" min="50" max="300" step="10" value="150">
206
+ <span class="val" id="val-linedist">150</span>
207
+ </div>
208
+
209
+ <div class="lewd-row">
210
+ <label for="ctrl-lewd"><i class="fas fa-exclamation-triangle"></i> Lewd Mode</label>
211
+ <span class="rating">18+</span>
212
+ <input type="checkbox" id="ctrl-lewd">
213
+ </div>
214
+ </div>
215
+
216
+ <!-- Code snippet -->
217
+ <div class="code-block">
218
+ <h3>Usage</h3>
219
+ <pre><code>&lt;canvas id="bg" style="position:fixed;inset:0;width:100%;height:100%;z-index:0;"&gt;&lt;/canvas&gt;
220
+ &lt;script src="src/lib/corrupted-particles.js"&gt;&lt;/script&gt;
221
+ &lt;script&gt;
222
+ new CorruptedParticles(document.getElementById('bg'), {
223
+ count: 60, // desktop (mobile auto-halved)
224
+ speed: 1.0,
225
+ lineDistance: 150,
226
+ includeLewd: false, // 18+ contexts only
227
+ });
228
+ &lt;/script&gt;</code></pre>
229
+ </div>
230
+
231
+ </div>
232
+
233
+ <script src="../../src/lib/corrupted-particles.js"></script>
234
+ <script>
235
+ const canvas = document.getElementById('particles-canvas');
236
+ let cp = new CorruptedParticles(canvas);
237
+
238
+ function rebuildWithOptions() {
239
+ cp.destroy();
240
+ cp = new CorruptedParticles(canvas, {
241
+ count: parseInt(document.getElementById('ctrl-count').value),
242
+ speed: parseFloat(document.getElementById('ctrl-speed').value),
243
+ lineDistance: parseInt(document.getElementById('ctrl-linedist').value),
244
+ includeLewd: document.getElementById('ctrl-lewd').checked,
245
+ });
246
+ }
247
+
248
+ function wire(id, valId, fmt) {
249
+ const el = document.getElementById(id);
250
+ const v = document.getElementById(valId);
251
+ el.addEventListener('input', () => {
252
+ v.textContent = fmt ? parseFloat(el.value).toFixed(2) : el.value;
253
+ });
254
+ el.addEventListener('change', rebuildWithOptions);
255
+ }
256
+
257
+ wire('ctrl-count', 'val-count', false);
258
+ wire('ctrl-speed', 'val-speed', true);
259
+ wire('ctrl-linedist', 'val-linedist', false);
260
+ document.getElementById('ctrl-lewd').addEventListener('change', rebuildWithOptions);
261
+ </script>
262
+ </body>
263
+ </html>
@@ -107,7 +107,6 @@
107
107
  <a href="../layout.html"><i class="fas fa-columns"></i> Layouts</a>
108
108
  <a href="corrupted-text.html" class="active"><i class="fas fa-terminal"></i> Character Corruption</a>
109
109
  <a href="typing-animation.html"><i class="fas fa-keyboard"></i> Buffer Corruption</a>
110
- <a href="../advanced/nsfw-corruption.html"><i class="fas fa-exclamation-triangle"></i> NSFW (18+)</a>
111
110
  </div>
112
111
  </li>
113
112
  <li><a href="../showcase-complete.html"><i class="fas fa-book"></i> Docs</a></li>
@@ -211,12 +210,12 @@ instance.start();</div>
211
210
  <li><strong>Character Sets:</strong> Katakana, Hiragana, Romaji, Symbols for visual glitch</li>
212
211
  <li><strong>Colors:</strong> Magenta/Purple corruption, White for decoded text</li>
213
212
  <li><strong>Auto-initialization:</strong> Elements with class <code>corrupted-multilang</code></li>
214
- <li><strong>Script:</strong> <code>src/core/corrupted-text.js</code></li>
213
+ <li><strong>Script:</strong> <code>src/lib/corrupted-text.js</code></li>
215
214
  </ul>
216
215
  </section>
217
216
  </div>
218
217
 
219
- <script src="../../src/core/corrupted-text.js"></script>
218
+ <script src="../../src/lib/corrupted-text.js"></script>
220
219
  <script>
221
220
  // Example 2: Manual control
222
221
  const example2 = document.getElementById('example2');
@@ -128,6 +128,61 @@
128
128
  border-color: var(--accent);
129
129
  box-shadow: 0 0 0 2px rgba(255, 0, 255, 0.1);
130
130
  }
131
+
132
+ /* Content rating toggle */
133
+ .content-toggle {
134
+ display: flex;
135
+ align-items: center;
136
+ gap: var(--spacing-sm);
137
+ padding: var(--spacing-md);
138
+ background: var(--glass);
139
+ border: 1px solid var(--border);
140
+ border-radius: var(--radius-md);
141
+ margin-bottom: var(--spacing-md);
142
+ }
143
+
144
+ .toggle-label {
145
+ display: flex;
146
+ align-items: center;
147
+ gap: var(--spacing-sm);
148
+ cursor: pointer;
149
+ color: var(--text);
150
+ user-select: none;
151
+ }
152
+
153
+ .toggle-label input[type="checkbox"] {
154
+ width: 18px;
155
+ height: 18px;
156
+ cursor: pointer;
157
+ accent-color: var(--corrupted-red);
158
+ }
159
+
160
+ .toggle-label .toggle-hint {
161
+ color: var(--text-secondary);
162
+ font-size: 0.85em;
163
+ }
164
+
165
+ /* NSFW warning banner (shown only when toggle is on) */
166
+ .nsfw-warning {
167
+ background: rgba(255, 0, 0, 0.1);
168
+ border: 2px solid var(--corrupted-red);
169
+ border-radius: var(--radius-lg);
170
+ padding: var(--spacing-lg);
171
+ margin-bottom: var(--spacing-xl);
172
+ box-shadow: 0 0 30px rgba(255, 0, 0, 0.2);
173
+ }
174
+
175
+ .nsfw-warning h3 {
176
+ color: var(--corrupted-red);
177
+ margin: 0 0 var(--spacing-sm);
178
+ font-size: 1.1rem;
179
+ }
180
+
181
+ .nsfw-warning p {
182
+ color: var(--text-secondary);
183
+ margin: 0;
184
+ line-height: 1.6;
185
+ }
131
186
  </style>
132
187
  </head>
133
188
  <body>
@@ -152,7 +207,6 @@
152
207
  <a href="../layout.html"><i class="fas fa-columns"></i> Layouts</a>
153
208
  <a href="corrupted-text.html"><i class="fas fa-terminal"></i> Character Corruption</a>
154
209
  <a href="typing-animation.html" class="active"><i class="fas fa-keyboard"></i> Buffer Corruption</a>
155
- <a href="../advanced/nsfw-corruption.html"><i class="fas fa-exclamation-triangle"></i> NSFW (18+)</a>
156
210
  </div>
157
211
  </li>
158
212
  <li><a href="../showcase-complete.html"><i class="fas fa-book"></i> Docs</a></li>
@@ -163,14 +217,33 @@
163
217
  <div class="container">
164
218
  <h1><i class="fas fa-keyboard"></i> Buffer Corruption</h1>
165
219
  <p style="color: var(--text-secondary); margin-bottom: var(--spacing-lg);">
166
- Pattern 2: Phrase flickering with buffer corruption (SFW mode).
220
+ Pattern 2: Phrase flickering with buffer corruption. Content rating is controlled by the
221
+ <code>nsfw</code> option — toggle below to switch between SFW and NSFW phrase pools.
167
222
  </p>
168
223
 
169
- <div class="info-badge sfw-badge">
224
+ <!-- Content rating toggle (off by default — NSFW is explicit opt-in per corrupted-theme spec) -->
225
+ <div class="content-toggle">
226
+ <label class="toggle-label">
227
+ <input type="checkbox" id="nsfwToggle">
228
+ <span><i class="fas fa-exclamation-triangle"></i> <strong>Enable NSFW phrases</strong></span>
229
+ <span class="toggle-hint">(18+ only — unchecked each page load)</span>
230
+ </label>
231
+ </div>
232
+
233
+ <!-- SFW badge (shown when NSFW is off) -->
234
+ <div id="sfwBadge" class="info-badge sfw-badge">
170
235
  <i class="fas fa-check-circle"></i>
171
236
  <span>SFW Mode - Cute & Playful</span>
172
237
  </div>
173
238
 
239
+ <!-- NSFW warning banner (shown when NSFW is on) -->
240
+ <div id="nsfwWarning" class="nsfw-warning" style="display: none;">
241
+ <h3><i class="fas fa-exclamation-triangle"></i> NSFW Mode Enabled (18+)</h3>
242
+ <p>Explicit, intimate, and suggestive phrases will appear in the corruption buffer in deep purple
243
+ (<code style="color: var(--corrupted-purple);">#8b5cf6</code>). This mode is for mature/horror
244
+ themed projects only. All demos below are re-instantiated with <code>nsfw: true</code>.</p>
245
+ </div>
246
+
174
247
  <!-- Basic Buffer Corruption -->
175
248
  <section id="basic" class="example-group">
176
249
  <h3>System Message with Buffer Corruption</h3>
@@ -197,8 +270,9 @@
197
270
  const element = document.getElementById('output');
198
271
  const typing = new TypingAnimation(element, {
199
272
  typingSpeed: 40, // Characters per second
200
- glitchChance: 0.08, // 8% corruption chance
201
- nsfw: false // SFW mode (default)
273
+ nsfw: false, // SFW mode (default)
274
+ loop: true, // Loop continuously
275
+ loopDelay: 2000 // 2s pause before looping
202
276
  });
203
277
 
204
278
  typing.start('Neural corruption detected...');</div>
@@ -219,12 +293,6 @@ typing.start('Neural corruption detected...');</div>
219
293
  <span id="speedValue">40 chars/sec</span>
220
294
  </div>
221
295
 
222
- <div class="slider-container">
223
- <label for="glitch"><i class="fas fa-bolt"></i> Corruption:</label>
224
- <input type="range" id="glitch" min="0" max="30" value="8" class="form-range">
225
- <span id="glitchValue">8%</span>
226
- </div>
227
-
228
296
  <div class="controls">
229
297
  <button class="btn" onclick="startExample2()">
230
298
  <i class="fas fa-play"></i> Start with Settings
@@ -232,8 +300,9 @@ typing.start('Neural corruption detected...');</div>
232
300
  </div>
233
301
 
234
302
  <div class="code-block">const typing = new TypingAnimation(element, {
235
- typingSpeed: 80, // Faster typing
236
- glitchChance: 0.20 // More corruption
303
+ typingSpeed: 80, // Faster typing
304
+ loop: true, // Loop continuously
305
+ loopDelay: 2000 // 2s pause before looping
237
306
  });</div>
238
307
  </section>
239
308
 
@@ -263,82 +332,94 @@ typing.start(message);</div>
263
332
  <h3><i class="fas fa-info-circle"></i> Component Information</h3>
264
333
  <ul style="color: var(--text-secondary); line-height: 1.8;">
265
334
  <li><strong>Type:</strong> Buffer Corruption / Phrase Flickering (Pattern 2)</li>
266
- <li><strong>Mode:</strong> SFW (Default) - Cute, playful, atmospheric phrases</li>
267
- <li><strong>Example Phrases:</strong> "かわいい", "nyaa~", "闇が...私を呼んでいる...", "Neural corruption detected..."</li>
268
- <li><strong>Color:</strong> Magenta (#d94f90) for SFW corruption, White for final text</li>
335
+ <li><strong>Default Mode:</strong> SFW cute, playful, atmospheric phrases</li>
336
+ <li><strong>NSFW Mode:</strong> Explicit opt-in via the toggle above (resets each page load)</li>
337
+ <li><strong>SFW Phrases:</strong> "かわいい", "nyaa~", "Neural corruption detected..."</li>
338
+ <li><strong>NSFW Phrases:</strong> Japanese/English intimate content, purple color scheme (see CORRUPTED_THEME_SPEC.md for full policy)</li>
339
+ <li><strong>Colors:</strong> White for final text, Magenta (<code>#d94f90</code>) for SFW buffer, Deep Purple (<code>#8b5cf6</code>) for NSFW buffer</li>
269
340
  <li><strong>Mental Model:</strong> Neural network decoding corrupted data buffer</li>
270
341
  <li><strong>Script:</strong> <code>src/core/typing-animation.js</code></li>
271
342
  </ul>
272
-
273
- <div class="alert alert-info" style="margin-top: var(--spacing-md);">
274
- <i class="fas fa-exclamation-circle"></i>
275
- <strong>NSFW Mode:</strong> For explicit content examples, see
276
- <a href="../advanced/nsfw-corruption.html" style="color: var(--accent);">advanced/nsfw-corruption.html</a> (18+ only)
277
- </div>
278
343
  </section>
279
344
  </div>
280
345
 
281
346
  <script type="module">
282
347
  import { TypingAnimation } from '../../src/core/typing-animation.js';
283
348
 
284
- // Example 1: Basic
285
- const output1 = document.getElementById('output1');
286
- let typing1 = new TypingAnimation(output1, {
287
- typingSpeed: 40,
288
- glitchChance: 0.08,
289
- nsfw: false
290
- });
291
-
292
- window.startExample1 = () => {
293
- typing1.start('Neural corruption detected... System stabilizing...');
294
- };
295
-
296
- window.stopExample1 = () => {
297
- typing1.stop();
298
- };
349
+ // NSFW toggle state — not persisted; checkbox resets on every page load so
350
+ // enabling NSFW is an explicit per-visit action (per corrupted-theme spec).
351
+ const nsfwToggle = document.getElementById('nsfwToggle');
352
+ const sfwBadge = document.getElementById('sfwBadge');
353
+ const nsfwWarning = document.getElementById('nsfwWarning');
299
354
 
300
- window.settleExample1 = () => {
301
- typing1.settle('System Online');
302
- };
355
+ const isNsfw = () => nsfwToggle.checked;
303
356
 
304
- // Example 2: Adjustable
357
+ // DOM references for all demo outputs + controls
358
+ const output1 = document.getElementById('output1');
305
359
  const output2 = document.getElementById('output2');
360
+ const output3 = document.getElementById('output3');
306
361
  const speedSlider = document.getElementById('speed');
307
- const glitchSlider = document.getElementById('glitch');
308
362
  const speedValue = document.getElementById('speedValue');
309
- const glitchValue = document.getElementById('glitchValue');
363
+ const customInput = document.getElementById('customMessage');
364
+
365
+ // Live instance for Example 1 (auto-loops). Examples 2 and 3 are
366
+ // click-to-start and construct fresh instances per click.
367
+ let typing1 = null;
310
368
 
311
369
  speedSlider.addEventListener('input', (e) => {
312
370
  speedValue.textContent = `${e.target.value} chars/sec`;
313
371
  });
314
372
 
315
- glitchSlider.addEventListener('input', (e) => {
316
- glitchValue.textContent = `${e.target.value}%`;
317
- });
373
+ function buildExample1() {
374
+ if (typing1) typing1.destroy();
375
+ typing1 = new TypingAnimation(output1, {
376
+ nsfw: isNsfw(),
377
+ loop: true,
378
+ loopDelay: 2000
379
+ });
380
+ typing1.start('Neural corruption detected... System stabilizing...');
381
+ }
382
+
383
+ window.startExample1 = buildExample1;
384
+ window.stopExample1 = () => typing1 && typing1.stop();
385
+ window.settleExample1 = () => typing1 && typing1.settle('System Online');
318
386
 
319
387
  window.startExample2 = () => {
320
388
  const typing2 = new TypingAnimation(output2, {
321
389
  typingSpeed: parseInt(speedSlider.value),
322
- glitchChance: parseInt(glitchSlider.value) / 100,
323
- nsfw: false
390
+ nsfw: isNsfw(),
391
+ loop: true,
392
+ loopDelay: 2000
324
393
  });
325
394
  typing2.start('Loading data streams... Reality.exe has stopped responding...');
326
395
  };
327
396
 
328
- // Example 3: Custom
329
- const output3 = document.getElementById('output3');
330
- const customInput = document.getElementById('customMessage');
331
-
332
397
  window.startExample3 = () => {
333
398
  const message = customInput.value || 'Enter a message above!';
334
399
  const typing3 = new TypingAnimation(output3, {
335
- nsfw: false
400
+ nsfw: isNsfw(),
401
+ loop: true,
402
+ loopDelay: 2000
336
403
  });
337
404
  typing3.start(message);
338
405
  };
339
406
 
340
- // Auto-start example 1 on load
341
- setTimeout(() => startExample1(), 500);
407
+ // Toggle handler swap badge visibility and rebuild the auto-looping demo
408
+ // so the change is immediately visible. Examples 2 & 3 pick up the flag
409
+ // on their next click.
410
+ nsfwToggle.addEventListener('change', () => {
411
+ if (isNsfw()) {
412
+ sfwBadge.style.display = 'none';
413
+ nsfwWarning.style.display = '';
414
+ } else {
415
+ sfwBadge.style.display = '';
416
+ nsfwWarning.style.display = 'none';
417
+ }
418
+ buildExample1();
419
+ });
420
+
421
+ // Auto-start Example 1 (SFW by default since toggle starts unchecked)
422
+ setTimeout(buildExample1, 500);
342
423
  </script>
343
424
  </body>
344
425
  </html>
@@ -137,7 +137,6 @@
137
137
  <a href="layout.html"><i class="fas fa-columns"></i> Layouts</a>
138
138
  <a href="basic/corrupted-text.html"><i class="fas fa-terminal"></i> Character Corruption</a>
139
139
  <a href="basic/typing-animation.html"><i class="fas fa-keyboard"></i> Buffer Corruption</a>
140
- <a href="advanced/nsfw-corruption.html"><i class="fas fa-exclamation-triangle"></i> NSFW (18+)</a>
141
140
  </div>
142
141
  </li>
143
142
  <li><a href="showcase-complete.html"><i class="fas fa-book"></i> Docs</a></li>
@@ -441,7 +440,7 @@
441
440
  </section>
442
441
 
443
442
  <footer style="text-align: center; padding: var(--spacing-2xl) var(--spacing-lg); margin-top: var(--spacing-2xl); border-top: 1px solid var(--border); color: var(--text-secondary);">
444
- <p>Button Component Documentation • Corrupted Theme v0.1.7</p>
443
+ <p>Button Component Documentation • Corrupted Theme v0.1.9</p>
445
444
  <p style="font-size: 0.875rem; margin-top: var(--spacing-md);">
446
445
  <a href="index.html" style="color: var(--accent); text-decoration: none;">← Back to Showcase</a>
447
446
  </p>
@@ -246,7 +246,6 @@
246
246
  <a href="layout.html"><i class="fas fa-columns"></i> Layouts</a>
247
247
  <a href="basic/corrupted-text.html"><i class="fas fa-terminal"></i> Character Corruption</a>
248
248
  <a href="basic/typing-animation.html"><i class="fas fa-keyboard"></i> Buffer Corruption</a>
249
- <a href="advanced/nsfw-corruption.html"><i class="fas fa-exclamation-triangle"></i> NSFW (18+)</a>
250
249
  </div>
251
250
  </li>
252
251
  <li><a href="showcase-complete.html"><i class="fas fa-book"></i> Docs</a></li>
@@ -684,7 +683,7 @@
684
683
  </section>
685
684
 
686
685
  <footer style="text-align: center; padding: var(--spacing-2xl) var(--spacing-lg); margin-top: var(--spacing-2xl); border-top: 1px solid var(--border); color: var(--text-secondary);">
687
- <p>Card Components Documentation • Corrupted Theme v0.1.7</p>
686
+ <p>Card Components Documentation • Corrupted Theme v0.1.9</p>
688
687
  <p style="font-size: 0.875rem; margin-top: var(--spacing-md);">
689
688
  <a href="index.html" style="color: var(--accent); text-decoration: none;">← Back to Showcase</a>
690
689
  </p>
@@ -147,6 +147,8 @@
147
147
  <a href="#nsfw"><i class="fas fa-eye-slash"></i> NSFW Blur</a>
148
148
  <a href="#social"><i class="fas fa-share-alt"></i> Social Links</a>
149
149
  <a href="#countdown"><i class="fas fa-hourglass-half"></i> Countdown</a>
150
+ <a href="advanced/glsl-vortex.html"><i class="fas fa-hurricane"></i> GLSL Vortex</a>
151
+ <a href="advanced/particles-bg.html"><i class="fas fa-atom"></i> Particles BG</a>
150
152
  </div>
151
153
  </li>
152
154
  <li class="has-submenu">
@@ -162,7 +164,6 @@
162
164
  <a href="layout.html"><i class="fas fa-columns"></i> Layouts</a>
163
165
  <a href="basic/corrupted-text.html"><i class="fas fa-terminal"></i> Character Corruption</a>
164
166
  <a href="basic/typing-animation.html"><i class="fas fa-keyboard"></i> Buffer Corruption</a>
165
- <a href="advanced/nsfw-corruption.html"><i class="fas fa-exclamation-triangle"></i> NSFW (18+)</a>
166
167
  </div>
167
168
  </li>
168
169
  <li><a href="showcase-complete.html"><i class="fas fa-book"></i> Docs</a></li>
@@ -632,6 +633,40 @@
632
633
  }</div>
633
634
  </section>
634
635
 
636
+ <section class="showcase-section" id="vortex">
637
+ <h2><i class="fas fa-hurricane"></i> GLSL Vortex</h2>
638
+ <p class="showcase-description">WebGL1 raymarched spiral tunnel with quasar multi-color mode. Full-screen canvas background with configurable speed, intensity, rotation, and hue. Zero dependencies.</p>
639
+ <a href="advanced/glsl-vortex.html" class="btn btn-primary"><i class="fas fa-external-link-alt"></i> Open Demo</a>
640
+ <h3>Usage</h3>
641
+ <div class="code-example">&lt;canvas id="vortex"&gt;&lt;/canvas&gt;
642
+ &lt;script src="src/lib/corrupted-vortex.js"&gt;&lt;/script&gt;
643
+ &lt;script&gt;
644
+ new CorruptedVortex(document.getElementById('vortex'), {
645
+ speed: 1.0,
646
+ intensity: 1.0,
647
+ rotationRate: 1.0,
648
+ hue: null, // null = quasar multi-color mode
649
+ });
650
+ &lt;/script&gt;</div>
651
+ </section>
652
+
653
+ <section class="showcase-section" id="particles">
654
+ <h2><i class="fas fa-atom"></i> Particles BG</h2>
655
+ <p class="showcase-description">Canvas 2D floating corrupted Japanese phrase background. Three depth layers (far/mid/near), hover repel, click burst, phrase flickering, connection lines. SFW by default; opt-in lewd mode adds magenta/purple NSFW phrases.</p>
656
+ <a href="advanced/particles-bg.html" class="btn btn-primary"><i class="fas fa-external-link-alt"></i> Open Demo</a>
657
+ <h3>Usage</h3>
658
+ <div class="code-example">&lt;canvas id="bg" style="position:fixed;inset:0;width:100%;height:100%;z-index:0;"&gt;&lt;/canvas&gt;
659
+ &lt;script src="src/lib/corrupted-particles.js"&gt;&lt;/script&gt;
660
+ &lt;script&gt;
661
+ new CorruptedParticles(document.getElementById('bg'), {
662
+ count: 60,
663
+ speed: 1.0,
664
+ lineDistance: 150,
665
+ includeLewd: false, // 18+ opt-in only
666
+ });
667
+ &lt;/script&gt;</div>
668
+ </section>
669
+
635
670
  <!-- Footer -->
636
671
  <footer style="text-align: center; padding: var(--spacing-2xl) var(--spacing-lg); margin-top: var(--spacing-xl); border-top: 1px solid var(--border); color: var(--text-secondary);">
637
672
  <p><strong>Corrupted Theme Extensions</strong> • Production-tested components from whykusanagi.xyz</p>