Files
mindflux/src/main/resources/static/css/devlabgame.css
T
AliceDarkest b88962da6f Dev Lab: server-autoritatives Entwicklerlabor mit 6 Mechaniken + 189 Aufgaben
Dev Lab bündelt mehrere Disziplinen (SQL, Java/Debugging, Git, HTML, CSS, Regex,
PHP, REST) in 11 Spielen mit zusammen 189 Aufgaben. Im Gegensatz zur ersten,
rein clientseitigen Skizze jetzt server-autoritativ, DB-gestützt und im Admin
pflegbar – mit echter Mechanik-Vielfalt statt überall Lückentext:
cloze (Lücke tippen), choice (Multiple Choice), order (Bausteine zusammensetzen),
spot (Bug anklicken), match (Paare zuordnen), regex (Muster schreiben mit
Live-Treffer-Vorschau).

Prüfung und Score ausschließlich serverseitig – die Lösungen verlassen nie das
Backend; Eingabe-Platzhalter sind neutrale Labels (Lösungs-Leak behoben).
Fehler-Mechanik mit Versuchen + Hinweis + Auflösung, kein Game-Over; Score über
die generische game_scores-Tabelle (Kennung devlab, deck=Spiel-Slug).

- Entities DevLabGame/DevLabTask (JSON-payload) + Flyway V8__devlab.sql
- DevLabService mit sechs Mechanik-Checkern; API /api/devlab/** (CSRF-ausgenommen,
  devlab in KNOWN_GAMES)
- Admin /admin/devlab (Spiele + Aufgaben pflegen); polymorphe Frontend-Engine
  devlabgame.js + DB-getriebener Hub devlab.js
- Inhalte aus devlab/content.json (idempotenter Seeder); ersetzt die erste
  clientseitige Dev-Lab-Skizze (devlab.js/devlabgame.js/-game.html/-game.css neu)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 16:32:03 +02:00

120 lines
11 KiB
CSS
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.
/* === Dev Lab – Spiel-Engine === polymorphe Mechaniken, Farben/Tokens zentral aus theme.css
(richtig = Blau, falsch = Rot, Akzent = Amber). Keine hartkodierten Farben. */
@keyframes dlgIn { 0% { opacity: 0; transform: translateY(14px); } 100% { opacity: 1; transform: translateY(0); } }
body.dlg-body { min-height: 100vh; display: flex; flex-direction: column; color: var(--text); }
.dlg-shell { flex: 1; width: 100%; max-width: 1100px; margin: 0 auto; display: flex; flex-direction: column; padding: 0.7rem 0.9rem 1.4rem; gap: 0.7rem; }
.dlg-header { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0.5rem 1.1rem; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--g-soft); }
.dlg-head-title { text-align: center; }
.dlg-head-title h1 { color: var(--accent); font-size: 1.25rem; text-shadow: 0 0 8px var(--glow-s); }
.dlg-header-tools { display: flex; align-items: center; gap: 0.7rem; }
.dlg-back, .dlg-logout { text-decoration: none; font-weight: bold; }
.dlg-back { color: var(--accent); } .dlg-logout { color: var(--danger); }
.dlg-bar { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.55rem; }
.dlg-bar-group { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; }
.dlg-stat { display: inline-flex; align-items: baseline; gap: 0.4rem; padding: 0.35rem 0.7rem; background: var(--surface-2); border: 1px solid var(--border); border-radius: 10px; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); white-space: nowrap; }
.dlg-stat b { font-size: 1.05rem; color: var(--accent); }
.dlg-stage { flex: 1; display: grid; grid-template-columns: 1fr 300px; gap: 0.8rem; align-items: start; }
.dlg-card { background: var(--surface); border: 1px solid var(--border-accent); border-radius: 16px; padding: 1.3rem 1.5rem 1.4rem; box-shadow: 0 0 24px var(--glow-w); animation: dlgIn 0.32s ease-out; min-width: 0; }
.dlg-card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.5rem; }
.dlg-points { color: var(--accent); font-weight: 800; }
.dlg-card h2 { color: var(--heading); font-size: 1.3rem; font-weight: 800; margin-bottom: 0.4rem; }
.dlg-narrative { color: var(--text); line-height: 1.55; margin-bottom: 0.5rem; }
.dlg-narrative[hidden], .dlg-instruction[hidden] { display: none; }
.dlg-instruction { color: var(--muted); font-size: 0.9rem; margin-bottom: 0.7rem; }
.dlg-playfield { margin: 0.4rem 0 0.8rem; }
.dlg-mini { color: var(--muted); font-size: 0.78rem; margin: 0.5rem 0 0.3rem; }
.dlg-mini.reveal { color: var(--secondary); font-family: monospace; }
/* Code + Lücken (cloze) */
.dlg-code { background: var(--surface-2); border: 1px solid var(--border); border-radius: 12px; padding: 1rem 1.1rem; overflow-x: auto; box-shadow: inset 0 0 22px var(--glow-w); }
.dlg-code, .dlg-code code { font-family: "JetBrains Mono", "Fira Code", "Consolas", monospace; font-size: 0.92rem; line-height: 2; white-space: pre; color: var(--text); }
.dlg-gap { font-family: inherit; font-size: inherit; color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); border: 1px solid var(--border-accent); border-radius: 5px; padding: 0.05rem 0.35rem; margin: 0 0.12rem; min-width: 3ch; }
.dlg-gap::placeholder { color: var(--muted); opacity: 0.7; }
.dlg-gap:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--glow-w); }
.dlg-gap.correct { color: var(--success); border-color: var(--success); background: color-mix(in srgb, var(--success) 16%, transparent); }
.dlg-gap.wrong { color: var(--danger); border-color: var(--danger); background: color-mix(in srgb, var(--danger) 16%, transparent); }
.dlg-gap.revealed { color: var(--secondary); border-color: var(--secondary); background: color-mix(in srgb, var(--secondary) 14%, transparent); }
/* Multiple Choice */
.dlg-question { color: var(--heading); font-weight: 600; margin-bottom: 0.6rem; }
.dlg-choices { display: grid; gap: 0.55rem; }
.dlg-choice { text-align: left; padding: 0.7rem 1rem; border: 1px solid var(--border-accent); border-radius: 10px; background: var(--surface-2); color: var(--text); font-size: 0.98rem; cursor: pointer; transition: border-color .18s, background .18s; }
.dlg-choice:hover:not(:disabled) { border-color: var(--accent); background: var(--surface); }
.dlg-choice.selected { border-color: var(--accent); box-shadow: 0 0 0 2px var(--glow-w); }
.dlg-choice.correct { border-color: var(--success); background: color-mix(in srgb, var(--success) 16%, transparent); color: var(--success); }
.dlg-choice.wrong { border-color: var(--danger); background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--danger); }
.dlg-choice:disabled { cursor: default; }
/* Tokens (order + spot) */
.dlg-token, .dlg-spot-token { font-family: "JetBrains Mono", "Consolas", monospace; font-size: 0.9rem; padding: 0.4rem 0.7rem; border: 1px solid var(--border-accent); border-radius: 8px; background: var(--surface-2); color: var(--text); cursor: pointer; transition: all .15s; }
.dlg-token:hover:not(:disabled), .dlg-spot-token:hover:not(:disabled) { border-color: var(--accent); transform: translateY(-1px); }
.dlg-order-answer { min-height: 2.6rem; display: flex; flex-wrap: wrap; gap: 0.5rem; padding: 0.6rem; border: 1px dashed var(--border-accent); border-radius: 10px; background: color-mix(in srgb, var(--accent) 5%, transparent); }
.dlg-order-answer:not(.filled)::before { content: attr(data-empty); color: var(--muted); font-size: 0.82rem; }
.dlg-order-bank { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.dlg-spot { display: flex; flex-wrap: wrap; gap: 0.45rem; padding: 0.8rem; background: var(--surface-2); border: 1px solid var(--border); border-radius: 12px; }
.dlg-spot-token.selected { border-color: var(--accent); box-shadow: 0 0 0 2px var(--glow-w); color: var(--accent); }
.dlg-spot-token.correct { border-color: var(--success); color: var(--success); background: color-mix(in srgb, var(--success) 14%, transparent); }
.dlg-spot-token.wrong { border-color: var(--danger); color: var(--danger); background: color-mix(in srgb, var(--danger) 14%, transparent); }
/* Zuordnen (match) */
.dlg-match { display: grid; grid-template-columns: 1fr 1fr; gap: 0.8rem; }
.dlg-match-col { display: flex; flex-direction: column; gap: 0.5rem; }
.dlg-match-item { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; padding: 0.6rem 0.8rem; border: 1px solid var(--border-accent); border-radius: 10px; background: var(--surface-2); color: var(--text); cursor: pointer; text-align: left; transition: all .15s; }
.dlg-match-item:hover:not(:disabled) { border-color: var(--accent); }
.dlg-match-item.active { border-color: var(--accent); box-shadow: 0 0 0 2px var(--glow-w); }
.dlg-match-item.connected { border-color: var(--secondary); background: color-mix(in srgb, var(--secondary) 12%, transparent); }
.dlg-match-badge { min-width: 1.4rem; height: 1.4rem; display: inline-flex; align-items: center; justify-content: center; border-radius: 50%; font-size: 0.72rem; font-weight: 800; color: var(--accent-ink); background: transparent; }
.dlg-match-item.connected .dlg-match-badge { background: var(--secondary); }
/* Regex */
.dlg-regex { display: flex; flex-direction: column; gap: 0.7rem; }
.dlg-regex-input { font-family: "JetBrains Mono", "Consolas", monospace; font-size: 1rem; padding: 0.6rem 0.8rem; border: 1px solid var(--border-accent); border-radius: 10px; background: var(--surface-2); color: var(--accent); }
.dlg-regex-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--glow-w); }
.dlg-regex-samples { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.dlg-sample { display: flex; flex-direction: column; gap: 0.15rem; padding: 0.4rem 0.7rem; border: 1px solid var(--border); border-radius: 9px; font-family: "JetBrains Mono", monospace; font-size: 0.85rem; background: var(--surface-2); }
.dlg-sample small { font-family: inherit; font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.dlg-sample.ok { border-color: var(--success); color: var(--success); }
.dlg-sample.bad { border-color: var(--danger); color: var(--danger); }
/* Feedback */
.dlg-feedback { min-height: 1.3rem; font-weight: 700; margin-bottom: 0.4rem; line-height: 1.5; }
.dlg-feedback.correct { color: var(--success); } .dlg-feedback.correct::before { content: "\2713 "; }
.dlg-feedback.wrong { color: var(--danger); } .dlg-feedback.wrong::before { content: "\2717 "; }
.dlg-feedback.revealed { color: var(--secondary); }
.dlg-success { color: var(--secondary); background: color-mix(in srgb, var(--secondary) 10%, transparent); border-left: 3px solid var(--secondary); border-radius: 6px; padding: 0.7rem 0.9rem; margin-bottom: 0.7rem; line-height: 1.5; }
.dlg-success[hidden] { display: none; }
.dlg-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.dlg-actions .mf-btn[hidden] { display: none; }
/* Seitenpanel */
.dlg-side h2 { color: var(--accent); font-size: 1rem; margin-bottom: 0.5rem; }
.dlg-description { color: var(--muted); font-size: 0.88rem; line-height: 1.5; margin-bottom: 0.9rem; }
.dlg-progress span { color: var(--muted); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; }
.dlg-progress .mf-bar { margin-top: 0.3rem; }
.dlg-best { color: var(--muted); font-size: 0.82rem; margin-top: 0.9rem; }
/* Ergebnis-Overlay */
.dlg-overlay { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; background: var(--bg-glow), rgba(0,0,0,.55); backdrop-filter: blur(4px); z-index: 1000; padding: 1rem; }
.dlg-overlay[hidden] { display: none; }
.dlg-result-card { background: var(--surface); border: 1px solid var(--border-accent); border-radius: 16px; padding: 1.6rem 1.8rem; width: min(440px, 94vw); text-align: center; box-shadow: 0 0 30px var(--glow-w); animation: dlgIn 0.4s ease-out; }
.dlg-result-card h2 { color: var(--accent); margin-bottom: 0.4rem; }
.dlg-result-stars { font-size: 2rem; color: var(--accent); letter-spacing: 0.2rem; margin-bottom: 0.5rem; text-shadow: 0 0 12px var(--glow-s); }
.dlg-result-score { font-size: 1.35rem; color: var(--text); margin-bottom: 0.4rem; } .dlg-result-score strong { color: var(--accent); }
.dlg-result-detail { color: var(--muted); margin-bottom: 0.5rem; }
.dlg-result-high { color: var(--accent); font-weight: 800; margin-bottom: 0.8rem; }
.dlg-result-high[hidden] { display: none; }
.dlg-result-actions { display: flex; flex-wrap: wrap; gap: 0.7rem; justify-content: center; margin-top: 1rem; }
@media (max-width: 820px) { .dlg-stage { grid-template-columns: 1fr; } }
@media (max-width: 560px) {
.dlg-head-title h1 { font-size: 1.05rem; }
.dlg-stat { font-size: 0.62rem; padding: 0.3rem 0.5rem; }
.dlg-code, .dlg-code code { font-size: 0.82rem; }
}