Files
geograsim/App/admin-styleguide.html
T
Adminator 3bc0f418be Bewertungs-Vorschau: EINE Skala-Darstellung + 4-stufige Triage
- Doppeldarstellung (Beispiel-Balken + Legende) zu EINER Tabelle
  zusammengefuehrt: Farbe + Bereich + Label + Beispiel-Balken je Zeile.
  Beispielwert = Bereichsschwelle (90/80/60/50), nicht willkuerlich.
- Triage jetzt 4 Felder an denselben Farbgrenzen:
  <50 Foerdern (Hilfe) / 50-79 Begleiten / 80-89 Laeuft gut /
  >=90 Fordern (herausfordern). Styleguide + Preview angeglichen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-25 02:51:50 +02:00

370 lines
25 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GeoGraSim — Style-Guide (Admin)</title>
<link rel="icon" type="image/png" href="favicon-96x96.png" sizes="96x96">
<link rel="icon" type="image/svg+xml" href="favicon.svg">
<link rel="stylesheet" href="assets/fonts/inter.css">
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:'Inter',sans-serif;background:#f7f6f3;min-height:100vh;color:#2a2a2a}
.topbar{background:#fff;padding:.6rem 1.2rem;display:flex;align-items:center;gap:.8rem;border-bottom:1px solid rgba(0,0,0,.06)}
.topbar h1{font-size:.95rem;font-weight:800;color:#4a7c8a;flex:1;display:flex;align-items:center;gap:.5rem}
.topbar h1 img{height:28px}
.btn-sm{padding:.3rem .6rem;border:1px solid rgba(0,0,0,.08);border-radius:6px;background:#fff;font-size:.68rem;font-weight:600;cursor:pointer;color:#4a4a4a;text-decoration:none}
.btn-sm:hover{background:#dae8ec;color:#4a7c8a}
.wrap{max-width:980px;margin:1rem auto;padding:0 1rem}
.card{background:#fff;border-radius:10px;padding:1.2rem 1.3rem;box-shadow:0 1px 4px rgba(0,0,0,.03);border:1px solid rgba(0,0,0,.04);margin-bottom:1rem}
.card-h{font-size:.65rem;font-weight:700;color:#4a7c8a;text-transform:uppercase;letter-spacing:.06em;margin-bottom:.65rem}
h2{font-size:1.15rem;font-weight:800;color:#1f4b37;margin-bottom:.4rem}
h3{font-size:.95rem;font-weight:700;color:#4a7c8a;margin:.9rem 0 .4rem}
p{font-size:.82rem;line-height:1.55;color:#4a4a4a;margin-bottom:.5rem}
p.lead{font-size:.78rem;color:#6a6a6a}
code{font-family:'JetBrains Mono','Fira Code',monospace;font-size:.78rem;background:#f0ede4;padding:.05rem .35rem;border-radius:4px;color:#1f4b37}
pre{font-family:'JetBrains Mono','Fira Code',monospace;font-size:.74rem;background:#f0ede4;padding:.7rem .9rem;border-radius:7px;color:#1f4b37;line-height:1.5;white-space:pre-wrap;word-break:break-word;margin:.4rem 0}
.copy-block{position:relative}
.copy-btn{position:absolute;top:.45rem;right:.5rem;font-size:.6rem;padding:.2rem .55rem;border:1.5px solid rgba(0,0,0,.1);border-radius:5px;background:#fff;cursor:pointer;font-weight:600;color:#4a7c8a}
.copy-btn:hover{background:#dae8ec}
.copy-btn.ok{background:#dceadd;color:#5a8a5e;border-color:#5a8a5e}
.swatches{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:.7rem;margin:.5rem 0}
.sw{border:1px solid rgba(0,0,0,.06);border-radius:7px;overflow:hidden;cursor:pointer;background:#fff;transition:transform .12s}
.sw:hover{transform:translateY(-1px);border-color:#4a7c8a}
.sw-color{height:60px}
.sw-meta{padding:.45rem .55rem;font-size:.68rem}
.sw-meta strong{display:block;color:#1f4b37}
.sw-meta span{color:#8a8a8a;font-family:'JetBrains Mono',monospace;font-size:.66rem}
.pill{display:inline-block;padding:.18rem .55rem;border-radius:999px;font-size:.65rem;font-weight:600;background:#dae8ec;color:#1f4e5a;margin-right:.3rem}
.pill.warn{background:#fde8d0;color:#a05a2b}
.pill.bad{background:#f2ddd8;color:#a04a3a}
table{width:100%;border-collapse:collapse;font-size:.76rem;margin:.4rem 0}
th{text-align:left;background:#f7f6f3;padding:.4rem .55rem;font-weight:700;color:#4a4a4a;border-bottom:2px solid rgba(0,0,0,.06)}
td{padding:.4rem .55rem;border-bottom:1px solid rgba(0,0,0,.04);vertical-align:top}
ul{margin:.3rem 0 .6rem 1.3rem;font-size:.82rem;line-height:1.55;color:#4a4a4a}
ul li{margin-bottom:.2rem}
.toc{display:flex;flex-wrap:wrap;gap:.4rem;margin-bottom:1rem}
.toc a{padding:.3rem .65rem;background:#fff;border:1.5px solid rgba(0,0,0,.06);border-radius:6px;font-size:.7rem;color:#4a7c8a;text-decoration:none;font-weight:600}
.toc a:hover{background:#dae8ec;border-color:#4a7c8a}
</style>
</head>
<body>
<div class="topbar">
<h1><img src="assets/img/geograsim_t.svg" alt="GeoGraSim"> Style-Guide (Admin)</h1>
<a href="admin-licenses.html" class="btn-sm">🔑 Lizenzen</a>
<a href="admin-modules.html" class="btn-sm">🧩 Module</a>
<a href="admin-levels.html" class="btn-sm">🎮 Level</a>
<a href="admin-accounts.html" class="btn-sm">👤 Admins</a>
<a href="admin.html" class="btn-sm">Logout</a>
</div>
<div class="wrap">
<div class="toc">
<a href="#bildstil">🎨 Bildstil</a>
<a href="#farben-bild">🌿 Bild-Farbpalette</a>
<a href="#farben-ui">🧩 UI-Farbtokens</a>
<a href="#leistung">📊 Leistungs-Skala</a>
<a href="#layout">📐 Layout &amp; Spacing</a>
<a href="#typo">🔤 Typografie</a>
<a href="#bilder">🖼️ Bildformate</a>
<a href="#ipad">📱 iPad-Patterns</a>
<a href="#sprache">🗣️ Sprache</a>
</div>
<div class="card">
<h2>Style-Guide</h2>
<p class="lead">Verbindliche Stil-Referenz für alle GeoGraSim-Module. Klick auf Farbfelder oder „Kopieren" überträgt den Wert in die Zwischenablage. Diese Seite ist die Single-Source-of-Truth — wenn du etwas änderst, musst du es hier auch aktualisieren.</p>
</div>
<!-- ============================================================== -->
<div class="card" id="bildstil">
<div class="card-h">DALL-E / Bildgenerierung</div>
<h3>Offizieller Prompt-Block</h3>
<p>Verbatim verwenden, NICHT umformulieren. Bei jedem Bild diesen Block voranstellen, danach nur den Szenen-Teil ergänzen.</p>
<div class="copy-block">
<button class="copy-btn" data-copy="prompt-base">Kopieren</button>
<pre id="prompt-base">Flat Scandinavian illustration, wide panoramic landscape filling the entire 16:9 frame edge-to-edge, painted style with clean vector shapes, dark forest green (#1f4b37) and sage green (#4a7c4e) tones, yellow-mustard (#e8c547) accents, beige (#e8e4d8) buildings and valleys, white highlights. No text, no watermark, no logos, no borders, no frame.</pre>
</div>
<h3>Eckdaten</h3>
<table>
<tr><th>Feld</th><th>Wert</th></tr>
<tr><td>Modell</td><td><code>dall-e-3</code></td></tr>
<tr><td>Splash-Auflösung</td><td>1792 × 1024 (16:9 panoramisch)</td></tr>
<tr><td>Glossar-Bilder</td><td>1792 × 1024, standard quality</td></tr>
<tr><td>Avatar-Bilder</td><td>1024 × 1024, kreisrund maskiert via CSS</td></tr>
<tr><td>Format</td><td>PNG</td></tr>
<tr><td>API-Key</td><td><code>OPENAI_API_KEY</code> in <code>App/.env.local</code> (nicht im Git)</td></tr>
</table>
<h3>Tabu</h3>
<p>
<span class="pill bad">keine Schrift im Bild</span>
<span class="pill bad">keine Logos</span>
<span class="pill bad">keine Wasserzeichen</span>
<span class="pill bad">keine Rahmen / Borders</span>
</p>
<h3>Single-Source-of-Truth</h3>
<p>Lauffähiger Referenz-Generator: <code>App/sims/logistik/scripts/generate-splash-images.sh</code> (Variable <code>PROMPT_BASE</code>). Bei Pipeline-Fragen dort als Vorlage abschauen.</p>
<h3>Why</h3>
<p>Konsistenz über alle Module. Die Sims stehen auf der Schülerseite nebeneinander; wenn ein Modul aus dem Stil ausbricht, fällt es sofort auf. Gilt nicht nur für Splashes, sondern auch für Spielfeld-Hintergründe, Sprites, Marker-Icons, Bewertungs-Visuals.</p>
</div>
<!-- ============================================================== -->
<div class="card" id="farben-bild">
<div class="card-h">Bild-Farbpalette (verbindlich für DALL-E + Sprites + SVGs)</div>
<p>Klick auf eine Karte kopiert den Hex-Wert.</p>
<div class="swatches">
<div class="sw" data-copy-text="#1f4b37"><div class="sw-color" style="background:#1f4b37"></div><div class="sw-meta"><strong>Forest green</strong><span>#1f4b37</span></div></div>
<div class="sw" data-copy-text="#4a7c4e"><div class="sw-color" style="background:#4a7c4e"></div><div class="sw-meta"><strong>Sage green</strong><span>#4a7c4e</span></div></div>
<div class="sw" data-copy-text="#e8c547"><div class="sw-color" style="background:#e8c547"></div><div class="sw-meta"><strong>Yellow-mustard</strong><span>#e8c547</span></div></div>
<div class="sw" data-copy-text="#e8e4d8"><div class="sw-color" style="background:#e8e4d8"></div><div class="sw-meta"><strong>Beige</strong><span>#e8e4d8</span></div></div>
<div class="sw" data-copy-text="#ffffff"><div class="sw-color" style="background:#ffffff;border:1px solid #ccc"></div><div class="sw-meta"><strong>Weiß-Highlights</strong><span>#ffffff</span></div></div>
</div>
</div>
<!-- ============================================================== -->
<div class="card" id="farben-ui">
<div class="card-h">UI-Farbtokens (CSS-Variablen aus design-system.css)</div>
<p>Diese Tokens nutzen alle Plattform-UIs (Cockpits, Admin, Wrapper, Modale). In Sims als <code>var(--ggs-fjord)</code> referenzieren.</p>
<h3>Akzent (Fjord)</h3>
<div class="swatches">
<div class="sw" data-copy-text="#4a7c8a"><div class="sw-color" style="background:#4a7c8a"></div><div class="sw-meta"><strong>--ggs-fjord</strong><span>#4a7c8a</span></div></div>
<div class="sw" data-copy-text="#1f4e5a"><div class="sw-color" style="background:#1f4e5a"></div><div class="sw-meta"><strong>--ggs-fjord-dark</strong><span>#1f4e5a</span></div></div>
<div class="sw" data-copy-text="#dae8ec"><div class="sw-color" style="background:#dae8ec"></div><div class="sw-meta"><strong>--ggs-fjord-light</strong><span>#dae8ec</span></div></div>
</div>
<h3>Erfolg (Moss)</h3>
<div class="swatches">
<div class="sw" data-copy-text="#5a8a5e"><div class="sw-color" style="background:#5a8a5e"></div><div class="sw-meta"><strong>--ggs-moss</strong><span>#5a8a5e</span></div></div>
<div class="sw" data-copy-text="#3a6b3e"><div class="sw-color" style="background:#3a6b3e"></div><div class="sw-meta"><strong>--ggs-moss-dark</strong><span>#3a6b3e</span></div></div>
<div class="sw" data-copy-text="#dcead0"><div class="sw-color" style="background:#dcead0"></div><div class="sw-meta"><strong>--ggs-moss-light</strong><span>#dcead0</span></div></div>
</div>
<h3>Warnung &amp; Fehler</h3>
<div class="swatches">
<div class="sw" data-copy-text="#e8833a"><div class="sw-color" style="background:#e8833a"></div><div class="sw-meta"><strong>--ggs-orange / warning</strong><span>#e8833a</span></div></div>
<div class="sw" data-copy-text="#c85c4a"><div class="sw-color" style="background:#c85c4a"></div><div class="sw-meta"><strong>--ggs-coral / danger</strong><span>#c85c4a</span></div></div>
<div class="sw" data-copy-text="#f0d0ca"><div class="sw-color" style="background:#f0d0ca"></div><div class="sw-meta"><strong>--ggs-coral-light</strong><span>#f0d0ca</span></div></div>
</div>
<h3>Neutral &amp; Sand</h3>
<div class="swatches">
<div class="sw" data-copy-text="#f5f2eb"><div class="sw-color" style="background:#f5f2eb;border:1px solid #ddd"></div><div class="sw-meta"><strong>--ggs-bg</strong><span>#f5f2eb</span></div></div>
<div class="sw" data-copy-text="#e8e4d8"><div class="sw-color" style="background:#e8e4d8;border:1px solid #ddd"></div><div class="sw-meta"><strong>--ggs-bg-dark</strong><span>#e8e4d8</span></div></div>
<div class="sw" data-copy-text="#e8d5b5"><div class="sw-color" style="background:#e8d5b5"></div><div class="sw-meta"><strong>--ggs-sand</strong><span>#e8d5b5</span></div></div>
<div class="sw" data-copy-text="#c4a97a"><div class="sw-color" style="background:#c4a97a"></div><div class="sw-meta"><strong>--ggs-sand-dark</strong><span>#c4a97a</span></div></div>
<div class="sw" data-copy-text="#e0ddd4"><div class="sw-color" style="background:#e0ddd4"></div><div class="sw-meta"><strong>--ggs-border</strong><span>#e0ddd4</span></div></div>
</div>
<h3>Text</h3>
<div class="swatches">
<div class="sw" data-copy-text="#2a2a2a"><div class="sw-color" style="background:#2a2a2a"></div><div class="sw-meta"><strong>--ggs-text</strong><span>#2a2a2a</span></div></div>
<div class="sw" data-copy-text="#8a8a8a"><div class="sw-color" style="background:#8a8a8a"></div><div class="sw-meta"><strong>--ggs-text-muted</strong><span>#8a8a8a</span></div></div>
<div class="sw" data-copy-text="#b0b0b0"><div class="sw-color" style="background:#b0b0b0"></div><div class="sw-meta"><strong>--ggs-text-light</strong><span>#b0b0b0</span></div></div>
</div>
<h3>Komplette CSS-Variable als Block</h3>
<div class="copy-block">
<button class="copy-btn" data-copy="css-tokens">Kopieren</button>
<pre id="css-tokens">--ggs-fjord: #4a7c8a;
--ggs-fjord-dark: #1f4e5a;
--ggs-fjord-light: #dae8ec;
--ggs-moss: #5a8a5e;
--ggs-moss-dark: #3a6b3e;
--ggs-moss-light: #dcead0;
--ggs-sand: #e8d5b5;
--ggs-sand-dark: #c4a97a;
--ggs-coral: #c85c4a;
--ggs-coral-light: #f0d0ca;
--ggs-orange: #e8833a;
--ggs-bg: #f5f2eb;
--ggs-bg-dark: #e8e4d8;
--ggs-white: #ffffff;
--ggs-text: #2a2a2a;
--ggs-text-muted: #8a8a8a;
--ggs-text-light: #b0b0b0;
--ggs-border: #e0ddd4;
--ggs-success: #5a8a5e;
--ggs-warning: #e8833a;
--ggs-danger: #c85c4a;
--ggs-info: #4a7c8a;</pre>
</div>
</div>
<!-- ============================================================== -->
<div class="card" id="leistung">
<div class="card-h">Leistungs-Skala — 5 Stufen (Standard für ALLE Sims)</div>
<p class="lead">EINE Skala für Schülerleistung überall im Programm: Prozentwert (0100) + dünner Balken in der Ampelfarbe. <strong>Sterne entfallen.</strong> Die Grenzen <strong>50 / 80 / 90</strong> sind zugleich die Triage-Grenzen (ab 90 % „Fordern", ab 80 % „Läuft gut", ab 50 % „Begleiten", darunter „Fördern"), damit Balkenfarbe und Feld immer übereinstimmen. Quelle in Code: <code>pctColor()</code> = <code>_tagTraffic()</code>.</p>
<div style="display:grid;grid-template-columns:26px auto 1fr 90px;gap:.55rem 1rem;align-items:center;max-width:520px;margin:.7rem 0 1.3rem;font-size:.85rem">
<span style="width:22px;height:22px;border-radius:6px;background:#1f7a3d"></span><b>≥ 90 %</b><span style="color:#5a5a5a">sehr gut &nbsp;<code style="font-size:.72rem">#1f7a3d</code></span><div><div style="font-weight:800;color:#1f7a3d;font-size:.82rem">90 %</div><div style="margin-top:2px;height:5px;border-radius:99px;background:rgba(0,0,0,.07);overflow:hidden"><div style="height:100%;width:90%;background:#1f7a3d"></div></div></div>
<span style="width:22px;height:22px;border-radius:6px;background:#7cb342"></span><b>8089 %</b><span style="color:#5a5a5a">gut &nbsp;<code style="font-size:.72rem">#7cb342</code></span><div><div style="font-weight:800;color:#7cb342;font-size:.82rem">80 %</div><div style="margin-top:2px;height:5px;border-radius:99px;background:rgba(0,0,0,.07);overflow:hidden"><div style="height:100%;width:80%;background:#7cb342"></div></div></div>
<span style="width:22px;height:22px;border-radius:6px;background:#f9c33b"></span><b>6079 %</b><span style="color:#5a5a5a">solide &nbsp;<code style="font-size:.72rem">#f9c33b</code></span><div><div style="font-weight:800;color:#f9c33b;font-size:.82rem">60 %</div><div style="margin-top:2px;height:5px;border-radius:99px;background:rgba(0,0,0,.07);overflow:hidden"><div style="height:100%;width:60%;background:#f9c33b"></div></div></div>
<span style="width:22px;height:22px;border-radius:6px;background:#ef8b2c"></span><b>5059 %</b><span style="color:#5a5a5a">wackelig &nbsp;<code style="font-size:.72rem">#ef8b2c</code></span><div><div style="font-weight:800;color:#ef8b2c;font-size:.82rem">50 %</div><div style="margin-top:2px;height:5px;border-radius:99px;background:rgba(0,0,0,.07);overflow:hidden"><div style="height:100%;width:50%;background:#ef8b2c"></div></div></div>
<span style="width:22px;height:22px;border-radius:6px;background:#d8453a"></span><b>&lt; 50 %</b><span style="color:#5a5a5a">kritisch &nbsp;<code style="font-size:.72rem">#d8453a</code></span><div><div style="font-weight:800;color:#d8453a;font-size:.82rem">40 %</div><div style="margin-top:2px;height:5px;border-radius:99px;background:rgba(0,0,0,.07);overflow:hidden"><div style="height:100%;width:40%;background:#d8453a"></div></div></div>
</div>
<h3>Triage-Felder (aus % × Fleiß)</h3>
<p><strong>&lt; 50 % → Fördern</strong> (Hilfe) · <strong>5079 % → Begleiten</strong> · <strong>8089 % → Läuft gut</strong> · <strong>≥ 90 % → Fordern</strong> (mehr herausfordern) — jeweils nur, wenn aktiv gearbeitet wurde, sonst „inaktiv".</p>
<div style="display:flex;gap:.6rem;flex-wrap:wrap;margin:.4rem 0 1rem">
<span style="font-size:.8rem;font-weight:700;color:#b04a3e;background:#f7e2dc;padding:.25rem .7rem;border-radius:12px">Fördern</span>
<span style="font-size:.8rem;font-weight:700;color:#9a6a12;background:#f7edd6;padding:.25rem .7rem;border-radius:12px">Begleiten</span>
<span style="font-size:.8rem;font-weight:700;color:#3a6b3e;background:#dceadd;padding:.25rem .7rem;border-radius:12px">Läuft gut</span>
<span style="font-size:.8rem;font-weight:700;color:#155e2a;background:#c8e6cd;padding:.25rem .7rem;border-radius:12px">Fordern</span>
<span style="font-size:.8rem;font-weight:700;color:#8a8a8a;background:#efeee8;padding:.25rem .7rem;border-radius:12px">inaktiv</span>
</div>
<h3>CSS-Variablen</h3>
<div style="background:#1f2733;border-radius:8px;padding:1rem;overflow:auto"><pre style="margin:0;color:#e8eef4;font-size:.78rem;font-family:'Courier New',monospace">--ggs-perf-5: #1f7a3d; /* ≥ 90 % sehr gut */
--ggs-perf-4: #7cb342; /* 8089 % gut */
--ggs-perf-3: #f9c33b; /* 6079 % solide */
--ggs-perf-2: #ef8b2c; /* 5059 % wackelig */
--ggs-perf-1: #d8453a; /* &lt; 50 % kritisch */
/* Triage */
--ggs-triage-foerdern: #b04a3e;
--ggs-triage-begleiten: #9a6a12;
--ggs-triage-gut: #3a6b3e;
--ggs-triage-inaktiv: #8a8a8a;</pre></div>
<p style="font-size:.78rem;color:#8a8a8a;margin-top:.6rem">Vorschau der Zuordnung je Sim: <a href="admin-lehrer-view.html">Lehrer-View Parameter-Überblick</a>.</p>
</div>
<!-- ============================================================== -->
<div class="card" id="layout">
<div class="card-h">Layout &amp; Spacing</div>
<table>
<tr><th>Token</th><th>Wert</th><th>Verwendung</th></tr>
<tr><td><code>--ggs-gap-xs</code></td><td>4 px</td><td>Inline-Abstände, Pill-Padding</td></tr>
<tr><td><code>--ggs-gap-sm</code></td><td>8 px</td><td>Button-Innenabstand, Form-Felder</td></tr>
<tr><td><code>--ggs-gap-md</code></td><td>16 px</td><td>Card-Innenabstand, Standard-Layout</td></tr>
<tr><td><code>--ggs-gap-lg</code></td><td>24 px</td><td>Sektion-Abstand</td></tr>
<tr><td><code>--ggs-gap-xl</code></td><td>32 px</td><td>Hero-Bereiche</td></tr>
<tr><td><code>--ggs-radius-sm</code></td><td>6 px</td><td>Pills, kleine Buttons</td></tr>
<tr><td><code>--ggs-radius-md</code></td><td>12 px</td><td>Karten, Modale</td></tr>
<tr><td><code>--ggs-radius-lg</code></td><td>16 px</td><td>Hero-Cards, große Modale</td></tr>
<tr><td><code>--ggs-radius-pill</code></td><td>999 px</td><td>Pills, Avatar-Kreise</td></tr>
<tr><td><code>--ggs-shadow-sm</code></td><td><code>0 1px 3px rgba(0,0,0,.08)</code></td><td>Karten</td></tr>
<tr><td><code>--ggs-shadow-md</code></td><td><code>0 2px 8px rgba(0,0,0,.12)</code></td><td>Modale, schwebende Layers</td></tr>
<tr><td><code>--ggs-shadow-lg</code></td><td><code>0 4px 16px rgba(0,0,0,.16)</code></td><td>Tooltips, Spectator-Banner</td></tr>
</table>
</div>
<!-- ============================================================== -->
<div class="card" id="typo">
<div class="card-h">Typografie</div>
<table>
<tr><th>Token</th><th>Wert</th></tr>
<tr><td><code>--ggs-font</code></td><td><code>'Inter', system-ui, -apple-system, sans-serif</code></td></tr>
<tr><td><code>--ggs-font-mono</code></td><td><code>'JetBrains Mono', 'Fira Code', monospace</code></td></tr>
</table>
<h3>Größenrichtlinien</h3>
<ul>
<li><strong>0.62 rem</strong> — Card-Header (uppercase, letter-spacing .05em)</li>
<li><strong>0.7 rem</strong> — Hilfstexte, Subtitles</li>
<li><strong>0.78 rem</strong> — Body-Text in Karten</li>
<li><strong>0.85 rem</strong> — Modul-Namen, Tabs</li>
<li><strong>0.95 rem</strong> — H3 / Section-Titel</li>
<li><strong>1.15 rem</strong> — H2 / Page-Titel</li>
</ul>
</div>
<!-- ============================================================== -->
<div class="card" id="bilder">
<div class="card-h">Bildformate &amp; Pfade</div>
<table>
<tr><th>Typ</th><th>Maße</th><th>Pfad</th></tr>
<tr><td>Modul-Card-Image (Cockpit)</td><td>≈ 800 × 450 (16:9)</td><td><code>App/assets/img/sim-NN-&lt;slug&gt;.png</code></td></tr>
<tr><td>Glossar-Bild</td><td>1792 × 1024</td><td><code>App/assets/img/glossar/&lt;slug&gt;.png</code></td></tr>
<tr><td>Glossar-SVG (Schemata)</td><td>vektor</td><td><code>App/assets/img/glossar/&lt;slug&gt;-schema.svg</code></td></tr>
<tr><td>Splash (Sim-Intro)</td><td>1792 × 1024</td><td><code>App/sims/&lt;slug&gt;/assets/splash-*.png</code></td></tr>
<tr><td>Avatar (User)</td><td>1024 × 1024</td><td><code>App/assets/img/avatars/avatar-&lt;slug&gt;.png</code></td></tr>
<tr><td>Logo (SVG)</td><td>vektor</td><td><code>App/assets/img/geograsim_t.svg</code></td></tr>
</table>
<h3>Avatar-Slugs (30 Stück, 3 Gruppen)</h3>
<ul>
<li><strong>Geo-Welt:</strong> pilotin · pilot · kartografin · geologe · meteorologin · stadtplaner · forscherin · forscher · taucherin · astronaut</li>
<li><strong>Cool &amp; lustig:</strong> coole-girl · coole-boy · lustige-girl · lustige-boy · nerd-girl · sportlich-boy · kuenstlerin · musiker · gaertnerin · abenteurer</li>
<li><strong>Tier-Begleiter:</strong> fuchs-explorer · eule-prof · baer-foerster · pinguin-polar · affe-tropen · delfin-meer · adler-pilot · schildkroete-w · katze-stadt · biene-natur</li>
</ul>
</div>
<!-- ============================================================== -->
<div class="card" id="ipad">
<div class="card-h">iPad-Patterns (Hauptzielgerät: iPad Landscape 1180 × 820)</div>
<ul>
<li><strong>Touch-Ziele</strong> ≥ 36 px Höhe, idealerweise 44 px für primäre Aktionen</li>
<li><strong>Kein Hover-Kleber</strong> — alle Interaktionen müssen ohne Hover funktionieren</li>
<li><strong>Modale nutzen</strong> <code>height: 100dvh</code> + <code>safe-area-inset-bottom</code></li>
<li><strong>Sticky Aktions-Buttons</strong> unten im Modal — nicht außerhalb scrollen lassen</li>
<li><strong>Float-✕ oben rechts</strong> bei Modalen, damit „Schließen" immer erreichbar ist</li>
<li><strong>Layout breit statt hoch</strong> — Badges horizontal, 2-Spalten-Grids wo möglich</li>
<li><strong>viewport-fit=cover</strong> + <code>100dvh</code> für Vollbild-Sims</li>
</ul>
</div>
<!-- ============================================================== -->
<div class="card" id="sprache">
<div class="card-h">Sprache (Lernarbeit-Lexikon)</div>
<p>Niemals „spielen / Spiel / Spieler*in" verwenden. GeoGraSim ist Lernarbeit nach Wygotski, kein Spiel.</p>
<table>
<tr><th>Statt</th><th>Verwende</th></tr>
<tr><td>spielen</td><td>arbeiten mit · bearbeiten</td></tr>
<tr><td>Spiel</td><td>Simulation · Modul</td></tr>
<tr><td>Spieler*in</td><td>Bearbeiter*in · Schüler*in</td></tr>
<tr><td>Spielrunde</td><td>Durchgang</td></tr>
<tr><td>Game Over</td><td>Durchgang beendet</td></tr>
</table>
<p>Ausnahme: in Code-Variablen (<code>state.gameOver</code>, <code>player_progress</code>) ist „game/player" als technischer Begriff unkritisch — Hauptsache an der UI nicht sichtbar.</p>
</div>
</div>
<script>
function copyText(text, el) {
navigator.clipboard.writeText(text).then(function() {
if (el) {
var orig = el.textContent;
el.textContent = '✓ kopiert';
el.classList.add('ok');
setTimeout(function() { el.textContent = orig; el.classList.remove('ok'); }, 1100);
}
});
}
// Copy-Buttons mit data-copy=ID
document.querySelectorAll('.copy-btn[data-copy]').forEach(function(btn) {
btn.addEventListener('click', function() {
var src = document.getElementById(btn.getAttribute('data-copy'));
if (src) copyText(src.textContent, btn);
});
});
// Swatches mit data-copy-text
document.querySelectorAll('.sw[data-copy-text]').forEach(function(sw) {
sw.addEventListener('click', function() {
var txt = sw.getAttribute('data-copy-text');
copyText(txt, null);
var meta = sw.querySelector('.sw-meta strong');
if (meta) {
var orig = meta.textContent;
meta.textContent = '✓ kopiert';
setTimeout(function() { meta.textContent = orig; }, 900);
}
});
});
// Auth-Check: nur eingeloggter Admin darf hier sein
fetch('/api/admin', {
method:'POST', headers:{'Content-Type':'application/json'}, credentials:'same-origin',
body: JSON.stringify({action:'status'})
}).then(function(r) { return r.json(); }).then(function(r) {
if (!r.authenticated) location.href = 'admin.html';
}).catch(function() {});
</script>
<script src="assets/js/version-tag.js" defer></script>
</body>
</html>