Files
geograsim/.dontDeploy/entwurfswerkzeug/live-konzept.html
T
Adminator 1e51ef7def Nachtrag: alle bisher untracked Ordner + hängende Änderungen mit-committen
- Konzept/, didaktik_geografie/, didaktik_simulation/, v2-modules/, v2-platform/
- 12 code-workspace-Files
- STATUS-*.md
- viele M/D/R-Änderungen an bereits getrackten Files
- .gitignore verstärkt: **/.humaninput/, **/secret_keys.txt

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-08 02:27:02 +02:00

1184 lines
74 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">
<title>Live-Cockpit Konzept — GeoGraSim</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
:root {
--bg: #f5f1e6;
--card: #fff;
--ink: #1a1a1a;
--muted: #6a6a6a;
--line: rgba(0,0,0,.08);
--green: #5a8a5e;
--green-d: #3a6a3e;
--green-soft: #dceadd;
--orange: #c9913a;
--orange-soft: #fbe6c2;
--red: #b04a3e;
--red-soft: #f4d8d2;
--gray: #9a9a9a;
--gray-soft: #ece9df;
--blue: #4a7c8a;
--blue-soft: #d8e8ed;
--gold: #e8c547;
}
* { margin:0; padding:0; box-sizing:border-box; }
body { font-family:Inter,system-ui,-apple-system,sans-serif; background:var(--bg); color:var(--ink); line-height:1.5; padding:0 1.5rem 4rem; }
/* === Top-Nav === */
.nav { background:rgba(245,241,230,.95); backdrop-filter:blur(20px); border-bottom:1px solid var(--line); padding:.7rem 0; position:sticky; top:0; z-index:50; margin:0 -1.5rem 0; padding-left:1.5rem; padding-right:1.5rem; }
.nav-wrap { max-width:1200px; margin:0 auto; display:flex; justify-content:space-between; align-items:center; }
.nav-title { font-weight:800; color:var(--green-d); font-size:1.05rem; }
.nav-meta { font-size:.78rem; color:var(--muted); }
.nav-meta b { color:var(--green-d); font-variant-numeric:tabular-nums; }
/* === Container === */
.wrap { max-width:1200px; margin:0 auto; padding:1.5rem 0; }
/* === H1 + Notiz === */
h1 { font-size:1.6rem; font-weight:900; color:var(--green-d); margin-bottom:.3rem; letter-spacing:-.02em; }
.lead { color:var(--muted); font-size:.92rem; max-width:780px; margin-bottom:1.5rem; }
/* === Abschnitt mit Erläuterung === */
.erklär { background:#fff8e1; border-left:4px solid var(--gold); border-radius:0 8px 8px 0; padding:.8rem 1.1rem; margin:1rem 0 1.6rem; font-size:.85rem; color:#5a4a1a; }
.erklär b { color:#3a2f0a; }
/* === Cards === */
.card { background:var(--card); border-radius:12px; padding:1.2rem 1.4rem; margin-bottom:1.2rem; border:1px solid var(--line); box-shadow:0 1px 4px rgba(0,0,0,.03); }
.card-h { font-size:.85rem; font-weight:700; color:var(--ink); margin-bottom:.8rem; text-transform:uppercase; letter-spacing:.04em; }
/* === EBENE 1: Status-Übersicht === */
.status-grid { display:grid; grid-template-columns:repeat(4, 1fr); gap:.7rem; margin-bottom:.9rem; }
.status-tile { padding:.9rem 1rem; border-radius:10px; border:1px solid var(--line); display:flex; align-items:center; gap:.7rem; }
.status-tile .num { font-size:1.7rem; font-weight:800; line-height:1; font-variant-numeric:tabular-nums; }
.status-tile .lab { font-size:.78rem; line-height:1.25; }
.status-tile.aktiv { background:var(--green-soft); border-color:rgba(90,138,94,.3); }
.status-tile.aktiv .num { color:var(--green-d); }
.status-tile.heute { background:var(--orange-soft); border-color:rgba(201,145,58,.3); }
.status-tile.heute .num { color:#8a6516; }
.status-tile.kalt { background:var(--gray-soft); border-color:rgba(0,0,0,.06); }
.status-tile.kalt .num { color:var(--gray); }
.status-tile.hilfe { background:var(--red-soft); border-color:rgba(176,74,62,.3); }
.status-tile.hilfe .num { color:var(--red); }
.status-tile.zero .num { opacity:.5; }
.heute-prog { display:flex; align-items:center; gap:.8rem; padding:.6rem 0 0; border-top:1px solid var(--line); }
.heute-prog .lab { font-size:.78rem; color:var(--muted); white-space:nowrap; }
.heute-prog .bar { flex:1; height:10px; background:#f0ede5; border-radius:4px; overflow:hidden; position:relative; }
.heute-prog .bar > div { position:absolute; left:0; top:0; height:100%; background:var(--green); }
.heute-prog .sum { font-size:.78rem; color:#3a3a3a; font-variant-numeric:tabular-nums; white-space:nowrap; }
.heute-prog .sum b { color:var(--green-d); }
/* === Filter-Bar === */
.filter-bar { display:flex; flex-wrap:wrap; gap:.4rem; align-items:center; }
.pill { display:inline-flex; align-items:center; gap:.3rem; padding:.32rem .7rem; border-radius:999px; font-size:.74rem; font-weight:600; border:1px solid rgba(0,0,0,.12); background:#fff; cursor:pointer; transition:all .15s; }
.pill:hover { background:#f5f0e0; }
.pill.active { background:var(--green-d); color:#fff; border-color:var(--green-d); }
.pill .dot { display:inline-block; width:8px; height:8px; border-radius:50%; }
.pill .dot.g { background:var(--green); }
.pill .dot.o { background:var(--orange); }
.pill .dot.k { background:var(--gray); }
.pill .dot.r { background:var(--red); }
.pill .badge { background:rgba(255,255,255,.3); padding:0 .5em; border-radius:99px; font-weight:800; }
.pill.active .badge { background:rgba(255,255,255,.25); }
.sep { width:1px; height:1.4rem; background:rgba(0,0,0,.12); margin:0 .35rem; }
.filter-lab { font-size:.7rem; color:var(--muted); }
.filter-select { font-size:.74rem; padding:.32rem .55rem; border:1px solid rgba(0,0,0,.15); border-radius:6px; background:#fff; }
/* === EBENE 2: Schüler-Liste === */
.student-list { display:flex; flex-direction:column; gap:.5rem; }
.stu-row { background:#fff; border:1px solid var(--line); border-left:4px solid transparent; border-radius:10px; padding:.7rem .9rem; display:grid; grid-template-columns:auto 1fr auto; gap:.8rem; align-items:start; transition:box-shadow .15s; }
.stu-row:hover { box-shadow:0 2px 8px rgba(0,0,0,.06); }
.stu-row.aktiv { border-left-color:var(--green); background:#fbfdf9; }
.stu-row.heute { border-left-color:var(--orange); background:#fdfaf2; }
.stu-row.kalt { border-left-color:var(--gray); background:#fafaf8; }
.stu-row.hilfe { border-left-color:var(--red); background:#fdf5f3; }
.stu-avatar-block { display:flex; align-items:center; gap:.55rem; }
.stu-status-icon { font-size:1.1rem; line-height:1; }
.stu-avatar { width:40px; height:40px; border-radius:50%; background:linear-gradient(135deg,#dceadd,#a8c3aa); display:flex; align-items:center; justify-content:center; font-size:1.4rem; }
.stu-meta { min-width:0; }
.stu-name { font-weight:700; font-size:.92rem; color:var(--ink); margin-bottom:.1rem; display:flex; align-items:center; gap:.4rem; }
.stu-name .pulse { display:inline-block; width:8px; height:8px; background:var(--green); border-radius:50%; animation:pulse 1.5s infinite; }
@keyframes pulse { 0%,100%{opacity:1; transform:scale(1)} 50%{opacity:.5; transform:scale(.8)} }
.stu-sub { font-size:.76rem; color:var(--muted); display:flex; flex-wrap:wrap; gap:.5rem .9rem; align-items:center; }
.stu-sub .module-chip { display:inline-flex; align-items:center; gap:.25rem; padding:.06rem .4rem; background:#f0ede5; border-radius:999px; font-size:.72rem; font-weight:600; color:#3a3a3a; }
.stu-sub .phase { font-style:italic; color:#3a3a3a; }
.stu-sub .heartbeat { color:var(--green-d); font-size:.7rem; font-weight:600; }
.stu-sub .heartbeat.warn { color:var(--orange); }
.stu-sub .heartbeat.stale { color:var(--gray); }
.stu-mini-stats { margin-top:.5rem; display:grid; grid-template-columns:repeat(4, minmax(80px, 1fr)); gap:.4rem; font-size:.7rem; }
.stu-mini-stats .ms { background:#f5f3eb; border-radius:6px; padding:.32rem .5rem; }
.stu-mini-stats .ms .l { color:var(--muted); font-size:.66rem; }
.stu-mini-stats .ms .v { font-weight:700; color:#3a3a3a; font-variant-numeric:tabular-nums; }
.stu-mini-stats .ms.good .v { color:var(--green-d); }
.stu-mini-stats .ms.warn .v { color:#8a6516; }
.stu-mini-stats .ms.bad .v { color:var(--red); }
.stu-actions { display:flex; flex-direction:column; gap:.3rem; align-items:flex-end; min-width:140px; }
.stu-btn { font-size:.72rem; padding:.32rem .65rem; border-radius:6px; border:none; cursor:pointer; font-weight:600; white-space:nowrap; }
.stu-btn.primary { background:var(--green-d); color:#fff; }
.stu-btn.outline { background:#fff; border:1px solid rgba(0,0,0,.12); color:#3a3a3a; }
.stu-btn.alert { background:var(--red); color:#fff; }
.stu-stars { font-size:.78rem; color:var(--gold); letter-spacing:1px; }
/* === Stille / Kalt-Liste kompakt === */
.stu-row.kalt { padding:.45rem .9rem; }
.stu-row.kalt .stu-mini-stats { display:none; }
/* === Hint-Box === */
.next { background:var(--blue-soft); border:1px solid rgba(74,124,138,.3); border-radius:10px; padding:1rem 1.3rem; margin-top:1.5rem; font-size:.86rem; line-height:1.55; }
.next b { color:var(--blue); }
.next ul { margin:.4rem 0 0 1.4rem; }
/* === Detail-Sketch === */
.detail-sketch { background:#1a2620; color:#d8d5cd; border-radius:14px; padding:1.4rem 1.6rem; font-family:'JetBrains Mono', Consolas, monospace; font-size:.78rem; line-height:1.55; overflow-x:auto; }
.detail-sketch .h { color:#a8c3aa; font-weight:700; }
.detail-sketch .k { color:#e8c547; }
.detail-sketch .v { color:#c9e1d0; }
.detail-sketch .ok { color:#8acf95; }
.detail-sketch .warn { color:#e8a247; }
/* === Mini-Stat mit Range-Balken === */
.stu-mini-stats .ms { display:flex; flex-direction:column; gap:.18rem; }
.ms-row { display:flex; justify-content:space-between; align-items:baseline; gap:.4rem; }
.ms-range { display:flex; align-items:center; gap:.3rem; font-size:.6rem; color:var(--muted); }
.ms-range .rmin, .ms-range .rmax { font-variant-numeric:tabular-nums; min-width:1.6em; }
.ms-range .rbar { flex:1; height:5px; background:#e8e2d2; border-radius:2px; position:relative; overflow:hidden; }
.ms-range .rfill { position:absolute; top:0; bottom:0; left:0; border-radius:2px; }
.ms-range .rfill.good { background:var(--green); }
.ms-range .rfill.warn { background:var(--orange); }
.ms-range .rfill.bad { background:var(--red); }
.ms-range .rfill.neut { background:var(--blue); }
/* Marker an der Stelle des Wertes — schmaler Strich oben drüber */
.ms-range .rmarker { position:absolute; top:-2px; bottom:-2px; width:2px; background:#1a1a1a; opacity:.85; }
/* === Top 3 / Schwächste 3 === */
.ranking-grid { display:grid; grid-template-columns:1fr 1fr; gap:1rem; margin-top:1rem; padding-top:.8rem; border-top:1px solid var(--line); }
.ranking-block h3 { font-size:.78rem; font-weight:700; text-transform:uppercase; letter-spacing:.04em; margin-bottom:.55rem; display:flex; align-items:center; gap:.4rem; }
.ranking-block.top h3 { color:var(--green-d); }
.ranking-block.bottom h3 { color:#8a6516; }
.ranking-list { display:flex; flex-direction:column; gap:.32rem; }
.rank-row { background:#fff; border:1px solid var(--line); border-radius:8px; padding:.4rem .6rem; display:grid; grid-template-columns:auto auto 1fr auto; gap:.55rem; align-items:center; }
.rank-row .rk { font-weight:800; color:var(--muted); font-size:.78rem; min-width:1.4em; text-align:center; }
.rank-row.top .rk { color:var(--green-d); }
.rank-row.bottom .rk { color:#8a6516; }
.rank-row .av { width:26px; height:26px; border-radius:50%; background:linear-gradient(135deg,#dceadd,#a8c3aa); display:flex; align-items:center; justify-content:center; font-size:.95rem; }
.rank-row .nm { font-size:.8rem; font-weight:600; color:#3a3a3a; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.rank-row .pc { font-size:.85rem; font-weight:800; font-variant-numeric:tabular-nums; }
.rank-row.top .pc { color:var(--green-d); }
.rank-row.bottom .pc { color:#8a6516; }
.rank-row .pcbar { position:relative; height:5px; background:#f0ede5; border-radius:3px; overflow:hidden; grid-column:2/-1; margin-top:.1rem; }
.rank-row .pcbar > div { position:absolute; left:0; top:0; height:100%; }
.rank-row.top .pcbar > div { background:var(--green); }
.rank-row.bottom .pcbar > div { background:var(--orange); }
/* === Klassen-Fleiß über Zeit (Säulen-Diagramm) === */
.klassen-fleiss-zeit { margin-top:1rem; padding-top:.9rem; border-top:1px solid var(--line); }
.kfz-head { display:flex; justify-content:space-between; align-items:baseline; gap:.6rem; margin-bottom:.5rem; }
.kfz-head h3 { font-size:.78rem; font-weight:700; text-transform:uppercase; letter-spacing:.04em; color:var(--ink); }
.kfz-head .meta { font-size:.7rem; color:var(--muted); }
.kfz-head .meta b { color:#3a3a3a; }
.kfz-grid { display:grid; grid-template-columns:repeat(7,1fr); gap:.45rem; align-items:end; padding:.4rem 0 .2rem; }
.kfz-col { display:flex; flex-direction:column; align-items:center; gap:.3rem; }
.kfz-col .col-wrap { height:90px; width:32px; display:flex; align-items:flex-end; }
.kfz-col .col-stack { width:100%; display:flex; flex-direction:column-reverse; border-radius:3px 3px 0 0; overflow:hidden; box-shadow:0 0 0 1px rgba(0,0,0,.05); }
.kfz-col .col-stack > span { display:block; min-height:1px; }
.kfz-col .col-empty { width:60%; border-top:1px dashed rgba(0,0,0,.12); }
.kfz-col .col-lab { font-size:.7rem; color:var(--muted); font-weight:600; }
.kfz-col .col-val { font-size:.65rem; color:#3a3a3a; font-variant-numeric:tabular-nums; }
.kfz-col.today .col-lab { color:var(--green-d); }
/* === Globaler Zeitraum-Filter für Fleiß-Anzeigen === */
.kfz-filter { display:flex; align-items:center; gap:.4rem; flex-wrap:wrap; padding:.55rem .7rem; background:#f5f3eb; border:1px solid var(--line); border-radius:8px; margin-bottom:.9rem; }
.kfz-filter-lab { font-size:.7rem; color:var(--muted); font-weight:600; text-transform:uppercase; letter-spacing:.04em; }
.kfz-filter-saved { margin-left:auto; font-size:.66rem; color:var(--muted); font-weight:600; cursor:help; }
.kfz-filter-hint { font-size:.66rem; color:var(--blue); font-weight:600; cursor:help; padding-left:.5rem; border-left:1px solid rgba(0,0,0,.10); }
/* === Zeitraum-Varianten (Tag / Monat / Schuljahr) === */
.zeitraum-variant { padding:.7rem 0 0; }
.zv-head { font-size:.78rem; font-weight:600; color:#3a3a3a; margin-bottom:.55rem; }
.zv-tag { display:inline-block; background:var(--green-d); color:#fff; font-size:.66rem; font-weight:700; padding:.13rem .55rem; border-radius:4px; margin-right:.4rem; text-transform:uppercase; letter-spacing:.04em; }
.zv-foot { margin-top:.55rem; font-size:.72rem; color:var(--muted); padding:.45rem .65rem; background:rgba(0,0,0,.02); border-radius:6px; }
.zv-foot b { color:#3a3a3a; }
/* Tag-Grid: 25 Stunden */
.zv-day-grid { display:grid; grid-template-columns:repeat(25, 1fr); gap:.2rem; align-items:end; padding:.4rem .15rem .2rem; background:#fbfaf3; border-radius:6px; }
.zv-day-col { display:flex; flex-direction:column; align-items:center; gap:.18rem; padding:.25rem 0; border-radius:3px; }
.zv-day-col.school { background:rgba(232,197,71,.18); }
.zv-day-col.today { box-shadow:0 0 0 2px var(--green-d); border-radius:4px; }
.zv-col-wrap { height:60px; width:100%; display:flex; align-items:flex-end; justify-content:center; }
.zv-col-stack { width:75%; display:flex; flex-direction:column-reverse; border-radius:2px 2px 0 0; overflow:hidden; box-shadow:0 0 0 1px rgba(0,0,0,.04); }
.zv-col-stack > span { display:block; min-height:1px; }
.zv-col-empty { width:50%; border-top:1px dashed rgba(0,0,0,.10); }
.zv-h { font-size:.6rem; color:var(--muted); font-weight:600; font-variant-numeric:tabular-nums; }
/* Monat-Grid: 30/31 Tage */
.zv-month-grid { display:grid; grid-template-columns:repeat(30, 1fr); gap:.2rem; align-items:end; padding:.4rem .15rem .2rem; background:#fbfaf3; border-radius:6px; }
.zv-month-grid .zv-day-col { padding:.18rem 0; }
.zv-month-grid .zv-col-wrap { height:55px; }
/* Schuljahr-Grid: bis zu 12 Monate */
.zv-year-grid { display:grid; grid-template-columns:repeat(10, 1fr); gap:.4rem; align-items:end; padding:.5rem .2rem .25rem; background:#fbfaf3; border-radius:6px; }
.zv-year-col { display:flex; flex-direction:column; align-items:center; gap:.18rem; padding:.3rem 0; border-radius:4px; }
.zv-year-col.today { box-shadow:0 0 0 2px var(--green-d); }
.zv-year-col .zv-col-wrap { width:34px; }
.zv-year-col .zv-col-stack { width:100%; }
.zv-y { font-size:.7rem; color:#3a3a3a; font-weight:600; }
.zv-y-sum { font-size:.62rem; color:var(--muted); font-variant-numeric:tabular-nums; }
/* === Polish-Sektion (Tooltips / Persistenz / Schuljahr-Land) === */
.polish-grid { display:grid; grid-template-columns:repeat(3, 1fr); gap:1rem; }
.polish-block { background:#fbfaf3; border:1px solid var(--line); border-radius:10px; padding:.95rem 1.1rem; }
.polish-block h3 { font-size:.86rem; color:var(--green-d); margin-bottom:.5rem; font-weight:700; }
.polish-block p { font-size:.82rem; color:#3a3a3a; margin-bottom:.6rem; line-height:1.5; }
.polish-block code { font-family:'JetBrains Mono',Consolas,monospace; font-size:.74rem; background:rgba(0,0,0,.05); padding:.05rem .3rem; border-radius:3px; color:#3a3a3a; }
.polish-spec { background:#fff; border:1px solid var(--line); border-radius:8px; padding:.55rem .7rem; font-size:.74rem; }
.ps-row { display:grid; grid-template-columns:60px 1fr; gap:.5rem; padding:.2rem 0; border-bottom:1px solid rgba(0,0,0,.04); }
.ps-row:last-child { border-bottom:none; }
.ps-k { font-weight:700; color:var(--green-d); }
.ps-v { color:#3a3a3a; line-height:1.4; }
.polish-code { background:#1a2620; color:#d8d5cd; border-radius:8px; padding:.7rem .9rem; font-family:'JetBrains Mono',Consolas,monospace; font-size:.72rem; line-height:1.55; white-space:pre; }
.polish-code .pc-k { color:#a8c3aa; font-weight:700; }
.polish-code .pc-v { color:#e8c547; }
.schuljahr-table { width:100%; border-collapse:collapse; font-size:.74rem; background:#fff; border-radius:6px; overflow:hidden; }
.schuljahr-table th { background:var(--green-d); color:#fff; padding:.35rem .55rem; text-align:left; font-weight:700; font-size:.68rem; text-transform:uppercase; letter-spacing:.03em; }
.schuljahr-table td { padding:.32rem .55rem; border-bottom:1px solid rgba(0,0,0,.05); color:#3a3a3a; }
.schuljahr-table tr:last-child td { border-bottom:none; }
.schuljahr-table tr:nth-child(even) td { background:rgba(0,0,0,.02); }
/* === Benchmark-Erklärbox === */
.benchmark { background:var(--blue-soft); border:1px solid rgba(74,124,138,.3); border-radius:10px; padding:.95rem 1.2rem; margin:1.2rem 0; font-size:.84rem; }
.benchmark h3 { color:var(--blue); font-size:.85rem; font-weight:700; margin-bottom:.4rem; }
.benchmark table { width:100%; border-collapse:collapse; margin:.4rem 0; font-size:.78rem; }
.benchmark th { background:rgba(74,124,138,.18); padding:.3rem .55rem; text-align:left; font-weight:700; color:var(--blue); font-size:.7rem; }
.benchmark td { padding:.3rem .55rem; border-bottom:1px solid rgba(0,0,0,.05); vertical-align:top; }
.benchmark td code { font-family:'JetBrains Mono',Consolas,monospace; font-size:.7rem; background:rgba(0,0,0,.04); padding:.05rem .3rem; border-radius:3px; }
@media (max-width:880px) {
.status-grid { grid-template-columns:repeat(2,1fr); }
.stu-row { grid-template-columns:auto 1fr; }
.stu-actions { grid-column:1/-1; flex-direction:row; align-items:center; justify-content:flex-end; flex-wrap:wrap; }
.stu-mini-stats { grid-template-columns:repeat(2,1fr); }
.ranking-grid { grid-template-columns:1fr; }
.kfz-col .col-wrap { width:24px; }
.zv-day-grid { grid-template-columns:repeat(13,1fr); }
.zv-day-grid .zv-day-col:nth-child(n+14) { display:none; }
.zv-month-grid { grid-template-columns:repeat(15,1fr); }
.zv-year-grid { grid-template-columns:repeat(5,1fr); }
.polish-grid { grid-template-columns:1fr; }
}
</style>
</head>
<body>
<div class="nav">
<div class="nav-wrap">
<span class="nav-title">📊 Live-Cockpit Konzept</span>
<span class="nav-meta">Entwurf · GeoGraSim Lehrer-Cockpit · Stand 2026-06-10</span>
</div>
</div>
<div class="wrap">
<h1>Live-Cockpit · Konzept-Entwurf <span style="font-size:.55em;font-weight:500;color:var(--muted);vertical-align:.4em">v2 — Thomas-Review eingearbeitet</span></h1>
<p class="lead">
Ziel: die Lehrperson sieht <b>auf einen Blick</b>, was in der Klasse gerade los ist —
wer aktiv ist, wer hinterher ist, wer heute noch nichts gemacht hat,
<b>wer die Top 3 und wer die Schwächsten 3 sind</b>
und kann pro Schüler:in bei Bedarf bis ins Detail einsteigen.
Vier Ebenen: <b>Status & Ranking</b> ganz oben, dann <b>Filter</b> auf die ganze Klassenliste,
dann <b>pro Schüler:in eine Zeile</b> mit Live-Stats (jeder Wert mit Range-Balken),
und auf Klick der <b>Detail-Drill-Down</b>.
</p>
<div class="erklär">
<b>Änderungen vs. v1 (Thomas-Review 2026-06-10):</b>
<ul style="margin:.4rem 0 0 1.4rem">
<li><b>Klassen-Fleiß-Balken „heute" raus</b> — wenig Aussagekraft. Stattdessen:</li>
<li><b>Top 3 + Schwächste 3</b> als Schüler:innen-Ranking nach <b>Benchmark-Prozent</b> über alle Apps</li>
<li><b>Klassen-Fleiß als Säulen über Zeit</b> (MoSo bzw. nach Filter) statt nur als Tages-Summe</li>
<li><b>In den Mini-Stats pro Schüler:in zusätzlich Range-Balken</b>, damit man weiß: ist 425 ppm CO₂ gut oder schlecht?</li>
</ul>
</div>
<!-- ============== EBENE 1: STATUS + RANKING + KLASSEN-FLEISS ============== -->
<div class="card">
<div class="card-h">Ebene 1 · Klassen-Status auf einen Blick</div>
<!-- A) Status-Tiles: alle 4 Zahlen beziehen sich auf SCHÜLER:INNEN -->
<div class="status-grid">
<div class="status-tile aktiv">
<span class="num">4</span>
<span class="lab"><b>jetzt aktiv</b><br><span style="color:var(--muted);font-size:.7rem">Schüler:innen mit Heartbeat in den letzten 30 s</span></span>
</div>
<div class="status-tile heute">
<span class="num">9</span>
<span class="lab"><b>heute aktiv</b><br><span style="color:var(--muted);font-size:.7rem">heute schon gearbeitet, gerade pausiert</span></span>
</div>
<div class="status-tile kalt">
<span class="num">12</span>
<span class="lab"><b>heute noch nichts</b><br><span style="color:var(--muted);font-size:.7rem">kein Login seit heute 0:00 Uhr</span></span>
</div>
<div class="status-tile hilfe zero">
<span class="num">0</span>
<span class="lab"><b>brauchen Hilfe</b><br><span style="color:var(--muted);font-size:.7rem">stockt · viele Fehlversuche · Pilot-Übernahme</span></span>
</div>
</div>
<!-- B) Ranking: Top 3 + Schwächste 3 (nach Benchmark über alle Apps) -->
<div class="ranking-grid">
<div class="ranking-block top">
<h3>🏆 Top 3 — Benchmark gesamt</h3>
<div class="ranking-list">
<div class="rank-row top">
<span class="rk">1.</span>
<span class="av">🐬</span>
<span class="nm">Lenchen</span>
<span class="pc">87 %</span>
<span class="pcbar"><div style="width:87%"></div></span>
</div>
<div class="rank-row top">
<span class="rk">2.</span>
<span class="av">🐝</span>
<span class="nm">Franz</span>
<span class="pc">81 %</span>
<span class="pcbar"><div style="width:81%"></div></span>
</div>
<div class="rank-row top">
<span class="rk">3.</span>
<span class="av">🦫</span>
<span class="nm">Teresa</span>
<span class="pc">76 %</span>
<span class="pcbar"><div style="width:76%"></div></span>
</div>
</div>
</div>
<div class="ranking-block bottom">
<h3>👀 Schwächste 3 — Benchmark gesamt</h3>
<div class="ranking-list">
<div class="rank-row bottom">
<span class="rk">23.</span>
<span class="av">🐉</span>
<span class="nm">Lukas</span>
<span class="pc">28 %</span>
<span class="pcbar"><div style="width:28%"></div></span>
</div>
<div class="rank-row bottom">
<span class="rk">24.</span>
<span class="av">🐧</span>
<span class="nm">bubi</span>
<span class="pc">19 %</span>
<span class="pcbar"><div style="width:19%"></div></span>
</div>
<div class="rank-row bottom">
<span class="rk">25.</span>
<span class="av" style="background:#e0dccd">?</span>
<span class="nm">Sabine</span>
<span class="pc" style="color:var(--gray)"> %</span>
<span class="pcbar"><div style="width:0%"></div></span>
</div>
</div>
</div>
</div>
<!-- C) Klassen-Fleiß über Zeit — Säulen pro Bucket -->
<div class="klassen-fleiss-zeit">
<!-- Globaler Zeitraum-Filter — gilt für ALLE Fleißanzeigen -->
<!-- Auswahl wird in localStorage 'ggs-fleiss-range' gespeichert,
sodass die Lehrperson sie nicht jedes Mal neu setzen muss. -->
<div class="kfz-filter">
<span class="kfz-filter-lab">Zeitraum:</span>
<span class="pill" title="Heute · 25 Stunden 0:00 24:00 · Schulkernzeit 813 Uhr hervorgehoben">
<span class="dot k"></span>Tag
</span>
<span class="pill active" title="Aktuelle Kalenderwoche · MoSo · heutiger Tag markiert">
Woche
</span>
<span class="pill" title="Letzte 30 Tage · alle Tage sichtbar, Wochenenden als Lücken erkennbar">
Monat
</span>
<span class="pill" title="Aktuelles Schuljahr · ab Schulanfang (Land-abhängig) bis Schulende · leere Monate am Anfang/Ende weggelassen">
Schuljahr
</span>
<span class="kfz-filter-saved" title="Die zuletzt gewählte Einstellung wird automatisch gespeichert (localStorage ggs-fleiss-range)">
💾 gemerkt
</span>
<span class="kfz-filter-hint" title="Der Filter gilt auch für die Schüler:innen-Fleiß-Säulen im Ergebnisse-Tab">
🔗 wirkt auch auf die Schüler-Fleißsäulen
</span>
</div>
<div class="kfz-head">
<h3>📊 Klassen-Fleiß über Zeit</h3>
<span class="meta"><b>Diese Woche · MoSo</b> · Säule = aktive Lernzeit der ganzen Klasse · Farbe = Modul · <b>Klassensumme 22 h 14 min</b></span>
</div>
<div class="kfz-grid">
<div class="kfz-col">
<span class="col-val">3 h 12 min</span>
<div class="col-wrap">
<div class="col-stack" style="height:65%">
<span style="background:var(--blue);height:55%"></span>
<span style="background:var(--green);height:30%"></span>
<span style="background:var(--orange);height:15%"></span>
</div>
</div>
<span class="col-lab">Mo</span>
</div>
<div class="kfz-col">
<span class="col-val">4 h 48 min</span>
<div class="col-wrap">
<div class="col-stack" style="height:95%">
<span style="background:var(--blue);height:45%"></span>
<span style="background:var(--green);height:35%"></span>
<span style="background:var(--orange);height:20%"></span>
</div>
</div>
<span class="col-lab">Di</span>
</div>
<div class="kfz-col">
<span class="col-val">2 h 30 min</span>
<div class="col-wrap">
<div class="col-stack" style="height:50%">
<span style="background:var(--green);height:60%"></span>
<span style="background:#7c3aed;height:40%"></span>
</div>
</div>
<span class="col-lab">Mi</span>
</div>
<div class="kfz-col">
<span class="col-val">3 h 50 min</span>
<div class="col-wrap">
<div class="col-stack" style="height:78%">
<span style="background:var(--orange);height:40%"></span>
<span style="background:var(--green);height:35%"></span>
<span style="background:var(--blue);height:25%"></span>
</div>
</div>
<span class="col-lab">Do</span>
</div>
<div class="kfz-col today">
<span class="col-val"><b style="color:var(--green-d)">4 h 22 min</b></span>
<div class="col-wrap">
<div class="col-stack" style="height:85%">
<span style="background:var(--blue);height:50%"></span>
<span style="background:var(--orange);height:30%"></span>
<span style="background:var(--green);height:20%"></span>
</div>
</div>
<span class="col-lab"><b>Fr · heute</b></span>
</div>
<div class="kfz-col">
<span class="col-val">45 min</span>
<div class="col-wrap">
<div class="col-stack" style="height:15%">
<span style="background:var(--green);height:100%"></span>
</div>
</div>
<span class="col-lab">Sa</span>
</div>
<div class="kfz-col">
<span class="col-val"></span>
<div class="col-wrap">
<div class="col-empty"></div>
</div>
<span class="col-lab">So</span>
</div>
</div>
<!-- Modul-Legende -->
<div style="display:flex;flex-wrap:wrap;gap:.4rem .8rem;margin-top:.7rem;font-size:.7rem;color:#3a3a3a">
<span style="display:inline-flex;align-items:center;gap:.3rem"><span style="display:inline-block;width:10px;height:10px;background:var(--blue);border-radius:2px"></span> 🌍 Klima</span>
<span style="display:inline-flex;align-items:center;gap:.3rem"><span style="display:inline-block;width:10px;height:10px;background:var(--green);border-radius:2px"></span> 🚁 Heli</span>
<span style="display:inline-flex;align-items:center;gap:.3rem"><span style="display:inline-block;width:10px;height:10px;background:var(--orange);border-radius:2px"></span> 🍽️ Weltküche</span>
<span style="display:inline-flex;align-items:center;gap:.3rem"><span style="display:inline-block;width:10px;height:10px;background:#7c3aed;border-radius:2px"></span> 🚌 Busfahrt</span>
</div>
</div>
</div>
<!-- ============== ZEITRAUM-FILTER · ALLE VARIANTEN ============== -->
<div class="card">
<div class="card-h">Zeitraum-Filter · alle vier Varianten im Vergleich</div>
<p style="font-size:.78rem;color:var(--muted);margin-bottom:1rem">
Der Filter oben (<b>Tag · Woche · Monat · Schuljahr</b>) wirkt auf alle Fleiß-Säulen-Anzeigen
gleichzeitig — Klassen-Fleiß im Live-Cockpit und Schüler:innen-Fleiß-Matrix im Ergebnisse-Tab.
Die folgenden Skizzen zeigen, wie die Säulen-Auflösung pro Variante aussieht.
</p>
<!-- Tag-Ansicht: 25 Stunden-Säulen, Schulzeit 8-13 hervorgehoben -->
<div class="zeitraum-variant">
<div class="zv-head"><span class="zv-tag">Tag</span> · Stunden 024 · Schulkernzeit grau hinterlegt</div>
<div class="zv-day-grid">
<!-- Nachtstunden 0-7: nur Marker, kaum Aktivität -->
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">0</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">1</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">2</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">3</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">4</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">5</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">6</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">7</span></div>
<!-- Schulkernzeit 8-13: hervorgehoben -->
<div class="zv-day-col school"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:70%"><span style="background:var(--blue);height:60%"></span><span style="background:var(--green);height:40%"></span></div></div><span class="zv-h">8</span></div>
<div class="zv-day-col school"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:88%"><span style="background:var(--blue);height:50%"></span><span style="background:var(--orange);height:30%"></span><span style="background:var(--green);height:20%"></span></div></div><span class="zv-h">9</span></div>
<div class="zv-day-col school"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:95%"><span style="background:var(--blue);height:55%"></span><span style="background:var(--green);height:25%"></span><span style="background:var(--orange);height:20%"></span></div></div><span class="zv-h">10</span></div>
<div class="zv-day-col school"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:62%"><span style="background:var(--orange);height:55%"></span><span style="background:#7c3aed;height:45%"></span></div></div><span class="zv-h">11</span></div>
<div class="zv-day-col school"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:48%"><span style="background:var(--green);height:100%"></span></div></div><span class="zv-h">12</span></div>
<div class="zv-day-col school"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:30%"><span style="background:#7c3aed;height:100%"></span></div></div><span class="zv-h">13</span></div>
<!-- Nachmittag 14-19: leichte Aktivität (HÜ) -->
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">14</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:22%"><span style="background:var(--blue);height:100%"></span></div></div><span class="zv-h">15</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:35%"><span style="background:var(--blue);height:70%"></span><span style="background:var(--orange);height:30%"></span></div></div><span class="zv-h">16</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:18%"><span style="background:var(--orange);height:100%"></span></div></div><span class="zv-h">17</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">18</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">19</span></div>
<!-- Abend 20-24: praktisch leer -->
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">20</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">21</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">22</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">23</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">24</span></div>
</div>
<div class="zv-foot">
<span>📌 Die <b>Schulkernzeit 813 Uhr</b> ist hellgelb hinterlegt — so erkennt die Lehrperson schnell, ob im Unterricht oder vor allem als Hausübung gearbeitet wurde.</span>
</div>
</div>
<!-- Monat-Ansicht: 30 Tage, leere am Anfang weglassen -->
<div class="zeitraum-variant" style="margin-top:1.4rem">
<div class="zv-head"><span class="zv-tag">Monat</span> · 30 Tage (1.30.) · alle Tage sichtbar, leere Tage als gestrichelte Baseline</div>
<div class="zv-month-grid">
<!-- 30 Säulen mit Beispiel-Heights -->
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:42%"><span style="background:var(--blue);height:100%"></span></div></div><span class="zv-h">1</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:58%"><span style="background:var(--blue);height:60%"></span><span style="background:var(--green);height:40%"></span></div></div><span class="zv-h">2</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:35%"><span style="background:var(--green);height:100%"></span></div></div><span class="zv-h">3</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">4</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">5</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:68%"><span style="background:var(--orange);height:50%"></span><span style="background:var(--blue);height:30%"></span><span style="background:var(--green);height:20%"></span></div></div><span class="zv-h">6</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:72%"><span style="background:var(--blue);height:70%"></span><span style="background:var(--orange);height:30%"></span></div></div><span class="zv-h">7</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:45%"><span style="background:var(--green);height:100%"></span></div></div><span class="zv-h">8</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:88%"><span style="background:var(--blue);height:60%"></span><span style="background:var(--orange);height:25%"></span><span style="background:#7c3aed;height:15%"></span></div></div><span class="zv-h">9</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:52%"><span style="background:var(--orange);height:100%"></span></div></div><span class="zv-h">10</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">11</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">12</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:65%"><span style="background:var(--blue);height:50%"></span><span style="background:var(--green);height:30%"></span><span style="background:var(--orange);height:20%"></span></div></div><span class="zv-h">13</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:78%"><span style="background:var(--blue);height:55%"></span><span style="background:var(--orange);height:45%"></span></div></div><span class="zv-h">14</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:42%"><span style="background:var(--green);height:100%"></span></div></div><span class="zv-h">15</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:38%"><span style="background:var(--orange);height:100%"></span></div></div><span class="zv-h">16</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:62%"><span style="background:var(--blue);height:80%"></span><span style="background:var(--green);height:20%"></span></div></div><span class="zv-h">17</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">18</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">19</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:82%"><span style="background:var(--blue);height:60%"></span><span style="background:var(--orange);height:40%"></span></div></div><span class="zv-h">20</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:55%"><span style="background:var(--orange);height:60%"></span><span style="background:var(--green);height:40%"></span></div></div><span class="zv-h">21</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:48%"><span style="background:var(--green);height:100%"></span></div></div><span class="zv-h">22</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:35%"><span style="background:var(--blue);height:100%"></span></div></div><span class="zv-h">23</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">24</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><span class="zv-col-empty"></span></div><span class="zv-h">25</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:72%"><span style="background:var(--blue);height:70%"></span><span style="background:var(--orange);height:30%"></span></div></div><span class="zv-h">26</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:88%"><span style="background:var(--blue);height:50%"></span><span style="background:var(--green);height:30%"></span><span style="background:var(--orange);height:20%"></span></div></div><span class="zv-h">27</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:65%"><span style="background:var(--orange);height:55%"></span><span style="background:var(--green);height:45%"></span></div></div><span class="zv-h">28</span></div>
<div class="zv-day-col"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:42%"><span style="background:var(--green);height:100%"></span></div></div><span class="zv-h">29</span></div>
<div class="zv-day-col today"><div class="zv-col-wrap"><div class="zv-col-stack" style="height:78%"><span style="background:var(--blue);height:50%"></span><span style="background:var(--orange);height:30%"></span><span style="background:var(--green);height:20%"></span></div></div><span class="zv-h"><b>30</b></span></div>
</div>
<div class="zv-foot">
<span>📌 <b>Wochenenden klar erkennbar</b> als systematische Lücken (4./5., 11./12., 18./19., 25./26.).</span>
</div>
</div>
<!-- Schuljahr-Ansicht: nur Monate mit Aktivität -->
<div class="zeitraum-variant" style="margin-top:1.4rem">
<div class="zv-head"><span class="zv-tag">Schuljahr</span> · AugJul · leere Monate am Anfang & Ende weggelassen</div>
<div class="zv-year-grid">
<!-- August und Juli werden hier weggelassen (Schulanfang fängt erst Sep an im Beispiel) -->
<div class="zv-year-col"><div class="zv-col-wrap" style="height:120px"><div class="zv-col-stack" style="height:25%"><span style="background:var(--blue);height:60%"></span><span style="background:var(--green);height:40%"></span></div></div><span class="zv-y">Sep</span><span class="zv-y-sum">8 h 12 min</span></div>
<div class="zv-year-col"><div class="zv-col-wrap" style="height:120px"><div class="zv-col-stack" style="height:60%"><span style="background:var(--blue);height:50%"></span><span style="background:var(--green);height:30%"></span><span style="background:var(--orange);height:20%"></span></div></div><span class="zv-y">Okt</span><span class="zv-y-sum">19 h 48 min</span></div>
<div class="zv-year-col"><div class="zv-col-wrap" style="height:120px"><div class="zv-col-stack" style="height:75%"><span style="background:var(--blue);height:45%"></span><span style="background:var(--orange);height:30%"></span><span style="background:var(--green);height:15%"></span><span style="background:#7c3aed;height:10%"></span></div></div><span class="zv-y">Nov</span><span class="zv-y-sum">24 h 30 min</span></div>
<div class="zv-year-col"><div class="zv-col-wrap" style="height:120px"><div class="zv-col-stack" style="height:55%"><span style="background:var(--orange);height:50%"></span><span style="background:var(--blue);height:30%"></span><span style="background:var(--green);height:20%"></span></div></div><span class="zv-y">Dez</span><span class="zv-y-sum">17 h 50 min</span></div>
<div class="zv-year-col"><div class="zv-col-wrap" style="height:120px"><div class="zv-col-stack" style="height:88%"><span style="background:var(--blue);height:40%"></span><span style="background:var(--green);height:30%"></span><span style="background:var(--orange);height:20%"></span><span style="background:#7c3aed;height:10%"></span></div></div><span class="zv-y">Jän</span><span class="zv-y-sum">28 h 04 min</span></div>
<div class="zv-year-col"><div class="zv-col-wrap" style="height:120px"><div class="zv-col-stack" style="height:72%"><span style="background:var(--blue);height:35%"></span><span style="background:var(--orange);height:35%"></span><span style="background:var(--green);height:20%"></span><span style="background:#7c3aed;height:10%"></span></div></div><span class="zv-y">Feb</span><span class="zv-y-sum">22 h 56 min</span></div>
<div class="zv-year-col"><div class="zv-col-wrap" style="height:120px"><div class="zv-col-stack" style="height:80%"><span style="background:var(--orange);height:40%"></span><span style="background:var(--blue);height:30%"></span><span style="background:var(--green);height:30%"></span></div></div><span class="zv-y">Mär</span><span class="zv-y-sum">25 h 30 min</span></div>
<div class="zv-year-col"><div class="zv-col-wrap" style="height:120px"><div class="zv-col-stack" style="height:48%"><span style="background:var(--green);height:50%"></span><span style="background:var(--blue);height:50%"></span></div></div><span class="zv-y">Apr</span><span class="zv-y-sum">15 h 18 min</span></div>
<div class="zv-year-col"><div class="zv-col-wrap" style="height:120px"><div class="zv-col-stack" style="height:92%"><span style="background:var(--blue);height:35%"></span><span style="background:var(--orange);height:30%"></span><span style="background:var(--green);height:25%"></span><span style="background:#7c3aed;height:10%"></span></div></div><span class="zv-y">Mai</span><span class="zv-y-sum">29 h 12 min</span></div>
<div class="zv-year-col today"><div class="zv-col-wrap" style="height:120px"><div class="zv-col-stack" style="height:38%"><span style="background:var(--blue);height:55%"></span><span style="background:var(--orange);height:30%"></span><span style="background:var(--green);height:15%"></span></div></div><span class="zv-y"><b>Jun · aktuell</b></span><span class="zv-y-sum">12 h 04 min</span></div>
</div>
<div class="zv-foot">
<span>📌 <b>Aug 2025</b> und <b>Jul 2026</b> ausgeblendet — vor Schulanfang und nach Schulschluss keine Aktivität, daher nicht relevant. Sobald in einem dieser Monate Aktivität entsteht, wird er automatisch eingeblendet.</span>
</div>
</div>
<!-- Woche-Ansicht-Verweis -->
<div style="margin-top:1rem;padding:.7rem .9rem;background:#f5f3eb;border-radius:8px;font-size:.78rem;color:var(--muted)">
<b style="color:var(--green-d)">Woche</b>-Ansicht: siehe Ebene-1-Sektion oben (MoSo, „heute" markiert) — das ist der Default-Filter beim ersten Aufruf des Cockpits (bei späteren Aufrufen die zuletzt gewählte Einstellung).
</div>
</div>
<!-- ============== POLISH-DETAILS DES FILTERS ============== -->
<div class="card">
<div class="card-h">Polish-Details des Zeitraum-Filters</div>
<div class="polish-grid">
<!-- 1) Tooltips -->
<div class="polish-block">
<h3>💡 Tooltips an den Filter-Pills</h3>
<p>
Hover über jede Pill zeigt eine Kurz-Spec — nützlich besonders für die Lehrperson,
die das Cockpit zum ersten Mal sieht. Probier es oben am Filter mal aus.
</p>
<div class="polish-spec">
<div class="ps-row"><span class="ps-k">Tag</span><span class="ps-v">Heute · 25 Stunden 0:00 24:00 · Schulkernzeit 813 Uhr hervorgehoben</span></div>
<div class="ps-row"><span class="ps-k">Woche</span><span class="ps-v">Aktuelle Kalenderwoche · MoSo · heutiger Tag markiert</span></div>
<div class="ps-row"><span class="ps-k">Monat</span><span class="ps-v">Letzte 30 Tage · alle Tage sichtbar, Wochenenden als Lücken erkennbar</span></div>
<div class="ps-row"><span class="ps-k">Schuljahr</span><span class="ps-v">Aktuelles Schuljahr · ab Schulanfang (Land-abhängig) bis Schulende · leere Monate am Anfang/Ende weggelassen</span></div>
</div>
</div>
<!-- 2) localStorage-Persistenz -->
<div class="polish-block">
<h3>💾 Persistenz der Auswahl</h3>
<p>
Die gewählte Einstellung wird in <code>localStorage</code> gespeichert.
Bei jedem späteren Aufruf des Cockpits steht der Filter direkt auf dem
zuletzt gewählten Wert — keine Mehrfach-Klicks pro Tag.
</p>
<div class="polish-code">
<span class="pc-k">localStorage-Key:</span> <span class="pc-v">ggs-fleiss-range</span>
<span class="pc-k">Mögliche Werte:</span> <span class="pc-v">day · week · month · year</span>
<span class="pc-k">Default beim ersten Aufruf:</span> <span class="pc-v">week</span>
<span class="pc-k">Sichtbar im UI:</span> <span class="pc-v">💾 gemerkt (rechts neben den Pills)</span></div>
<p style="font-size:.78rem;color:var(--muted);margin-top:.5rem">
Der Wert ist <b>pro Lehrperson</b> (Browser-lokal), nicht pro Klasse — das hält die
Bedienung leichtgewichtig. Falls jemand mehrere Klassen oft umschaltet, kann
später auf Server-Seite ein User-Preference-Feld dazu (siehe Memory).
</p>
</div>
<!-- 3) Land-basierte Schuljahre — DACH+LI -->
<div class="polish-block">
<h3>🌍 Schuljahr aus Land · DACH+LI</h3>
<p>
Die Plattform bedient gezielt <b>Österreich, Deutschland, Schweiz, Liechtenstein</b>.
Schul-Anfangs- und Endmonate ziehen wir aus <code>App/php/lib/Country.php</code>
(existiert schon für andere Sprach-/Lehrplan-Themen).
</p>
<table class="schuljahr-table">
<thead>
<tr><th>Land</th><th>Schulanfang</th><th>Schulende</th><th>Bemerkung</th></tr>
</thead>
<tbody>
<tr><td>🇦🇹 Österreich</td><td>September</td><td>Juli</td><td>1. Schultag Mo nach 1. September (Ost) bzw. 2. Mo im September (West)</td></tr>
<tr><td>🇩🇪 Deutschland</td><td>August / September</td><td>Juli</td><td>variiert nach Bundesland · BY/BW: Mitte Sep · HH/B/MV: Anfang Aug</td></tr>
<tr><td>🇨🇭 Schweiz</td><td>August</td><td>Juli / August</td><td>variiert nach Kanton · ZH/BE/SG: Mitte Aug · TI: Anfang Sep</td></tr>
<tr><td>🇱🇮 Liechtenstein</td><td>August</td><td>Juli</td><td>angelehnt an Schweiz (Mitte Aug)</td></tr>
</tbody>
</table>
<p style="font-size:.78rem;color:var(--muted);margin-top:.5rem">
<b>Konkret im Code:</b> <code>Country::schoolYearStart('AT')</code> liefert <code>{month: 9, dayApprox: 5}</code>,
<code>Country::schoolYearStart('CH')</code> liefert <code>{month: 8, dayApprox: 15}</code>.
Die Schuljahr-Säulen-Anzeige beginnt beim ersten Monat nach dem Schulanfang mit Aktivität
und endet beim letzten — leere Monate am Rand werden weggelassen (Sommerferien-Lücken
im Schuljahr also auch automatisch unsichtbar, falls eine Klasse über Ferien nichts spielt).
</p>
<p style="font-size:.78rem;color:var(--muted);margin-top:.4rem">
<b>DE-Bundesland-Logik</b>: in DE genauer Schulanfang ist Bundesland-spezifisch.
Pragmatisch: pro Klasse ein Feld <code>classes.school_region</code> (optional) — sonst Default „Mitte August".
Sehr selten relevant für die Säulen-Anzeige, weil ein Säulen-Bucket ein ganzer Monat ist.
</p>
</div>
</div>
<!-- Implementations-Notiz -->
<div style="margin-top:1.2rem;padding:.8rem 1rem;background:#fff8e1;border-left:4px solid var(--gold);border-radius:0 8px 8px 0;font-size:.78rem">
<b style="color:#8a6516">Implementierungs-Aufwand für die drei Polish-Punkte zusammen:</b>
ca. <b>1,5 Stunden</b>. Tooltips sind reine <code>title</code>-Attribute (~15 min), localStorage-Persistenz ist
ein Wrapper um das State-Setting (~20 min), das Schuljahr-aus-Country für AT/DE/CH/LI braucht
eine neue Methode in <code>Country.php</code> plus die kleine 4-Zeilen-Mapping-Tabelle (~30 min)
sowie eine kleine Anpassung im Säulen-Renderer (~15 min). Tests + Edge-Cases
(Schuljahres-Wechsel im August/September, Halbjahr-Ferien-Lücken) ~10 min.
</div>
</div>
<!-- ============== BENCHMARK-KONZEPT (Erklärung) ============== -->
<div class="benchmark">
<h3>🎯 Wie funktioniert das Benchmark-Prozent über alle Apps?</h3>
<p>
Jede Simulation liefert einen normalisierten <b>Modul-Score 0100 %</b>, der die
Leistung in einer Session widerspiegelt. Der <b>Gesamt-Benchmark einer Schüler:in</b>
ist der Mittelwert aller ihrer abgeschlossenen Sessions — gewichtet so, dass eine
häufig gespielte Sim nicht alles dominiert (max. 3 Sessions pro Modul zählen ein,
danach gilt nur das beste Ergebnis).
</p>
<table>
<tr><th>Modul</th><th>Was ergibt 100 %?</th><th>Berechnung (Vorschlag)</th></tr>
<tr>
<td>🌍 Klimawächter</td>
<td>Temp ≤ +1 °C, Inselüberflutung 0 %, Budget &gt; 1000, Bevölkerung 100 %</td>
<td><code>(tempScore + inselScore + budgetScore + popScore) / 4</code></td>
</tr>
<tr>
<td>🚁 Heli</td>
<td>Alle Wegpunkte ohne Fehlversuch, Audio durch</td>
<td><code>planCorrect/planTotal × (1 planAttempts/15)</code></td>
</tr>
<tr>
<td>🚌 Busfahrt</td>
<td>Quiz Erste-Wahl-Quote 100 %, Distanz-Abweichung &lt; 30 km Ø</td>
<td><code>0.7×quizFirstTryRate + 0.3×(1 distMean/200)</code></td>
</tr>
<tr>
<td>🍽️ Weltküche</td>
<td>Alle Gerichte abgeschlossen, &lt;3 Fehlklicks pro Zutat</td>
<td><code>completedDishes/totalDishes × (1 mistakes/maxMistakes)</code></td>
</tr>
<tr>
<td>🌾 Farmer</td>
<td>Erfolgsrate 100 %, Jahr ≥ 20 erreicht, CO₂ niedrig</td>
<td><code>0.5×successRate + 0.3×(years/20) + 0.2×(1 co2Norm)</code></td>
</tr>
<tr>
<td>🪐 Sonnensystem</td>
<td>Alle 20 Aufgaben gelöst, möglichst Erste-Wahl</td>
<td><code>completed/total × (1 attempts/maxAttempts)</code></td>
</tr>
<tr>
<td>🏛️ EU-Werkstatt</td>
<td>Alle 4 Fälle korrekt, Mülleimer leer</td>
<td><code>firstTryHits/totalSteps × (1 muelleimer/totalAttempts)</code></td>
</tr>
<tr>
<td>⚡ Energiemanager</td>
<td>Alle 8 Blöcke ohne Defizit, alle 6 Sets durch</td>
<td><code>perfectBlocks/totalBlocks × setIndex/setTotal</code></td>
</tr>
<tr>
<td>🌊 Fluss</td>
<td>Biodiv ≥ 80, Economy ≥ 60, Flood &lt; 20, Population stabil</td>
<td><code>(biodiv + economy + (100-flood) + popStable) / 4</code></td>
</tr>
<tr>
<td>✈️ Fluggesellschaft</td>
<td>Alle Aufträge gewonnen, Quiz Erste-Wahl 100 %, hohe Marge</td>
<td><code>0.5×wonRate + 0.3×quizFirstTry + 0.2×marginScore</code></td>
</tr>
<tr>
<td>📦 Logistik</td>
<td>≥80 % Aufträge pünktlich abgeschlossen, Endbilanz positiv</td>
<td><code>0.7×onTimeRate + 0.3×profitNorm</code></td>
</tr>
<tr>
<td>📅 Entscheidungstag</td>
<td>Tag-Ziel erreicht, CO₂/kWh-Limit eingehalten</td>
<td><code>noch zu definieren</code></td>
</tr>
</table>
<p style="margin-top:.5rem;color:#3a3a3a;font-size:.78rem">
<b>Wichtig:</b> der Prozentwert ist <b>nicht</b> eine Note — er ist eine Orientierung.
Beim Klick auf „Detail" sieht die Lehrperson, woraus sich die Zahl zusammensetzt
(welches Modul, welche Dimension hat ihn nach unten oder oben gezogen).
Schüler:innen sehen den eigenen Wert nicht direkt — das verhindert Wettkampfdruck.
Die Lehrperson kann pro Klasse entscheiden, ob sie ihn teilen möchte.
</p>
</div>
<!-- ============== FILTER ============== -->
<div class="card">
<div class="card-h">Ebene 2 · Filter & Sortierung</div>
<div class="filter-bar">
<span class="pill active">Alle <span class="badge">25</span></span>
<span class="pill"><span class="dot g"></span>Jetzt aktiv <span class="badge">4</span></span>
<span class="pill"><span class="dot o"></span>Heute aktiv <span class="badge">9</span></span>
<span class="pill"><span class="dot k"></span>Heute nichts <span class="badge">12</span></span>
<span class="pill"><span class="dot r"></span>Brauchen Hilfe <span class="badge">0</span></span>
<span class="sep"></span>
<span class="filter-lab">Modul:</span>
<select class="filter-select">
<option>Alle Module</option>
<option>🌍 Klimawächter</option>
<option>🚁 Heli-Navigation</option>
<option>🍽️ Weltküche</option>
<option>🚌 Busfahrt</option>
<option>📅 Entscheidungstag</option>
</select>
<span class="sep"></span>
<span class="filter-lab">Sortierung:</span>
<select class="filter-select">
<option>Status (aktiv zuerst)</option>
<option>Name AZ</option>
<option>Lernzeit heute ↓</option>
<option>Letzter Heartbeat ↓</option>
</select>
</div>
</div>
<!-- ============== EBENE 3: SCHÜLERLISTE ============== -->
<div class="card">
<div class="card-h">Ebene 3 · Klassenliste (Mockup mit Beispieldaten)</div>
<div class="student-list">
<!-- Jetzt aktiv: Klima -->
<div class="stu-row aktiv">
<div class="stu-avatar-block">
<span class="stu-status-icon" title="Jetzt aktiv">🟢</span>
<div class="stu-avatar">🐬</div>
</div>
<div class="stu-meta">
<div class="stu-name">Lenchen <span class="pulse"></span></div>
<div class="stu-sub">
<span class="module-chip">🌍 Klimawächter</span>
<span class="phase">Jahr 12 von 75</span>
<span class="heartbeat">⏱ aktiv vor 3 s · Sitzung 14 min</span>
</div>
<div class="stu-mini-stats">
<div class="ms good">
<div class="ms-row"><div class="l">CO₂</div><div class="v">425 ppm</div></div>
<div class="ms-range"><span class="rmin">280</span><div class="rbar"><div class="rfill good" style="width:33%"></div><div class="rmarker" style="left:33%"></div></div><span class="rmax">600</span></div>
</div>
<div class="ms">
<div class="ms-row"><div class="l">ΔTemp</div><div class="v">+0,4 °C</div></div>
<div class="ms-range"><span class="rmin">0</span><div class="rbar"><div class="rfill good" style="width:13%"></div><div class="rmarker" style="left:13%"></div></div><span class="rmax">+3°</span></div>
</div>
<div class="ms warn">
<div class="ms-row"><div class="l">Budget</div><div class="v">480 Mio</div></div>
<div class="ms-range"><span class="rmin">0</span><div class="rbar"><div class="rfill warn" style="width:48%"></div><div class="rmarker" style="left:48%"></div></div><span class="rmax">1000</span></div>
</div>
<div class="ms good">
<div class="ms-row"><div class="l">Bevölkerung</div><div class="v">98 %</div></div>
<div class="ms-range"><span class="rmin">0</span><div class="rbar"><div class="rfill good" style="width:98%"></div><div class="rmarker" style="left:98%"></div></div><span class="rmax">100</span></div>
</div>
</div>
</div>
<div class="stu-actions">
<button class="stu-btn primary">Live anschauen →</button>
<button class="stu-btn outline">Letzte Ergebnisse</button>
</div>
</div>
<!-- Jetzt aktiv: Heli mit Sternen -->
<div class="stu-row aktiv">
<div class="stu-avatar-block">
<span class="stu-status-icon" title="Jetzt aktiv">🟢</span>
<div class="stu-avatar">🐝</div>
</div>
<div class="stu-meta">
<div class="stu-name">Franz <span class="pulse"></span></div>
<div class="stu-sub">
<span class="module-chip">🚁 Heli-Navigation</span>
<span class="phase">M2 „Bergrettung Bezau" · Wegpunkt 3/6</span>
<span class="heartbeat">⏱ aktiv vor 2 s · Sitzung 8 min</span>
<span class="stu-stars">★★★☆☆</span>
</div>
<div class="stu-mini-stats">
<div class="ms good">
<div class="ms-row"><div class="l">Wegpunkte</div><div class="v">3/6</div></div>
<div class="ms-range"><span class="rmin">0</span><div class="rbar"><div class="rfill good" style="width:50%"></div><div class="rmarker" style="left:50%"></div></div><span class="rmax">6</span></div>
</div>
<div class="ms good">
<div class="ms-row"><div class="l">Treffer-Quote</div><div class="v">3/5 · 60 %</div></div>
<div class="ms-range"><span class="rmin">0</span><div class="rbar"><div class="rfill warn" style="width:60%"></div><div class="rmarker" style="left:60%"></div></div><span class="rmax">100</span></div>
</div>
<div class="ms">
<div class="ms-row"><div class="l">Fehlversuche</div><div class="v">2</div></div>
<div class="ms-range"><span class="rmin">0</span><div class="rbar"><div class="rfill good" style="width:13%"></div><div class="rmarker" style="left:13%"></div></div><span class="rmax">15</span></div>
</div>
<div class="ms good">
<div class="ms-row"><div class="l">Phase</div><div class="v">Plan</div></div>
<div class="ms-range"><span class="rmin">Audio</span><div class="rbar"><div class="rfill good" style="width:50%"></div><div class="rmarker" style="left:50%"></div></div><span class="rmax">Flug</span></div>
</div>
</div>
</div>
<div class="stu-actions">
<button class="stu-btn primary">Live anschauen →</button>
<button class="stu-btn outline">Audio nochmal</button>
</div>
</div>
<!-- Jetzt aktiv: Weltküche mit Fortschritt -->
<div class="stu-row aktiv">
<div class="stu-avatar-block">
<span class="stu-status-icon" title="Jetzt aktiv">🟢</span>
<div class="stu-avatar">🦫</div>
</div>
<div class="stu-meta">
<div class="stu-name">Teresa <span class="pulse"></span></div>
<div class="stu-sub">
<span class="module-chip">🍽️ Weltküche</span>
<span class="phase">Moussaka · Zutat 4/15 · Lamm gesucht</span>
<span class="heartbeat">⏱ aktiv vor 1 s · Sitzung 6 min</span>
</div>
<div class="stu-mini-stats">
<div class="ms warn">
<div class="ms-row"><div class="l">Gerichte fertig</div><div class="v">3/8</div></div>
<div class="ms-range"><span class="rmin">0</span><div class="rbar"><div class="rfill warn" style="width:38%"></div><div class="rmarker" style="left:38%"></div></div><span class="rmax">8</span></div>
</div>
<div class="ms warn">
<div class="ms-row"><div class="l">Score</div><div class="v">540</div></div>
<div class="ms-range"><span class="rmin">0</span><div class="rbar"><div class="rfill warn" style="width:34%"></div><div class="rmarker" style="left:34%"></div></div><span class="rmax">1600</span></div>
</div>
<div class="ms warn">
<div class="ms-row"><div class="l">Fehlklicks (Ø/Zutat)</div><div class="v">7 · Ø 2,3</div></div>
<div class="ms-range"><span class="rmin">0</span><div class="rbar"><div class="rfill warn" style="width:46%"></div><div class="rmarker" style="left:46%"></div></div><span class="rmax">5</span></div>
</div>
<div class="ms good">
<div class="ms-row"><div class="l">Abzeichen</div><div class="v">2/10</div></div>
<div class="ms-range"><span class="rmin">0</span><div class="rbar"><div class="rfill good" style="width:20%"></div><div class="rmarker" style="left:20%"></div></div><span class="rmax">10</span></div>
</div>
</div>
</div>
<div class="stu-actions">
<button class="stu-btn primary">Live anschauen →</button>
<button class="stu-btn outline">Rezept-Verlauf</button>
</div>
</div>
<!-- Hilfe-Bedarf: jemand der hängt -->
<div class="stu-row hilfe">
<div class="stu-avatar-block">
<span class="stu-status-icon" title="Braucht Hilfe">🆘</span>
<div class="stu-avatar">🐉</div>
</div>
<div class="stu-meta">
<div class="stu-name">Lukas <span class="pulse" style="background:var(--red)"></span></div>
<div class="stu-sub">
<span class="module-chip">🚁 Heli-Navigation</span>
<span class="phase">M1 „St. Anton" · Wegpunkt 2/4</span>
<span class="heartbeat warn">⏱ aktiv vor 1 s · <b>14 Fehlversuche</b> · Pilot bald übernimmt</span>
</div>
<div class="stu-mini-stats">
<div class="ms bad">
<div class="ms-row"><div class="l">Fehlversuche</div><div class="v">14 / 15</div></div>
<div class="ms-range"><span class="rmin">0</span><div class="rbar"><div class="rfill bad" style="width:93%"></div><div class="rmarker" style="left:93%"></div></div><span class="rmax">15</span></div>
</div>
<div class="ms bad">
<div class="ms-row"><div class="l">Treffer-Quote</div><div class="v">1/4 · 25 %</div></div>
<div class="ms-range"><span class="rmin">0</span><div class="rbar"><div class="rfill bad" style="width:25%"></div><div class="rmarker" style="left:25%"></div></div><span class="rmax">100</span></div>
</div>
<div class="ms warn">
<div class="ms-row"><div class="l">Sitzungsdauer</div><div class="v">22 min</div></div>
<div class="ms-range"><span class="rmin">0</span><div class="rbar"><div class="rfill warn" style="width:55%"></div><div class="rmarker" style="left:55%"></div></div><span class="rmax">40 min</span></div>
</div>
<div class="ms warn">
<div class="ms-row"><div class="l">Letzter Treffer</div><div class="v">vor 18 min</div></div>
<div class="ms-range"><span class="rmin">jetzt</span><div class="rbar"><div class="rfill bad" style="width:60%"></div><div class="rmarker" style="left:60%"></div></div><span class="rmax">30+</span></div>
</div>
</div>
</div>
<div class="stu-actions">
<button class="stu-btn alert">Eingreifen →</button>
<button class="stu-btn outline">Hinweis schicken</button>
</div>
</div>
<!-- Heute aktiv, pausiert -->
<div class="stu-row heute">
<div class="stu-avatar-block">
<span class="stu-status-icon" title="Heute aktiv, gerade pausiert">🟡</span>
<div class="stu-avatar">🦊</div>
</div>
<div class="stu-meta">
<div class="stu-name">Marie</div>
<div class="stu-sub">
<span class="module-chip">🍽️ Weltküche</span>
<span class="phase">Pizza erfolgreich abgeschlossen</span>
<span class="heartbeat stale">⏱ letzter Heartbeat vor 12 min</span>
<span class="stu-stars">★★★★★</span>
</div>
</div>
<div class="stu-actions">
<button class="stu-btn outline">Was hat sie gemacht?</button>
<button class="stu-btn outline">Tagesübersicht</button>
</div>
</div>
<!-- Heute aktiv, abgeschlossen -->
<div class="stu-row heute">
<div class="stu-avatar-block">
<span class="stu-status-icon" title="Heute aktiv, fertig">🟡</span>
<div class="stu-avatar">🐢</div>
</div>
<div class="stu-meta">
<div class="stu-name">Hannah</div>
<div class="stu-sub">
<span class="module-chip">🚌 Busfahrt</span>
<span class="phase">Tour 3 abgeschlossen · 12 Städte, Ø 47 km Abweichung</span>
<span class="heartbeat stale">⏱ letzter Heartbeat vor 1 h 12 min</span>
<span class="stu-stars">★★★★☆</span>
</div>
</div>
<div class="stu-actions">
<button class="stu-btn outline">Ergebnis öffnen</button>
<button class="stu-btn outline">Reflexion sehen</button>
</div>
</div>
<!-- Heute noch nichts -->
<div class="stu-row kalt">
<div class="stu-avatar-block">
<span class="stu-status-icon" title="Heute noch nicht aktiv"></span>
<div class="stu-avatar">🐧</div>
</div>
<div class="stu-meta">
<div class="stu-name">bubi</div>
<div class="stu-sub">
<span class="phase" style="color:var(--gray)">heute noch nicht eingeloggt</span>
<span class="heartbeat stale">letzter Login: gestern 14:30 · Heli M1 abgebrochen</span>
</div>
</div>
<div class="stu-actions">
<button class="stu-btn outline">Erinnerung senden</button>
<button class="stu-btn outline">Verlauf öffnen</button>
</div>
</div>
<!-- Heute noch nichts -->
<div class="stu-row kalt">
<div class="stu-avatar-block">
<span class="stu-status-icon" title="Heute noch nicht aktiv"></span>
<div class="stu-avatar">🐺</div>
</div>
<div class="stu-meta">
<div class="stu-name">Jonas</div>
<div class="stu-sub">
<span class="phase" style="color:var(--gray)">heute noch nicht eingeloggt</span>
<span class="heartbeat stale">letzter Login: vor 3 Tagen</span>
</div>
</div>
<div class="stu-actions">
<button class="stu-btn outline">Erinnerung senden</button>
<button class="stu-btn outline">Verlauf öffnen</button>
</div>
</div>
<!-- Nie aktiv -->
<div class="stu-row kalt">
<div class="stu-avatar-block">
<span class="stu-status-icon" title="Noch nie eingeloggt"></span>
<div class="stu-avatar" style="background:#e0dccd">?</div>
</div>
<div class="stu-meta">
<div class="stu-name" style="color:var(--gray)">Sabine</div>
<div class="stu-sub">
<span class="phase" style="color:var(--gray)">noch nie eingeloggt</span>
<span class="heartbeat stale">Konto angelegt vor 5 Tagen</span>
</div>
</div>
<div class="stu-actions">
<button class="stu-btn outline">Erstanleitung schicken</button>
</div>
</div>
</div>
</div>
<!-- ============== DETAIL-DRILL-DOWN ============== -->
<div class="card">
<div class="card-h">Ebene 4 · Detail-Drill-Down („Live anschauen →")</div>
<p style="font-size:.85rem;color:var(--muted);margin-bottom:.8rem">
Klick auf <b>„Live anschauen →"</b> öffnet einen Vollbild-Spectator-Modus, in dem die Lehrperson
die Sim aus Schüler-Perspektive mit-sieht (heute schon teilweise via <code>?view=teacher</code>).
Plus: rechts daneben ein <b>Daten-Panel</b> mit den Modul-spezifischen Live-Werten der API.
</p>
<div class="detail-sketch">
<span class="h"># Detail-View für Lenchen · 🌍 Klimawächter · Jahr 12/75</span>
<span class="k">Modul-Live-State</span> <span class="k">Tageshistorie heute</span>
───────────────── ─────────────────────
CO₂ <span class="ok">425 ppm</span> 08:42 → Lenchen startet Klima L1
ΔTemp +0,4 °C 08:46 → erste Maßnahme gekauft: Solaranlage
Budget <span class="warn">480 Mio</span> 09:01 → +10 Jahre, Budget 510 Mio
Bevölkerung <span class="ok">98 %</span> 09:08 → Sturmflut-Ereignis (akzeptiert)
Überflutet 4 % 09:14 → Deich gebaut Zone B
Status <span class="ok">stabil</span> 09:15 → JETZT (live)
<span class="k">Schnellaktionen</span>
- Tempo-Sperre [⏸ pausieren]
- Auftrag wechseln [Modul ▾]
- Hinweis senden [✉ Text]
<span class="k">Was Lenchen sieht (Spectator):</span>
╔═══════════════════════════════════════╗
║ [Live-Karte der Insel · 2D] ║
║ ║
║ ⚡ Wind, ☀ Solar, 🌊 Deich ║
║ ║
║ Status-Leiste mit Mini-Graphen ║
╚═══════════════════════════════════════╝
</div>
</div>
<!-- ============== IMPLEMENTATIONS-HINWEISE ============== -->
<div class="next">
<b>Implementations-Skizze v2</b> (technisch, falls Konzept passt):
<ul>
<li><b>Benchmark-Engine</b> als neue Plattform-Lib <code>App/php/lib/Benchmark.php</code> — pro Modul eine Formel laut Tabelle oben. Input: <code>assessments.results</code>-JSON pro Submission. Output: <code>{moduleId, modulePct, dimensions:[{key,label,score}]}</code>. Aggregat pro Schüler:in: max. 3 beste pro Modul, dann Mittelwert über alle Module mit Submissions.</li>
<li><b>Backend Live-API</b>: <code>/api/live?class_id=X</code> erweitern um:
<ul>
<li>Komplette Klassenliste (auch stille Schüler:innen)</li>
<li>Status pro Person (<code>aktiv|heute|kalt|nie</code>) + Tages-Summary</li>
<li><code>benchmarkPct</code> pro Schüler:in (über alle Apps) + <code>perModule</code>-Breakdown</li>
<li><code>topN</code> / <code>bottomN</code> als bequeme Ranking-Listen</li>
<li><code>weeklyByDay</code>: Klassen-Lernzeit pro Tag, gestapelt nach Modul</li>
<li><code>needsHelp</code>-Heuristik (Heli-Fails ≥10, Klima-Budget &lt; 0, Weltküche-Fehlklicks &gt; 15/Runde, &gt;10 min ohne Heartbeat während Sim offen)</li>
</ul>
</li>
<li><b>Modul-Range-Definition</b> als JSON-Schema in jeder Sim: <code>GGS_LIVE_RANGES = { co2:{min:280, max:600, bad:'high'}, budget:{min:0, max:1000, bad:'low'} }</code>. Frontend rendert dann automatisch die Range-Bars in den Mini-Stats. Spart das Hartkodieren pro Sim.</li>
<li><b>Frontend</b>: <code>renderLiveSummary</code> komplett ersetzen — 4 neue Render-Funktionen: <code>renderLiveStatus</code> (Tiles + Ranking + Klassen-Säulen), <code>renderLiveFilter</code>, <code>renderLiveStudentList</code>, <code>renderLiveDetail</code>.</li>
<li><b>Auto-Refresh</b>: alle 5 s, nur Daten-Diff, kein Re-Render des ganzen DOMs (DOM-Patches statt innerHTML).</li>
<li><b>„Eingreifen"-Aktion</b>: neue API <code>POST /api/live {action:'nudge', studentId, text}</code> — pusht Toast in laufende Schüler-Sim via Pause-Polling-Channel.</li>
<li><b>Aufwand-Schätzung neu</b>: 23 Tage. Benchmark-Engine 1 Tag · Backend-Erweiterung ½ Tag · Frontend 1 Tag · Range-Definitionen pro Sim ½ Tag.</li>
</ul>
<p style="margin-top:.6rem"><b>Erste Schritte konkret</b>:
(1) Benchmark.php-Formeln mit Thomas durchgehen und finalisieren.
(2) Range-Definitionen pro Sim als JSON-Schema spec'en (zentrale Stelle).
(3) Lokal renderLiveStatus prototypisch bauen, gegen Mock-Daten testen.
(4) Echtes Backend nachziehen wenn UI sitzt.
</p>
</div>
<p style="font-size:.75rem;color:var(--muted);margin-top:1.5rem;text-align:center">
Entwurf · liegt unter <code>.dontDeploy/entwurfswerkzeug/live-konzept.html</code> ·
Stand <b>2026-06-10</b> · GeoGraSim/Atlas
</p>
</div>
</body>
</html>