2 Commits
Author SHA1 Message Date
dextatc cfa5985f44 close but not there yet 2026-07-20 19:44:35 +02:00
dextatc a6abe939e8 another media expolre digital content snippet idear 2026-07-20 08:36:20 +02:00
4 changed files with 418 additions and 43 deletions
@@ -0,0 +1,348 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Computer Historyz - Progressive Klick-Decryption</title>
<style>
/* --- KERNFARBEN AUS DESIGN-DOKU: MASCHINEN-INSTANZEN --- */
:root {
--bg-deep: #05070a;
--bg-panel: #0b0e14;
--accent-cyan: #00f2ff;
--accent-green: #00ff73;
--accent-amber: #ffb700;
--accent-red: #ff3e3e;
--text-dim: #888899;
--font-mono: "JetBrains Mono", "Fira Code", "Courier Prime", monospace;
}
body {
background: var(--bg-deep);
color: var(--text-dim);
font-family: var(--font-mono);
margin: 20px;
line-height: 1.5;
}
.panel {
background: var(--bg-panel);
border: 1px solid var(--text-dim);
backdrop-filter: blur(4px);
padding: 15px;
margin-bottom: 25px;
box-shadow: 0 0 6px rgba(0, 242, 255, 0.1);
}
.panel-title {
color: var(--accent-green);
font-weight: bold;
text-transform: uppercase;
letter-spacing: 1px;
margin-top: 0;
margin-bottom: 15px;
border-bottom: 1px dashed var(--text-dim);
padding-bottom: 5px;
}
input, textarea, button {
background: #07090e;
border: 1px solid var(--text-dim);
color: var(--accent-green);
padding: 8px;
font-family: var(--font-mono);
width: 100%;
box-sizing: border-box;
margin-bottom: 10px;
}
input:focus, textarea:focus {
outline: none;
border-color: var(--accent-cyan);
box-shadow: 0 0 6px var(--accent-cyan);
}
button {
cursor: pointer;
font-weight: bold;
background: #0c161a;
border-color: var(--accent-cyan);
color: var(--accent-cyan);
transition: all 0.2s ease;
}
button:hover {
background: var(--accent-cyan);
color: var(--bg-deep);
box-shadow: 0 0 6px var(--accent-cyan);
}
/* --- CRYPTO BLÖCKE SYSTEM --- */
.lock-chain {
white-space: pre-wrap;
word-break: break-all;
background: #020407;
padding: 12px;
border-left: 3px solid var(--text-dim);
margin: 15px 0;
color: #555566;
transition: all 0.3s ease;
opacity: 0.6;
}
/* Zustand: Block wartet darauf, geklickt zu werden */
.lock-chain.is-active {
border-left: 3px solid var(--accent-amber);
color: var(--accent-cyan);
cursor: pointer;
opacity: 1;
box-shadow: 0 0 6px rgba(255, 183, 0, 0.2);
animation: pulse-active 2s infinite ease-in-out;
}
/* Zustand: Erfolgreich decodiert */
.lock-chain.is-decrypted {
border-left: 3px solid var(--accent-green);
color: var(--accent-green);
background: transparent;
white-space: normal;
opacity: 1;
animation: none;
cursor: default;
}
/* Zustand: Fehler bei der Entschlüsselung */
.lock-chain.error {
border-left: 3px solid var(--accent-red);
color: var(--accent-red);
opacity: 1;
animation: blink-error 1s infinite;
}
@keyframes pulse-active {
0% { background: #020407; }
50% { background: #0a121c; }
100% { background: #020407; }
}
@keyframes blink-error {
50% { opacity: 0.4; }
}
.control-panel {
max-width: 600px;
}
.status-badge {
display: inline-block;
padding: 2px 6px;
font-size: 0.85em;
background: #111;
border: 1px solid var(--text-dim);
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="panel control-panel">
<div class="panel-title">Decryption Control Deck</div>
<label for="master-pass">Master-Passwort (Key 0):</label>
<input type="password" id="master-pass" value="OortscheWolke2448">
<button onclick="initializeCryptoChain()">Krypto-Kette initialisieren</button>
<div id="deck-status" class="status-badge" style="color: var(--accent-amber);">Status: Warte auf Initialisierung...</div>
</div>
<div class="panel">
<div class="panel-title">Dokument-Struktur (Instanzen-Protokoll)</div>
<h3>Knotenpunkt-Datenstrom</h3>
<p><em>Dieser Textbereich liegt außerhalb der Kette und bleibt dauerhaft sichtbar.</em></p>
<div class="lock-chain" id="block-0" onclick="triggerBlockDecryption(0)">&#x02;
4a21184a44f9deeb8db93ee5c56dfba2d28fbfb3970b880197d19e9eb10a
a011de36bdfc1103f6f14066094ef5ad0554ba739cae9dfc01991a0c0f99
8ee2954aef83fbdf9842a2acb119cb
&#x03;</div>
<div class="lock-chain" id="block-1" onclick="triggerBlockDecryption(1)">&#x02;
108b688d01a3579ab5a6c117b38d388f8d689b9d3ff02102554dfa45bbca
c0a7cc02ccff5d8ee9d110f01ccba1dd010ea4fbc11e22778da5a6c1deba
99a9cf588b
&#x03;</div>
<div class="lock-chain" id="block-2" onclick="triggerBlockDecryption(2)">&#x02;
92da21085ba1f43a99e7d9b9d62da3ffde4bb8df115dd0ca31bdaef9d877
bbad84ff4da92da74e99a4c11100bb17dca5ffca188e7d22cb54fb77ac90
d22bb488de1a56daff8e9b
&#x03;</div>
</div>
<div class="panel">
<div class="panel-title">Ketten-Generator (Text-zu-Klick-Block)</div>
<textarea id="gen-input" rows="4">Das Ur-Ding der Erbauer war die Energie.
Die Hauptmaschinen sind monumentale Datenbanken.
Das Nina-Protokoll verhindert den Ressourcen-Kollaps.</textarea>
<button onclick="generateNewChain()">Neue Krypto-Kette generieren</button>
<div id="gen-output" style="white-space: pre; font-family: var(--font-mono); color: var(--accent-cyan); margin-top: 10px; font-size: 0.9em;"></div>
</div>
<script>
// --- STATE MACHINE FÜR DIE KLICK-KETTE ---
let currentActiveIndex = -1;
let nextKeyString = "";
// --- UTILITIES (Native Web Crypto) ---
function bufToHex(buf) {
return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');
}
function hexToBuf(hex) {
const bytes = new Uint8Array(hex.length / 2);
for (let i = 0; i < hex.length; i += 2) {
bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);
}
return bytes.buffer;
}
async function deriveKey(passwordString) {
const encoder = new TextEncoder();
const data = encoder.encode(passwordString);
const hash = await crypto.subtle.digest('SHA-256', data);
return await crypto.subtle.importKey('raw', hash, { name: 'AES-GCM' }, false, ['encrypt', 'decrypt']);
}
// --- INTERAKTIVE LOGIK ---
// Schritt 1: Master-Passwort laden und Block 0 scharf schalten
function initializeCryptoChain() {
const masterPassword = document.getElementById('master-pass').value;
if (!masterPassword) {
updateStatus("FEHLER: Passwort fehlt", "var(--accent-red)");
return;
}
nextKeyString = masterPassword;
currentActiveIndex = 0;
// Alle UI-Klassen zurücksetzen
const blocks = document.querySelectorAll('.lock-chain');
blocks.forEach((block, idx) => {
block.classList.remove('is-active', 'is-decrypted', 'error');
// Wenn es der erste Block ist, aktiv schalten
if(idx === 0) {
block.classList.add('is-active');
}
});
updateStatus("Kette bereit. Klicke auf Block 1...", "var(--accent-cyan)");
}
// Schritt 2: Klick-Handler für die einzelnen Blöcke
async function triggerBlockDecryption(blockIndex) {
// Ignoriere Klicks, wenn der Block noch nicht an der Reihe ist
if (blockIndex !== currentActiveIndex) return;
const block = document.getElementById(`block-${blockIndex}`);
let rawContent = block.innerText.replace(/\r?\n|\r/g, "");
// Format-Sicherheitscheck (\x02 STX und \x03 ETX)
if (!rawContent.startsWith('\x02') || !rawContent.endsWith('\x03')) {
markError(block, "Formatierungsfehler (Steuerzeichen fehlen)");
return;
}
// Payload-Filterung
const payload = rawContent.substring(1, rawContent.length - 1).replace(/\s/g, "");
const ivHex = payload.substring(0, 24);
const cipherHex = payload.substring(24);
try {
const iv = hexToBuf(ivHex);
const cipherData = hexToBuf(cipherHex);
const key = await deriveKey(nextKeyString);
const decryptedBuf = await crypto.subtle.decrypt(
{ name: 'AES-GCM', iv: iv },
key,
cipherData
);
const plaintext = new TextDecoder().decode(decryptedBuf);
// DOM-Austausch unter Beibehaltung der Struktur
block.innerHTML = plaintext;
block.classList.remove('is-active', 'error');
block.classList.add('is-decrypted');
// HIER PASSIERT DIE FORTLAUFENDE SCHLÜSSEL-ÜBERGABE:
nextKeyString = plaintext;
// Nächsten Block in der Kette freischalten
currentActiveIndex++;
const nextBlock = document.getElementById(`block-${currentActiveIndex}`);
if (nextBlock) {
nextBlock.classList.add('is-active');
updateStatus(`Block ${blockIndex + 1} gelöst. Nächster Block freigegeben!`, "var(--accent-cyan)");
} else {
updateStatus("System vollständig decodiert. Kette beendet.", "var(--accent-green)");
}
} catch (err) {
markError(block, `Kettenschluss fehlgeschlagen. Falscher Key.`);
}
}
function markError(element, message) {
element.classList.remove('is-active');
element.classList.add('error');
element.innerText = `[CRITICAL CODE CORRUPTION: ${message}]`;
updateStatus("Kette dauerhaft unterbrochen.", "var(--accent-red)");
currentActiveIndex = -1; // Blockiert weitere Klicks
}
function updateStatus(text, color) {
const badge = document.getElementById('deck-status');
badge.innerText = `Status: ${text}`;
badge.style.color = color;
badge.style.borderColor = color;
}
// --- CHIP-GENERATOR FÜR DEINE TEXTE ---
async function generateNewChain() {
const masterPassword = document.getElementById('master-pass').value;
const lines = document.getElementById('gen-input').value.split('\n').filter(l => l.trim() !== "");
let currentKeyString = masterPassword;
let htmlOutput = "";
for (let i = 0; i < lines.length; i++) {
const plaintext = lines[i];
const iv = crypto.getRandomValues(new Uint8Array(12));
const key = await deriveKey(currentKeyString);
const encryptedBuf = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv: iv },
key,
new TextEncoder().encode(plaintext)
);
const fullPayloadHex = bufToHex(iv) + bufToHex(encryptedBuf);
let formattedHex = "";
for (let j = 0; j < fullPayloadHex.length; j += 60) {
formattedHex += "\n" + fullPayloadHex.substring(j, j + 60);
}
// Generiert direkt die korrekten Klick-IDs und Handler für deinen Quelltext
htmlOutput += `&lt;div class="lock-chain" id="block-${i}" onclick="triggerBlockDecryption(${i})"&gt;&#x02;${formattedHex}\n&#x03;&lt;/div&gt;\n\n`;
currentKeyString = plaintext;
}
document.getElementById('gen-output').innerHTML = htmlOutput;
}
</script>
</body>
</html>
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/bash
BASEDIR=$(pwd)
INPUT_DIR="$BASEDIR/input"
OUTPUT_DIR="$BASEDIR/91_sonnensystem"
TEMPLATES="$BASEDIR/templates"
chown -R appuser:appgroup "$OUTPUT_DIR"
function convert_adoc() {
if [ -f "$1" ]; then
echo "-> Konvertiere $1 zu HTML..."
asciidoctor -b html5 -a stylesheet=$TEMPLATES/retro-dark.css -a linkcss -a toc=left "$INPUT_DIR/$1" -o "$OUTPUT_DIR/$2"
else
echo " [INFO] $1 nicht gefunden, überspringe..."
fi
}
echo '--- Baue README ---'
convert_adoc README.adoc README.html
echo '--- Baue Lore (Master-Dokument) ---'
LORE_SRC="$INPUT_DIR/index.adoc"
if [ -f "$INPUT_DIR/master.adoc" ]; then LORE_SRC="$INPUT_DIR/master.adoc"; fi
if [ -f "$LORE_SRC" ]; then
echo "-> Generiere Lore-Dokument (HTML & Markdown) aus $LORE_SRC..."
asciidoctor -b html5 -d book -a stylesheet=$TEMPLATES/retro-dark.css -a linkcss -a toc=left "$LORE_SRC" -o "$OUTPUT_DIR/lore.html"
asciidoctor -b docbook -d book "$LORE_SRC" -o "$OUTPUT_DIR/temp_lore.xml"
pandoc -f docbook -t markdown_strict "$OUTPUT_DIR/temp_lore.xml" -o "$OUTPUT_DIR/lore.md"
rm "$OUTPUT_DIR/temp_lore.xml"
else
echo " [WARNUNG] Weder index.adoc noch master.adoc gefunden!"
fi
echo '--- Baue Fließtexte / Geschichten ---'
if [ -f "$INPUT_DIR/darkCenter.adoc" ]; then
echo "-> Konvertiere darkCenter.adoc zu HTML..."
asciidoctor -b html5 -d book -a stylesheet=$TEMPLATES/retro-dark.css -a linkcss -a toc=left "$INPUT_DIR/darkCenter.adoc" -o "$OUTPUT_DIR/darkCenter.html"
fi
rm -rf ./export
mkdir "$OUTPUT_DIR/css"
cp "$TEMPLATES/retro-dark.css" "$OUTPUT_DIR/css/"
cp "$TEMPLATES/index.html" "$OUTPUT_DIR/"
sed -i 's/\/workspace\/templates/css/g' "$OUTPUT_DIR/darkCenter.html"
chown -R appuser:appgroup "$OUTPUT_DIR"
+16
View File
@@ -0,0 +1,16 @@
FROM debian:stable-slim
RUN apt-get update && apt-get upgrade && apt-get -y install asciidoctor pandoc bash
RUN groupadd --gid 1000 appgroup && \
useradd --uid 1000 --gid appgroup --shell /bin/bash --create-home appuser
WORKDIR /workspace
ADD ./90_builder/templates templates
ADD ./90_builder/bookFold.sh ./
RUN chown -R appuser:appgroup /workspace
CMD ["/usr/bin/bash" "./bookFold.sh"]
+7 -43
View File
@@ -1,15 +1,15 @@
#!/bin/bash
# Name des lokalen Docker-Images
IMAGE_NAME="lore-builder"
IMAGE_NAME="ian-lore-builder"
# Input Ordner
INP_DIR=$(pwd)
# Build Ordner
BID_DIR="90_builder"
# BID_DIR="90_builder"
# Build templares
TEMPLATES="$BID_DIR/templates"
# TEMPLATES="$BID_DIR/templates"
# Ausgabeordner
OUT_DIR="91_sonnensystem"
OUT_DIR="$INP_DIR/91_sonnensystem"
# Farben für Output
GREEN='\033[0;32m'
@@ -26,11 +26,7 @@ echo -e "Output-Ordner '${GREEN}$OUT_DIR${NC}' bereinigt und bereit."
# 2. Prüfen, ob das Docker-Image existiert, ansonsten on-the-fly bauen
if [[ "$(docker images -q $IMAGE_NAME 2> /dev/null)" == "" ]]; then
echo -e "${BLUE}Baue flüchtiges Docker-Image '$IMAGE_NAME' (Alpine, Asciidoctor, Pandoc)...${NC}"
docker build -t $IMAGE_NAME - <<EOF
FROM alpine:latest
RUN apk add --no-cache asciidoctor pandoc bash
WORKDIR /workspace
EOF
docker build -t $IMAGE_NAME -f ./90_builder/container/deb_Dockerfile .
fi
# 3. CSS Datei für Retro Space Dark Theme in den Export-Ordner generieren
@@ -39,40 +35,8 @@ fi
echo -e "${BLUE}Starte Build-Container und generiere Dokumente...${NC}"
# 4. Container starten und Build-Schritte im Container ausführen
docker run --rm -v "$INP_DIR:/workspace" $IMAGE_NAME bash -c "
function convert_adoc() {
if [ -f \"\$1\" ]; then
echo \"-> Konvertiere \$1 zu HTML...\"
asciidoctor -b html5 -a stylesheet=$TEMPLATES/retro-dark.css -a linkcss -a toc=left \"\$1\" -o \"$OUT_DIR/\$2\"
else
echo \" [INFO] \$1 nicht gefunden, überspringe...\"
fi
}
echo '--- Baue README ---'
convert_adoc README.adoc README.html
echo '--- Baue Lore (Master-Dokument) ---'
LORE_SRC=\"index.adoc\"
if [ -f master.adoc ]; then LORE_SRC=\"master.adoc\"; fi
if [ -f \"\$LORE_SRC\" ]; then
echo \"-> Generiere Lore-Dokument (HTML & Markdown) aus \$LORE_SRC...\"
asciidoctor -b html5 -d book -a stylesheet=$TEMPLATES/retro-dark.css -a linkcss -a toc=left \"\$LORE_SRC\" -o \"$OUT_DIR/lore.html\"
asciidoctor -b docbook -d book \"\$LORE_SRC\" -o \"$OUT_DIR/temp_lore.xml\"
pandoc -f docbook -t markdown_strict \"$OUT_DIR/temp_lore.xml\" -o \"$OUT_DIR/lore.md\"
rm \"$OUT_DIR/temp_lore.xml\"
else
echo \" [WARNUNG] Weder index.adoc noch master.adoc gefunden!\"
fi
echo '--- Baue Fließtexte / Geschichten ---'
if [ -f darkCenter.adoc ]; then
echo \"-> Konvertiere darkCenter.adoc zu HTML...\"
asciidoctor -b html5 -d book -a stylesheet=$TEMPLATES/retro-dark.css -a linkcss -a toc=left darkCenter.adoc -o \"$OUT_DIR/darkCenter.html\"
fi
"
# docker run --rm -v "$INP_DIR:/workspace" $IMAGE_NAME /workspace/bookFold.sh
docker run --rm -v "$(pwd):/workspace/input" -v "$(pwd)/91_sonnensystem:/workspace/91_sonnensystem" $IMAGE_NAME
# 5. index.html vollautomatisch und direkt generieren
# moved to $BID_OUT/templates/index.html