import React, { useState, useEffect, useRef } from 'react';
import { Coffee, FileText, PenTool } from 'lucide-react';
/**
* ARCHIVIST DEMO - EZGI EDITION (1923 BAYREUTH)
* Setting: German Hyperinflation.
* Protagonist: Ezgi (History of Economics Student).
*/
// --- UTILS ---
const HighlightedText = ({ text }) => {
if (!text.includes('*')) return {text};
const parts = text.split('*');
return (
{parts.map((part, i) =>
i % 2 === 1 ? (
{part}
) : (
{part}
)
)}
);
};
const resolveFinalText = (rawText) => {
if (!rawText) return "";
let result = "";
for (let i = 0; i < rawText.length; i++) {
if (rawText[i] === '^') {
result = result.slice(0, -1);
} else {
result += rawText[i];
}
}
return result;
};
const processTextForFatigue = (rawText, fatigue) => {
if (!rawText.includes('^')) return rawText;
if (fatigue < 44) return resolveFinalText(rawText);
if (fatigue >= 44 && fatigue < 70) {
if (rawText.length % 2 === 0) return resolveFinalText(rawText);
}
return rawText;
};
// --- DATA ---
const FATIGUE_WARNINGS = [
"I really need a coffee.",
"I can't keep going on like this.",
"I should stop for a while.",
"My eyes are burning.",
"The letters are swimming on the page."
];
const DEMO_DATA = {
manuscript: [
// INTRO
"Field Journal: Bayreuth,\nGermany. October 12, 1923.\n\nSubject: The Inflation Crisis.",
"I arrived at the station\nthis morning. The price of\na ticket has tripled since\nI left Munich.",
"The Papiermark is dead.\nPeople are carrying cash in\nwheelbarrows just to buy\nbread.",
"I secured a room at a\nboarding house near the\nold Opera district.",
"The landlady demanded\n40 billion Marks for the\nweek. I paid it.",
"I have locked the door to\nmy room. The city feels\ndesperate. Unsafe.", // Page 5: Sets up the "Door" anomaly
"Section I: Economic Collapse.\nShops are open, but shelves\nare empty for those paying\nwith currency.",
"Yet, I see locals leaving\nthe back rooms with meat\nand coal. They hold no\nmoney.",
"I asked a baker what the\nprice of a loaf was. He\nsmiled and said, 'Too\nexpensive for you.'",
"The cafe is crowded today.\nEveryone is smoking cheap\ntobacco to curb their\nhunger.", // Page 9: Sets up the "Smell" anomaly
"Section II: The Shadow Ledger.\nI followed a merchant to\nthe cellars beneath the\nmarket square.",
"There is a secondary\neconomy operating here.\nA barter system.",
"But they are not trading\ngoods. I watched an old\nwoman buy potatoes.",
"She did not offer money.\nShe offered a small glass\nvial filled with... breath?", // Page 13: Sets up the "Hands" anomaly (writing strain)
"I am writing this hastily.\nMy hands are stiff from\nthe cold in this cellar.",
"The merchant inhaled the\nsmoke from the vial. He\nshuddered. The deal was\nstruck.",
"What was in that vial?\nA memory? A year of life?\nThe exchange rates are\nirrational.",
"I am back in my room.\nI am safe here. I am\nalone.", // Page 17: Sets up the "Safe" anomaly
"November 1st. Inflation is\nworse. Bread is now 200\nbillion Marks.",
"My research grant is\nworthless. I am hungry.\nThe landlady is looking\nat me strangely.",
"She asked me if I had\n'good years' to trade.\nI did not answer.",
"I tried to leave the city.\nThe trains are stopped.\nThe tracks are rusted.",
"I returned to the desk.\nI must document this.\nMy back aches terribly.", // Page 23: Sets up the "Legs" anomaly
"I went back to the cellar.\nI needed to know who runs\nthis market.",
"They call him 'The\nCollector'. He takes the\nvials. He eats the time.",
"I made a mistake. I was\ntaking notes. The ink on\nmy paper started to glow.",
"They saw me. The merchant,\nthe baker, the landlady.\nThey all stopped trading.",
"They don't want my money.\nThey want my history.\nThey want to consume who\nI am.",
"My name is Ezgi. I am\na student of history.\nAnd I am being erased.", // NAME DROP
"They are breaking the\ndoor down. The wood is\nsplintering.",
"I will hide this journal\nin the floorboards. Please.\nRemember me."
],
comments: {
0: "Document recovered from demolition\nsite, Bavaria, 1998.",
3: "Historical context: 1923 Hyperinflation.\nMatches records.",
5: "The locking mechanism on 1920s\ndoors was notoriously weak.",
9: "Tobacco was often used to\nsuppress appetite during the famine.",
13: "Glass vials? No historical\nprecedent for this currency.",
16: "The writing becomes erratic here.\nHands shaking?",
20: "Subject is showing signs of\nsevere malnutrition.",
24: "The Collector. No civil record\nof this individual exists.",
28: "Ezgi. Student records confirm\na disappearance in 1923.",
30: "The journal ends abruptly.\nThe rest is scratched out."
},
narrativeThreads: [
// Keeping your original threads as requested
{ triggerPage: 2, text: "I have a slight headache.", type: 'thought' },
{ triggerPage: 7, text: "Headache is getting stronger.", type: 'thought' },
{ triggerPage: 4, text: "I can see a pigeon flying near the window.", type: 'thought' },
{ triggerPage: 11, text: "The pigeon is staring right at me.", type: 'thought' },
{ triggerPage: 5, text: "My candle is flickering.", type: 'thought' },
{ triggerPage: 16, text: "The candle's light is just a tiny bit more red.", type: 'thought' },
{ triggerPage: 27, text: "The candle is out. I should light it again.", type: 'thought' },
{ triggerPage: 12, text: "My ears are ringing.", type: 'thought' },
{ triggerPage: 18, text: "The sounds outside are getting muffled.", type: 'thought' },
{ triggerPage: 25, text: "The sounds have stopped. Complete silence.", type: 'thought' },
{ triggerPage: 24, text: "It is getting dark.", type: 'thought' }
],
mundaneThoughts: [
"I need to adjust my chair. My back aches.",
"Writing this long hurts my hand.",
"The wind is howling outside today.",
"I need a new pillow. Neck is stiff.",
"I feel a little cold. The fire must be dying.",
"My coffee cup is empty.",
"The 'A' key is sticking again.",
"This ink smells strange."
],
events: [
// YOUR ORIGINAL ANOMALIES (Kept exactly as requested)
{
id: 'glitch_door',
triggerPage: 5,
type: 'LOG_GASLIGHT_INSTANT',
normalText: "The door is locked.",
glitchText: "The door is *unlocked*.", // Highlighted (Gaslight)
duration: 800
},
{
id: 'glitch_smell',
triggerPage: 9,
type: 'LOG_GASLIGHT_INSTANT',
normalText: "There is a faint smell of cigarette smoke.",
glitchText: "There is a faint smell of *burning meat*.", // Highlighted (Gaslight)
duration: 900
},
{
id: 'glitch_hands',
triggerPage: 13,
type: 'LOG_GASLIGHT_INSTANT', // Moved to page 13 to match story flow
normalText: "My hands are stiff.",
glitchText: "My hands are covered in *oil*.", // Highlighted (Gaslight)
duration: 800
},
{
id: 'glitch_safe',
triggerPage: 17,
type: 'LOG_GASLIGHT_INSTANT',
normalText: "I am safe and alone.",
glitchText: "I am safe. I feel *safe?*", // Highlighted (Gaslight)
duration: 1000
},
{
id: 'glitch_legs',
triggerPage: 23,
type: 'LOG_GASLIGHT_INSTANT',
normalText: "My back hurts.",
glitchText: "I can't feel my *legs*.", // Highlighted (Gaslight)
duration: 1000
},
{
id: 'glitch_phantom',
triggerPage: 10,
type: 'LOG_PHANTOM_SEQUENCE',
},
{
id: 'autosave_normal_1',
triggerPage: 15,
type: 'LOG_NORMAL_AUTOSAVE',
text: "The ink is drying."
}
]
};
// --- TYPEWRITER COMPONENTS ---
const TypewriterText = ({ text, onComplete, speedMultiplier = 1 }) => {
const [displayedText, setDisplayedText] = useState("");
const isCancelled = useRef(false);
useEffect(() => {
isCancelled.current = false;
setDisplayedText("");
if (!text) return;
const operations = [];
let i = 0;
while(i < text.length) {
if (text[i] === '^') {
operations.push({ type: 'PAUSE', duration: 400 });
while(i < text.length && text[i] === '^') {
operations.push({ type: 'BACKSPACE' });
i++;
}
operations.push({ type: 'PAUSE', duration: 300 });
} else {
operations.push({ type: 'ADD', char: text[i] });
i++;
}
}
let opIndex = 0;
let currentStr = "";
const processNextOp = () => {
if (isCancelled.current) return;
if (opIndex >= operations.length) {
if(onComplete) onComplete();
return;
}
const op = operations[opIndex];
opIndex++;
if (op.type === 'ADD') {
currentStr += op.char;
setDisplayedText(currentStr);
const speed = (30 + Math.random() * 20) * speedMultiplier;
setTimeout(processNextOp, speed);
} else if (op.type === 'BACKSPACE') {
currentStr = currentStr.slice(0, -1);
setDisplayedText(currentStr);
setTimeout(processNextOp, 100);
} else if (op.type === 'PAUSE') {
setTimeout(processNextOp, op.duration);
}
};
processNextOp();
return () => { isCancelled.current = true; };
}, [text, speedMultiplier]);
return {displayedText};
};
// --- REDACTION ---
const RedactedBlock = ({ length = 8 }) => {
const chars = "█▓▒░#&@$";
const [text, setText] = useState("");
useEffect(() => {
let str = "";
for(let i=0; i{text};
};
// --- BUTTON ---
const Button = ({ children, onClick, disabled, className = '', variant = 'primary' }) => {
const baseClass = "px-6 py-4 font-mono text-sm uppercase tracking-widest transition-all duration-200 border flex items-center justify-center gap-3 relative overflow-hidden";
const variants = {
primary: disabled ? 'bg-neutral-900 border-neutral-800 text-neutral-700 cursor-not-allowed' : 'bg-neutral-900 border-neutral-700 text-neutral-400 hover:bg-neutral-800 hover:text-white hover:border-neutral-500',
action: disabled ? 'bg-neutral-900 border-neutral-800 text-neutral-700 cursor-not-allowed' : 'bg-neutral-200 border-neutral-200 text-black hover:bg-white',
warning: "border-amber-900/30 text-amber-700 hover:bg-amber-900/10 hover:border-amber-800"
};
return (
);
};
// --- INTRO OVERLAY ---
const IntroOverlay = ({ onDismiss }) => {
return (
"The damp air is ruining the paper. I really need to finish translating these records before the ink dissolves completely. Just thirty pages left..."
);
};
// --- OUTRO OVERLAY ---
const OutroOverlay = ({ show }) => {
if (!show) return null;
const text = "End of demo, eğer oyunu beğendiyseniz uğraşcam";
const [displayed, setDisplayed] = useState("");
useEffect(() => {
let i = 0;
const interval = setInterval(() => {
if (i < text.length) {
setDisplayed(text.substring(0, i + 1));
i++;
} else {
clearInterval(interval);
}
}, 100);
return () => clearInterval(interval);
}, []);
return (