init: extract awareness-coach from qognio-bot-widget-template@d2c816f

Source files (src/) and rendered bundle (www/) extracted on 2026-04-29T01:35:15+02:00.
Adds nginx:alpine Dockerfile + docker-compose.yml (Caddy-labels) so the bot
runs stand-alone or as a per-customer template clone.

Parent monorepo commit: d2c816f3edbc9760802a11b29ff4151c7aad4b46
Bot version: 2026-04-21
This commit is contained in:
Qognio Bot Extract 2026-04-29 01:35:15 +02:00
commit 25bb61feaf
16 changed files with 4576 additions and 0 deletions

7
.dockerignore Normal file
View file

@ -0,0 +1,7 @@
.git
.gitignore
README.md
bot.json
src/
docker-compose.yml
*.md

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
.DS_Store
*.log
*.tmp
node_modules/

13
Dockerfile Normal file
View file

@ -0,0 +1,13 @@
# Static-bundle bot — nginx:alpine serves www/ on port 80.
FROM nginx:1.27-alpine
# nginx config: gzip + cache headers + index.html no-store
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Static bundle
COPY www/ /usr/share/nginx/html/
# Run as non-root via nginx's built-in unprivileged image features
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget -q --spider http://127.0.0.1/index.html || exit 1

67
README.md Normal file
View file

@ -0,0 +1,67 @@
# Ava — Awareness & Club-Manager-Coach
Ava — Awareness- und Club-Manager-Coach. Policy, Incident-Response, Haftung, Safer Spaces. Läuft im deutschen Bunker.
```
slug : awareness-coach
version : 2026-04-21
accent : #7c3aed
runtime : nginx:alpine (static bundle)
template : qognio-bot-template-core (former qognio-bot-widget-template)
```
## Layout
```
.
├── src/ source — config.yaml, welcome.html, curricula.json, etc.
├── www/ rendered, directly servable static bundle
├── Dockerfile nginx:alpine + www/ → port 80
├── docker-compose.yml bot-host pattern (Caddy-labels, restart unless-stopped)
├── nginx.conf gzip + cache + SPA fallback
└── bot.json metadata + parent_core_commit
```
## Run locally
```bash
docker compose up --build
# → http://localhost (you'll need to tweak ports for local-only use)
```
## Re-render after upstream core changes
This repo only stores src + rendered output; the rendering engine lives in
`qognio-bot-template-core`. To pull in core changes:
```bash
cd /path/to/qognio-bot-template-core
./scripts/render.sh awareness-coach --bot-repo /path/to/this/repo
git -C /path/to/this/repo commit -am "render: refresh from core@<sha>"
```
## Per-customer copy (template usage)
This repo is a **template**. To clone for a customer:
```bash
git clone <this-repo> my-customer-awareness-coach
cd my-customer-awareness-coach
# tweak src/config.yaml (slug, bot_key_value, accent), src/welcome.html, src/curricula.json
docker compose -f docker-compose.yml up --build
```
## Deploy to qognio bot-host (.42 LXC pattern — legacy)
The bot-manager spawns LXC containers named after the slug. Push www/ via:
```bash
ssh fmh@46.243.203.42
sudo lxc file push /tmp/www/* awareness-coach/var/www/html/
```
(Or run the docker-compose pattern on a Docker host — same network as Caddy.)
---
Generated by `qognio-bot-template-core/scripts/extract-to-repo.sh` on 2026-04-29T01:35:15+02:00.

14
bot.json Normal file
View file

@ -0,0 +1,14 @@
{
"slug": "awareness-coach",
"name": "Ava",
"title": "Awareness &amp; Club-Manager-Coach",
"tagline": "Awareness & Club-Manager-Coach",
"description": "Ava — Awareness- und Club-Manager-Coach. Policy, Incident-Response, Haftung, Safer Spaces. Läuft im deutschen Bunker.",
"version": "2026-04-21",
"accent": "#7c3aed",
"extracted_from": "qognio-bot-widget-template",
"parent_core_commit": "d2c816f3edbc9760802a11b29ff4151c7aad4b46",
"extracted_at": "2026-04-29T01:35:15+02:00",
"runtime": "nginx:alpine",
"default_port": 80
}

20
docker-compose.yml Normal file
View file

@ -0,0 +1,20 @@
# Stand-alone bot container.
# Designed for the "caddy" external network on the bot host (qognio pattern).
# Override the hostname via SLUG env var if you reuse this template per customer.
services:
bot:
build: .
image: qognio/bot-awareness-coach:${TAG:-latest}
container_name: bot-awareness-coach
restart: unless-stopped
networks:
- caddy
labels:
caddy: "awareness-coach.on.qognio.com"
caddy.reverse_proxy: "{{upstreams 80}}"
qognio.bot.slug: "awareness-coach"
qognio.bot.version: "2026-04-21"
networks:
caddy:
external: true

27
nginx.conf Normal file
View file

@ -0,0 +1,27 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# gzip
gzip on;
gzip_vary on;
gzip_types text/css application/javascript application/json image/svg+xml text/plain;
gzip_min_length 512;
# index.html: never cache (so welcome screen / wiring updates land instantly)
location = /index.html {
add_header Cache-Control "no-store, must-revalidate" always;
}
# static assets: cache 1h
location ~* \.(?:css|js|json|svg|png|jpe?g|webp|gif|ico|woff2?)$ {
add_header Cache-Control "public, max-age=3600" always;
try_files $uri =404;
}
location / {
try_files $uri $uri/ /index.html;
}
}

25
src/check-badges.js Normal file
View file

@ -0,0 +1,25 @@
const done = state.completedCurricula || [];
// Policy-Architekt:in — erste Quiz-Frage zu Policy-Struktur richtig
if ((state.completedQuizzes || 0) >= 1) unlockBadge('erste_policy');
// AGG-Schutzmauer — Diskriminierungsschutz-Modul komplett
if (done.includes('agg_diskriminierung')) unlockBadge('agg_shield');
// Incident-Profi — Vorfall-Dokumentation komplett
if (done.includes('dokumentation') || done.includes('save_protokoll')) unlockBadge('incident_keeper');
// Krisenkommunikations-Profi — beide Krise-Module
if (done.includes('statement') && done.includes('medien')) unlockBadge('crisis_comm_pro');
// Harm-Reduction-Advocate — beide Harm-Module
if (done.includes('notfaelle') && done.includes('drogenhilfe')) unlockBadge('harm_reducer');
// Safer-Space-Architekt:in — Fundament + Policy + Team komplett
const foundations = ['awareness_grundlagen', 'parteilichkeit'];
const policy = ['policy_struktur', 'eskalationskette'];
const team = ['team_aufbau', 'konflikte_fuehrung'];
if (foundations.every(m => done.includes(m)) && policy.every(m => done.includes(m)) && team.every(m => done.includes(m))) {
unlockBadge('safer_space_builder');
}
// Awareness-Master — alle 16 Module
if (done.length >= 16) unlockBadge('policy_master');
// Monats-Disziplin — 30-Tage-Streak
if (state.maxStreak >= 30) unlockBadge('streak_30');
// Night Owl (late-night Lerner) — Nightlife-Flavour
const h = new Date().getHours();
if (h >= 22) unlockBadge('night_owl');

32
src/config.yaml Normal file
View file

@ -0,0 +1,32 @@
slug: awareness-coach
bot_name: Ava
bot_title: "Awareness &amp; Club-Manager-Coach"
brand_letter: A
title: "Ava · Awareness & Club-Manager-Coach"
tagline: "Awareness-Coach"
tagline_short: "Awareness & Club-Manager-Coach"
meta_description: "Ava — Awareness- und Club-Manager-Coach. Policy, Incident-Response, Haftung, Safer Spaces. Läuft im deutschen Bunker."
bot_key_var: __AVA_KEY__
bot_key_value: qb_cbfx31vpj6z5
ls_prefix: ava
bot_version: "2026-04-21"
# Color theme (Ava — purple)
accent: "#7c3aed"
accent_2: "#a855f7"
accent_dark: "#5b21b6"
accent_rgb: "124, 58, 237"
success_color: "#a855f7"
msg_strong_color: "#ddd6fe"
# UI Labels
tab_flash_label: Flashcards
tab_curriculum_label: Policy-Bibliothek
curriculum_long_label: Policy-Bibliothek
# Bot personality
quiz_intro_hint: "Wähle ein Modul — Ava generiert realistische Management-Szenario-Fragen."
quiz_verb: erstellt
quiz_noun: "Szenario-Fragen"
flash_intro_hint: "Ava erstellt Karteikarten zu einem Thema. Bewerte dein Erinnerungsvermögen — das System wiederholt schwere Karten öfter (SM-2)."
flash_verb: erstellt

306
src/curricula.json Normal file
View file

