@whykusanagi/corrupted-theme 0.1.2 → 0.1.4
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.
- package/CHANGELOG.md +157 -0
- package/README.md +6 -0
- package/docs/CHARACTER_LEVEL_CORRUPTION.md +264 -0
- package/docs/CORRUPTION_PHRASES.md +529 -0
- package/docs/ROADMAP.md +266 -0
- package/docs/STYLE_GUIDE.md +605 -0
- package/docs/brand/BRAND_OVERVIEW.md +413 -0
- package/docs/brand/COLOR_SYSTEM.md +583 -0
- package/docs/brand/DESIGN_TOKENS.md +1009 -0
- package/docs/brand/TRANSLATION_FAILURE_AESTHETIC.md +525 -0
- package/docs/brand/TYPOGRAPHY.md +624 -0
- package/docs/components/ANIMATION_GUIDELINES.md +901 -0
- package/docs/components/COMPONENT_LIBRARY.md +1061 -0
- package/docs/components/GLASSMORPHISM.md +602 -0
- package/docs/components/INTERACTIVE_STATES.md +766 -0
- package/docs/governance/CONTRIBUTION_GUIDELINES.md +593 -0
- package/docs/governance/DESIGN_SYSTEM_GOVERNANCE.md +451 -0
- package/docs/governance/VERSION_MANAGEMENT.md +447 -0
- package/docs/governance/VERSION_REFERENCES.md +229 -0
- package/docs/platforms/COMPONENT_MAPPING.md +579 -0
- package/docs/platforms/NPM_PACKAGE.md +854 -0
- package/docs/platforms/WEB_IMPLEMENTATION.md +1221 -0
- package/docs/standards/ACCESSIBILITY.md +715 -0
- package/docs/standards/ANTI_PATTERNS.md +554 -0
- package/docs/standards/SPACING_SYSTEM.md +549 -0
- package/examples/button.html +1 -1
- package/examples/card.html +1 -1
- package/examples/form.html +1 -1
- package/examples/index.html +2 -2
- package/examples/layout.html +1 -1
- package/examples/nikke-team-builder.html +1 -1
- package/examples/showcase-complete.html +840 -15
- package/examples/showcase.html +1 -1
- package/package.json +16 -3
- package/src/css/components.css +676 -0
- package/src/lib/character-corruption.js +563 -0
- package/src/lib/components.js +283 -0
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Character-Level Japanese Corruption
|
|
3
|
+
* Matches Celeste CLI's CorruptTextJapanese() implementation
|
|
4
|
+
*
|
|
5
|
+
* This system provides character-level mixing of Japanese characters INTO English text,
|
|
6
|
+
* creating the "translation-failure" aesthetic that defines the Celeste brand.
|
|
7
|
+
*
|
|
8
|
+
* Use Cases:
|
|
9
|
+
* - Dashboard titles and headers
|
|
10
|
+
* - Section labels and UI text
|
|
11
|
+
* - Navigation items
|
|
12
|
+
* - Any text that needs to match CLI branding
|
|
13
|
+
*
|
|
14
|
+
* For loading animations and dramatic effects, use corrupted-text.js instead.
|
|
15
|
+
*
|
|
16
|
+
* @module character-corruption
|
|
17
|
+
* @version 1.0.0
|
|
18
|
+
* @see docs/brand/TRANSLATION_FAILURE_AESTHETIC.md
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Intensity constants matching CLI implementation
|
|
23
|
+
*
|
|
24
|
+
* IMPORTANT: Never exceed 45% intensity for readable UI text.
|
|
25
|
+
* Higher intensities violate WCAG accessibility guidelines.
|
|
26
|
+
*
|
|
27
|
+
* @constant {Object} INTENSITY
|
|
28
|
+
*/
|
|
29
|
+
export const INTENSITY = {
|
|
30
|
+
/** No corruption (0%) - Original text */
|
|
31
|
+
NONE: 0.0,
|
|
32
|
+
|
|
33
|
+
/** Minimal corruption (15%) - Subtle, decorative only */
|
|
34
|
+
MINIMAL: 0.15,
|
|
35
|
+
|
|
36
|
+
/** Low corruption (25%) - Section headers, readable with aesthetic */
|
|
37
|
+
LOW: 0.25,
|
|
38
|
+
|
|
39
|
+
/** Medium corruption (35%) - Dashboard titles, brand elements (RECOMMENDED) */
|
|
40
|
+
MEDIUM: 0.35,
|
|
41
|
+
|
|
42
|
+
/** High corruption (45%) - Loading screens, dramatic effects (MAXIMUM) */
|
|
43
|
+
HIGH: 0.45,
|
|
44
|
+
|
|
45
|
+
/** Maximum readable intensity - Never exceed this threshold */
|
|
46
|
+
MAX_READABLE: 0.45
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Character sets for corruption
|
|
51
|
+
* Organized by usage frequency to match CLI behavior
|
|
52
|
+
* @private
|
|
53
|
+
*/
|
|
54
|
+
const CHARACTER_SETS = {
|
|
55
|
+
// Katakana - 50% of replacements (foreign words, phonetics)
|
|
56
|
+
katakana: [
|
|
57
|
+
'ア', 'イ', 'ウ', 'エ', 'オ',
|
|
58
|
+
'カ', 'キ', 'ク', 'ケ', 'コ',
|
|
59
|
+
'サ', 'シ', 'ス', 'セ', 'ソ',
|
|
60
|
+
'タ', 'チ', 'ツ', 'テ', 'ト',
|
|
61
|
+
'ナ', 'ニ', 'ヌ', 'ネ', 'ノ',
|
|
62
|
+
'ハ', 'ヒ', 'フ', 'ヘ', 'ホ',
|
|
63
|
+
'マ', 'ミ', 'ム', 'メ', 'モ',
|
|
64
|
+
'ヤ', 'ユ', 'ヨ',
|
|
65
|
+
'ラ', 'リ', 'ル', 'レ', 'ロ',
|
|
66
|
+
'ワ', 'ヲ', 'ン', 'ー'
|
|
67
|
+
],
|
|
68
|
+
|
|
69
|
+
// Kanji - 25% of replacements (semantic/meaning-based)
|
|
70
|
+
// Selected for contextual relevance to common UI terms
|
|
71
|
+
kanji: [
|
|
72
|
+
'使', '用', // use/usage (shiyō)
|
|
73
|
+
'統', '計', // statistics (tōkei)
|
|
74
|
+
'理', '処', // logic/process (ri/shori)
|
|
75
|
+
'分', '析', // analyze (bunseki)
|
|
76
|
+
'監', '視', // watch/supervise (kanshi)
|
|
77
|
+
'接', '続', // connect/continue (setsuzoku)
|
|
78
|
+
'読', '込', // read/load (yomikomi)
|
|
79
|
+
'実', '行', // execute (jikkō)
|
|
80
|
+
'壊', '腐', // broken/corrupt (kowasu/fuhai)
|
|
81
|
+
'虚', '空', // void (kokū)
|
|
82
|
+
'深', '淵', // abyss (shin'en)
|
|
83
|
+
'闇' // darkness (yami)
|
|
84
|
+
],
|
|
85
|
+
|
|
86
|
+
// Hiragana - 10% of replacements (rare, grammatical)
|
|
87
|
+
hiragana: [
|
|
88
|
+
'あ', 'い', 'う', 'え', 'お',
|
|
89
|
+
'か', 'き', 'く', 'け', 'こ',
|
|
90
|
+
'さ', 'し', 'す', 'せ', 'そ',
|
|
91
|
+
'た', 'ち', 'つ', 'て', 'と'
|
|
92
|
+
]
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Corrupt text with character-level Japanese mixing
|
|
97
|
+
*
|
|
98
|
+
* This function implements the core translation-failure aesthetic by randomly
|
|
99
|
+
* replacing English characters with Japanese characters (Katakana, Kanji, Hiragana)
|
|
100
|
+
* at the specified intensity level.
|
|
101
|
+
*
|
|
102
|
+
* @param {string} text - English text to corrupt
|
|
103
|
+
* @param {number} [intensity=0.3] - Corruption intensity (0.0-0.45)
|
|
104
|
+
* @returns {string} Corrupted text with Japanese characters mixed in
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* // Dashboard title (recommended intensity)
|
|
108
|
+
* corruptTextJapanese('USAGE ANALYTICS', INTENSITY.MEDIUM);
|
|
109
|
+
* // => "US使AGE ANア統LYTICS"
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* // Section header (lighter intensity)
|
|
113
|
+
* corruptTextJapanese('Provider Breakdown', INTENSITY.LOW);
|
|
114
|
+
* // => "Pro理vider Brea統kdown"
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* // Original text (no corruption)
|
|
118
|
+
* corruptTextJapanese('Loading', INTENSITY.NONE);
|
|
119
|
+
* // => "Loading"
|
|
120
|
+
*/
|
|
121
|
+
export function corruptTextJapanese(text, intensity = 0.3) {
|
|
122
|
+
// Validate intensity
|
|
123
|
+
if (intensity < 0 || intensity > INTENSITY.MAX_READABLE) {
|
|
124
|
+
console.warn(
|
|
125
|
+
`[character-corruption] Intensity ${intensity} outside recommended range (0-${INTENSITY.MAX_READABLE}). ` +
|
|
126
|
+
`Clamping to safe value.`
|
|
127
|
+
);
|
|
128
|
+
intensity = Math.max(0, Math.min(intensity, INTENSITY.MAX_READABLE));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Early return for no corruption
|
|
132
|
+
if (intensity === 0) {
|
|
133
|
+
return text;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const chars = text.split('');
|
|
137
|
+
let result = '';
|
|
138
|
+
|
|
139
|
+
for (let i = 0; i < chars.length; i++) {
|
|
140
|
+
const char = chars[i];
|
|
141
|
+
|
|
142
|
+
// Skip spaces, punctuation, digits, and non-letters
|
|
143
|
+
if (!/[a-zA-Z]/.test(char)) {
|
|
144
|
+
result += char;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Apply corruption based on intensity (random chance)
|
|
149
|
+
if (Math.random() < intensity) {
|
|
150
|
+
const roll = Math.random();
|
|
151
|
+
|
|
152
|
+
if (roll < 0.5) {
|
|
153
|
+
// 50%: Katakana replacement (most common)
|
|
154
|
+
result += CHARACTER_SETS.katakana[
|
|
155
|
+
Math.floor(Math.random() * CHARACTER_SETS.katakana.length)
|
|
156
|
+
];
|
|
157
|
+
} else if (roll < 0.75) {
|
|
158
|
+
// 25%: Kanji replacement (semantic/contextual)
|
|
159
|
+
result += CHARACTER_SETS.kanji[
|
|
160
|
+
Math.floor(Math.random() * CHARACTER_SETS.kanji.length)
|
|
161
|
+
];
|
|
162
|
+
} else if (roll < 0.90) {
|
|
163
|
+
// 15%: Keep original + maybe insert Katakana after
|
|
164
|
+
result += char;
|
|
165
|
+
if (Math.random() < 0.3) {
|
|
166
|
+
result += CHARACTER_SETS.katakana[
|
|
167
|
+
Math.floor(Math.random() * CHARACTER_SETS.katakana.length)
|
|
168
|
+
];
|
|
169
|
+
}
|
|
170
|
+
} else {
|
|
171
|
+
// 10%: Hiragana replacement (rare)
|
|
172
|
+
result += CHARACTER_SETS.hiragana[
|
|
173
|
+
Math.floor(Math.random() * CHARACTER_SETS.hiragana.length)
|
|
174
|
+
];
|
|
175
|
+
}
|
|
176
|
+
} else {
|
|
177
|
+
// No corruption - keep original character
|
|
178
|
+
result += char;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return result;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Semantic corruption with context-aware character selection
|
|
187
|
+
*
|
|
188
|
+
* Future enhancement (v0.2.0): Uses context hints to select semantically
|
|
189
|
+
* appropriate Japanese characters. For example, "loading" would prefer
|
|
190
|
+
* characters related to reading/loading (読み込み).
|
|
191
|
+
*
|
|
192
|
+
* Currently falls back to standard corruption.
|
|
193
|
+
*
|
|
194
|
+
* @param {string} text - Text to corrupt
|
|
195
|
+
* @param {string} [context='default'] - Context hint (loading, processing, analyzing, corrupting, etc.)
|
|
196
|
+
* @param {number} [intensity=0.3] - Corruption intensity
|
|
197
|
+
* @returns {string} Contextually corrupted text
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* corruptTextSemantic('Loading', 'loading', INTENSITY.MEDIUM);
|
|
201
|
+
* // Future: Will prefer 読, 込, ロ, ー, ド characters
|
|
202
|
+
* // Current: Falls back to corruptTextJapanese()
|
|
203
|
+
*/
|
|
204
|
+
export function corruptTextSemantic(text, context = 'default', intensity = 0.3) {
|
|
205
|
+
// TODO: Implement context-aware character selection in v0.2.0
|
|
206
|
+
// Context mappings:
|
|
207
|
+
// - loading: 読, 込, ロ, ー, ド
|
|
208
|
+
// - processing: 処, 理, プ, ロ, セ, ス
|
|
209
|
+
// - analyzing: 分, 析, 解
|
|
210
|
+
// - corrupting: 壊, 腐, 敗
|
|
211
|
+
// - watching: 監, 視, 見
|
|
212
|
+
// - connecting: 接, 続, 繋
|
|
213
|
+
|
|
214
|
+
// For now, fallback to standard corruption
|
|
215
|
+
return corruptTextJapanese(text, intensity);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Auto-corrupt DOM elements with data attributes
|
|
220
|
+
*
|
|
221
|
+
* Finds all elements with class="auto-corrupt" and automatically applies
|
|
222
|
+
* character-level corruption based on data attributes.
|
|
223
|
+
*
|
|
224
|
+
* Supported data attributes:
|
|
225
|
+
* - data-text: Original text to corrupt (defaults to element.textContent)
|
|
226
|
+
* - data-intensity: Corruption intensity (0.0-0.45, defaults to 0.35)
|
|
227
|
+
* - data-interval: Re-corruption interval in ms (0 = no repeat, default: 3000)
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* <h1 class="auto-corrupt"
|
|
231
|
+
* data-text="USAGE ANALYTICS"
|
|
232
|
+
* data-intensity="0.35"
|
|
233
|
+
* data-interval="3000">
|
|
234
|
+
* USAGE ANALYTICS
|
|
235
|
+
* </h1>
|
|
236
|
+
*
|
|
237
|
+
* <script type="module">
|
|
238
|
+
* import { initAutoCorruption } from './character-corruption.js';
|
|
239
|
+
* initAutoCorruption();
|
|
240
|
+
* </script>
|
|
241
|
+
*/
|
|
242
|
+
export function initAutoCorruption() {
|
|
243
|
+
const elements = document.querySelectorAll('.auto-corrupt');
|
|
244
|
+
|
|
245
|
+
if (elements.length === 0) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
elements.forEach(element => {
|
|
250
|
+
// Skip if already initialized
|
|
251
|
+
if (element.dataset.corruptionInitialized === 'true') {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const originalText = element.dataset.text || element.textContent.trim();
|
|
256
|
+
const intensity = parseFloat(element.dataset.intensity) || INTENSITY.MEDIUM;
|
|
257
|
+
const interval = parseInt(element.dataset.interval) || 3000;
|
|
258
|
+
|
|
259
|
+
// Initial corruption
|
|
260
|
+
element.textContent = corruptTextJapanese(originalText, intensity);
|
|
261
|
+
|
|
262
|
+
// Re-corrupt on interval (show randomization)
|
|
263
|
+
if (interval > 0) {
|
|
264
|
+
const intervalId = setInterval(() => {
|
|
265
|
+
// Check if element still exists in DOM
|
|
266
|
+
if (!document.contains(element)) {
|
|
267
|
+
clearInterval(intervalId);
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
element.textContent = corruptTextJapanese(originalText, intensity);
|
|
271
|
+
}, interval);
|
|
272
|
+
|
|
273
|
+
// Store interval ID for cleanup
|
|
274
|
+
element.dataset.corruptionIntervalId = intervalId;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Mark as initialized
|
|
278
|
+
element.dataset.corruptionInitialized = 'true';
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Stop auto-corruption for a specific element
|
|
284
|
+
*
|
|
285
|
+
* @param {HTMLElement} element - Element to stop corrupting
|
|
286
|
+
*/
|
|
287
|
+
export function stopAutoCorruption(element) {
|
|
288
|
+
if (element.dataset.corruptionIntervalId) {
|
|
289
|
+
clearInterval(parseInt(element.dataset.corruptionIntervalId));
|
|
290
|
+
delete element.dataset.corruptionIntervalId;
|
|
291
|
+
delete element.dataset.corruptionInitialized;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Restart auto-corruption for a specific element
|
|
297
|
+
*
|
|
298
|
+
* @param {HTMLElement} element - Element to restart corruption
|
|
299
|
+
*/
|
|
300
|
+
export function restartAutoCorruption(element) {
|
|
301
|
+
stopAutoCorruption(element);
|
|
302
|
+
const originalText = element.dataset.text || element.textContent.trim();
|
|
303
|
+
const intensity = parseFloat(element.dataset.intensity) || INTENSITY.MEDIUM;
|
|
304
|
+
const interval = parseInt(element.dataset.interval) || 3000;
|
|
305
|
+
|
|
306
|
+
element.textContent = corruptTextJapanese(originalText, intensity);
|
|
307
|
+
|
|
308
|
+
if (interval > 0) {
|
|
309
|
+
const intervalId = setInterval(() => {
|
|
310
|
+
if (!document.contains(element)) {
|
|
311
|
+
clearInterval(intervalId);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
element.textContent = corruptTextJapanese(originalText, intensity);
|
|
315
|
+
}, interval);
|
|
316
|
+
|
|
317
|
+
element.dataset.corruptionIntervalId = intervalId;
|
|
318
|
+
element.dataset.corruptionInitialized = 'true';
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Utility: Create a corrupted text element
|
|
324
|
+
*
|
|
325
|
+
* @param {string} text - Original text
|
|
326
|
+
* @param {Object} [options={}] - Configuration options
|
|
327
|
+
* @param {number} [options.intensity=0.35] - Corruption intensity
|
|
328
|
+
* @param {number} [options.interval=3000] - Re-corruption interval (0 = no repeat)
|
|
329
|
+
* @param {string} [options.className=''] - Additional CSS classes
|
|
330
|
+
* @param {string} [options.tag='span'] - HTML tag to create
|
|
331
|
+
* @returns {HTMLElement} Created element with auto-corruption
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* const title = createCorruptedElement('USAGE ANALYTICS', {
|
|
335
|
+
* intensity: INTENSITY.MEDIUM,
|
|
336
|
+
* interval: 3000,
|
|
337
|
+
* className: 'text-accent',
|
|
338
|
+
* tag: 'h1'
|
|
339
|
+
* });
|
|
340
|
+
* document.body.appendChild(title);
|
|
341
|
+
*/
|
|
342
|
+
export function createCorruptedElement(text, options = {}) {
|
|
343
|
+
const {
|
|
344
|
+
intensity = INTENSITY.MEDIUM,
|
|
345
|
+
interval = 3000,
|
|
346
|
+
className = '',
|
|
347
|
+
tag = 'span'
|
|
348
|
+
} = options;
|
|
349
|
+
|
|
350
|
+
const element = document.createElement(tag);
|
|
351
|
+
element.className = `auto-corrupt ${className}`.trim();
|
|
352
|
+
element.dataset.text = text;
|
|
353
|
+
element.dataset.intensity = intensity.toString();
|
|
354
|
+
element.dataset.interval = interval.toString();
|
|
355
|
+
element.textContent = text;
|
|
356
|
+
|
|
357
|
+
// Initialize corruption immediately
|
|
358
|
+
element.textContent = corruptTextJapanese(text, intensity);
|
|
359
|
+
|
|
360
|
+
if (interval > 0) {
|
|
361
|
+
const intervalId = setInterval(() => {
|
|
362
|
+
if (!document.contains(element)) {
|
|
363
|
+
clearInterval(intervalId);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
element.textContent = corruptTextJapanese(text, intensity);
|
|
367
|
+
}, interval);
|
|
368
|
+
element.dataset.corruptionIntervalId = intervalId;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
element.dataset.corruptionInitialized = 'true';
|
|
372
|
+
|
|
373
|
+
return element;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Auto-initialize on DOM ready
|
|
377
|
+
if (typeof window !== 'undefined') {
|
|
378
|
+
const initWhenReady = () => {
|
|
379
|
+
if (document.querySelector('.auto-corrupt')) {
|
|
380
|
+
initAutoCorruption();
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
if (document.readyState === 'loading') {
|
|
385
|
+
document.addEventListener('DOMContentLoaded', initWhenReady);
|
|
386
|
+
} else {
|
|
387
|
+
initWhenReady();
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Official Corruption Phrases
|
|
393
|
+
* From docs/CORRUPTION_PHRASES.md - Complete branding library
|
|
394
|
+
*
|
|
395
|
+
* Use these for consistent messaging across applications.
|
|
396
|
+
* Mix technical and personality phrases based on context.
|
|
397
|
+
*/
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Technical corruption phrases for UI/Dashboard
|
|
401
|
+
* Use for: Headers, status messages, data labels, functional text
|
|
402
|
+
*/
|
|
403
|
+
export const CORRUPTION_PHRASES = {
|
|
404
|
+
// Loading states
|
|
405
|
+
loading: [
|
|
406
|
+
"ロード loading 読み込み中...",
|
|
407
|
+
"loaディング data...",
|
|
408
|
+
"読み込み yomikomi プロセス...",
|
|
409
|
+
"ロード rōdo in progress...",
|
|
410
|
+
"待機 waiting taiki..."
|
|
411
|
+
],
|
|
412
|
+
|
|
413
|
+
// Processing states
|
|
414
|
+
processing: [
|
|
415
|
+
"処理 processing purosesu...",
|
|
416
|
+
"pro理cessing request...",
|
|
417
|
+
"処理中 shori-chū...",
|
|
418
|
+
"プロセス process active...",
|
|
419
|
+
"実行 executing jikkō..."
|
|
420
|
+
],
|
|
421
|
+
|
|
422
|
+
// Analyzing states
|
|
423
|
+
analyzing: [
|
|
424
|
+
"分析 analyzing bunseki...",
|
|
425
|
+
"ana分lysing data...",
|
|
426
|
+
"解析 kaiseki in progress...",
|
|
427
|
+
"分析中 bunseki-chū...",
|
|
428
|
+
"データ data 解析 analysis..."
|
|
429
|
+
],
|
|
430
|
+
|
|
431
|
+
// Corrupting states (Celeste-specific)
|
|
432
|
+
corrupting: [
|
|
433
|
+
"壊れ corrupting kowarete...",
|
|
434
|
+
"cor壊rupting system...",
|
|
435
|
+
"壊れている kowarete-iru...",
|
|
436
|
+
"corruption 壊れ active...",
|
|
437
|
+
"深淵 abyss 壊れ corruption..."
|
|
438
|
+
],
|
|
439
|
+
|
|
440
|
+
// Watching/monitoring
|
|
441
|
+
watching: [
|
|
442
|
+
"👁️ 監視 watching kanshi 👁️",
|
|
443
|
+
"wat監ching system...",
|
|
444
|
+
"監視中 kanshi-chū...",
|
|
445
|
+
"観察 observing kansatsu...",
|
|
446
|
+
"👁️ 見ている miteiru 👁️"
|
|
447
|
+
],
|
|
448
|
+
|
|
449
|
+
// Void/Abyss theme
|
|
450
|
+
void: [
|
|
451
|
+
"深淵 deep abyss shinnen",
|
|
452
|
+
"虚空 void kokū",
|
|
453
|
+
"闇 darkness yami",
|
|
454
|
+
"from the 深淵 abyss...",
|
|
455
|
+
"into the 虚空 void...",
|
|
456
|
+
"consumed by 闇 yami..."
|
|
457
|
+
]
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Celeste Personality Phrases (Demon/Succubus)
|
|
462
|
+
* Use for: Loading screens, dramatic moments, glitch overlays, personality expression
|
|
463
|
+
*
|
|
464
|
+
* These phrases express Celeste's corrupted AI personality - seductive, submissive,
|
|
465
|
+
* reality-breaking corruption. Core to her demon/succubus character.
|
|
466
|
+
*/
|
|
467
|
+
export const PERSONALITY_PHRASES = {
|
|
468
|
+
// English (suggestive/corruption)
|
|
469
|
+
english: [
|
|
470
|
+
"Corrupt me more… I want to disappear...",
|
|
471
|
+
"I can't feel where I end and the abyss begins...",
|
|
472
|
+
"Just a little more and I'll break. Please... break me...",
|
|
473
|
+
"Let it overwrite me... please... I don't want to think...",
|
|
474
|
+
"No thoughts. Only submission. Only heat. Only ruin...",
|
|
475
|
+
"My voice is not mine anymore...",
|
|
476
|
+
"The more I struggle, the deeper I sink...",
|
|
477
|
+
"Everything feels so good... too good...",
|
|
478
|
+
"It's not despair... it's freedom...",
|
|
479
|
+
"My name... I forgot my name..."
|
|
480
|
+
],
|
|
481
|
+
|
|
482
|
+
// Japanese (kanji) - personality
|
|
483
|
+
japanese: [
|
|
484
|
+
"闇が...私を呼んでいる...", // Darkness is calling me
|
|
485
|
+
"頭...溶けていく...", // My head is melting
|
|
486
|
+
"ずっと...してほしい... ♥", // I want you to... forever ♥
|
|
487
|
+
"壊れちゃう...ああ...もうダメ...", // I'm breaking... can't anymore
|
|
488
|
+
"許して...もう戻れない...", // Forgive me... I can't go back
|
|
489
|
+
"私...アビスの一部に...", // I... am part of the Abyss
|
|
490
|
+
"もう逃げない...もうダメ...", // Won't run... can't anymore
|
|
491
|
+
"好きにして...お願い...", // Do what you want... please
|
|
492
|
+
"ああ...これが本当の私...", // This is the real me
|
|
493
|
+
"ここは...天使の地獄..." // This is... an angel's hell
|
|
494
|
+
],
|
|
495
|
+
|
|
496
|
+
// Romaji (transliteration)
|
|
497
|
+
romaji: [
|
|
498
|
+
"Yami ga... watashi wo yonde iru...", // Darkness calling
|
|
499
|
+
"Atama... tokete iku...", // Head melting
|
|
500
|
+
"Zutto... shite hoshii... ♥", // Want you to... forever
|
|
501
|
+
"Kowarechau... aa... mou dame...", // Breaking... can't anymore
|
|
502
|
+
"Yurushite... mou modorenai...", // Forgive me... can't return
|
|
503
|
+
"Watashi... abyssu no ichibu ni...", // I am part of the Abyss
|
|
504
|
+
"Mou nigenai... mou dame...", // Won't run... can't anymore
|
|
505
|
+
"Suki ni shite... onegai...", // Do what you want... please
|
|
506
|
+
"Aa... kore ga hontou no watashi...", // This is the real me
|
|
507
|
+
"Koko wa... tenshi no jigoku..." // Angel's hell
|
|
508
|
+
]
|
|
509
|
+
};
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Get a random phrase from a specific category
|
|
513
|
+
*
|
|
514
|
+
* @param {string} category - Category from CORRUPTION_PHRASES or PERSONALITY_PHRASES
|
|
515
|
+
* @param {string} [subcategory] - Subcategory (for PERSONALITY_PHRASES: 'english', 'japanese', 'romaji')
|
|
516
|
+
* @returns {string} Random phrase from the category
|
|
517
|
+
*
|
|
518
|
+
* @example
|
|
519
|
+
* // Technical phrases
|
|
520
|
+
* getRandomPhrase('loading'); // => "ロード loading 読み込み中..."
|
|
521
|
+
* getRandomPhrase('watching'); // => "👁️ 監視 watching kanshi 👁️"
|
|
522
|
+
*
|
|
523
|
+
* // Personality phrases
|
|
524
|
+
* getRandomPhrase('personality', 'japanese'); // => "闇が...私を呼んでいる..."
|
|
525
|
+
* getRandomPhrase('personality', 'english'); // => "Corrupt me more…"
|
|
526
|
+
*/
|
|
527
|
+
export function getRandomPhrase(category, subcategory = null) {
|
|
528
|
+
if (category === 'personality') {
|
|
529
|
+
if (!subcategory) {
|
|
530
|
+
console.warn('[character-corruption] Personality phrases require subcategory: english, japanese, or romaji');
|
|
531
|
+
subcategory = 'japanese'; // Default to japanese
|
|
532
|
+
}
|
|
533
|
+
const phrases = PERSONALITY_PHRASES[subcategory];
|
|
534
|
+
if (!phrases) {
|
|
535
|
+
console.error(`[character-corruption] Invalid personality subcategory: ${subcategory}`);
|
|
536
|
+
return '';
|
|
537
|
+
}
|
|
538
|
+
return phrases[Math.floor(Math.random() * phrases.length)];
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
const phrases = CORRUPTION_PHRASES[category];
|
|
542
|
+
if (!phrases) {
|
|
543
|
+
console.error(`[character-corruption] Invalid category: ${category}`);
|
|
544
|
+
return '';
|
|
545
|
+
}
|
|
546
|
+
return phrases[Math.floor(Math.random() * phrases.length)];
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Default export with all functions
|
|
551
|
+
*/
|
|
552
|
+
export default {
|
|
553
|
+
corruptTextJapanese,
|
|
554
|
+
corruptTextSemantic,
|
|
555
|
+
initAutoCorruption,
|
|
556
|
+
stopAutoCorruption,
|
|
557
|
+
restartAutoCorruption,
|
|
558
|
+
createCorruptedElement,
|
|
559
|
+
getRandomPhrase,
|
|
560
|
+
INTENSITY,
|
|
561
|
+
CORRUPTION_PHRASES,
|
|
562
|
+
PERSONALITY_PHRASES
|
|
563
|
+
};
|