Files
beh-rde-brief/webseite/demo.html
T
JUSNandClaude Opus 5 585f027ba5 Bezahlseite erscheint in der Sprache des Nutzers
Wer von der tuerkischen Seite kam, landete bisher auf einer deutschen
Stripe-Seite — fuer die Zielgruppe die groesste Huerde im Kaufvorgang.

/kaufen nimmt jetzt 'sprache' entgegen und gibt sie als locale an Stripe
weiter. Nur Sprachen aus STRIPE_SPRACHEN werden geschickt: Ein unbekannter
Wert laesst Stripe die Session mit 400 ablehnen, der Kauf waere kaputt. Fuer
Arabisch, Tigrinya usw. (kennt Stripe nicht) wird nichts mitgeschickt, dann
waehlt Stripe selbst anhand des Browsers.

Alle drei Kauf-Stellen geben die Sprache mit: Sprachseiten fest ihre eigene,
Demo-Seite die dort gewaehlte Zielsprache, Startseite 'de'.

Geprueft: tr/de/pl/ar liefern Bezahlseiten, und eine erfundene Sprache faellt
sauber zurueck statt den Kauf zu brechen.

Stripe Link (die vorausgewaehlte Schnellzahlung) laesst sich NICHT per API
abschalten — laut Stripe-Docs nur in den Zahlungsmethoden-Einstellungen des
Dashboards.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 15:59:46 +02:00