@ -0,0 +1,306 @@
{
"version": "2026-04-24",
"updated": "2026-04-24",
"curricula": [
{
"id": "foundations",
"title": "1 · Fundament",
"short": "Awareness, Safer Spaces, Historie",
"icon": "shield",
"color": "#7c3aed",
"description": "Was ist Awareness, was bedeutet Safer Space, wie ist die Szene entstanden? Abgrenzung zu Security.",
"source_md": "awareness-grundlagen.md",
"modules": [
{
"id": "awareness_grundlagen",
"title": "Awareness-Konzept & Historie",
"objectives": [
"Definition Awareness und Abgrenzung zu Security erklären",
"Safer Space vs. Safe Space sauber unterscheiden",
"Clubcommission-Berlin-Historie und Initiative Awareness kennen"
],
"topics": ["Awareness", "Safer Space", "Clubcommission", "Reclaim Club Culture", "Feiern? Safe."],
"difficulty": "einfach",
"source_heading": "Was ist ein Awareness-Konzept?"
},
{
"id": "parteilichkeit",
"title": "Parteilichkeit & Grundhaltung",
"objectives": [
"Parteilichkeit für Betroffene als Leitprinzip benennen",
"Unterschied Parteilichkeit ↔ Vorverurteilung klären",
"Schutz-vor-Umsatz in Grundsatz-Entscheidungen anwenden"
],
"topics": ["Parteilichkeit", "Betroffenen-Schutz", "Deutungshoheit", "Schutz vor Umsatz"],
"difficulty": "mittel",
"source_heading": "Haltungs-Kern: Parteilichkeit"
}
]
},
{
"id": "policy",
"title": "2 · Policy bauen",
"short": "Verhaltenskodex, Eskalation, Konsequenzen",
"icon": "star",
"color": "#8b5cf6",
"description": "Wie du eine Awareness-Policy schreibst, die Team, Gäste und Gerichte trägt.",
"source_md": "awareness-policy-erstellen.md",
"modules": [
{
"id": "policy_struktur",
"title": "Policy-Struktur & Verhaltenskodex",
"objectives": [
"8 Bausteine einer Awareness-Policy benennen",
"Konsequenzen-Stufen klar formulieren",
"Do's & Don'ts für Policy-Formulierung anwenden"
],
"topics": ["Präambel", "Verhaltenskodex", "Konsens-Prinzip", "Konsequenzen-Stufen", "Template"],
"difficulty": "mittel",
"source_heading": "Bausteine einer Policy"
},
{
"id": "eskalationskette",
"title": "Eskalationskette & Beschwerdeweg",
"objectives": [
"Eskalationsstufen Awareness → Schichtleitung → GF → Krise sauber abgrenzen",
"Sofort-Meldeweg + nachträglicher Meldeweg parallel etablieren",
"Dokumentation als vierte Säule implementieren"
],
"topics": ["Eskalation", "Beschwerdeweg", "Anonyme Meldung", "Dokumentation", "Hausverbot"],
"difficulty": "mittel",
"source_heading": "Eskalationskette"
}
]
},
{
"id": "team",
"title": "3 · Team & Führung",
"short": "Recruiting, Briefing, Supervision, Konflikte",
"icon": "handshake",
"color": "#6d28d9",
"description": "Awareness-Team aufbauen, Konflikte auf Manager-Ebene lösen, Burnout verhindern.",
"source_md": "team-recruiting-briefing.md, konfliktmanagement-fuehrung.md",
"modules": [
{
"id": "team_aufbau",
"title": "Team aufbauen, Briefen, Schützen",
"objectives": [
"Rollen (Contact, Front-Door, Floor) und Minimum-Ratio je Größe kennen",
"Auswahl-Kriterien und Red Flags im Recruiting anwenden",
"Supervision & Buddy-System als Burnout-Prävention etablieren"
],
"topics": ["Awareness-Rollen", "Minimum-Ratio", "Briefing", "Supervision", "Buddy-System"],
"difficulty": "mittel",
"source_heading": "Rollen (typisches Team)"
},
{
"id": "konflikte_fuehrung",
"title": "Konfliktmanagement auf Führungsebene",
"objectives": [
"Selbst-Moderation vs. externe Mediation vs. Personalgespräch abgrenzen",
"Personalgespräch gerichtsfest strukturieren",
"Kündigungs-Eskalation (Ermahnung → Abmahnung → Kündigung) korrekt führen"
],
"topics": ["Mediation", "Personalgespräch", "Abmahnung", "§ 626 BGB", "Awareness vs. Security"],
"difficulty": "schwer",
"source_heading": "Teamkonflikte"
}
]
},
{
"id": "incident",
"title": "4 · Vorfall-Management",
"short": "S-A-V-E, Dokumentation, Nachsorge",
"icon": "detective",
"color": "#5b21b6",
"description": "Wenn der Ernstfall da ist: sofortige Schritte, trauma-informierte Kommunikation, Dokumentation.",
"source_md": "incident-response.md",
"modules": [
{
"id": "save_protokoll",
"title": "S-A-V-E: Sichern, Anhören, Verständigen, Einschreiben",
"objectives": [
"S-A-V-E-Protokoll in der ersten Stunde sicher anwenden",
"Trauma-informierte Gesprächsführung mit Betroffenen führen",
"Beschuldigte-Person-Umgang ohne Beweismittel-Verlust"
],
"topics": ["S-A-V-E", "Trauma-informiert", "Anonyme Spurensicherung", "Awareness-Raum"],
"difficulty": "mittel",
"source_heading": "Die Basis-Struktur: S-A-V-E"
},
{
"id": "dokumentation",
"title": "Vorfall-Dokumentation & Nachsorge",
"objectives": [
"Vorfall-Formular rechtssicher ausfüllen (Was/Wann/Wer/Zeug:innen)",
"Follow-Up-Plan Woche 1-4 aufbauen",
"Häufige Fehler im Vorfall-Management vermeiden"
],
"topics": ["Vorfall-Formular", "Follow-Up", "Team-Debrief", "DSGVO-Grenzen"],
"difficulty": "mittel",
"source_heading": "Stunde 1-24: Einschreiben"
}
]
},
{
"id": "recht",
"title": "5 · Recht & Haftung",
"short": "StGB, BGB, ArbSchG, AGG, VStättVO",
"icon": "shield",
"color": "#4c1d95",
"description": "Die Paragraphen, die dich als Manager:in direkt treffen — plus AGG-Diskriminierungsschutz.",
"source_md": "recht-haftung-manager.md, diskriminierungsschutz-agg.md",
"modules": [
{
"id": "manager_haftung",
"title": "Manager-Haftung (StGB, BGB, ArbSchG)",
"objectives": [
"Garantenpflicht § 13 StGB + Unterlassene Hilfeleistung § 323c StGB anwenden",
"ArbSchG-Grundpflichten + Gefährdungsbeurteilung psych. Belastung kennen",
"§ 831 BGB Haftung für Verrichtungsgehilfen + Exkulpations-Doku"
],
"topics": ["§ 13 StGB", "§ 323c StGB", "§ 3 ArbSchG", "§ 618 BGB", "§ 831 BGB", "VStättVO"],
"difficulty": "schwer",
"source_heading": "Die Paragraphen, die du kennen musst"
},
{
"id": "agg_diskriminierung",
"title": "AGG & Diskriminierungsschutz",
"objectives": [
"Sechs geschützte AGG-Merkmale benennen und anwenden",
"Beweislastumkehr § 22 AGG verstehen und durch Doku entlasten",
"Dress-Code legitim vs. diskriminierend formulieren"
],
"topics": ["§ 19 AGG", "§ 22 AGG", "Beweislastumkehr", "Dress-Code", "Einlasskriterien"],
"difficulty": "schwer",
"source_heading": "Die entscheidende Frage: Merkmal vs. Verhalten"
}
]
},
{
"id": "harm",
"title": "6 · Harm Reduction",
"short": "Notfall-Erkennung, Drogenhilfe, Kein-Richter-Protokoll",
"icon": "medal",
"color": "#a855f7",
"description": "Drogen im Club sind Realität. Wie du Risiko minimierst, ohne Polizei zu spielen.",
"source_md": "harm-reduction-basics.md",
"modules": [
{
"id": "notfaelle",
"title": "Notfall-Erkennung: GHB, Opioide, Stimulanzien",
"objectives": [
"Die 5 häufigsten Notfall-Muster (GHB, Opioide, Stimulanzien, Mischkonsum, Panik) erkennen",
"Erste Schritte + 112 klar protokollieren",
"Naloxon / Kühlen / stabile Seitenlage korrekt einsetzen"
],
"topics": ["GHB/GBL", "Opioide", "Naloxon", "MDMA-Hitzschlag", "K.O.-Tropfen", "Mischkonsum"],
"difficulty": "mittel",
"source_heading": "Notfall-Erkennung: die 5 häufigsten Szenarien"
},
{
"id": "drogenhilfe",
"title": "Kooperationen & Kein-Richter-Protokoll",
"objectives": [
"Lokale Drogenhilfe (Mindzone, Eve & Rave, DeGePo) anbinden",
"Kein-Richter-Protokoll mit Security etablieren",
"Eigenkonsum vs. Handel rechtssicher trennen"
],
"topics": ["Mindzone", "Eve & Rave", "Drug Checking", "Kein-Richter-Protokoll", "Eigenkonsum vs. Handel"],
"difficulty": "mittel",
"source_heading": "Zusammenarbeit mit Drogenhilfe"
}
]
},
{
"id": "krise",
"title": "7 · Krisenkommunikation",
"short": "Statement, Team, Medien, Community",
"icon": "star",
"color": "#9333ea",
"description": "Nach dem Vorfall: drei Zielgruppen, drei Texte. Datenschutz, Opfer-Sensibilität, Community-Vertrauen.",
"source_md": "krisenkommunikation.md",
"modules": [
{
"id": "statement",
"title": "Community-Statement & Social Media",
"objectives": [
"Statement-Elemente (Anerkennung, Maßnahmen, Verweise) korrekt platzieren",
"Täter-Opfer-Umkehr in der Formulierung vermeiden",
"Social-Media-Moderation und Kommentar-Strategie anwenden"
],
"topics": ["Statement-Template", "Datenschutz", "Opfer-Sensibel", "Social Media", "Kommentar-Moderation"],
"difficulty": "schwer",
"source_heading": "Community (Social Media, Web, Mail)"
},
{
"id": "medien",
"title": "Medien, Presse, Follow-Up",
"objectives": [
"Medien-Kontakt professionell handhaben (eine Adresse, schriftlich)",
"Off-the-Record & Korrekturrecht kennen",
"Mittel- und langfristige Community-Vertrauensbildung strukturieren"
],
"topics": ["Presse-Strategie", "Off-the-Record", "Korrekturrecht", "Town Hall", "Jahres-Report"],
"difficulty": "schwer",
"source_heading": "Medien"
}
]
},
{
"id": "dilemmata",
"title": "8 · Dilemmata",
"short": "Stammgast, Mitarbeiter:in-Täter, Umsatz vs. Schutz",
"icon": "detective",
"color": "#c084fc",
"description": "Die zehn schwersten Management-Fragen — ethisch, rechtlich, praktisch.",
"source_md": "faq-manager-dilemmata.md",
"modules": [
{
"id": "stammgast_taeter",
"title": "Stammgast mit Vorwurf + Mitarbeiter:in-Täter",
"objectives": [
"Hausverbot vs. Warten auf Urteil sauber begründen",
"Suspendierung/Freistellung/Kündigung bei Mitarbeiter:in-Übergriff führen",
"§ 626 BGB 2-Wochen-Frist bei außerordentlicher Kündigung einhalten"
],
"topics": ["Hausverbot", "Suspendierung", "§ 626 BGB", "Betroffenen-Schutz intern", "Awareness-Null-Toleranz"],
"difficulty": "schwer",
"source_heading": "Stammgast mit Übergriffs-Vorwurf"
},
{
"id": "grundsatz_konflikte",
"title": "Grundsatz-Konflikte & Grauzonen",
"objectives": [
"Umsatz vs. Awareness in Grundsatz-Entscheidungen priorisieren",
"Datenschutz-Grenzen bei Hausverbots-Listen kennen",
"Polizei- und Presse-Anfragen professionell handhaben"
],
"topics": ["Schutz vs. Umsatz", "Hausverbots-Liste DSGVO", "Polizei-Anfrage", "Presse-Anfrage", "Falsche Anzeige"],
"difficulty": "schwer",
"source_heading": "Umsatz vs. Awareness — Grundsatz-Konflikt"
}
]
}
],
"badges": [
{"id": "erste_policy", "title": "Policy-Architekt:in", "icon": "award", "description": "Erste Awareness-Policy-Frage richtig beantwortet."},
{"id": "agg_shield", "title": "AGG-Schutzmauer", "icon": "shield", "description": "Diskriminierungsschutz-Modul abgeschlossen."},
{"id": "incident_keeper", "title": "Incident-Profi", "icon": "clock", "description": "Vorfall-Dokumentations-Modul abgeschlossen."},
{"id": "crisis_comm_pro", "title": "Krisenkommunikations-Profi", "icon": "star", "description": "Krisenkommunikations-Modul abgeschlossen."},
{"id": "harm_reducer", "title": "Harm-Reduction-Advocate", "icon": "medal", "description": "Harm-Reduction-Modul abgeschlossen."},
{"id": "safer_space_builder", "title": "Safer-Space-Architekt:in", "icon": "diamond", "description": "Alle 3 Safer-Space-Module (Fundament + Policy + Team) abgeschlossen."},
{"id": "policy_master", "title": "Awareness-Master", "icon": "crown", "description": "Alle 16 Module abgeschlossen — Awareness auf Geschäftsführungs-Niveau."},
{"id": "streak_30", "title": "Monats-Disziplin", "icon": "flame", "description": "30 Tage in Folge gelernt."},
{"id": "night_owl", "title": "Nachteule", "icon": "moon", "description": "Nach 22 Uhr gelernt — ein echtes Nightlife-Profil."}
],
"levels": [
{"min": 0, "title": "Einsteiger:in"},
{"min": 50, "title": "Schicht-Leiter:in"},
{"min": 200, "title": "Bar-/Club-Manager:in"},
{"min": 500, "title": "Betriebsleiter:in"},
{"min": 1250, "title": "Awareness-Beauftragte:r"},
{"min": 2500, "title": "Geschäftsführung Gastro/Events"},
{"min": 5000, "title": "Branchen-Expert:in"}
]
}

4
src/levels-fallback.js Normal file
View file

@ -0,0 +1,4 @@
{ min: 0, title: 'Einsteiger:in' }, { min: 50, title: 'Schicht-Leiter:in' },
{ min: 200, title: 'Bar-/Club-Manager:in' }, { min: 500, title: 'Betriebsleiter:in' },
{ min: 1250, title: 'Awareness-Beauftragte:r' }, { min: 2500, title: 'Geschäftsführung Gastro/Events' },
{ min: 5000, title: 'Branchen-Expert:in' }

398
src/welcome.html Normal file
View file

@ -0,0 +1,398 @@
<style>
/* Ava — Welcome polish (scoped to .welcome, only this bot) */
#welcome-screen.welcome {
display: block;
text-align: left;
padding: 0 !important;
min-height: auto !important;
max-width: 920px;
margin: 0 auto;
}
#welcome-screen.welcome > h2,
#welcome-screen.welcome > p {
display: none; /* hide default */
}
.ava-hero {
position: relative;
border-radius: 20px;
padding: 2.2rem 2rem 1.9rem;
margin: .25rem 0 1.4rem;
background:
radial-gradient(1200px 240px at 0% 0%, rgba(124,58,237,0.32), transparent 60%),
radial-gradient(900px 200px at 100% 100%, rgba(245,158,11,0.18), transparent 60%),
linear-gradient(160deg, #14101e 0%, #0d0a17 60%, #0a0a0f 100%);
border: 1px solid rgba(255,255,255,0.06);
overflow: hidden;
isolation: isolate;
}
.ava-hero::before {
content: "";
position: absolute; inset: 0;
background-image: radial-gradient(rgba(255,255,255,0.06) 1px, transparent 1px);
background-size: 3px 3px;
opacity: .25;
pointer-events: none;
mask-image: linear-gradient(180deg, rgba(0,0,0,.6), transparent 70%);
-webkit-mask-image: linear-gradient(180deg, rgba(0,0,0,.6), transparent 70%);
}
.ava-hero::after {
content: "";
position: absolute;
top: -40%; right: -20%;
width: 480px; height: 480px;
background: radial-gradient(closest-side, rgba(168,85,247,0.22), transparent 70%);
filter: blur(8px);
pointer-events: none;
z-index: 0;
}
.ava-hero > * { position: relative; z-index: 1; }
.ava-eyebrow {
display: inline-flex;
align-items: center;
gap: .5rem;
font-size: .72rem;
letter-spacing: .12em;
text-transform: uppercase;
color: #cbb8ff;
background: rgba(124,58,237,0.12);
border: 1px solid rgba(124,58,237,0.32);
padding: .28rem .65rem;
border-radius: 999px;
font-weight: 600;
}
.ava-eyebrow .dot {
width: 6px; height: 6px; border-radius: 50%;
background: #a855f7;
box-shadow: 0 0 10px #a855f7;
}
.ava-title {
margin: .85rem 0 .35rem;
font-size: clamp(1.55rem, 3vw, 2.05rem);
letter-spacing: -0.025em;
line-height: 1.15;
font-weight: 800;
background: linear-gradient(120deg, #f5f3ff 0%, #c4b5fd 45%, #fcd34d 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.ava-sub {
color: #c8c5d4;
font-size: 1rem;
line-height: 1.55;
margin: 0 0 1.1rem;
max-width: 60ch;
}
.ava-sub strong { color: #ede9fe; font-weight: 600; }
.ava-trust {
display: flex;
flex-wrap: wrap;
gap: .55rem;
margin-top: .25rem;
}
.ava-trust .badge {
display: inline-flex;
align-items: center;
gap: .45rem;
padding: .35rem .7rem;
background: rgba(255,255,255,0.04);
border: 1px solid rgba(255,255,255,0.1);
border-radius: 999px;
font-size: .76rem;
color: #d4d2de;
}
.ava-trust .badge svg {
width: 14px; height: 14px; flex: none;
color: #a855f7;
}
.ava-trust .badge.amber svg { color: #fbbf24; }
.ava-trust .badge.teal svg { color: #5eead4; }
/* Use-case grid */
.ava-uc {
margin-bottom: 1.5rem;
}
.ava-section-head {
display: flex;
align-items: baseline;
justify-content: space-between;
margin: .25rem .25rem .65rem;
gap: 1rem;
}
.ava-section-head h3 {
font-size: .92rem;
letter-spacing: -.005em;
font-weight: 600;
color: #ede9fe;
margin: 0;
}
.ava-section-head .hint {
font-size: .76rem;
color: var(--text-mute);
}
.uc-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: .65rem;
}
.uc-card {
position: relative;
text-align: left;
background: linear-gradient(165deg, #16131f 0%, #110f19 100%);
border: 1px solid rgba(255,255,255,0.07);
border-radius: 14px;
padding: .95rem 1rem 1rem;
cursor: pointer;
font-family: inherit;
color: inherit;
transition: transform .18s ease, border-color .18s ease, background .18s ease;
overflow: hidden;
}
.uc-card::before {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(135deg, rgba(124,58,237,0.0), rgba(245,158,11,0.0));
opacity: 0;
transition: opacity .2s ease;
pointer-events: none;
}
.uc-card:hover {
transform: translateY(-2px);
border-color: rgba(124,58,237,0.45);
background: linear-gradient(165deg, #1c1729 0%, #16131f 100%);
}
.uc-card:hover::before { opacity: 1; background: linear-gradient(135deg, rgba(124,58,237,0.12), rgba(245,158,11,0.05)); }
.uc-card:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
.uc-icon {
width: 34px; height: 34px;
display: grid; place-items: center;
border-radius: 10px;
background: linear-gradient(140deg, rgba(124,58,237,0.18), rgba(245,158,11,0.10));
border: 1px solid rgba(124,58,237,0.32);
color: #ddd6fe;
margin-bottom: .65rem;
}
.uc-icon svg { width: 18px; height: 18px; }
.uc-card.amber .uc-icon { background: linear-gradient(140deg, rgba(245,158,11,0.22), rgba(124,58,237,0.10)); border-color: rgba(245,158,11,0.32); color: #fde68a; }
.uc-card.teal .uc-icon { background: linear-gradient(140deg, rgba(94,234,212,0.18), rgba(124,58,237,0.10)); border-color: rgba(94,234,212,0.32); color: #99f6e4; }
.uc-card.rose .uc-icon { background: linear-gradient(140deg, rgba(244,114,182,0.16), rgba(124,58,237,0.10)); border-color: rgba(244,114,182,0.30); color: #fbcfe8; }
.uc-card h4 {
margin: 0 0 .25rem;
font-size: .94rem;
letter-spacing: -.01em;
font-weight: 600;
color: #f1f0f5;
}
.uc-card p {
margin: 0;
font-size: .8rem;
line-height: 1.45;
color: var(--text-dim);
}
.uc-card .uc-tag {
display: inline-block;
margin-top: .55rem;
font-size: .68rem;
letter-spacing: .04em;
text-transform: uppercase;
color: #a78bfa;
font-weight: 600;
}
.uc-card.amber .uc-tag { color: #fbbf24; }
.uc-card.teal .uc-tag { color: #5eead4; }
.uc-card.rose .uc-tag { color: #f9a8d4; }
/* Compact mode-row (the old big mode-cards become a thin strip) */
.ava-modes { margin-top: .5rem; }
.mode-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: .5rem;
}
.mode-pill {
display: flex;
align-items: center;
gap: .55rem;
padding: .65rem .8rem;
background: rgba(255,255,255,0.03);
border: 1px solid rgba(255,255,255,0.08);
border-radius: 10px;
cursor: pointer;
font-family: inherit;
color: inherit;
text-align: left;
font-size: .85rem;
transition: background .15s, border-color .15s, transform .15s;
}
.mode-pill:hover {
background: rgba(124,58,237,0.10);
border-color: rgba(124,58,237,0.4);
transform: translateY(-1px);
}
.mode-pill svg { width: 16px; height: 16px; color: #a78bfa; flex: none; }
.mode-pill .label { font-weight: 600; color: #f1f0f5; }
.mode-pill .sub { color: var(--text-mute); font-size: .72rem; display: block; margin-top: 1px; }
.ava-foot {
margin-top: 1.4rem;
padding-top: .9rem;
border-top: 1px dashed rgba(255,255,255,0.08);
font-size: .76rem;
color: var(--text-mute);
line-height: 1.55;
}
.ava-foot strong { color: #ddd6fe; font-weight: 600; }
@media (max-width: 640px) {
.ava-hero { padding: 1.6rem 1.25rem 1.4rem; border-radius: 16px; }
.ava-title { font-size: 1.45rem; }
.ava-sub { font-size: .92rem; }
.uc-grid { grid-template-columns: 1fr; }
.mode-row { grid-template-columns: repeat(2, 1fr); }
}
</style>
<section class="ava-hero" aria-labelledby="ava-hero-title">
<span class="ava-eyebrow"><span class="dot"></span>Sovereign AI · Bunker Schleswig-Holstein</span>
<h2 id="ava-hero-title" class="ava-title">Hi, ich bin Ava — Awareness &amp; Club-Manager-Coach.</h2>
<p class="ava-sub">
Ich helfe dir, deine Location <strong>sicher, inklusiv und rechtsfest</strong> zu führen — von der Awareness-Policy über Incident-Response bis zu Veranstalter-Haftung und Krisen-PR. <strong>Safer Spaces entstehen durch klare Strukturen, nicht durch Zufall.</strong>
</p>
<div class="ava-trust">
<span class="badge">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
Inferenz im deutschen Bunker
</span>
<span class="badge teal">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 12l2 2 4-4"/><circle cx="12" cy="12" r="10"/></svg>
DSGVO &amp; AI-Act-konform
</span>
<span class="badge amber">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
45-Sekunden-Spawn pro Org
</span>
</div>
</section>
<section class="ava-uc" aria-labelledby="ava-uc-head">
<div class="ava-section-head">
<h3 id="ava-uc-head">Konkret unterstütze ich dich bei …</h3>
<span class="hint">Klick → Frage landet im Chat</span>
</div>
<div class="uc-grid">
<button class="uc-card" data-prompt="Wir planen ein Festival in 4 Monaten (ca. 3.000 Gäste, 2 Tage). Welche Awareness-Bausteine brauchen wir minimum, und in welcher Reihenfolge sollten wir sie aufsetzen?">
<div class="uc-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 21V8l9-5 9 5v13"/><path d="M9 21V12h6v9"/></svg>
</div>
<h4>Festival-Saison vorbereiten</h4>
<p>Awareness-Konzept, Team-Recruiting, Briefing-Pakete und Sicherheits-Schnittstellen vor Saisonstart.</p>
<span class="uc-tag">Veranstalter</span>
</button>
<button class="uc-card rose" data-prompt="Heute Nacht hat eine Gästin sexualisierte Belästigung an der Bar gemeldet. Awareness-Team hat erstes Gespräch geführt. Was sind die nächsten 24 Stunden — Doku, Personalentscheidung, Kommunikation?">
<div class="uc-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 9v4"/><path d="M12 17h.01"/><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/></svg>
</div>
<h4>Vorfall passiert — was jetzt?</h4>
<p>Incident-Response Schritt für Schritt: Erstgespräch, Doku, Polizei?, Personal, Kommunikation in den nächsten 24 h.</p>
<span class="uc-tag">Akut</span>
</button>
<button class="uc-card" data-prompt="Ich eröffne in 6 Wochen einen Club. Wie schreibe ich eine AGG-konforme Hausordnung und eine sinnvolle Türkommunikation, ohne mich als Veranstalter angreifbar zu machen?">
<div class="uc-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="9" y1="13" x2="15" y2="13"/><line x1="9" y1="17" x2="15" y2="17"/></svg>
</div>
<h4>Hausordnung &amp; Türpolitik</h4>
<p>AGG-konforme Hausordnung, Türkommunikation, Aushänge — mit konkreten Formulierungen statt Goodwill.</p>
<span class="uc-tag">Eröffnung</span>
</button>
<button class="uc-card amber" data-prompt="Auf Instagram macht seit 3 Stunden ein Vorwurf gegen unsere Location die Runde — angeblich übergriffiges Türpersonal. Wie reagieren wir die nächsten 48 Stunden, was sagen wir öffentlich, was intern?">
<div class="uc-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 11l18-5v12L3 14v-3z"/><path d="M11.6 16.8a3 3 0 1 1-5.8-1.6"/></svg>
</div>
<h4>Krisenkommunikation</h4>
<p>Statement nach Vorfall, Social-Media-Reaktion, Crew-Kommunikation — was sagen, was lassen, in welcher Reihenfolge.</p>
<span class="uc-tag">Öffentlichkeit</span>
</button>
<button class="uc-card" data-prompt="Welche rechtlichen Pflichten habe ich als Veranstalter:in bei sicherheitsrelevanten Vorfällen — was muss ich melden, dokumentieren, versichern? Inklusive Verkehrssicherungspflicht und Anzeigepflichten.">
<div class="uc-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6l9-3 9 3v6c0 5-4 8-9 10-5-2-9-5-9-10V6z"/><path d="M9 12l2 2 4-4"/></svg>
</div>
<h4>Recht &amp; Haftung</h4>
<p>Veranstalter-Pflichten, Anzeige- und Doku-Pflichten, Versicherungs-Logik — mit § und Praxis-Bezug.</p>
<span class="uc-tag">Recht</span>
</button>
<button class="uc-card teal" data-prompt="Wir wollen ein Awareness-Team aufbauen — 6-8 Leute, Schichtbetrieb. Wo fangen wir an: Recruiting-Kanäle, Auswahl, Schulung, Schichtmodell, Vergütung, rechtlicher Status?">
<div class="uc-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
</div>
<h4>Awareness-Team aufbauen</h4>
<p>Recruiting-Kanäle, Auswahl, Schulung, Schichtmodell, Vergütung — von 0 auf einsatzfähig in 8 Wochen.</p>
<span class="uc-tag">Personal</span>
</button>
<button class="uc-card" data-prompt="Zwischen Awareness-Team und Security gibt es ständig Reibung — Security will durchgreifen, Awareness will hören. Wie strukturiere ich Joint-Briefings und kläre Mandate, ohne dass ein Team das andere übergeht?">
<div class="uc-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>
</div>
<h4>Konflikt im Team</h4>
<p>Awareness ↔ Security, Schichtleiter-Streit, Mitarbeiter-Trennung — Eskalations- und Gesprächsstruktur.</p>
<span class="uc-tag">Führung</span>
</button>
<button class="uc-card amber" data-prompt="Wie gehe ich pragmatisch mit Drogenkonsum am Tresen und im Backstage um — ohne Rechtsbruch und ohne die Branchenrealität zu ignorieren? Inklusive Notfall-Kette, Tür-Politik und Awareness-Schnittstelle.">
<div class="uc-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 8v4l3 2"/></svg>
</div>
<h4>Harm Reduction</h4>
<p>Drogenkonsum in der Realität: Notfall-Kette, Türentscheidungen, Awareness-Schnittstelle — ohne § zu verletzen.</p>
<span class="uc-tag">Pragmatik</span>
</button>
</div>
</section>
<section class="ava-modes" aria-labelledby="ava-modes-head">
<div class="ava-section-head">
<h3 id="ava-modes-head">Oder direkt in einen Modus springen:</h3>
<span class="hint">Tabs ⌃1⌃5</span>
</div>
<div class="mode-row">
<button class="mode-pill" data-goto="chat">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
<span><span class="label">Chat</span><span class="sub">Frei fragen</span></span>
</button>
<button class="mode-pill" data-goto="quiz">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/><circle cx="12" cy="12" r="10"/></svg>
<span><span class="label">Quiz</span><span class="sub">Szenarien · 16 Module</span></span>
</button>
<button class="mode-pill" data-goto="flash">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M3 10h18"/></svg>
<span><span class="label">Flashcards</span><span class="sub">Spaced-Repetition</span></span>
</button>
<button class="mode-pill" data-goto="progress">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
<span><span class="label">Fortschritt</span><span class="sub">XP · Streaks · Badges</span></span>
</button>
<button class="mode-pill" data-goto="curriculum">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>
<span><span class="label">Bibliothek</span><span class="sub">8 Curricula · 16 Module</span></span>
</button>
</div>
</section>
<p class="ava-foot">
<strong>Wie ich arbeite:</strong> Chat zum Verstehen → Quiz zum Testen → Flashcards zum Merken → Case-Requests im Chat für Rollenspiele auf Führungsebene. Quellen sind kuratiert (Clubcommission, Awareness-Akademie, AGG, BGB, StGB, OWiG); ich erfinde keine Paragraphen — wenn ich unsicher bin, sag ich's.
</p>

1821
www/app.js Normal file

File diff suppressed because it is too large Load diff

306
www/curricula.json Normal file
View file

@ -0,0 +1,306 @@
{
"version": "2026-04-24",
"updated": "2026-04-24",
"curricula": [
{
"id": "foundations",
"title": "1 · Fundament",
"short": "Awareness, Safer Spaces, Historie",
"icon": "shield",
"color": "#7c3aed",
"description": "Was ist Awareness, was bedeutet Safer Space, wie ist die Szene entstanden? Abgrenzung zu Security.",
"source_md": "awareness-grundlagen.md",
"modules": [
{
"id": "awareness_grundlagen",
"title": "Awareness-Konzept & Historie",
"objectives": [
"Definition Awareness und Abgrenzung zu Security erklären",
"Safer Space vs. Safe Space sauber unterscheiden",
"Clubcommission-Berlin-Historie und Initiative Awareness kennen"
],
"topics": ["Awareness", "Safer Space", "Clubcommission", "Reclaim Club Culture", "Feiern? Safe."],
"difficulty": "einfach",
"source_heading": "Was ist ein Awareness-Konzept?"
},
{
"id": "parteilichkeit",
"title": "Parteilichkeit & Grundhaltung",
"objectives": [
"Parteilichkeit für Betroffene als Leitprinzip benennen",
"Unterschied Parteilichkeit ↔ Vorverurteilung klären",
"Schutz-vor-Umsatz in Grundsatz-Entscheidungen anwenden"
],
"topics": ["Parteilichkeit", "Betroffenen-Schutz", "Deutungshoheit", "Schutz vor Umsatz"],
"difficulty": "mittel",
"source_heading": "Haltungs-Kern: Parteilichkeit"
}
]
},
{
"id": "policy",
"title": "2 · Policy bauen",
"short": "Verhaltenskodex, Eskalation, Konsequenzen",
"icon": "star",
"color": "#8b5cf6",
"description": "Wie du eine Awareness-Policy schreibst, die Team, Gäste und Gerichte trägt.",
"source_md": "awareness-policy-erstellen.md",
"modules": [
{
"id": "policy_struktur",
"title": "Policy-Struktur & Verhaltenskodex",
"objectives": [
"8 Bausteine einer Awareness-Policy benennen",
"Konsequenzen-Stufen klar formulieren",
"Do's & Don'ts für Policy-Formulierung anwenden"
],
"topics": ["Präambel", "Verhaltenskodex", "Konsens-Prinzip", "Konsequenzen-Stufen", "Template"],
"difficulty": "mittel",
"source_heading": "Bausteine einer Policy"
},
{
"id": "eskalationskette",
"title": "Eskalationskette & Beschwerdeweg",
"objectives": [
"Eskalationsstufen Awareness → Schichtleitung → GF → Krise sauber abgrenzen",
"Sofort-Meldeweg + nachträglicher Meldeweg parallel etablieren",
"Dokumentation als vierte Säule implementieren"
],
"topics": ["Eskalation", "Beschwerdeweg", "Anonyme Meldung", "Dokumentation", "Hausverbot"],
"difficulty": "mittel",
"source_heading": "Eskalationskette"
}
]
},
{
"id": "team",
"title": "3 · Team & Führung",
"short": "Recruiting, Briefing, Supervision, Konflikte",
"icon": "handshake",
"color": "#6d28d9",
"description": "Awareness-Team aufbauen, Konflikte auf Manager-Ebene lösen, Burnout verhindern.",
"source_md": "team-recruiting-briefing.md, konfliktmanagement-fuehrung.md",
"modules": [
{
"id": "team_aufbau",
"title": "Team aufbauen, Briefen, Schützen",
"objectives": [
"Rollen (Contact, Front-Door, Floor) und Minimum-Ratio je Größe kennen",
"Auswahl-Kriterien und Red Flags im Recruiting anwenden",
"Supervision & Buddy-System als Burnout-Prävention etablieren"
],
"topics": ["Awareness-Rollen", "Minimum-Ratio", "Briefing", "Supervision", "Buddy-System"],
"difficulty": "mittel",
"source_heading": "Rollen (typisches Team)"
},
{
"id": "konflikte_fuehrung",
"title": "Konfliktmanagement auf Führungsebene",
"objectives": [
"Selbst-Moderation vs. externe Mediation vs. Personalgespräch abgrenzen",
"Personalgespräch gerichtsfest strukturieren",
"Kündigungs-Eskalation (Ermahnung → Abmahnung → Kündigung) korrekt führen"
],
"topics": ["Mediation", "Personalgespräch", "Abmahnung", "§ 626 BGB", "Awareness vs. Security"],
"difficulty": "schwer",
"source_heading": "Teamkonflikte"
}
]
},
{
"id": "incident",
"title": "4 · Vorfall-Management",
"short": "S-A-V-E, Dokumentation, Nachsorge",
"icon": "detective",
"color": "#5b21b6",
"description": "Wenn der Ernstfall da ist: sofortige Schritte, trauma-informierte Kommunikation, Dokumentation.",
"source_md": "incident-response.md",
"modules": [
{
"id": "save_protokoll",
"title": "S-A-V-E: Sichern, Anhören, Verständigen, Einschreiben",
"objectives": [
"S-A-V-E-Protokoll in der ersten Stunde sicher anwenden",
"Trauma-informierte Gesprächsführung mit Betroffenen führen",
"Beschuldigte-Person-Umgang ohne Beweismittel-Verlust"
],
"topics": ["S-A-V-E", "Trauma-informiert", "Anonyme Spurensicherung", "Awareness-Raum"],
"difficulty": "mittel",
"source_heading": "Die Basis-Struktur: S-A-V-E"
},
{
"id": "dokumentation",
"title": "Vorfall-Dokumentation & Nachsorge",
"objectives": [
"Vorfall-Formular rechtssicher ausfüllen (Was/Wann/Wer/Zeug:innen)",
"Follow-Up-Plan Woche 1-4 aufbauen",
"Häufige Fehler im Vorfall-Management vermeiden"
],
"topics": ["Vorfall-Formular", "Follow-Up", "Team-Debrief", "DSGVO-Grenzen"],
"difficulty": "mittel",
"source_heading": "Stunde 1-24: Einschreiben"
}
]
},
{
"id": "recht",
"title": "5 · Recht & Haftung",
"short": "StGB, BGB, ArbSchG, AGG, VStättVO",
"icon": "shield",
"color": "#4c1d95",
"description": "Die Paragraphen, die dich als Manager:in direkt treffen — plus AGG-Diskriminierungsschutz.",
"source_md": "recht-haftung-manager.md, diskriminierungsschutz-agg.md",
"modules": [
{
"id": "manager_haftung",
"title": "Manager-Haftung (StGB, BGB, ArbSchG)",
"objectives": [
"Garantenpflicht § 13 StGB + Unterlassene Hilfeleistung § 323c StGB anwenden",
"ArbSchG-Grundpflichten + Gefährdungsbeurteilung psych. Belastung kennen",
"§ 831 BGB Haftung für Verrichtungsgehilfen + Exkulpations-Doku"
],
"topics": ["§ 13 StGB", "§ 323c StGB", "§ 3 ArbSchG", "§ 618 BGB", "§ 831 BGB", "VStättVO"],
"difficulty": "schwer",
"source_heading": "Die Paragraphen, die du kennen musst"
},
{
"id": "agg_diskriminierung",
"title": "AGG & Diskriminierungsschutz",
"objectives": [
"Sechs geschützte AGG-Merkmale benennen und anwenden",
"Beweislastumkehr § 22 AGG verstehen und durch Doku entlasten",
"Dress-Code legitim vs. diskriminierend formulieren"
],
"topics": ["§ 19 AGG", "§ 22 AGG", "Beweislastumkehr", "Dress-Code", "Einlasskriterien"],
"difficulty": "schwer",
"source_heading": "Die entscheidende Frage: Merkmal vs. Verhalten"
}
]
},
{
"id": "harm",
"title": "6 · Harm Reduction",
"short": "Notfall-Erkennung, Drogenhilfe, Kein-Richter-Protokoll",
"icon": "medal",
"color": "#a855f7",
"description": "Drogen im Club sind Realität. Wie du Risiko minimierst, ohne Polizei zu spielen.",
"source_md": "harm-reduction-basics.md",
"modules": [
{
"id": "notfaelle",
"title": "Notfall-Erkennung: GHB, Opioide, Stimulanzien",
"objectives": [
"Die 5 häufigsten Notfall-Muster (GHB, Opioide, Stimulanzien, Mischkonsum, Panik) erkennen",
"Erste Schritte + 112 klar protokollieren",
"Naloxon / Kühlen / stabile Seitenlage korrekt einsetzen"
],
"topics": ["GHB/GBL", "Opioide", "Naloxon", "MDMA-Hitzschlag", "K.O.-Tropfen", "Mischkonsum"],
"difficulty": "mittel",
"source_heading": "Notfall-Erkennung: die 5 häufigsten Szenarien"
},
{
"id": "drogenhilfe",
"title": "Kooperationen & Kein-Richter-Protokoll",
"objectives": [
"Lokale Drogenhilfe (Mindzone, Eve & Rave, DeGePo) anbinden",
"Kein-Richter-Protokoll mit Security etablieren",
"Eigenkonsum vs. Handel rechtssicher trennen"
],
"topics": ["Mindzone", "Eve & Rave", "Drug Checking", "Kein-Richter-Protokoll", "Eigenkonsum vs. Handel"],
"difficulty": "mittel",
"source_heading": "Zusammenarbeit mit Drogenhilfe"
}
]
},
{
"id": "krise",
"title": "7 · Krisenkommunikation",
"short": "Statement, Team, Medien, Community",
"icon": "star",
"color": "#9333ea",
"description": "Nach dem Vorfall: drei Zielgruppen, drei Texte. Datenschutz, Opfer-Sensibilität, Community-Vertrauen.",
"source_md": "krisenkommunikation.md",
"modules": [
{
"id": "statement",
"title": "Community-Statement & Social Media",
"objectives": [
"Statement-Elemente (Anerkennung, Maßnahmen, Verweise) korrekt platzieren",
"Täter-Opfer-Umkehr in der Formulierung vermeiden",
"Social-Media-Moderation und Kommentar-Strategie anwenden"
],
"topics": ["Statement-Template", "Datenschutz", "Opfer-Sensibel", "Social Media", "Kommentar-Moderation"],
"difficulty": "schwer",
"source_heading": "Community (Social Media, Web, Mail)"
},
{
"id": "medien",
"title": "Medien, Presse, Follow-Up",
"objectives": [
"Medien-Kontakt professionell handhaben (eine Adresse, schriftlich)",
"Off-the-Record & Korrekturrecht kennen",
"Mittel- und langfristige Community-Vertrauensbildung strukturieren"
],
"topics": ["Presse-Strategie", "Off-the-Record", "Korrekturrecht", "Town Hall", "Jahres-Report"],
"difficulty": "schwer",
"source_heading": "Medien"
}
]
},
{
"id": "dilemmata",
"title": "8 · Dilemmata",
"short": "Stammgast, Mitarbeiter:in-Täter, Umsatz vs. Schutz",
"icon": "detective",
"color": "#c084fc",
"description": "Die zehn schwersten Management-Fragen — ethisch, rechtlich, praktisch.",
"source_md": "faq-manager-dilemmata.md",
"modules": [
{
"id": "stammgast_taeter",
"title": "Stammgast mit Vorwurf + Mitarbeiter:in-Täter",
"objectives": [
"Hausverbot vs. Warten auf Urteil sauber begründen",
"Suspendierung/Freistellung/Kündigung bei Mitarbeiter:in-Übergriff führen",
"§ 626 BGB 2-Wochen-Frist bei außerordentlicher Kündigung einhalten"
],
"topics": ["Hausverbot", "Suspendierung", "§ 626 BGB", "Betroffenen-Schutz intern", "Awareness-Null-Toleranz"],
"difficulty": "schwer",
"source_heading": "Stammgast mit Übergriffs-Vorwurf"
},
{
"id": "grundsatz_konflikte",
"title": "Grundsatz-Konflikte & Grauzonen",
"objectives": [
"Umsatz vs. Awareness in Grundsatz-Entscheidungen priorisieren",
"Datenschutz-Grenzen bei Hausverbots-Listen kennen",
"Polizei- und Presse-Anfragen professionell handhaben"
],
"topics": ["Schutz vs. Umsatz", "Hausverbots-Liste DSGVO", "Polizei-Anfrage", "Presse-Anfrage", "Falsche Anzeige"],
"difficulty": "schwer",
"source_heading": "Umsatz vs. Awareness — Grundsatz-Konflikt"
}
]
}
],
"badges": [
{"id": "erste_policy", "title": "Policy-Architekt:in", "icon": "award", "description": "Erste Awareness-Policy-Frage richtig beantwortet."},
{"id": "agg_shield", "title": "AGG-Schutzmauer", "icon": "shield", "description": "Diskriminierungsschutz-Modul abgeschlossen."},
{"id": "incident_keeper", "title": "Incident-Profi", "icon": "clock", "description": "Vorfall-Dokumentations-Modul abgeschlossen."},
{"id": "crisis_comm_pro", "title": "Krisenkommunikations-Profi", "icon": "star", "description": "Krisenkommunikations-Modul abgeschlossen."},
{"id": "harm_reducer", "title": "Harm-Reduction-Advocate", "icon": "medal", "description": "Harm-Reduction-Modul abgeschlossen."},
{"id": "safer_space_builder", "title": "Safer-Space-Architekt:in", "icon": "diamond", "description": "Alle 3 Safer-Space-Module (Fundament + Policy + Team) abgeschlossen."},
{"id": "policy_master", "title": "Awareness-Master", "icon": "crown", "description": "Alle 16 Module abgeschlossen — Awareness auf Geschäftsführungs-Niveau."},
{"id": "streak_30", "title": "Monats-Disziplin", "icon": "flame", "description": "30 Tage in Folge gelernt."},
{"id": "night_owl", "title": "Nachteule", "icon": "moon", "description": "Nach 22 Uhr gelernt — ein echtes Nightlife-Profil."}
],
"levels": [
{"min": 0, "title": "Einsteiger:in"},
{"min": 50, "title": "Schicht-Leiter:in"},
{"min": 200, "title": "Bar-/Club-Manager:in"},
{"min": 500, "title": "Betriebsleiter:in"},
{"min": 1250, "title": "Awareness-Beauftragte:r"},
{"min": 2500, "title": "Geschäftsführung Gastro/Events"},
{"min": 5000, "title": "Branchen-Expert:in"}
]
}

494
www/index.html Normal file
View file

@ -0,0 +1,494 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>Ava · Awareness & Club-Manager-Coach</title>
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<meta name="theme-color" content="#0a0a0f">
<meta name="description" content="Ava — Awareness- und Club-Manager-Coach. Policy, Incident-Response, Haftung, Safer Spaces. Läuft im deutschen Bunker.">
<link rel="stylesheet" href="styles.css">
<script>window.__AVA_KEY__ = 'qb_cbfx31vpj6z5';</script>
</head>
<body>
<div class="app" role="application" aria-label="Ava Awareness-Coach">
<header class="topbar">
<div class="brand">
<span class="brand-icon" aria-hidden="true">A</span>
<span>Ava <small>Awareness & Club-Manager-Coach</small></span>
</div>
<div class="spacer"></div>
<span class="status" role="status" aria-live="polite">Online</span>
</header>
<nav class="tabbar" role="tablist" aria-label="Modi">
<button class="tab" role="tab" aria-selected="true" aria-controls="view-chat" data-mode="chat">
Chat
<span class="tab-kbd">⌃1</span>
</button>
<button class="tab" role="tab" aria-selected="false" aria-controls="view-quiz" data-mode="quiz">
Quiz
<span class="tab-kbd">⌃2</span>
</button>
<button class="tab" role="tab" aria-selected="false" aria-controls="view-flash" data-mode="flash">
Flashcards
<span class="tab-kbd">⌃3</span>
</button>
<button class="tab" role="tab" aria-selected="false" aria-controls="view-progress" data-mode="progress">
Fortschritt
<span class="tab-kbd">⌃4</span>
</button>
<button class="tab" role="tab" aria-selected="false" aria-controls="view-curriculum" data-mode="curriculum">
Policy-Bibliothek
<span class="tab-kbd">⌃5</span>
</button>
</nav>
<main class="main">
<!-- CHAT -->
<section id="view-chat" class="view" role="tabpanel" aria-labelledby="tab-chat" data-active="true">
<div id="welcome-screen" class="welcome hidden" aria-hidden="true">
<style>
/* Ava — Welcome polish (scoped to .welcome, only this bot) */
#welcome-screen.welcome {
display: block;
text-align: left;
padding: 0 !important;
min-height: auto !important;
max-width: 920px;
margin: 0 auto;
}
#welcome-screen.welcome > h2,
#welcome-screen.welcome > p {
display: none; /* hide default */
}
.ava-hero {
position: relative;
border-radius: 20px;
padding: 2.2rem 2rem 1.9rem;
margin: .25rem 0 1.4rem;
background:
radial-gradient(1200px 240px at 0% 0%, rgba(124,58,237,0.32), transparent 60%),
radial-gradient(900px 200px at 100% 100%, rgba(245,158,11,0.18), transparent 60%),
linear-gradient(160deg, #14101e 0%, #0d0a17 60%, #0a0a0f 100%);
border: 1px solid rgba(255,255,255,0.06);
overflow: hidden;
isolation: isolate;
}
.ava-hero::before {
content: "";
position: absolute; inset: 0;
background-image: radial-gradient(rgba(255,255,255,0.06) 1px, transparent 1px);
background-size: 3px 3px;
opacity: .25;
pointer-events: none;
mask-image: linear-gradient(180deg, rgba(0,0,0,.6), transparent 70%);
-webkit-mask-image: linear-gradient(180deg, rgba(0,0,0,.6), transparent 70%);
}
.ava-hero::after {
content: "";
position: absolute;
top: -40%; right: -20%;
width: 480px; height: 480px;
background: radial-gradient(closest-side, rgba(168,85,247,0.22), transparent 70%);
filter: blur(8px);
pointer-events: none;
z-index: 0;
}
.ava-hero > * { position: relative; z-index: 1; }
.ava-eyebrow {
display: inline-flex;
align-items: center;
gap: .5rem;
font-size: .72rem;
letter-spacing: .12em;
text-transform: uppercase;
color: #cbb8ff;
background: rgba(124,58,237,0.12);
border: 1px solid rgba(124,58,237,0.32);
padding: .28rem .65rem;
border-radius: 999px;
font-weight: 600;
}
.ava-eyebrow .dot {
width: 6px; height: 6px; border-radius: 50%;
background: #a855f7;
box-shadow: 0 0 10px #a855f7;
}
.ava-title {
margin: .85rem 0 .35rem;
font-size: clamp(1.55rem, 3vw, 2.05rem);
letter-spacing: -0.025em;
line-height: 1.15;
font-weight: 800;
background: linear-gradient(120deg, #f5f3ff 0%, #c4b5fd 45%, #fcd34d 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.ava-sub {
color: #c8c5d4;
font-size: 1rem;
line-height: 1.55;
margin: 0 0 1.1rem;
max-width: 60ch;
}
.ava-sub strong { color: #ede9fe; font-weight: 600; }
.ava-trust {
display: flex;
flex-wrap: wrap;
gap: .55rem;
margin-top: .25rem;
}
.ava-trust .badge {
display: inline-flex;
align-items: center;
gap: .45rem;
padding: .35rem .7rem;
background: rgba(255,255,255,0.04);
border: 1px solid rgba(255,255,255,0.1);
border-radius: 999px;
font-size: .76rem;
color: #d4d2de;
}
.ava-trust .badge svg {
width: 14px; height: 14px; flex: none;
color: #a855f7;
}
.ava-trust .badge.amber svg { color: #fbbf24; }
.ava-trust .badge.teal svg { color: #5eead4; }
/* Use-case grid */
.ava-uc {
margin-bottom: 1.5rem;
}
.ava-section-head {
display: flex;
align-items: baseline;
justify-content: space-between;
margin: .25rem .25rem .65rem;
gap: 1rem;
}
.ava-section-head h3 {
font-size: .92rem;
letter-spacing: -.005em;
font-weight: 600;
color: #ede9fe;
margin: 0;
}
.ava-section-head .hint {
font-size: .76rem;
color: var(--text-mute);
}
.uc-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: .65rem;
}
.uc-card {
position: relative;
text-align: left;
background: linear-gradient(165deg, #16131f 0%, #110f19 100%);
border: 1px solid rgba(255,255,255,0.07);
border-radius: 14px;
padding: .95rem 1rem 1rem;
cursor: pointer;
font-family: inherit;
color: inherit;
transition: transform .18s ease, border-color .18s ease, background .18s ease;
overflow: hidden;
}
.uc-card::before {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(135deg, rgba(124,58,237,0.0), rgba(245,158,11,0.0));
opacity: 0;
transition: opacity .2s ease;
pointer-events: none;
}
.uc-card:hover {
transform: translateY(-2px);
border-color: rgba(124,58,237,0.45);
background: linear-gradient(165deg, #1c1729 0%, #16131f 100%);
}
.uc-card:hover::before { opacity: 1; background: linear-gradient(135deg, rgba(124,58,237,0.12), rgba(245,158,11,0.05)); }
.uc-card:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
.uc-icon {
width: 34px; height: 34px;
display: grid; place-items: center;
border-radius: 10px;
background: linear-gradient(140deg, rgba(124,58,237,0.18), rgba(245,158,11,0.10));
border: 1px solid rgba(124,58,237,0.32);
color: #ddd6fe;
margin-bottom: .65rem;
}
.uc-icon svg { width: 18px; height: 18px; }
.uc-card.amber .uc-icon { background: linear-gradient(140deg, rgba(245,158,11,0.22), rgba(124,58,237,0.10)); border-color: rgba(245,158,11,0.32); color: #fde68a; }
.uc-card.teal .uc-icon { background: linear-gradient(140deg, rgba(94,234,212,0.18), rgba(124,58,237,0.10)); border-color: rgba(94,234,212,0.32); color: #99f6e4; }
.uc-card.rose .uc-icon { background: linear-gradient(140deg, rgba(244,114,182,0.16), rgba(124,58,237,0.10)); border-color: rgba(244,114,182,0.30); color: #fbcfe8; }
.uc-card h4 {
margin: 0 0 .25rem;
font-size: .94rem;
letter-spacing: -.01em;
font-weight: 600;
color: #f1f0f5;
}
.uc-card p {
margin: 0;
font-size: .8rem;
line-height: 1.45;
color: var(--text-dim);
}
.uc-card .uc-tag {
display: inline-block;
margin-top: .55rem;
font-size: .68rem;
letter-spacing: .04em;
text-transform: uppercase;
color: #a78bfa;
font-weight: 600;
}
.uc-card.amber .uc-tag { color: #fbbf24; }
.uc-card.teal .uc-tag { color: #5eead4; }
.uc-card.rose .uc-tag { color: #f9a8d4; }
/* Compact mode-row (the old big mode-cards become a thin strip) */
.ava-modes { margin-top: .5rem; }
.mode-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: .5rem;
}
.mode-pill {
display: flex;
align-items: center;
gap: .55rem;
padding: .65rem .8rem;
background: rgba(255,255,255,0.03);
border: 1px solid rgba(255,255,255,0.08);
border-radius: 10px;
cursor: pointer;
font-family: inherit;
color: inherit;
text-align: left;
font-size: .85rem;
transition: background .15s, border-color .15s, transform .15s;
}
.mode-pill:hover {
background: rgba(124,58,237,0.10);
border-color: rgba(124,58,237,0.4);
transform: translateY(-1px);
}
.mode-pill svg { width: 16px; height: 16px; color: #a78bfa; flex: none; }
.mode-pill .label { font-weight: 600; color: #f1f0f5; }
.mode-pill .sub { color: var(--text-mute); font-size: .72rem; display: block; margin-top: 1px; }
.ava-foot {
margin-top: 1.4rem;
padding-top: .9rem;
border-top: 1px dashed rgba(255,255,255,0.08);
font-size: .76rem;
color: var(--text-mute);
line-height: 1.55;
}
.ava-foot strong { color: #ddd6fe; font-weight: 600; }
@media (max-width: 640px) {
.ava-hero { padding: 1.6rem 1.25rem 1.4rem; border-radius: 16px; }
.ava-title { font-size: 1.45rem; }
.ava-sub { font-size: .92rem; }
.uc-grid { grid-template-columns: 1fr; }
.mode-row { grid-template-columns: repeat(2, 1fr); }
}
</style>
<section class="ava-hero" aria-labelledby="ava-hero-title">
<span class="ava-eyebrow"><span class="dot"></span>Sovereign AI · Bunker Schleswig-Holstein</span>
<h2 id="ava-hero-title" class="ava-title">Hi, ich bin Ava — Awareness &amp; Club-Manager-Coach.</h2>
<p class="ava-sub">
Ich helfe dir, deine Location <strong>sicher, inklusiv und rechtsfest</strong> zu führen — von der Awareness-Policy über Incident-Response bis zu Veranstalter-Haftung und Krisen-PR. <strong>Safer Spaces entstehen durch klare Strukturen, nicht durch Zufall.</strong>
</p>
<div class="ava-trust">
<span class="badge">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
Inferenz im deutschen Bunker
</span>
<span class="badge teal">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 12l2 2 4-4"/><circle cx="12" cy="12" r="10"/></svg>
DSGVO &amp; AI-Act-konform
</span>
<span class="badge amber">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
45-Sekunden-Spawn pro Org
</span>
</div>
</section>
<section class="ava-uc" aria-labelledby="ava-uc-head">
<div class="ava-section-head">
<h3 id="ava-uc-head">Konkret unterstütze ich dich bei …</h3>
<span class="hint">Klick → Frage landet im Chat</span>
</div>
<div class="uc-grid">
<button class="uc-card" data-prompt="Wir planen ein Festival in 4 Monaten (ca. 3.000 Gäste, 2 Tage). Welche Awareness-Bausteine brauchen wir minimum, und in welcher Reihenfolge sollten wir sie aufsetzen?">
<div class="uc-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 21V8l9-5 9 5v13"/><path d="M9 21V12h6v9"/></svg>
</div>
<h4>Festival-Saison vorbereiten</h4>
<p>Awareness-Konzept, Team-Recruiting, Briefing-Pakete und Sicherheits-Schnittstellen vor Saisonstart.</p>
<span class="uc-tag">Veranstalter</span>
</button>
<button class="uc-card rose" data-prompt="Heute Nacht hat eine Gästin sexualisierte Belästigung an der Bar gemeldet. Awareness-Team hat erstes Gespräch geführt. Was sind die nächsten 24 Stunden — Doku, Personalentscheidung, Kommunikation?">
<div class="uc-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 9v4"/><path d="M12 17h.01"/><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/></svg>
</div>
<h4>Vorfall passiert — was jetzt?</h4>
<p>Incident-Response Schritt für Schritt: Erstgespräch, Doku, Polizei?, Personal, Kommunikation in den nächsten 24 h.</p>
<span class="uc-tag">Akut</span>
</button>
<button class="uc-card" data-prompt="Ich eröffne in 6 Wochen einen Club. Wie schreibe ich eine AGG-konforme Hausordnung und eine sinnvolle Türkommunikation, ohne mich als Veranstalter angreifbar zu machen?">
<div class="uc-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="9" y1="13" x2="15" y2="13"/><line x1="9" y1="17" x2="15" y2="17"/></svg>
</div>
<h4>Hausordnung &amp; Türpolitik</h4>
<p>AGG-konforme Hausordnung, Türkommunikation, Aushänge — mit konkreten Formulierungen statt Goodwill.</p>
<span class="uc-tag">Eröffnung</span>
</button>
<button class="uc-card amber" data-prompt="Auf Instagram macht seit 3 Stunden ein Vorwurf gegen unsere Location die Runde — angeblich übergriffiges Türpersonal. Wie reagieren wir die nächsten 48 Stunden, was sagen wir öffentlich, was intern?">
<div class="uc-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 11l18-5v12L3 14v-3z"/><path d="M11.6 16.8a3 3 0 1 1-5.8-1.6"/></svg>
</div>
<h4>Krisenkommunikation</h4>
<p>Statement nach Vorfall, Social-Media-Reaktion, Crew-Kommunikation — was sagen, was lassen, in welcher Reihenfolge.</p>
<span class="uc-tag">Öffentlichkeit</span>
</button>
<button class="uc-card" data-prompt="Welche rechtlichen Pflichten habe ich als Veranstalter:in bei sicherheitsrelevanten Vorfällen — was muss ich melden, dokumentieren, versichern? Inklusive Verkehrssicherungspflicht und Anzeigepflichten.">
<div class="uc-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6l9-3 9 3v6c0 5-4 8-9 10-5-2-9-5-9-10V6z"/><path d="M9 12l2 2 4-4"/></svg>
</div>
<h4>Recht &amp; Haftung</h4>
<p>Veranstalter-Pflichten, Anzeige- und Doku-Pflichten, Versicherungs-Logik — mit § und Praxis-Bezug.</p>
<span class="uc-tag">Recht</span>
</button>
<button class="uc-card teal" data-prompt="Wir wollen ein Awareness-Team aufbauen — 6-8 Leute, Schichtbetrieb. Wo fangen wir an: Recruiting-Kanäle, Auswahl, Schulung, Schichtmodell, Vergütung, rechtlicher Status?">
<div class="uc-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
</div>
<h4>Awareness-Team aufbauen</h4>
<p>Recruiting-Kanäle, Auswahl, Schulung, Schichtmodell, Vergütung — von 0 auf einsatzfähig in 8 Wochen.</p>
<span class="uc-tag">Personal</span>
</button>
<button class="uc-card" data-prompt="Zwischen Awareness-Team und Security gibt es ständig Reibung — Security will durchgreifen, Awareness will hören. Wie strukturiere ich Joint-Briefings und kläre Mandate, ohne dass ein Team das andere übergeht?">
<div class="uc-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>
</div>
<h4>Konflikt im Team</h4>
<p>Awareness ↔ Security, Schichtleiter-Streit, Mitarbeiter-Trennung — Eskalations- und Gesprächsstruktur.</p>
<span class="uc-tag">Führung</span>
</button>
<button class="uc-card amber" data-prompt="Wie gehe ich pragmatisch mit Drogenkonsum am Tresen und im Backstage um — ohne Rechtsbruch und ohne die Branchenrealität zu ignorieren? Inklusive Notfall-Kette, Tür-Politik und Awareness-Schnittstelle.">
<div class="uc-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 8v4l3 2"/></svg>
</div>
<h4>Harm Reduction</h4>
<p>Drogenkonsum in der Realität: Notfall-Kette, Türentscheidungen, Awareness-Schnittstelle — ohne § zu verletzen.</p>
<span class="uc-tag">Pragmatik</span>
</button>
</div>
</section>
<section class="ava-modes" aria-labelledby="ava-modes-head">
<div class="ava-section-head">
<h3 id="ava-modes-head">Oder direkt in einen Modus springen:</h3>
<span class="hint">Tabs ⌃1⌃5</span>
</div>
<div class="mode-row">
<button class="mode-pill" data-goto="chat">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
<span><span class="label">Chat</span><span class="sub">Frei fragen</span></span>
</button>
<button class="mode-pill" data-goto="quiz">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/><circle cx="12" cy="12" r="10"/></svg>
<span><span class="label">Quiz</span><span class="sub">Szenarien · 16 Module</span></span>
</button>
<button class="mode-pill" data-goto="flash">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M3 10h18"/></svg>
<span><span class="label">Flashcards</span><span class="sub">Spaced-Repetition</span></span>
</button>
<button class="mode-pill" data-goto="progress">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
<span><span class="label">Fortschritt</span><span class="sub">XP · Streaks · Badges</span></span>
</button>
<button class="mode-pill" data-goto="curriculum">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>
<span><span class="label">Bibliothek</span><span class="sub">8 Curricula · 16 Module</span></span>
</button>
</div>
</section>
<p class="ava-foot">
<strong>Wie ich arbeite:</strong> Chat zum Verstehen → Quiz zum Testen → Flashcards zum Merken → Case-Requests im Chat für Rollenspiele auf Führungsebene. Quellen sind kuratiert (Clubcommission, Awareness-Akademie, AGG, BGB, StGB, OWiG); ich erfinde keine Paragraphen — wenn ich unsicher bin, sag ich's.
</p>
</div>
<div id="chat-box" class="chat-box" aria-live="polite" aria-label="Gespräch"></div>
</section>
<!-- QUIZ -->
<section id="view-quiz" class="view" role="tabpanel" aria-labelledby="tab-quiz">
<div id="quiz-host"></div>
</section>
<!-- FLASHCARDS -->
<section id="view-flash" class="view" role="tabpanel" aria-labelledby="tab-flash">
<div id="flash-host"></div>
</section>
<!-- PROGRESS -->
<section id="view-progress" class="view" role="tabpanel" aria-labelledby="tab-progress">
<div id="progress-host"></div>
</section>
<!-- CURRICULUM -->
<section id="view-curriculum" class="view" role="tabpanel" aria-labelledby="tab-curr">
<div id="curr-host"></div>
</section>
</main>
<form id="composer-form" class="composer" aria-label="Nachricht verfassen">
<div id="attach-strip" class="attach-strip" aria-live="polite"></div>
<div class="composer-row">
<button type="button" class="btn-attach" id="composer-attach" aria-label="Datei anhängen" title="Datei anhängen (PDF, Bild, Text — max 5 Dateien, 8 MB)">📎</button>
<input type="file" id="composer-file" multiple accept=".pdf,.txt,.md,.csv,.json,.xml,.yaml,.yml,.log,.png,.jpg,.jpeg,.webp,.gif" hidden>
<textarea id="composer" rows="1" placeholder="Frag Ava — Enter zum Senden, Shift+Enter für Zeilenumbruch" aria-label="Nachricht"></textarea>
<button type="submit" class="btn-primary" id="composer-send">Senden</button>
</div>
</form>
<footer class="footer">
Sovereign AI · Deutscher Bunker · <a href="https://qognio.com">Qognio</a> &nbsp;·&nbsp; DSGVO-konform · Keine externen Fonts · Keine Cookies
</footer>
</div>
<div id="toast-stack" class="toast-stack" aria-live="polite"></div>
<script src="app.js"></script>
</body>
</html>

1038
www/styles.css Normal file

File diff suppressed because it is too large Load diff