893 lines
40 KiB
HTML

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gratis-Demo: Behördenbrief online erklären lassen | BehördenKlar</title>
<meta name="description" content="Testen Sie BehördenKlar direkt im Browser: Brief fotografieren, hochladen, in einfacher Sprache erklärt bekommen. 2 Analysen gratis, ohne Konto.">
<meta name="keywords" content="Amtsbrief, Behördenbrief, verständlich, einfache Sprache, Jobcenter, Ausländerbehörde, Warteliste">
<meta name="author" content="BehördenKlar">
<meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1">
<meta name="theme-color" content="#1d4e89">
<meta name="apple-mobile-web-app-title" content="BehördenKlar">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta property="og:locale:alternate" content="tr_TR">
<meta property="og:locale:alternate" content="ar_AR">
<meta property="og:locale:alternate" content="en_US">
<meta property="og:locale:alternate" content="uk_UA">
<meta property="og:locale:alternate" content="ru_RU">
<meta property="og:locale:alternate" content="pl_PL">
<link rel="manifest" href="/manifest.json">
<meta name="google-site-verification" content="6o1sIKmK7WSloQrdTs2q4WtQsCUBB-bRa24gNXzVeFc">
<meta name="msvalidate.01" content="...">
<meta name="apple-app-site-association" content="...">
<meta name="app-links" content="...">
<meta name="target-audience" content="Alle, die schwierige Post bekommen — Privatpersonen, Selbständige, Menschen mit Deutsch als Fremdsprache">
<meta name="accessibility" content="WCAG 2.1 AA, Vorlesen, einfache Sprache, mehrsprachig">
<meta name="topics" content="civic-tech, legal-tech, accessibility, education, language-simplification, vulnerable-populations">
<meta name="target-organizations" content="Beratungsstellen, Jobcenter, Caritas, Diakonie, VHS, Migrationsberatung">
<meta name="problem-statement" content="Amtsdeutsch und Vertragssprache sind unnötig schwer. BehördenKlar macht daraus Klartext mit Frist und To-do-Liste.">
<link rel="canonical" href="https://behoerdenklar.de/demo">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<meta property="og:site_name" content="BehördenKlar">
<meta property="og:type" content="website">
<meta property="og:locale" content="de_DE">
<meta property="og:url" content="https://behoerdenklar.de/demo">
<meta property="og:title" content="Probieren Sie es aus: Ihr Behördenbrief, einfach erklärt">
<meta property="og:description" content="Direkt im Browser testen — 2 Gratis-Analysen, ohne Konto. Brief fotografieren, Klartext lesen.">
<meta property="og:image" content="https://behoerdenklar.de/vorschau.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta name="twitter:card" content="summary_large_image">
<style>
:root {
--papier: #faf7f0;
--papier-dunkel: #f1ecdf;
--tinte: #21211d;
--grau: #6b675e;
--amtsblau: #1d4e89;
--stempelrot: #b3372b;
--marker: #ffe66b;
--gruen: #2e7d4f;
--rot: #b3372b;
--gelb: #a06b00;
color-scheme: light;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
font-family: Georgia, 'Times New Roman', serif;
background:
repeating-linear-gradient(0deg, transparent 0 34px, rgba(33, 33, 29, 0.025) 34px 35px),
var(--papier);
color: var(--tinte);
line-height: 1.7;
font-size: 17px;
}
.mono { font-family: 'Courier New', ui-monospace, monospace; letter-spacing: 0.02em; }
.wrap { max-width: 720px; margin: 0 auto; padding: 0 20px 72px; }
.briefkopf {
display: flex; justify-content: space-between; align-items: baseline;
padding: 20px 0 12px; border-bottom: 2px solid var(--tinte);
font-size: 14px;
}
.briefkopf .absender { font-weight: 700; font-size: 16px; }
.briefkopf .absender a { color: inherit; text-decoration: none; }
.briefkopf .az { color: var(--grau); font-size: 13px; }
header { padding: 40px 0 8px; }
.betreff-label {
font-size: 13px; color: var(--grau); text-transform: uppercase;
letter-spacing: 0.14em; margin-bottom: 10px;
}
h1 {
font-size: clamp(30px, 6vw, 44px);
line-height: 1.15; font-weight: 700; letter-spacing: -0.01em;
}
.markiert {
background: linear-gradient(104deg, transparent 2%, var(--marker) 4%, var(--marker) 96%, transparent 98%);
padding: 0 6px; box-decoration-break: clone; -webkit-box-decoration-break: clone;
}
.anrede { margin-top: 20px; font-size: 18px; max-width: 580px; }
section { margin-top: 44px; }
h2 {
font-size: 15px; text-transform: uppercase; letter-spacing: 0.14em;
color: var(--grau); font-weight: 400; margin-bottom: 20px;
display: flex; align-items: center; gap: 12px;
}
h2::after { content: ''; flex: 1; border-top: 1px solid rgba(33,33,29,0.25); }
h2 .nr { font-family: 'Courier New', ui-monospace, monospace; }
.antrag {
background: #fff; border: 2px solid var(--tinte);
box-shadow: 7px 8px 0 rgba(33, 33, 29, 0.9);
padding: 28px 26px; position: relative;
}
.formular-kopf {
font-family: 'Courier New', ui-monospace, monospace;
font-size: 13px; text-transform: uppercase; letter-spacing: 0.1em;
color: var(--grau); margin-bottom: 10px;
}
.cta {
display: inline-block; width: 100%; padding: 17px 30px;
background: var(--amtsblau); color: #fff; text-decoration: none;
font-family: inherit; font-size: 18px; font-weight: 700; text-align: center;
border: 2px solid var(--tinte);
box-shadow: 5px 5px 0 var(--tinte);
transition: transform 0.12s ease, box-shadow 0.12s ease;
cursor: pointer;
}
.cta:hover:not(:disabled) { transform: translate(2px, 2px); box-shadow: 3px 3px 0 var(--tinte); }
.cta:disabled { opacity: 0.45; cursor: not-allowed; }
.konsens {
display: flex; gap: 12px; align-items: flex-start;
font-size: 15px; color: var(--grau); margin: 14px 0 18px;
}
.konsens input { width: 22px; height: 22px; margin-top: 4px; flex-shrink: 0; accent-color: var(--amtsblau); }
.konsens a { color: var(--amtsblau); }
.klein { font-size: 13.5px; color: var(--grau); margin-top: 12px; }
.klein a { color: var(--grau); }
.status { text-align: center; padding: 26px 10px; display: none; }
.status .gross { font-size: 20px; font-weight: 700; }
.status .sub { color: var(--grau); margin-top: 6px; font-size: 15px; }
.sanduhr {
display: inline-block; font-size: 34px;
animation: drehen 2.4s linear infinite;
}
@keyframes drehen { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.fehlerbox {
display: none; margin-top: 16px;
border: 2px solid var(--stempelrot); background: #fdf1ef;
color: #7c2018; padding: 14px 16px; font-size: 16px;
}
.email-teil { display: none; margin-top: 16px; }
.wl-input {
width: 100%; padding: 15px 16px; font-size: 17px; font-family: inherit;
border: 2px solid var(--tinte); background: #fff; color: var(--tinte);
margin-bottom: 12px;
}
.wl-input::placeholder { color: #9a958a; }
/* Ergebnis */
#ergebnis { display: none; }
.brief-karte {
background: #fff; border: 1px solid rgba(33, 33, 29, 0.28);
padding: 22px 24px; position: relative; margin-top: 22px;
box-shadow: 4px 5px 0 rgba(33, 33, 29, 0.08);
}
.karten-label {
position: absolute; top: -12px; left: 16px;
font-family: 'Courier New', ui-monospace, monospace; font-size: 12px;
text-transform: uppercase; letter-spacing: 0.1em;
background: var(--gruen); color: var(--papier); padding: 3px 10px;
}
.karten-label.neutral { background: var(--tinte); }
.ampelzeile {
margin-top: 14px; padding-top: 12px;
border-top: 1px dashed rgba(33, 33, 29, 0.3);
font-size: 16px; font-weight: 700;
}
.todo { padding: 8px 0 8px 2px; border-bottom: 1px dotted rgba(33,33,29,0.3); font-size: 16.5px; }
.todo::before { content: '☐'; margin-right: 10px; color: var(--amtsblau); font-size: 18px; }
details { border-bottom: 1px solid rgba(33, 33, 29, 0.2); padding: 12px 4px; }
summary { font-weight: 700; cursor: pointer; font-size: 16.5px; list-style: none; }
summary::-webkit-details-marker { display: none; }
details p { margin-top: 8px; color: var(--grau); font-size: 15.5px; }
.stempel {
display: inline-block; padding: 7px 14px;
border: 2.5px solid var(--stempelrot); color: var(--stempelrot);
font-family: 'Courier New', ui-monospace, monospace; font-weight: 700;
font-size: 14px; letter-spacing: 0.1em; text-transform: uppercase;
transform: rotate(-4deg); opacity: 0.9;
}
.hinweis-recht {
margin-top: 18px; font-size: 14px; color: var(--grau);
border-top: 1px dashed rgba(33,33,29,0.3); padding-top: 12px;
}
/* Warteliste-Formular (wie Startseite) */
.wl-form { display: flex; flex-direction: column; gap: 12px; margin-top: 4px; }
.bonus-zeile {
margin: 14px 0; padding: 12px 16px;
background: linear-gradient(104deg, transparent 1%, var(--marker) 3%, var(--marker) 97%, transparent 99%);
font-size: 16px;
}
footer { margin-top: 48px; font-size: 14.5px; color: var(--grau); }
footer a { color: var(--grau); }
</style>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "BehördenKlar",
"description": "KI erklärt schwierige Briefe von Ämtern, Versicherungen, Vermietern und Banken in einfacher Sprache — mit Fristen und Handlungsanleitung",
"applicationCategory": "AccessibilityApplication",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "EUR"
},
"inLanguage": ["de", "tr", "ar", "en", "uk", "ru", "pl", "fa", "ro", "fr"],
"featureList": [
"Amtsbriefe fotografieren und erklären lassen",
"Klartext in einfacher Sprache",
"Übersetzung in über 25 Sprachen",
"Automatische Erinnerungen für Fristen",
"Fertige Antworten generieren",
"Vorlesen der Inhalte",
"Keine Anmeldung erforderlich"
],
"targetGroup": "Alle, die schwierige offizielle Post bekommen — Privatpersonen und Selbständige",
"author": {
"@type": "Organization",
"name": "BehördenKlar"
}
}
</script>
</head>
<body>
<div class="wrap">
<div class="briefkopf">
<span class="absender"><a href="index.html">📬 BehördenKlar</a> <span style="font-weight:400;font-size:.62em;opacity:.6;letter-spacing:.04em;">by Webklar</span></span>
<span class="az mono">Formular D-01 · Gratis-Demo</span>
</div>
<header>
<p class="betreff-label">Betreff</p>
<h1>Probieren Sie es aus —<br><span class="markiert">mit Ihrem eigenen Brief.</span></h1>
<p class="anrede">
Kein Konto. Keine App-Installation. Laden Sie ein Foto Ihres
Behördenbriefs hoch — in etwa einer Minute lesen Sie ihn in einfacher
Sprache. <strong>2 Analysen gratis.</strong>
</p>
</header>
<section id="demo">
<h2><span class="nr">§ 1</span> Brief hochladen</h2>
<div class="antrag">
<p class="formular-kopf">Antrag auf Klartext · 2 Gratis-Analysen</p>
<div id="eingabe">
<p id="kaufOk" style="display: none; background: #e7f4ea; border: 1px solid #b7dfc1; color: #1a7f37; padding: 12px 14px; border-radius: 8px; margin-bottom: 14px; font-weight: 600;">
✅ Kauf erfolgreich! Ihr Guthaben wurde aktiviert.
</p>
<p id="guthabenBanner" class="bonus-zeile" style="display: none;">
💳 Ihr Guthaben: <strong id="guthabenZahl">0</strong> Analysen — laden Sie den nächsten Brief hoch.
</p>
<p style="margin-bottom: 14px; font-size: 15.5px;">
🌐 <label for="sprachWahl">Erklärung in dieser Sprache:</label>
<select id="sprachWahl" style="font-family: inherit; font-size: 15.5px; padding: 5px 8px; border: 1.5px solid var(--tinte); background: #fff; margin-inline-start: 6px;"></select>
</p>
<label class="konsens">
<input type="checkbox" id="konsens">
<span>
Ich bin einverstanden, dass mein Brief-Foto zur Analyse an den
Server von BehördenKlar und an den KI-Dienst Anthropic (USA)
geschickt wird. Es wird dort nicht dauerhaft gespeichert.
Behördenbriefe enthalten persönliche Daten — laden Sie nur hoch,
was Sie analysieren lassen möchten.
<a href="datenschutz.html" target="_blank">Datenschutzerklärung</a>
</span>
</label>
<div id="emailTeil" class="email-teil">
<p style="margin-bottom: 10px;">
🎉 <strong>Ihre erste Analyse ist verbraucht.</strong> Für die
zweite geben Sie bitte Ihre E-Mail-Adresse ein — so stellen wir
sicher, dass jeder genau 2 Gratis-Analysen bekommt.
</p>
<input class="wl-input" type="email" id="email" placeholder="Ihre E-Mail-Adresse" autocomplete="email">
<p class="klein" style="margin: 0 0 12px;">
Die Adresse wird nur verschlüsselt (als Prüfsumme) gespeichert,
um mitzuzählen — Sie bekommen dadurch keine E-Mails von uns.
</p>
</div>
<input type="file" id="datei" accept="image/jpeg,image/png,application/pdf" style="display: none;">
<button class="cta" id="startKnopf" disabled>📷 Brief auswählen &amp; erklären lassen</button>
<div class="cf-turnstile" data-sitekey="0x4AAAAAAESi2p41B915R4hW" data-action="turnstile-spin-v1" style="margin-top: 14px;"></div>
<p class="klein">
Geht mit Foto (JPG/PNG) oder PDF, max. 5 MB. Tipp: gutes Licht,
Brief von oben, ganzer Text im Bild.
</p>
<p class="klein">
📱 <strong>Am Handy:</strong> Wählen Sie „Galerie" oder „Dateien",
wenn Sie den Brief schon fotografiert haben. Tippen Sie auf
„Kamera", öffnet sich die Kamera-App Ihres Handys — und die fragt
nach ihren eigenen Berechtigungen. <strong>Diese Abfrage kommt von
Ihrem Handy, nicht von uns:</strong> Diese Seite greift weder auf
Kamera noch auf Mikrofon zu.
</p>
</div>
<div class="status" id="status">
<span class="sanduhr">⏳</span>
<p class="gross">Ihr Brief wird analysiert…</p>
<p class="sub">Das dauert bis zu einer Minute. Bitte lassen Sie die Seite geöffnet.</p>
</div>
<div class="fehlerbox" id="fehler"></div>
</div>
</section>
<section id="kaufBlock" style="display: none;">
<h2><span class="nr">§ 2</span> Guthaben kaufen &amp; sofort nutzen</h2>
<div class="antrag">
<p class="formular-kopf">Im Browser nutzen · ohne App Store</p>
<h3 style="font-size: 24px; line-height: 1.3;">Guthaben kaufen — sofort loslegen</h3>
<p style="margin-top: 10px;">
Sie müssen nicht erst testen: Kaufen Sie direkt Guthaben und nutzen Sie
BehördenKlar hier im Browser — auf jedem Gerät, ohne App. Ihr Guthaben
bleibt gespeichert und verfällt nicht.
</p>
<div id="paketListe" style="display: flex; flex-direction: column; gap: 12px; margin-top: 18px;"></div>
<p style="margin-top: 16px; background: #eef4fb; border-inline-start: 4px solid var(--amtsblau); padding: 12px 14px; font-size: 15.5px;">
📧 <strong>Bitte geben Sie beim Bezahlen Ihre E-Mail-Adresse an.</strong>
Sie bekommen danach einen persönlichen Zugangs-Link — damit nutzen Sie
Ihr Guthaben auf <strong>jedem Gerät</strong>: Handy, Tablet, Computer.
Ohne diesen Link ist Ihr Guthaben nur in diesem einen Browser
gespeichert und wäre weg, wenn Sie den Verlauf löschen.
</p>
<label class="konsens" style="margin-top: 18px;">
<input type="checkbox" id="kaufKonsens">
<span>
Ich verlange ausdrücklich, dass die Analysen sofort nach dem Kauf zur
Verfügung stehen, und bestätige, dass mein Widerrufsrecht damit
erlischt. Ich habe die <a href="agb.html" target="_blank">AGB</a> und
die <a href="widerruf.html" target="_blank">Widerrufsbelehrung</a>
gelesen.
</span>
</label>
<div class="fehlerbox" id="kaufFehler" style="display: none; margin-top: 12px;"></div>
<p class="klein" style="margin-top: 12px;">
🔒 Sichere Bezahlung über Stripe — wir sehen Ihre Kartendaten nie.
Keine Umsatzsteuer (§ 19 UStG). Guthaben verfällt nicht.
</p>
<p class="klein" style="margin-top: 10px;">
Anbieter: <strong>Webklar GbR</strong> — BehördenKlar ist ein Angebot von
Webklar. Auf Ihrer Kontoabrechnung erscheint deshalb
<strong>„Webklar"</strong>.
</p>
</div>
</section>
<section id="ergebnis">
<h2><span class="nr">§ 3</span> Ihr Brief in Klartext</h2>
<div class="brief-karte">
<span class="karten-label neutral" id="ergBrieftyp">Brief</span>
<p style="margin-top: 6px;"><strong id="ergKern"></strong></p>
<p class="ampelzeile" id="ergAmpel" style="display: none;"></p>
</div>
<div class="brief-karte">
<span class="karten-label">Einfach erklärt</span>
<p id="ergErklaerung" style="white-space: pre-line;"></p>
</div>
<div class="brief-karte" id="ergChecklisteKarte" style="display: none;">
<span class="karten-label neutral">Das müssen Sie tun</span>
<div id="ergCheckliste"></div>
</div>
<div class="brief-karte" id="ergBegriffeKarte" style="display: none;">
<span class="karten-label neutral">Schwere Wörter erklärt</span>
<div id="ergBegriffe"></div>
</div>
<p class="hinweis-recht">
⚖️ BehördenKlar erklärt Briefe, ersetzt aber keine Rechtsberatung. Bei
wichtigen Entscheidungen hilft eine Beratungsstelle oder ein Anwalt.
</p>
</section>
<section id="werbung" style="display: none;">
<h2><span class="nr">§ 4</span> Wie geht es weiter?</h2>
<div class="antrag">
<p class="formular-kopf" id="restZeile">Warteliste</p>
<h3 id="wlTitel" style="font-size: 24px; line-height: 1.3;">Das hat Ihnen geholfen?</h3>
<p style="margin-top: 10px;">
Die App kann noch mehr: Briefe <strong>übersetzen in über 25 Sprachen</strong>,
Fristen mit <strong>Erinnerung</strong>, fertige
<strong>Antwort-Entwürfe</strong> — und Ihre Briefe bleiben
verschlüsselt auf Ihrem Handy gespeichert.
</p>
<p class="bonus-zeile">
🎁 Warteliste = <strong>5 Gratis-Analysen</strong> in der App statt 3.
</p>
<p id="nochmalZeile" style="display: none; margin-bottom: 14px;">
<a href="#demo" style="color: var(--amtsblau); font-weight: 700;">↑ Noch einen
Brief testen? Ihre zweite Gratis-Analyse wartet oben.</a>
</p>
<form class="wl-form" action="https://86550585.sibforms.com/serve/MUIFAAvOQCpFg148k-xD2Ze2PDVKKaFEIaLECCCMe9fGKd_uIurPljyn_IhTrkR0EkM_pQp_8VBzcHZ6N9sKDX5GBZi9elYKN6isXGPUUxcAgO37OKhTFZyMlJiC9ikRmPI8Q2tU2GvqP6esJ5ReGfv1htZV_OfXRIgW59P6pkeUsYKxqdXA7nWOaWxNTYz4MzzoGg7czJMJ2fxuEg==" method="POST">
<input class="wl-input" style="margin-bottom: 0;" type="email" name="EMAIL" id="wlEmail" placeholder="Ihre E-Mail-Adresse" required autocomplete="email">
<input type="text" name="email_address_check" value="" style="position:absolute; left:-5000px;" tabindex="-1" autocomplete="off" aria-hidden="true">
<input type="hidden" name="locale" value="de">
<input type="hidden" name="html_type" value="simple">
<button class="cta" type="submit">Auf die Warteliste eintragen →</button>
</form>
<p class="klein">
Eine E-Mail zum Start, keine Werbung, jederzeit abmeldbar —
<a href="datenschutz.html">Datenschutzerklärung</a>.
</p>
<div style="margin-top: 16px;"><span class="stempel">Bald im App Store</span></div>
</div>
</section>
<footer>
<a href="index.html">← Zur Startseite</a> ·
<a href="agb.html">AGB</a> ·
<a href="widerruf.html">Widerruf</a> ·
<a href="impressum.html">Impressum</a> ·
<a href="datenschutz.html">Datenschutzerklärung</a>
</footer>
</div>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<script>
(function () {
'use strict';
var BASIS = 'https://behoerdenklar-proxy.behoerdenbrief.workers.dev';
var ENDPUNKT = BASIS + '/demo';
var KAUFEN_ENDPUNKT = BASIS + '/kaufen';
var STATUS_ENDPUNKT = BASIS + '/kauf-status';
var MAX_KANTE = 2000; // wie in der App: reicht für A4, spart Datenvolumen
// Guthaben-Pakete (Stripe TEST-Preise). Für Live später die Live-price_…-IDs.
var PAKETE = [
{ priceId: 'price_1U6BNnBsRA1AOdnedGW5eefh', titel: '5 Analysen', preis: '2,99 €' },
{ priceId: 'price_1U6BPRBsRA1AOdnemDUalzb8', titel: '15 Analysen', preis: '6,99 €', best: true },
];
// Zielsprache: kommt als ?sprache=tr von den Sprachseiten, wird gemerkt.
var SPRACH_SCHLUESSEL = 'bk_sprache';
var SPRACH_NAMEN = {
de:'Deutsch', tr:'Türkçe', ar:'العربية', ru:'Русский', uk:'Українська', pl:'Polski',
ro:'Română', en:'English', fa:'فارسی', ku:'Kurdî', bg:'Български', hr:'Hrvatski',
sr:'Српски', bs:'Bosanski', sq:'Shqip', it:'Italiano', el:'Ελληνικά', es:'Español',
pt:'Português', fr:'Français', hu:'Magyar', vi:'Tiếng Việt', hi:'हिन्दी', ur:'اردو',
ps:'پښتو', ti:'ትግርኛ', so:'Soomaali', zh:'中文'
};
function zielsprache() {
var p = new URLSearchParams(window.location.search).get('sprache');
if (p && SPRACH_NAMEN[p]) { try { localStorage.setItem(SPRACH_SCHLUESSEL, p); } catch (e) {} return p; }
try { var g = localStorage.getItem(SPRACH_SCHLUESSEL); if (g && SPRACH_NAMEN[g]) return g; } catch (e) {}
return 'de';
}
var konsens = document.getElementById('konsens');
var startKnopf = document.getElementById('startKnopf');
var dateiFeld = document.getElementById('datei');
var emailTeil = document.getElementById('emailTeil');
var emailFeld = document.getElementById('email');
var status = document.getElementById('status');
var eingabe = document.getElementById('eingabe');
var fehlerBox = document.getElementById('fehler');
var kaufBlock = document.getElementById('kaufBlock');
var werbung = document.getElementById('werbung');
var guthabenBanner = document.getElementById('guthabenBanner');
var guthabenZahl = document.getElementById('guthabenZahl');
var kaufOk = document.getElementById('kaufOk');
var paketListe = document.getElementById('paketListe');
var kaufKonsens = document.getElementById('kaufKonsens');
var kaufFehler = document.getElementById('kaufFehler');
// Wallet (passwortloses Guthaben) — Token + zuletzt bekannter Stand lokal.
var WALLET_SCHLUESSEL = 'bk_wallet';
var GUTHABEN_SCHLUESSEL = 'bk_guthaben';
function walletToken() { return localStorage.getItem(WALLET_SCHLUESSEL) || ''; }
function setzeWallet(t) { localStorage.setItem(WALLET_SCHLUESSEL, t); }
function guthaben() { return parseInt(localStorage.getItem(GUTHABEN_SCHLUESSEL) || '0', 10); }
function setzeGuthaben(n) { localStorage.setItem(GUTHABEN_SCHLUESSEL, String(Math.max(0, n | 0))); }
function hatGuthaben() { return !!walletToken() && guthaben() > 0; }
// Schlüsselname bewusst 'v2': setzt evtl. falsch gezählte Stände (aus der
// Testphase) bei bestehenden Besuchern automatisch einmalig zurück.
var SPEICHER_SCHLUESSEL = 'bk_demo_v2';
function benutzt() { return parseInt(localStorage.getItem(SPEICHER_SCHLUESSEL) || '0', 10); }
function setzeBenutzt(n) { localStorage.setItem(SPEICHER_SCHLUESSEL, String(n)); }
function zeigeStand() {
// Bezahlter Modus: Eingabe offen, Guthaben-Stand zeigen, Gratis-Sperre egal
if (hatGuthaben()) {
eingabe.style.display = 'block';
guthabenBanner.style.display = 'block';
guthabenZahl.textContent = guthaben();
emailTeil.style.display = 'none';
fehlerBox.style.display = 'none';
kaufBlock.style.display = 'none';
return;
}
guthabenBanner.style.display = 'none';
// Kauf ist IMMER möglich — auch sofort, ohne die Gratis-Analysen zu nutzen.
kaufBlock.style.display = 'block';
// 2. Versuch: E-Mail-Feld einblenden; alles verbraucht: Gratis-Weg sperren
if (benutzt() >= 2) {
eingabe.style.display = 'none';
fehlerBox.style.display = 'block';
fehlerBox.innerHTML = 'Ihre 2 Gratis-Analysen sind verbraucht. Kaufen Sie unten <strong>Guthaben</strong>, um hier direkt weiterzumachen — oder tragen Sie sich für die App ein.';
werbung.style.display = 'block';
} else if (benutzt() === 1) {
emailTeil.style.display = 'block';
}
}
konsens.addEventListener('change', function () { startKnopf.disabled = !konsens.checked; });
startKnopf.addEventListener('click', function () {
fehlerBox.style.display = 'none';
if (!hatGuthaben() && benutzt() >= 1 && !emailFeld.value.trim()) {
emailTeil.style.display = 'block';
emailFeld.focus();
zeigeFehler('Bitte geben Sie zuerst Ihre E-Mail-Adresse ein — dann wählen Sie den Brief aus.');
return;
}
dateiFeld.click();
});
dateiFeld.addEventListener('change', function () {
if (dateiFeld.files && dateiFeld.files[0]) starteAnalyse(dateiFeld.files[0]);
});
function zeigeFehler(text) {
fehlerBox.style.display = 'block';
fehlerBox.textContent = text;
}
function turnstileToken() {
var feld = document.querySelector('[name="cf-turnstile-response"]');
return feld ? feld.value : '';
}
/** Foto verkleinern (max 2000px, JPEG 60%) — wie in der App. */
function bildVerkleinern(datei) {
return new Promise(function (resolve, reject) {
var img = new Image();
var url = URL.createObjectURL(datei);
img.onload = function () {
URL.revokeObjectURL(url);
var f = Math.min(1, MAX_KANTE / Math.max(img.width, img.height));
var c = document.createElement('canvas');
c.width = Math.round(img.width * f);
c.height = Math.round(img.height * f);
c.getContext('2d').drawImage(img, 0, 0, c.width, c.height);
resolve(c.toDataURL('image/jpeg', 0.6).split(',')[1]);
};
img.onerror = function () { URL.revokeObjectURL(url); reject(new Error('Bild unlesbar')); };
img.src = url;
});
}
function pdfAlsBase64(datei) {
return new Promise(function (resolve, reject) {
var leser = new FileReader();
leser.onload = function () { resolve(String(leser.result).split(',')[1]); };
leser.onerror = function () { reject(new Error('Datei unlesbar')); };
leser.readAsDataURL(datei);
});
}
async function starteAnalyse(datei) {
fehlerBox.style.display = 'none';
if (datei.size > 5 * 1024 * 1024 && datei.type === 'application/pdf') {
zeigeFehler('Die PDF-Datei ist zu groß (max. 5 MB). Tipp: Fotografieren Sie den Brief stattdessen.');
return;
}
var token = turnstileToken();
if (!token) {
zeigeFehler('Die Sicherheitsprüfung lädt noch — bitte warten Sie 2 Sekunden und versuchen Sie es erneut.');
return;
}
eingabe.style.display = 'none';
status.querySelector('.gross').textContent = 'Ihr Brief wird analysiert…';
status.style.display = 'block';
try {
var istPdf = datei.type === 'application/pdf';
var base64 = istPdf ? await pdfAlsBase64(datei) : await bildVerkleinern(datei);
var bezahlt = hatGuthaben();
var body = {
bild: base64,
mimeType: istPdf ? 'application/pdf' : 'image/jpeg',
turnstileToken: token,
};
var email = emailFeld.value.trim();
body.zielsprache = zielsprache();
if (bezahlt) body.walletToken = walletToken();
else if (benutzt() >= 1 && email) body.email = email;
var antwort = await fetch(ENDPUNKT, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(body),
});
var daten = await antwort.json();
if (!antwort.ok) {
status.style.display = 'none';
eingabe.style.display = 'block';
if (window.turnstile) window.turnstile.reset();
if (daten.code === 'email_noetig') {
// Nur das E-Mail-Feld zeigen — NICHT als verbraucht markieren.
// (Sonst würde ein serverseitiges "E-Mail nötig", z. B. bei
// geteiltem Anschluss, den Browser dauerhaft blockieren, obwohl
// gar keine Analyse gelungen ist.)
emailTeil.style.display = 'block';
emailFeld.focus();
}
if (daten.code === 'aufgebraucht') {
setzeBenutzt(2);
zeigeStand();
return;
}
if (daten.code === 'kein_guthaben') {
setzeGuthaben(0);
guthabenBanner.style.display = 'none';
kaufBlock.style.display = 'block';
kaufBlock.scrollIntoView({ behavior: 'smooth' });
return;
}
zeigeFehler(daten.meldung || 'Etwas ist schiefgelaufen. Bitte erneut versuchen.');
return;
}
// Token erneuern — sonst würde die nächste Analyse ein "Seite neu laden" verlangen
if (window.turnstile) window.turnstile.reset();
if (daten.versuch === 'bezahlt' || typeof daten.guthaben === 'number') {
setzeGuthaben(daten.guthaben);
zeigeErgebnis(daten.analyse, null, daten.guthaben);
return;
}
setzeBenutzt(Math.max(benutzt(), daten.versuch));
if (email) document.getElementById('wlEmail').value = email;
zeigeErgebnis(daten.analyse, daten.versuch);
} catch (e) {
status.style.display = 'none';
eingabe.style.display = 'block';
if (window.turnstile) window.turnstile.reset();
zeigeFehler('Verbindung fehlgeschlagen. Bitte prüfen Sie Ihr Internet und versuchen Sie es erneut.');
}
}
/** Ampel wie in der App: rot ≤ 7 Tage, gelb ≤ 21, sonst grün. */
function ampel(analyse) {
var daten = [];
if (analyse.frist && analyse.frist.datum) daten.push(analyse.frist.datum);
if (analyse.termin && analyse.termin.datum) daten.push(analyse.termin.datum);
if (!daten.length) return null;
daten.sort();
var tage = Math.ceil((new Date(daten[0] + 'T12:00:00') - new Date()) / 86400000);
if (isNaN(tage)) return null;
var farbe = tage <= 7 ? 'var(--rot)' : tage <= 21 ? 'var(--gelb)' : 'var(--gruen)';
var punkt = tage <= 7 ? '🔴' : tage <= 21 ? '🟡' : '🟢';
var text = tage < 0 ? 'Die Frist ist womöglich schon vorbei!' :
tage === 0 ? 'HEUTE ist der wichtige Tag!' :
'Noch ' + tage + ' Tage Zeit (' + daten[0].split('-').reverse().join('.') + ')';
return { farbe: farbe, text: punkt + ' ' + text };
}
function zeigeErgebnis(analyse, versuch, guthabenRest) {
status.style.display = 'none';
document.getElementById('ergBrieftyp').textContent = analyse.brieftyp || 'Ihr Brief';
document.getElementById('ergKern').textContent = analyse.kernaussage || '';
document.getElementById('ergErklaerung').textContent = analyse.erklaerung_einfach || '';
var a = ampel(analyse);
var ampelEl = document.getElementById('ergAmpel');
if (a) {
ampelEl.style.display = 'block';
ampelEl.style.color = a.farbe;
var teile = [a.text];
if (analyse.frist && analyse.frist.aktion) teile.push(analyse.frist.aktion);
ampelEl.textContent = teile.join(' · ');
}
if (analyse.checkliste && analyse.checkliste.length) {
document.getElementById('ergChecklisteKarte').style.display = 'block';
document.getElementById('ergCheckliste').innerHTML = analyse.checkliste
.map(function (t) { var d = document.createElement('div'); d.className = 'todo'; d.textContent = t; return d.outerHTML; })
.join('');
}
if (analyse.fachbegriffe && analyse.fachbegriffe.length) {
document.getElementById('ergBegriffeKarte').style.display = 'block';
document.getElementById('ergBegriffe').innerHTML = analyse.fachbegriffe
.map(function (b) {
var det = document.createElement('details');
var sum = document.createElement('summary');
sum.textContent = b.begriff;
var p = document.createElement('p');
p.textContent = b.erklaerung;
det.appendChild(sum); det.appendChild(p);
return det.outerHTML;
})
.join('');
}
document.getElementById('ergebnis').style.display = 'block';
// Bezahlter Modus: Guthaben-Stand zeigen, Eingabe für den nächsten Brief öffnen
if (typeof guthabenRest === 'number') {
werbung.style.display = 'none';
kaufOk.style.display = 'none';
if (guthabenRest > 0) {
eingabe.style.display = 'block';
guthabenBanner.style.display = 'block';
guthabenZahl.textContent = guthabenRest;
emailTeil.style.display = 'none';
kaufBlock.style.display = 'none';
} else {
eingabe.style.display = 'none';
guthabenBanner.style.display = 'none';
kaufBlock.style.display = 'block';
}
document.getElementById('ergebnis').scrollIntoView({ behavior: 'smooth' });
return;
}
var rest = 2 - benutzt();
document.getElementById('restZeile').textContent =
rest > 0 ? 'Noch ' + rest + ' Gratis-Analyse übrig' : 'Ihre 2 Gratis-Analysen sind verbraucht';
document.getElementById('wlTitel').textContent =
rest > 0 ? 'Das hat Ihnen geholfen?' : 'Weiter geht es in der App';
document.getElementById('werbung').style.display = 'block';
if (rest > 0) {
// Upload-Bereich für die 2. Analyse wieder anbieten (mit E-Mail-Feld)
eingabe.style.display = 'block';
emailTeil.style.display = 'block';
document.getElementById('nochmalZeile').style.display = 'block';
}
document.getElementById('ergebnis').scrollIntoView({ behavior: 'smooth' });
}
// ---- Guthaben kaufen ------------------------------------------------
function rendrePakete() {
paketListe.innerHTML = '';
PAKETE.forEach(function (p) {
var b = document.createElement('button');
b.className = 'cta';
b.type = 'button';
b.style.width = '100%';
b.style.display = 'flex';
b.style.justifyContent = 'space-between';
b.style.alignItems = 'center';
var links = document.createElement('span');
links.textContent = (p.best ? '⭐ ' : '') + p.titel;
var rechts = document.createElement('strong');
rechts.textContent = p.preis;
b.appendChild(links);
b.appendChild(rechts);
b.addEventListener('click', function () { starteKauf(p.priceId, b); });
paketListe.appendChild(b);
});
}
function starteKauf(priceId, knopf) {
if (!kaufKonsens.checked) {
kaufFehler.style.display = 'block';
kaufFehler.textContent = 'Bitte bestätigen Sie zuerst das Häkchen, um fortzufahren.';
kaufKonsens.focus();
return;
}
kaufFehler.style.display = 'none';
var alt = knopf.innerHTML;
knopf.disabled = true;
knopf.textContent = 'Weiter zu Stripe …';
fetch(KAUFEN_ENDPUNKT, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ priceId: priceId, sprache: zielsprache() }),
})
.then(function (r) { return r.json(); })
.then(function (d) {
if (d && d.url) { window.location.href = d.url; return; }
throw new Error('keine url');
})
.catch(function () {
knopf.disabled = false;
knopf.innerHTML = alt;
kaufFehler.style.display = 'block';
kaufFehler.textContent = 'Die Bezahlseite konnte nicht geöffnet werden. Bitte erneut versuchen.';
});
}
// ---- Rückkehr von Stripe / Wallet-Wiederherstellung -----------------
function reinigeUrl() {
if (window.history.replaceState) {
window.history.replaceState({}, document.title, window.location.pathname);
}
}
function holeKaufStatus(sid, n) {
fetch(STATUS_ENDPUNKT + '?session_id=' + encodeURIComponent(sid))
.then(function (r) { return r.json().then(function (d) { return { ok: r.ok, d: d }; }); })
.then(function (res) {
if (res.ok && res.d && res.d.token) {
setzeWallet(res.d.token);
setzeGuthaben(res.d.guthaben);
status.style.display = 'none';
kaufOk.style.display = 'block';
zeigeStand();
document.getElementById('demo').scrollIntoView({ behavior: 'smooth' });
return;
}
if (n < 4) { setTimeout(function () { holeKaufStatus(sid, n + 1); }, 1500); return; }
status.style.display = 'none';
zeigeFehler('Ihre Zahlung wird noch bestätigt. Bitte laden Sie die Seite in einer Minute neu.');
})
.catch(function () {
status.style.display = 'none';
zeigeFehler('Die Zahlungsbestätigung konnte nicht geladen werden. Bitte Seite neu laden.');
});
}
function pruefeRueckkehr() {
var p = new URLSearchParams(window.location.search);
var w = p.get('wallet');
if (w) { setzeWallet(w); setzeGuthaben(Math.max(guthaben(), 1)); reinigeUrl(); return; }
var kauf = p.get('kauf');
if (kauf === 'abbruch') {
reinigeUrl();
fehlerBox.style.display = 'block';
fehlerBox.textContent = 'Kauf abgebrochen — es wurde nichts berechnet.';
return;
}
if (kauf === 'ok') {
var sid = p.get('session_id');
reinigeUrl();
if (!sid) return;
status.querySelector('.gross').textContent = 'Ihr Kauf wird bestätigt …';
eingabe.style.display = 'none';
status.style.display = 'block';
holeKaufStatus(sid, 0);
}
}
kaufKonsens.addEventListener('change', function () {
if (kaufKonsens.checked) kaufFehler.style.display = 'none';
});
// Sprachauswahl aufbauen
(function () {
var feld = document.getElementById('sprachWahl');
var aktiv = zielsprache();
Object.keys(SPRACH_NAMEN).forEach(function (c) {
var o = document.createElement('option');
o.value = c; o.textContent = SPRACH_NAMEN[c];
if (c === aktiv) o.selected = true;
feld.appendChild(o);
});
feld.addEventListener('change', function () {
try { localStorage.setItem(SPRACH_SCHLUESSEL, feld.value); } catch (e) {}
});
})();
rendrePakete();
pruefeRueckkehr();
zeigeStand();
})();
</script>
<!-- Cloudflare Web Analytics: cookielose Reichweitenmessung, keine Nutzer-Profile -->
<script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "11f017e9a707466b9151921db6125dde"}'></script>
</body>
</html>