Style Guide v1.0.0: Indigo-Palette + lokale Web-Fonts

Komplette visuelle Umstellung nach dem generierten Style-Guide
(3d-lehrstun-de-v1.0.0). 3D-Druck-AG bekommt eine eigene Marke,
getrennt vom Teal der arduino.lehrstun.de-Schwester.

Farben: Teal #00979D -> Indigo #5B6EAE, warmes Off-White Surface
  #F0EEE9 statt Kuehlweiss, Lavendel-Akzent #9B8EC4.
Fonts: Raleway (Headings), Lato (Body), Inconsolata (Mono) — lokal
  gehostet in static/fonts/ (DSGVO-konform, kein Google-CDN),
  via @font-face + unicode-range (latin + latin-ext).
Form: Radius/Schatten/Spacing als Tokens (--radius-*, --shadow-*).

Technik:
  - base.html :root: neue --color-*/--font-*/--radius-* Tokens,
    alte Variablennamen (--primary etc.) als Aliase -> alle 33
    Templates ziehen sofort mit, kein Template-Rewrite noetig.
  - Semantische Banner-Tokens (--info/warn/success/error-bg+text+border)
    loesen ~130 Hardcoded-Pastelle ab (per sed gemappt).
  - Komponenten (Card, Button, Badge, Flash, Table, Code) auf Tokens.

Alle 13 Hauptseiten gegengeprueft (HTTP 200, keine Render-Fehler).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-04 12:52:14 +02:00
parent ae68da996f
commit 8a55e175a2
33 changed files with 349 additions and 110 deletions

View File

@@ -0,0 +1,70 @@
# Style Guide: 3d.lehrstun.de
Du arbeitest an einem Projekt mit folgendem Style Guide. **Verwende ausschließlich die unten definierten Design Tokens** für alle neuen oder geänderten Komponenten. Keine eigenen Farben, Schriften oder Abstände einführen.
## Projektkontext
- **Projekt:** 3d.lehrstun.de
- **Typ:** website
- **Zielgruppe:** Schülerinnen und Schüler
- **Sprache:** de-DE
## Tonalität
- **Soll wirken:** jugendlich, technisch, freundlich, modern
- **Soll NICHT wirken:** altmodisch, beliebig
## Do's
- Verwende abgerundete Ecken (border-radius: sm) für Karten und Buttons, um eine einladende, moderne Wirkung zu erzeugen
- Setze subtile Schatten ein, um Tiefe und Hierarchie zu schaffen, ohne die helle Cloud-Dancer-Palette zu überladen
- Nutze großzügige, komfortable Abstände zwischen Elementen, damit Inhalte für Schüler leicht scanbar und lesbar bleiben
- Kombiniere technische Akzentfarben (z. B. leuchtendes Cyan oder Electric Blue) mit der hellen Basispalette, um 3D-Themen jugendlich und modern zu inszenieren
## Don'ts
- Verwende keine harten, eckigen Container oder scharfe Drop-Shadows das wirkt altmodisch und bricht die freundliche Formensprache
- Nutze keine generischen Stock-Illustrationen oder Clip-Art das wirkt beliebig und verfehlt die technisch-moderne Markenpersönlichkeit
- Überhäufe Seiten nicht mit zu vielen Schriftgrößen oder Farben auf einmal das erzeugt visuelle Unruhe und widerspricht der comfortable Dichte
## Design Tokens (CSS Custom Properties)
```css
:root {
--color-primary: #5B6EAE;
--color-primary-hover: #4A5B96;
--color-secondary: #2C3E50;
--color-accent: #9B8EC4;
--color-surface: #F0EEE9;
--color-surface-muted: #E8E5DF;
--color-border: #D5D1CC;
--color-text: #2C3E50;
--color-text-muted: #6B7C8D;
--color-error: #C0392B;
--color-success: #27AE60;
--color-warning: #E67E22;
--font-heading: 'Raleway', system-ui, sans-serif;
--font-body: 'Lato', Georgia, serif;
--font-mono: 'Inconsolata', 'Courier New', monospace;
--radius-sm: 2px;
--radius-md: 4px;
--radius-lg: 8px;
--spacing-xs: 4px;
--spacing-sm: 8px;
--spacing-md: 16px;
--spacing-lg: 24px;
--spacing-xl: 40px;
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
--shadow-md: 0 2px 8px rgba(0,0,0,0.08);
--shadow-lg: 0 4px 16px rgba(0,0,0,0.1);
}
```
## Komponentenregeln
- **Buttons:** Radius `4px`, Padding `8px 16px`, Schatten `0 1px 2px rgba(0,0,0,0.05)`
- **Cards:** Radius `8px`, Border via `--color-border`, Schatten `0 2px 8px rgba(0,0,0,0.08)`
- **Inputs:** Radius `2px`, Border via `--color-border`
- **Icons:** Stil `outline`, Strichstärke `1.75px`, Line-Cap `round`
## Regel für neuen Code
Wenn du eine Komponente oder ein Stylesheet änderst: nutze `var(--color-…)`, `var(--font-…)`, `var(--spacing-…)` etc. Greife nie zu Hardcoded-Werten. Wenn dir ein Token fehlt, frage nach, bevor du eines erfindest.

View File

@@ -0,0 +1,78 @@
# Style Guide: 3d.lehrstun.de
> Version 1.0.0 | Revision 1 | 2026-06-04T09:57:23.143Z
## Projektinfo
- **Typ:** website
- **Zielgruppe:** Schülerinnen und Schüler
- **Sprache:** de-DE
## Designprinzipien
### Tonalität
- jugendlich
- technisch
- freundlich
- modern
### Anti-Tonalität
- altmodisch
- beliebig
### Do's
✓ Verwende abgerundete Ecken (border-radius: sm) für Karten und Buttons, um eine einladende, moderne Wirkung zu erzeugen
✓ Setze subtile Schatten ein, um Tiefe und Hierarchie zu schaffen, ohne die helle Cloud-Dancer-Palette zu überladen
✓ Nutze großzügige, komfortable Abstände zwischen Elementen, damit Inhalte für Schüler leicht scanbar und lesbar bleiben
✓ Kombiniere technische Akzentfarben (z. B. leuchtendes Cyan oder Electric Blue) mit der hellen Basispalette, um 3D-Themen jugendlich und modern zu inszenieren
### Don'ts
✗ Verwende keine harten, eckigen Container oder scharfe Drop-Shadows das wirkt altmodisch und bricht die freundliche Formensprache
✗ Nutze keine generischen Stock-Illustrationen oder Clip-Art das wirkt beliebig und verfehlt die technisch-moderne Markenpersönlichkeit
✗ Überhäufe Seiten nicht mit zu vielen Schriftgrößen oder Farben auf einmal das erzeugt visuelle Unruhe und widerspricht der comfortable Dichte
## Farbpalette
| Token | Wert |
|-------|------|
| Primary | `#5B6EAE` |
| Primary Hover | `#4A5B96` |
| Secondary | `#2C3E50` |
| Accent | `#9B8EC4` |
| Surface | `#F0EEE9` |
| Surface Muted | `#E8E5DF` |
| Border | `#D5D1CC` |
| Text | `#2C3E50` |
| Text Muted | `#6B7C8D` |
| Error | `#C0392B` |
| Success | `#27AE60` |
| Warning | `#E67E22` |
## Typografie
- **Überschriften:** Raleway
- **Fließtext:** Lato
- **Monospace:** Inconsolata
## Formensprache
- **Radius:** 2px / 4px / 8px
- **Schatten:** 0 1px 2px rgba(0,0,0,0.05) / 0 2px 8px rgba(0,0,0,0.08)
- **Spacing:** 4px / 8px / 16px / 24px / 40px
## Komponenten
### Button
- Radius: 4px
- Padding: 8px 16px
### Card
- Radius: 8px
- Border: 1px solid #D5D1CC
### Input
- Radius: 2px
- Border: 1px solid #D5D1CC
## Assets
- Icon-Stil: outline
- Strichstärke: 1.75
---
*Generiert am 2026-06-04T09:57:23.143Z*

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -11,7 +11,7 @@
</div> </div>
</div> </div>
<div class="card" style="background:#FEF9E7; border-left: 4px solid var(--warning);"> <div class="card" style="background:var(--warn-bg); border-left: 4px solid var(--warning);">
<strong>Hinweis:</strong> Live-Status via Bambu-Cloud-API kommt mit Etappe 5 (siehe <strong>Hinweis:</strong> Live-Status via Bambu-Cloud-API kommt mit Etappe 5 (siehe
<code>docs/offene-fragen.md</code> &mdash; Bambu-Account muss noch geklaert werden). <code>docs/offene-fragen.md</code> &mdash; Bambu-Account muss noch geklaert werden).
Bis dahin pflegst du den Status hier manuell. Bis dahin pflegst du den Status hier manuell.

View File

@@ -22,7 +22,7 @@
<img src="{{ url_for('api.projekt_cover', projekt_id=p.id) }}" alt="" <img src="{{ url_for('api.projekt_cover', projekt_id=p.id) }}" alt=""
style="width: 100%; height: 160px; object-fit: cover; border-radius: 6px;"> style="width: 100%; height: 160px; object-fit: cover; border-radius: 6px;">
{% else %} {% else %}
<div style="height: 160px; background: linear-gradient(135deg, #ECF0F1, #D5DBDB); border-radius: 6px; <div style="height: 160px; background: linear-gradient(135deg, var(--surface-muted), var(--surface-hover)); border-radius: 6px;
display: flex; align-items: center; justify-content: center; font-size: 2.5rem; color: var(--text-light);"> display: flex; align-items: center; justify-content: center; font-size: 2.5rem; color: var(--text-light);">
🎯 🎯
</div> </div>

View File

@@ -15,7 +15,7 @@
<img src="{{ url_for('api.projekt_cover', projekt_id=p.id) }}" alt="" <img src="{{ url_for('api.projekt_cover', projekt_id=p.id) }}" alt=""
style="width: 100%; max-height: 240px; object-fit: cover; border-radius: 6px;"> style="width: 100%; max-height: 240px; object-fit: cover; border-radius: 6px;">
{% else %} {% else %}
<div style="height: 200px; background: linear-gradient(135deg, #ECF0F1, #D5DBDB); border-radius: 6px; <div style="height: 200px; background: linear-gradient(135deg, var(--surface-muted), var(--surface-hover)); border-radius: 6px;
display: flex; align-items: center; justify-content: center; font-size: 3rem; color: var(--text-light);"> display: flex; align-items: center; justify-content: center; font-size: 3rem; color: var(--text-light);">
🎯 🎯
</div> </div>
@@ -46,7 +46,7 @@
<div class="card"> <div class="card">
<h2>Selbstbewertung</h2> <h2>Selbstbewertung</h2>
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0.6rem; margin-bottom: 1rem;"> <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0.6rem; margin-bottom: 1rem;">
<div style="text-align: center; padding: 0.6rem; background: #F4F6F7; border-radius: 6px;"> <div style="text-align: center; padding: 0.6rem; background: var(--surface-muted); border-radius: 6px;">
<div style="font-size: 0.75rem; color: var(--text-light);">Gesamt</div> <div style="font-size: 0.75rem; color: var(--text-light);">Gesamt</div>
<div style="font-size: 1.4rem; margin-top: 0.2rem;"> <div style="font-size: 1.4rem; margin-top: 0.2rem;">
{% if p.selbsteinschaetzung == 'zufrieden' %}🟢 {% if p.selbsteinschaetzung == 'zufrieden' %}🟢
@@ -55,7 +55,7 @@
</div> </div>
<div style="font-size: 0.85rem; margin-top: 0.2rem;">{{ p.selbsteinschaetzung or '—' }}</div> <div style="font-size: 0.85rem; margin-top: 0.2rem;">{{ p.selbsteinschaetzung or '—' }}</div>
</div> </div>
<div style="text-align: center; padding: 0.6rem; background: #F4F6F7; border-radius: 6px;"> <div style="text-align: center; padding: 0.6rem; background: var(--surface-muted); border-radius: 6px;">
<div style="font-size: 0.75rem; color: var(--text-light);">Planung</div> <div style="font-size: 0.75rem; color: var(--text-light);">Planung</div>
<div style="font-size: 1.4rem; margin-top: 0.2rem;"> <div style="font-size: 1.4rem; margin-top: 0.2rem;">
{% if p.selbsteinschaetzung_planung == 'gut' %}🟢 {% if p.selbsteinschaetzung_planung == 'gut' %}🟢
@@ -65,7 +65,7 @@
</div> </div>
<div style="font-size: 0.85rem; margin-top: 0.2rem;">{{ p.selbsteinschaetzung_planung or '—' }}</div> <div style="font-size: 0.85rem; margin-top: 0.2rem;">{{ p.selbsteinschaetzung_planung or '—' }}</div>
</div> </div>
<div style="text-align: center; padding: 0.6rem; background: #F4F6F7; border-radius: 6px;"> <div style="text-align: center; padding: 0.6rem; background: var(--surface-muted); border-radius: 6px;">
<div style="font-size: 0.75rem; color: var(--text-light);">Ausfuehrung</div> <div style="font-size: 0.75rem; color: var(--text-light);">Ausfuehrung</div>
<div style="font-size: 1.4rem; margin-top: 0.2rem;"> <div style="font-size: 1.4rem; margin-top: 0.2rem;">
{% if p.selbsteinschaetzung_ausfuehrung == 'gut' %}🟢 {% if p.selbsteinschaetzung_ausfuehrung == 'gut' %}🟢
@@ -96,7 +96,7 @@
<h2>Rueckfragen-Historie</h2> <h2>Rueckfragen-Historie</h2>
{% for r in rueckfragen %} {% for r in rueckfragen %}
<div style="border-left: 3px solid {% if r.status == 'offen' %}var(--warning){% else %}var(--success){% endif %}; <div style="border-left: 3px solid {% if r.status == 'offen' %}var(--warning){% else %}var(--success){% endif %};
padding: 0.5rem 0.8rem; margin-bottom: 0.5rem; background: #F4F6F7; border-radius: 4px;"> padding: 0.5rem 0.8rem; margin-bottom: 0.5rem; background: var(--surface-muted); border-radius: 4px;">
<div style="font-size: 0.85rem; color: var(--text-light); margin-bottom: 0.2rem;"> <div style="font-size: 0.85rem; color: var(--text-light); margin-bottom: 0.2rem;">
{{ r.erstellt_am[:16].replace('T', ' ') }}{% if r.status == 'erledigt' %} · ✓ erledigt{% endif %} {{ r.erstellt_am[:16].replace('T', ' ') }}{% if r.status == 'erledigt' %} · ✓ erledigt{% endif %}
</div> </div>

View File

@@ -38,7 +38,7 @@
<img src="{{ url_for('api.projekt_cover', projekt_id=p.id) }}" alt="" <img src="{{ url_for('api.projekt_cover', projekt_id=p.id) }}" alt=""
style="width: 100%; height: 140px; object-fit: cover; border-radius: 6px;"> style="width: 100%; height: 140px; object-fit: cover; border-radius: 6px;">
{% else %} {% else %}
<div style="height: 140px; background: linear-gradient(135deg, #ECF0F1, #D5DBDB); border-radius: 6px; <div style="height: 140px; background: linear-gradient(135deg, var(--surface-muted), var(--surface-hover)); border-radius: 6px;
display: flex; align-items: center; justify-content: center; font-size: 2rem; color: var(--text-light);"> display: flex; align-items: center; justify-content: center; font-size: 2rem; color: var(--text-light);">
🎯 🎯
</div> </div>

View File

@@ -8,12 +8,12 @@
</div> </div>
{% if not profile %} {% if not profile %}
<div class="card" style="background:#FADBD8; border-left: 4px solid var(--danger);"> <div class="card" style="background:var(--error-bg); border-left: 4px solid var(--danger);">
<strong>Keine aktiven SuS-Profile.</strong> <strong>Keine aktiven SuS-Profile.</strong>
<a href="{{ url_for('admin.profile_liste') }}">Erst ein Profil anlegen.</a> <a href="{{ url_for('admin.profile_liste') }}">Erst ein Profil anlegen.</a>
</div> </div>
{% elif not drucker_liste %} {% elif not drucker_liste %}
<div class="card" style="background:#FADBD8; border-left: 4px solid var(--danger);"> <div class="card" style="background:var(--error-bg); border-left: 4px solid var(--danger);">
<strong>Keine Drucker eingerichtet.</strong> <strong>Keine Drucker eingerichtet.</strong>
</div> </div>
{% else %} {% else %}
@@ -81,7 +81,7 @@
style="padding: 0.6rem; width: 100%; border: 1px solid var(--border); border-radius: 4px; font-size: 0.95rem;"> style="padding: 0.6rem; width: 100%; border: 1px solid var(--border); border-radius: 4px; font-size: 0.95rem;">
</div> </div>
<div style="background: #EBF5FB; padding: 0.6rem 0.8rem; border-radius: 4px; font-size: 0.85rem; color: var(--text);"> <div style="background: var(--info-bg); padding: 0.6rem 0.8rem; border-radius: 4px; font-size: 0.85rem; color: var(--text);">
<strong>Hinweis:</strong> Du kannst auch fuer SuS reservieren, die noch nicht freigeschaltet <strong>Hinweis:</strong> Du kannst auch fuer SuS reservieren, die noch nicht freigeschaltet
sind, und auch fuer gesperrte Drucker (du bekommst dann eine Warnung). sind, und auch fuer gesperrte Drucker (du bekommst dann eine Warnung).
</div> </div>

View File

@@ -21,7 +21,7 @@
</p> </p>
<div id="drop-zone" style="border: 3px dashed var(--border); border-radius: 12px; padding: 3rem; <div id="drop-zone" style="border: 3px dashed var(--border); border-radius: 12px; padding: 3rem;
text-align: center; cursor: pointer; transition: border-color 0.2s; background: #fafafa;"> text-align: center; cursor: pointer; transition: border-color 0.2s; background: var(--surface-soft);">
<p style="font-size: 1.2rem; color: var(--text-light);">Strg+V zum Einfuegen</p> <p style="font-size: 1.2rem; color: var(--text-light);">Strg+V zum Einfuegen</p>
<p style="font-size: 0.85rem; color: var(--text-light);">oder klicken um Datei auszuwaehlen</p> <p style="font-size: 0.85rem; color: var(--text-light);">oder klicken um Datei auszuwaehlen</p>
<input type="file" id="datei-input" accept="image/*" style="display: none;"> <input type="file" id="datei-input" accept="image/*" style="display: none;">
@@ -54,7 +54,7 @@
<div style="min-width: 200px; text-align: center;"> <div style="min-width: 200px; text-align: center;">
<h3>Vorschau</h3> <h3>Vorschau</h3>
<canvas id="vorschau-canvas" width="200" height="200" <canvas id="vorschau-canvas" width="200" height="200"
style="border: 1px solid var(--border); border-radius: 8px; background: #f0f0f0;"></canvas> style="border: 1px solid var(--border); border-radius: 8px; background: var(--surface-muted);"></canvas>
</div> </div>
</div> </div>
@@ -149,16 +149,16 @@ dateiInput.addEventListener('change', function() {
dropZone.addEventListener('dragover', function(e) { dropZone.addEventListener('dragover', function(e) {
e.preventDefault(); e.preventDefault();
this.style.borderColor = 'var(--primary)'; this.style.borderColor = 'var(--primary)';
this.style.background = '#EBF5FB'; this.style.background = 'var(--info-bg)';
}); });
dropZone.addEventListener('dragleave', function() { dropZone.addEventListener('dragleave', function() {
this.style.borderColor = 'var(--border)'; this.style.borderColor = 'var(--border)';
this.style.background = '#fafafa'; this.style.background = 'var(--surface-soft)';
}); });
dropZone.addEventListener('drop', function(e) { dropZone.addEventListener('drop', function(e) {
e.preventDefault(); e.preventDefault();
this.style.borderColor = 'var(--border)'; this.style.borderColor = 'var(--border)';
this.style.background = '#fafafa'; this.style.background = 'var(--surface-soft)';
if (e.dataTransfer.files[0] && e.dataTransfer.files[0].type.indexOf('image') >= 0) { if (e.dataTransfer.files[0] && e.dataTransfer.files[0].type.indexOf('image') >= 0) {
var reader = new FileReader(); var reader = new FileReader();
reader.onload = function(ev) { bildLaden(ev.target.result); }; reader.onload = function(ev) { bildLaden(ev.target.result); };

View File

@@ -20,7 +20,7 @@
<img src="{{ url_for('static', filename='img/software/' ~ karte.bild_pfad) }}" <img src="{{ url_for('static', filename='img/software/' ~ karte.bild_pfad) }}"
style="max-width: 200px; max-height: 200px; border-radius: 8px; border: 1px solid var(--border); background: #fff;"> style="max-width: 200px; max-height: 200px; border-radius: 8px; border: 1px solid var(--border); background: #fff;">
{% else %} {% else %}
<div style="width:200px; height:200px; background:#ECF0F1; border-radius: 8px; display:flex; align-items:center; justify-content:center; font-size:3rem; color: var(--text-light);"> <div style="width:200px; height:200px; background:var(--surface-muted); border-radius: 8px; display:flex; align-items:center; justify-content:center; font-size:3rem; color: var(--text-light);">
{%- if karte.kategorie == 'app' -%}📱 {%- if karte.kategorie == 'app' -%}📱
{%- elif karte.kategorie == 'generator' -%}🧩 {%- elif karte.kategorie == 'generator' -%}🧩
{%- else -%}🖥️ {%- else -%}🖥️
@@ -54,7 +54,7 @@
<div> <div>
<label style="display:block; font-size: 0.85rem; color: var(--text-light);">Slug (unveraenderbar)</label> <label style="display:block; font-size: 0.85rem; color: var(--text-light);">Slug (unveraenderbar)</label>
<input type="text" value="{{ karte.slug }}" disabled <input type="text" value="{{ karte.slug }}" disabled
style="padding: 0.5rem; width: 100%; border: 1px solid var(--border); border-radius: 4px; background: #f5f5f5;"> style="padding: 0.5rem; width: 100%; border: 1px solid var(--border); border-radius: 4px; background: var(--surface-soft);">
</div> </div>
<div> <div>
<label style="display:block; font-size: 0.85rem; color: var(--text-light);">Titel *</label> <label style="display:block; font-size: 0.85rem; color: var(--text-light);">Titel *</label>

View File

@@ -5,30 +5,120 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}3D-Druck-AG{% endblock %}</title> <title>{% block title %}3D-Druck-AG{% endblock %}</title>
<style> <style>
/* ===========================================================================
Web-Fonts (lokal gehostet, DSGVO-konform — kein Google-CDN).
Raleway = Headings, Lato = Body, Inconsolata = Mono.
Raleway ist ein Variable Font (deckt 400-700 ab).
=========================================================================== */
@font-face {
font-family: 'Raleway'; font-style: normal; font-weight: 400 700; font-display: swap;
src: url('/static/fonts/raleway-400-latin.woff2') format('woff2');
unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
font-family: 'Raleway'; font-style: normal; font-weight: 400 700; font-display: swap;
src: url('/static/fonts/raleway-400-latin-ext.woff2') format('woff2');
unicode-range: U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
font-family: 'Lato'; font-style: normal; font-weight: 400; font-display: swap;
src: url('/static/fonts/lato-400-latin.woff2') format('woff2');
unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
font-family: 'Lato'; font-style: normal; font-weight: 400; font-display: swap;
src: url('/static/fonts/lato-400-latin-ext.woff2') format('woff2');
unicode-range: U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
font-family: 'Lato'; font-style: normal; font-weight: 700; font-display: swap;
src: url('/static/fonts/lato-700-latin.woff2') format('woff2');
unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
font-family: 'Lato'; font-style: normal; font-weight: 700; font-display: swap;
src: url('/static/fonts/lato-700-latin-ext.woff2') format('woff2');
unicode-range: U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
font-family: 'Inconsolata'; font-style: normal; font-weight: 400; font-display: swap;
src: url('/static/fonts/inconsolata-400-latin.woff2') format('woff2');
unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
font-family: 'Inconsolata'; font-style: normal; font-weight: 400; font-display: swap;
src: url('/static/fonts/inconsolata-400-latin-ext.woff2') format('woff2');
unicode-range: U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
:root { :root {
--primary: #00979D; /* Teal — identisch zum Arduino-Kurs fuer einheitliches Wirken */ /* === Style Guide v1.0.0 (2026-06-04): Indigo-Palette "Cloud Dancer" === */
--primary-dark: #007A80; --color-primary: #5B6EAE;
--secondary: #E67E22; --color-primary-hover: #4A5B96;
--bg: #F8F9FA; --color-secondary: #2C3E50;
--color-accent: #9B8EC4;
--color-surface: #F0EEE9;
--color-surface-muted: #E8E5DF;
--color-border: #D5D1CC;
--color-text: #2C3E50;
--color-text-muted: #6B7C8D;
--color-error: #C0392B;
--color-success: #27AE60;
--color-warning: #E67E22;
--font-heading: 'Raleway', system-ui, sans-serif;
--font-body: 'Lato', system-ui, sans-serif;
--font-mono: 'Inconsolata', 'Consolas', monospace;
--radius-sm: 2px;
--radius-md: 4px;
--radius-lg: 8px;
--spacing-xs: 4px;
--spacing-sm: 8px;
--spacing-md: 16px;
--spacing-lg: 24px;
--spacing-xl: 40px;
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
--shadow-md: 0 2px 8px rgba(0,0,0,0.08);
--shadow-lg: 0 4px 16px rgba(0,0,0,0.1);
/* === Alte Variablennamen als Aliase — alle 33 Templates ziehen sofort mit === */
--primary: var(--color-primary);
--primary-dark: var(--color-primary-hover);
--secondary: var(--color-accent);
--bg: var(--color-surface);
--card-bg: #FFFFFF; --card-bg: #FFFFFF;
--text: #2C3E50; --text: var(--color-text);
--text-light: #7F8C8D; --text-light: var(--color-text-muted);
--border: #DEE2E6; --border: var(--color-border);
--code-bg: #2D2D2D; --code-bg: #2C3E50;
--success: #27AE60; --success: var(--color-success);
--warning: #F39C12; --warning: var(--color-warning);
--danger: #E74C3C; --danger: var(--color-error);
/* === Semantische Banner-/Status-Toene (loesen Hardcoded-Pastelle ab) === */
--info-bg: #ECEEF7; --info-border: #C8CEE8; --info-text: #41508A;
--warn-bg: #FBF2E2; --warn-border: #F0DBBC; --warn-text: #8A5A12;
--success-bg: #E5F4EB; --success-border: #B6E0C4; --success-text: #1E8449;
--error-bg: #F8E5E2; --error-border: #EFC4BD; --error-text: #A5352A;
--surface-soft: #FAF9F6; /* sehr helles Off-White (war #fafafa) */
--surface-muted: var(--color-surface-muted);
--surface-hover: #DDD9D2;
} }
* { box-sizing: border-box; margin: 0; padding: 0; } * { box-sizing: border-box; margin: 0; padding: 0; }
body { body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; font-family: var(--font-body);
background: var(--bg); background: var(--bg);
color: var(--text); color: var(--text);
line-height: 1.6; line-height: 1.6;
} }
h1, h2, h3, h4, nav .brand { font-family: var(--font-heading); }
/* Navigation */ /* Navigation */
nav { nav {
background: var(--primary); background: var(--primary);
@@ -81,11 +171,11 @@
/* Karten */ /* Karten */
.card { .card {
background: var(--card-bg); background: var(--card-bg);
border-radius: 8px; border-radius: var(--radius-lg);
padding: 1.5rem; padding: 1.5rem;
margin-bottom: 1rem; margin-bottom: 1rem;
border: 1px solid var(--border); border: 1px solid var(--border);
box-shadow: 0 1px 3px rgba(0,0,0,0.08); box-shadow: var(--shadow-md);
} }
.card h2, .card h3 { .card h2, .card h3 {
@@ -109,55 +199,56 @@
font-weight: 600; font-weight: 600;
text-transform: uppercase; text-transform: uppercase;
} }
.badge-pflicht { background: #FDEBD0; color: #BA4A00; } .badge-pflicht { background: var(--warn-bg); color: var(--warn-text); }
.badge-frei { background: #D5F5E3; color: #1E8449; } .badge-frei { background: var(--success-bg); color: var(--success-text); }
.badge-anfaenger { background: #D5F5E3; color: #1E8449; } .badge-anfaenger { background: var(--success-bg); color: var(--success-text); }
.badge-mittel { background: #FEF9E7; color: #B7950B; } .badge-mittel { background: var(--warn-bg); color: var(--warn-text); }
.badge-fortgeschritten { background: #FADBD8; color: #943126; } .badge-fortgeschritten { background: var(--error-bg); color: var(--error-text); }
/* Buttons */ /* Buttons */
.btn { .btn {
display: inline-block; display: inline-block;
padding: 0.5rem 1.2rem; padding: 0.5rem 1.2rem;
border-radius: 6px; border-radius: var(--radius-md);
text-decoration: none; text-decoration: none;
font-size: 0.9rem; font-size: 0.9rem;
font-weight: 500; font-weight: 600;
border: none; border: none;
cursor: pointer; cursor: pointer;
transition: background 0.2s; transition: background 0.2s;
box-shadow: var(--shadow-sm);
} }
.btn-primary { background: var(--primary); color: white; } .btn-primary { background: var(--primary); color: white; }
.btn-primary:hover { background: var(--primary-dark); } .btn-primary:hover { background: var(--primary-dark); }
.btn-secondary { background: #ECF0F1; color: var(--text); } .btn-secondary { background: var(--surface-muted); color: var(--text); }
.btn-secondary:hover { background: #D5DBDB; } .btn-secondary:hover { background: var(--surface-hover); }
/* Tabellen */ /* Tabellen */
table { width: 100%; border-collapse: collapse; margin: 1rem 0; } table { width: 100%; border-collapse: collapse; margin: 1rem 0; }
th, td { padding: 0.6rem 0.8rem; text-align: left; border-bottom: 1px solid var(--border); } th, td { padding: 0.6rem 0.8rem; text-align: left; border-bottom: 1px solid var(--border); }
th { background: #F2F3F4; font-weight: 600; font-size: 0.85rem; } th { background: var(--surface-muted); font-weight: 600; font-size: 0.85rem; }
/* Code */ /* Code */
pre { pre {
background: var(--code-bg); background: var(--code-bg);
color: #F8F8F2; color: #F0EEE9;
padding: 1.2rem; padding: 1.2rem;
border-radius: 8px; border-radius: var(--radius-lg);
overflow-x: auto; overflow-x: auto;
font-size: 0.85rem; font-size: 0.85rem;
line-height: 1.5; line-height: 1.5;
margin: 0.5rem 0; margin: 0.5rem 0;
} }
code { font-family: 'Fira Code', 'Consolas', 'Monaco', monospace; } code { font-family: var(--font-mono); }
/* Flash Messages */ /* Flash Messages */
.flash { .flash {
padding: 0.8rem 1.2rem; padding: 0.8rem 1.2rem;
border-radius: 6px; border-radius: var(--radius-md);
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.flash-success { background: #D5F5E3; color: #1E8449; border: 1px solid #A9DFBF; } .flash-success { background: var(--success-bg); color: var(--success-text); border: 1px solid var(--success-border); }
.flash-error { background: #FADBD8; color: #943126; border: 1px solid #F5B7B1; } .flash-error { background: var(--error-bg); color: var(--error-text); border: 1px solid var(--error-border); }
h1 { font-size: 1.6rem; margin-bottom: 1rem; } h1 { font-size: 1.6rem; margin-bottom: 1rem; }
h2 { font-size: 1.3rem; } h2 { font-size: 1.3rem; }

View File

@@ -13,8 +13,8 @@
{# ====== BANNER: Lehrer-Notizen (V5-Quick-Action) ====== #} {# ====== BANNER: Lehrer-Notizen (V5-Quick-Action) ====== #}
{% for n in status.notizen %} {% for n in status.notizen %}
<div class="card" style="background: #FEF9E7; border-left: 5px solid var(--warning); margin-bottom: 0.5rem;"> <div class="card" style="background: var(--warn-bg); border-left: 5px solid var(--warning); margin-bottom: 0.5rem;">
<p style="margin: 0; color: #B7950B;"> <p style="margin: 0; color: var(--warn-text);">
<strong>📌 Lehrer-Notiz:</strong> {{ n.text }} <strong>📌 Lehrer-Notiz:</strong> {{ n.text }}
</p> </p>
<form method="post" action="{{ url_for('profil.notiz_gelesen', notiz_id=n.id) }}" style="margin-top: 0.5rem;"> <form method="post" action="{{ url_for('profil.notiz_gelesen', notiz_id=n.id) }}" style="margin-top: 0.5rem;">
@@ -25,8 +25,8 @@
{# ====== BANNER: Offene Rueckfragen zu eigenen Projekten (V6) ====== #} {# ====== BANNER: Offene Rueckfragen zu eigenen Projekten (V6) ====== #}
{% for r in status.rueckfragen %} {% for r in status.rueckfragen %}
<div class="card" style="background: #FEF9E7; border-left: 5px solid var(--warning); margin-bottom: 0.5rem;"> <div class="card" style="background: var(--warn-bg); border-left: 5px solid var(--warning); margin-bottom: 0.5rem;">
<p style="margin: 0; color: #B7950B;"> <p style="margin: 0; color: var(--warn-text);">
<strong>❓ Rueckfrage zu „{{ r.projekt_titel }}":</strong> {{ r.text }} <strong>❓ Rueckfrage zu „{{ r.projekt_titel }}":</strong> {{ r.text }}
</p> </p>
<p style="margin-top: 0.5rem; font-size: 0.85rem; color: var(--text-light);"> <p style="margin-top: 0.5rem; font-size: 0.85rem; color: var(--text-light);">
@@ -37,7 +37,7 @@
{# ====== BANNER: Eingegangene Paarungs-Anfragen ====== #} {# ====== BANNER: Eingegangene Paarungs-Anfragen ====== #}
{% for a in status.offene_anfragen %} {% for a in status.offene_anfragen %}
<div class="card" style="background: #EBF5FB; border-left: 5px solid var(--primary); margin-bottom: 0.5rem;"> <div class="card" style="background: var(--info-bg); border-left: 5px solid var(--primary); margin-bottom: 0.5rem;">
<p style="margin: 0;"> <p style="margin: 0;">
<strong>{{ tier_emoji(a.von_tier) }} {{ a.von_vorname }}</strong> moechte mit dir <strong>{{ tier_emoji(a.von_tier) }} {{ a.von_vorname }}</strong> moechte mit dir
zusammenarbeiten. Magst du? zusammenarbeiten. Magst du?
@@ -117,7 +117,7 @@
</form> </form>
</div> </div>
{% else %} {% else %}
<div class="card" style="background: #EAFBF1; border-left: 4px solid var(--success); display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap;"> <div class="card" style="background: var(--success-bg); border-left: 4px solid var(--success); display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap;">
<p style="margin: 0; font-size: 0.9rem;"> <p style="margin: 0; font-size: 0.9rem;">
<strong>Heute eingecheckt:</strong> <strong>Heute eingecheckt:</strong>
{% if status.check_in_heute.modus == 'weiter_wie_bisher' %}Arbeite weiter {% if status.check_in_heute.modus == 'weiter_wie_bisher' %}Arbeite weiter
@@ -151,7 +151,7 @@
<img src="{{ url_for('api.projekt_cover', projekt_id=status.projekt.aktiv.id) }}" alt="" <img src="{{ url_for('api.projekt_cover', projekt_id=status.projekt.aktiv.id) }}" alt=""
style="width: 120px; height: 120px; object-fit: cover; border-radius: 8px;"> style="width: 120px; height: 120px; object-fit: cover; border-radius: 8px;">
{% else %} {% else %}
<div style="width: 120px; height: 120px; background: linear-gradient(135deg, #ECF0F1, #D5DBDB); <div style="width: 120px; height: 120px; background: linear-gradient(135deg, var(--surface-muted), var(--surface-hover));
border-radius: 8px; display: flex; align-items: center; justify-content: center; border-radius: 8px; display: flex; align-items: center; justify-content: center;
font-size: 2.5rem; color: var(--text-light);">🎯</div> font-size: 2.5rem; color: var(--text-light);">🎯</div>
{% endif %} {% endif %}
@@ -173,7 +173,7 @@
</div> </div>
{% elif status.projekt.letztes and status.projekt.letztes.freigabe_status == 'wartet_auf_freigabe' %} {% elif status.projekt.letztes and status.projekt.letztes.freigabe_status == 'wartet_auf_freigabe' %}
<div style="background: #FEF9E7; padding: 0.8rem; border-radius: 6px; border-left: 4px solid var(--warning);"> <div style="background: var(--warn-bg); padding: 0.8rem; border-radius: 6px; border-left: 4px solid var(--warning);">
<strong>⏳ Wartet auf Freigabe:</strong> <strong>⏳ Wartet auf Freigabe:</strong>
<a href="{{ url_for('profil.projekt_detail', projekt_id=status.projekt.letztes.id) }}">{{ status.projekt.letztes.titel }}</a> <a href="{{ url_for('profil.projekt_detail', projekt_id=status.projekt.letztes.id) }}">{{ status.projekt.letztes.titel }}</a>
<div style="font-size: 0.85rem; margin-top: 0.3rem; color: var(--text-light);"> <div style="font-size: 0.85rem; margin-top: 0.3rem; color: var(--text-light);">
@@ -182,7 +182,7 @@
</div> </div>
{% elif status.projekt.letztes and status.projekt.letztes.freigabe_status == 'rueckfrage' %} {% elif status.projekt.letztes and status.projekt.letztes.freigabe_status == 'rueckfrage' %}
<div style="background: #FADBD8; padding: 0.8rem; border-radius: 6px; border-left: 4px solid var(--danger);"> <div style="background: var(--error-bg); padding: 0.8rem; border-radius: 6px; border-left: 4px solid var(--danger);">
<strong>❓ Rueckfrage offen zu:</strong> <strong>❓ Rueckfrage offen zu:</strong>
<a href="{{ url_for('profil.projekt_detail', projekt_id=status.projekt.letztes.id) }}">{{ status.projekt.letztes.titel }}</a> <a href="{{ url_for('profil.projekt_detail', projekt_id=status.projekt.letztes.id) }}">{{ status.projekt.letztes.titel }}</a>
<div style="font-size: 0.85rem; margin-top: 0.3rem;"> <div style="font-size: 0.85rem; margin-top: 0.3rem;">
@@ -197,7 +197,7 @@
{% if status.projekt.darf_neues %} {% if status.projekt.darf_neues %}
<a href="{{ url_for('profil.projekt_neu') }}" class="btn btn-primary">+ Neues Projekt anfangen</a> <a href="{{ url_for('profil.projekt_neu') }}" class="btn btn-primary">+ Neues Projekt anfangen</a>
{% else %} {% else %}
<div style="background: #FEF9E7; padding: 0.6rem 0.8rem; border-radius: 6px; font-size: 0.9rem;"> <div style="background: var(--warn-bg); padding: 0.6rem 0.8rem; border-radius: 6px; font-size: 0.9rem;">
{{ status.projekt.sperr_grund }} {{ status.projekt.sperr_grund }}
</div> </div>
{% endif %} {% endif %}
@@ -324,17 +324,17 @@
padding: 0.5rem 0.7rem; border-radius: 6px; cursor: pointer; padding: 0.5rem 0.7rem; border-radius: 6px; cursor: pointer;
transition: background 0.15s; transition: background 0.15s;
} }
.ci-option:hover { background: #F2F3F4; } .ci-option:hover { background: var(--surface-muted); }
.ci-option input[type=radio] { margin: 0; } .ci-option input[type=radio] { margin: 0; }
.onboarding-liste { display: flex; flex-direction: column; gap: 0.5rem; } .onboarding-liste { display: flex; flex-direction: column; gap: 0.5rem; }
.onb-zeile { .onb-zeile {
display: flex; gap: 0.7rem; align-items: center; display: flex; gap: 0.7rem; align-items: center;
padding: 0.5rem 0.7rem; border-radius: 6px; padding: 0.5rem 0.7rem; border-radius: 6px;
background: #F2F3F4; background: var(--surface-muted);
} }
.onb-zeile.onb-fertig { background: #EAFBF1; opacity: 0.8; } .onb-zeile.onb-fertig { background: var(--success-bg); opacity: 0.8; }
.onb-zeile.onb-aktuell { background: #EBF5FB; border-left: 4px solid var(--primary); } .onb-zeile.onb-aktuell { background: var(--info-bg); border-left: 4px solid var(--primary); }
.onb-icon { font-size: 1.2rem; } .onb-icon { font-size: 1.2rem; }
.onb-titel { flex: 1; } .onb-titel { flex: 1; }
.onb-aktion { display: flex; gap: 0.3rem; } .onb-aktion { display: flex; gap: 0.3rem; }

View File

@@ -9,7 +9,7 @@
<a href="{{ url_for('profil.logout') }}" class="btn btn-secondary">Abmelden</a> <a href="{{ url_for('profil.logout') }}" class="btn btn-secondary">Abmelden</a>
</div> </div>
<div class="card" style="background: #FEF9E7; border-color: #F5C842;"> <div class="card" style="background: var(--warn-bg); border-color: #F5C842;">
<h3>Cockpit-Stub &mdash; Etappe 1</h3> <h3>Cockpit-Stub &mdash; Etappe 1</h3>
<p>Hier kommt in Etappe 2 das progressive Cockpit (V1):</p> <p>Hier kommt in Etappe 2 das progressive Cockpit (V1):</p>
<ul style="margin-top: 0.5rem; padding-left: 1.5rem;"> <ul style="margin-top: 0.5rem; padding-left: 1.5rem;">

View File

@@ -16,7 +16,7 @@
font-size: 0.85rem; color: var(--text-light); margin-top: 0.2rem; font-size: 0.85rem; color: var(--text-light); margin-top: 0.2rem;
} }
.druckerkachel-gross .sperre-banner { .druckerkachel-gross .sperre-banner {
background: #FADBD8; color: #943126; border: 1px solid #F5B7B1; background: var(--error-bg); color: var(--error-text); border: 1px solid var(--error-border);
border-radius: 6px; padding: 0.6rem 0.8rem; font-size: 0.9rem; border-radius: 6px; padding: 0.6rem 0.8rem; font-size: 0.9rem;
} }
.druckerkachel-gross .api-hinweis { .druckerkachel-gross .api-hinweis {
@@ -39,7 +39,7 @@
</p> </p>
{% if not darf_reservieren %} {% if not darf_reservieren %}
<div class="card" style="background:#FEF9E7; border-left: 4px solid var(--warning);"> <div class="card" style="background:var(--warn-bg); border-left: 4px solid var(--warning);">
<strong>Reservierung noch nicht freigeschaltet.</strong> <strong>Reservierung noch nicht freigeschaltet.</strong>
Du kannst die Drucker bisher nur ansehen. Lass dich beim Lehrer freischalten, Du kannst die Drucker bisher nur ansehen. Lass dich beim Lehrer freischalten,
dann kannst du selbst Slots reservieren. dann kannst du selbst Slots reservieren.
@@ -48,7 +48,7 @@
{% set gesperrte = drucker_liste | selectattr('freigegeben', 'equalto', 0) | list %} {% set gesperrte = drucker_liste | selectattr('freigegeben', 'equalto', 0) | list %}
{% if gesperrte %} {% if gesperrte %}
<div class="card" style="background:#FADBD8; border-left: 4px solid var(--danger);"> <div class="card" style="background:var(--error-bg); border-left: 4px solid var(--danger);">
<strong>⚠ {{ gesperrte|length }} Drucker derzeit gesperrt:</strong> <strong>⚠ {{ gesperrte|length }} Drucker derzeit gesperrt:</strong>
{{ gesperrte | map(attribute='name') | join(', ') }} {{ gesperrte | map(attribute='name') | join(', ') }}
— Details auf den jeweiligen Kacheln. — Details auf den jeweiligen Kacheln.
@@ -111,7 +111,7 @@
{% endif %} {% endif %}
{# Belegung: aktuell + naechste 3 Slots #} {# Belegung: aktuell + naechste 3 Slots #}
<div style="background:#F4F6F7; border-radius: 6px; padding: 0.6rem 0.8rem; font-size: 0.85rem;"> <div style="background:var(--surface-muted); border-radius: 6px; padding: 0.6rem 0.8rem; font-size: 0.85rem;">
{% if d.belegung %} {% if d.belegung %}
<div><strong>🔖 Jetzt belegt:</strong> <div><strong>🔖 Jetzt belegt:</strong>
{{ tier_emoji(d.belegung.tier or '') }} {{ d.belegung.vorname or '—' }} {{ tier_emoji(d.belegung.tier or '') }} {{ d.belegung.vorname or '—' }}

View File

@@ -43,7 +43,7 @@
</div> </div>
<div class="card" style="max-width: 800px; margin: 2rem auto 0; background: #FEF9E7; border-color: #F5C842;"> <div class="card" style="max-width: 800px; margin: 2rem auto 0; background: var(--warn-bg); border-color: #F5C842;">
<h3 style="margin-bottom: 0.5rem;">Hinweis</h3> <h3 style="margin-bottom: 0.5rem;">Hinweis</h3>
<p style="margin: 0;"> <p style="margin: 0;">
Diese Seite ist im Aufbau. Stand: 2026-05-23, Skelett. Inhalte werden in Diese Seite ist im Aufbau. Stand: 2026-05-23, Skelett. Inhalte werden in

View File

@@ -30,7 +30,7 @@
{# Wenn eingeloggt: Status-Buttons zum Selbst-Zertifizieren #} {# Wenn eingeloggt: Status-Buttons zum Selbst-Zertifizieren #}
{% if session.profil_id %} {% if session.profil_id %}
<div class="card" style="background: #EBF5FB; border-left: 4px solid var(--primary);"> <div class="card" style="background: var(--info-bg); border-left: 4px solid var(--primary);">
<p style="margin: 0;"><strong>Status setzen</strong> (du entscheidest selbst, wann du fertig bist):</p> <p style="margin: 0;"><strong>Status setzen</strong> (du entscheidest selbst, wann du fertig bist):</p>
<div style="display: flex; gap: 0.5rem; margin-top: 0.5rem; flex-wrap: wrap;"> <div style="display: flex; gap: 0.5rem; margin-top: 0.5rem; flex-wrap: wrap;">
{% for opt, label in [('offen', '⚪ noch nicht angefangen'), ('laeuft', '🟡 läuft'), ('fertig', '✅ fertig')] %} {% for opt, label in [('offen', '⚪ noch nicht angefangen'), ('laeuft', '🟡 läuft'), ('fertig', '✅ fertig')] %}

View File

@@ -49,7 +49,7 @@
} }
.profil-power { .profil-power {
border-color: var(--primary); border-color: var(--primary);
background: linear-gradient(180deg, #fff, #EBF5FB); background: linear-gradient(180deg, #fff, var(--info-bg));
} }
</style> </style>
{% endblock %} {% endblock %}

View File

@@ -8,7 +8,7 @@
</div> </div>
{% if not drucker_liste %} {% if not drucker_liste %}
<div class="card" style="background:#FADBD8; border-left: 4px solid var(--danger);"> <div class="card" style="background:var(--error-bg); border-left: 4px solid var(--danger);">
<strong>Kein Drucker frei.</strong> Alle Drucker sind derzeit gesperrt (Wartung / Reparatur). <strong>Kein Drucker frei.</strong> Alle Drucker sind derzeit gesperrt (Wartung / Reparatur).
Frag den Lehrer, wann wieder reserviert werden kann. Frag den Lehrer, wann wieder reserviert werden kann.
</div> </div>
@@ -62,7 +62,7 @@
style="padding: 0.6rem; width: 100%; border: 1px solid var(--border); border-radius: 4px; font-size: 0.95rem;"> style="padding: 0.6rem; width: 100%; border: 1px solid var(--border); border-radius: 4px; font-size: 0.95rem;">
</div> </div>
<div style="background: #EBF5FB; padding: 0.6rem 0.8rem; border-radius: 4px; font-size: 0.85rem; color: var(--text);"> <div style="background: var(--info-bg); padding: 0.6rem 0.8rem; border-radius: 4px; font-size: 0.85rem; color: var(--text);">
<strong>Regeln:</strong> Mindest-Dauer 15 Minuten, Maximum 24 Stunden. <strong>Regeln:</strong> Mindest-Dauer 15 Minuten, Maximum 24 Stunden.
Achte darauf, dass dein Druck in deinem Slot fertig wird — sonst kann der naechste SuS nicht starten. Achte darauf, dass dein Druck in deinem Slot fertig wird — sonst kann der naechste SuS nicht starten.
</div> </div>

View File

@@ -13,7 +13,7 @@
</div> </div>
{% if not darf_reservieren %} {% if not darf_reservieren %}
<div class="card" style="background:#FEF9E7; border-left: 4px solid var(--warning);"> <div class="card" style="background:var(--warn-bg); border-left: 4px solid var(--warning);">
<strong>Reservierung noch nicht freigeschaltet.</strong> <strong>Reservierung noch nicht freigeschaltet.</strong>
Bitte den Lehrer kurz darum — er muss dich einmalig freischalten, danach kannst du selbst reservieren. Bitte den Lehrer kurz darum — er muss dich einmalig freischalten, danach kannst du selbst reservieren.
</div> </div>

View File

@@ -9,13 +9,13 @@
.eval-optionen { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; } .eval-optionen { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; }
.eval-option { .eval-option {
cursor: pointer; padding: 0.7rem 0.5rem; border-radius: 6px; text-align: center; cursor: pointer; padding: 0.7rem 0.5rem; border-radius: 6px; text-align: center;
background: #F4F6F7; border: 2px solid transparent; transition: all 0.15s; background: var(--surface-muted); border: 2px solid transparent; transition: all 0.15s;
} }
.eval-option:hover { background: #ECF0F1; } .eval-option:hover { background: var(--surface-muted); }
.eval-option input[type=radio] { display: none; } .eval-option input[type=radio] { display: none; }
.eval-option input[type=radio]:checked + span { font-weight: 600; } .eval-option input[type=radio]:checked + span { font-weight: 600; }
.eval-option:has(input[type=radio]:checked) { .eval-option:has(input[type=radio]:checked) {
background: #EBF5FB; border-color: var(--primary); background: var(--info-bg); border-color: var(--primary);
} }
.eval-emoji { font-size: 1.4rem; display: block; margin-bottom: 0.2rem; } .eval-emoji { font-size: 1.4rem; display: block; margin-bottom: 0.2rem; }
</style> </style>
@@ -25,7 +25,7 @@
<a href="{{ url_for('profil.projekt_detail', projekt_id=p.id) }}" class="btn btn-secondary">Abbrechen</a> <a href="{{ url_for('profil.projekt_detail', projekt_id=p.id) }}" class="btn btn-secondary">Abbrechen</a>
</div> </div>
<div class="card" style="background:#EBF5FB; border-left: 4px solid var(--primary);"> <div class="card" style="background:var(--info-bg); border-left: 4px solid var(--primary);">
<strong>Ehrlich bleiben.</strong> Niemand wird benotet — die Bewertung ist fuer dich selbst, <strong>Ehrlich bleiben.</strong> Niemand wird benotet — die Bewertung ist fuer dich selbst,
damit du beim naechsten Projekt besser einschaetzen kannst, was du planen musst. damit du beim naechsten Projekt besser einschaetzen kannst, was du planen musst.
</div> </div>

View File

@@ -21,7 +21,7 @@
</p> </p>
<div id="drop-zone" style="border: 3px dashed var(--border); border-radius: 12px; padding: 3rem; <div id="drop-zone" style="border: 3px dashed var(--border); border-radius: 12px; padding: 3rem;
text-align: center; cursor: pointer; transition: border-color 0.2s; background: #fafafa;"> text-align: center; cursor: pointer; transition: border-color 0.2s; background: var(--surface-soft);">
<p style="font-size: 1.2rem; color: var(--text-light);">Strg+V zum Einfuegen</p> <p style="font-size: 1.2rem; color: var(--text-light);">Strg+V zum Einfuegen</p>
<p style="font-size: 0.85rem; color: var(--text-light);">oder klicken um Datei auszuwaehlen</p> <p style="font-size: 0.85rem; color: var(--text-light);">oder klicken um Datei auszuwaehlen</p>
<input type="file" id="datei-input" accept="image/*" style="display: none;"> <input type="file" id="datei-input" accept="image/*" style="display: none;">
@@ -52,7 +52,7 @@
<div style="min-width: 200px; text-align: center;"> <div style="min-width: 200px; text-align: center;">
<h3>Vorschau</h3> <h3>Vorschau</h3>
<canvas id="vorschau-canvas" width="200" height="200" <canvas id="vorschau-canvas" width="200" height="200"
style="border: 1px solid var(--border); border-radius: 8px; background: #f0f0f0;"></canvas> style="border: 1px solid var(--border); border-radius: 8px; background: var(--surface-muted);"></canvas>
</div> </div>
</div> </div>
@@ -139,14 +139,14 @@ dateiInput.addEventListener('change', function() {
} }
}); });
dropZone.addEventListener('dragover', function(e) { dropZone.addEventListener('dragover', function(e) {
e.preventDefault(); this.style.borderColor = 'var(--primary)'; this.style.background = '#EBF5FB'; e.preventDefault(); this.style.borderColor = 'var(--primary)'; this.style.background = 'var(--info-bg)';
}); });
dropZone.addEventListener('dragleave', function() { dropZone.addEventListener('dragleave', function() {
this.style.borderColor = 'var(--border)'; this.style.background = '#fafafa'; this.style.borderColor = 'var(--border)'; this.style.background = 'var(--surface-soft)';
}); });
dropZone.addEventListener('drop', function(e) { dropZone.addEventListener('drop', function(e) {
e.preventDefault(); e.preventDefault();
this.style.borderColor = 'var(--border)'; this.style.background = '#fafafa'; this.style.borderColor = 'var(--border)'; this.style.background = 'var(--surface-soft)';
if (e.dataTransfer.files[0] && e.dataTransfer.files[0].type.indexOf('image') >= 0) { if (e.dataTransfer.files[0] && e.dataTransfer.files[0].type.indexOf('image') >= 0) {
var reader = new FileReader(); var reader = new FileReader();
reader.onload = function(ev) { bildLaden(ev.target.result); }; reader.onload = function(ev) { bildLaden(ev.target.result); };

View File

@@ -12,7 +12,7 @@
{# ============== Lineage-Banner: Vorlage + Wiederholungen ============== #} {# ============== Lineage-Banner: Vorlage + Wiederholungen ============== #}
{% if vorlage %} {% if vorlage %}
<div class="card" style="background: #EBF5FB; border-left: 4px solid var(--primary); margin-bottom: 0.8rem;"> <div class="card" style="background: var(--info-bg); border-left: 4px solid var(--primary); margin-bottom: 0.8rem;">
<strong>🔗 Vorlage:</strong> <strong>🔗 Vorlage:</strong>
<a href="{{ url_for('profil.projekt_detail', projekt_id=vorlage.id) }}">{{ vorlage.titel }}</a> <a href="{{ url_for('profil.projekt_detail', projekt_id=vorlage.id) }}">{{ vorlage.titel }}</a>
von {{ tier_emoji(vorlage.tier or '') }} {{ vorlage.vorname or '—' }} von {{ tier_emoji(vorlage.tier or '') }} {{ vorlage.vorname or '—' }}
@@ -23,7 +23,7 @@
{% endif %} {% endif %}
{% if wiederholungen %} {% if wiederholungen %}
<div class="card" style="background: #EAFBF1; border-left: 4px solid var(--success); margin-bottom: 0.8rem;"> <div class="card" style="background: var(--success-bg); border-left: 4px solid var(--success); margin-bottom: 0.8rem;">
<strong>🔁 Wurde wiederholt von:</strong> <strong>🔁 Wurde wiederholt von:</strong>
{% for w in wiederholungen %} {% for w in wiederholungen %}
{{ tier_emoji(w.tier or '') }} {{ tier_emoji(w.tier or '') }}
@@ -57,7 +57,7 @@
<img src="{{ url_for('api.projekt_cover', projekt_id=p.id) }}" alt="" <img src="{{ url_for('api.projekt_cover', projekt_id=p.id) }}" alt=""
style="width: 100%; max-height: 240px; object-fit: cover; border-radius: 6px;"> style="width: 100%; max-height: 240px; object-fit: cover; border-radius: 6px;">
{% else %} {% else %}
<div style="height: 200px; background: linear-gradient(135deg, #ECF0F1, #D5DBDB); border-radius: 6px; <div style="height: 200px; background: linear-gradient(135deg, var(--surface-muted), var(--surface-hover)); border-radius: 6px;
display: flex; align-items: center; justify-content: center; font-size: 3rem; color: var(--text-light);"> display: flex; align-items: center; justify-content: center; font-size: 3rem; color: var(--text-light);">
🎯 🎯
</div> </div>
@@ -97,7 +97,7 @@
<div class="card"> <div class="card">
<h2>Deine Bewertung</h2> <h2>Deine Bewertung</h2>
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0.6rem; margin-bottom: 1rem;"> <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0.6rem; margin-bottom: 1rem;">
<div style="text-align: center; padding: 0.6rem; background: #F4F6F7; border-radius: 6px;"> <div style="text-align: center; padding: 0.6rem; background: var(--surface-muted); border-radius: 6px;">
<div style="font-size: 0.75rem; color: var(--text-light);">Gesamt</div> <div style="font-size: 0.75rem; color: var(--text-light);">Gesamt</div>
<div style="font-size: 1.4rem; margin-top: 0.2rem;"> <div style="font-size: 1.4rem; margin-top: 0.2rem;">
{% if p.selbsteinschaetzung == 'zufrieden' %}🟢 {% if p.selbsteinschaetzung == 'zufrieden' %}🟢
@@ -107,7 +107,7 @@
</div> </div>
<div style="font-size: 0.85rem; margin-top: 0.2rem;">{{ p.selbsteinschaetzung or '—' }}</div> <div style="font-size: 0.85rem; margin-top: 0.2rem;">{{ p.selbsteinschaetzung or '—' }}</div>
</div> </div>
<div style="text-align: center; padding: 0.6rem; background: #F4F6F7; border-radius: 6px;"> <div style="text-align: center; padding: 0.6rem; background: var(--surface-muted); border-radius: 6px;">
<div style="font-size: 0.75rem; color: var(--text-light);">Planung</div> <div style="font-size: 0.75rem; color: var(--text-light);">Planung</div>
<div style="font-size: 1.4rem; margin-top: 0.2rem;"> <div style="font-size: 1.4rem; margin-top: 0.2rem;">
{% if p.selbsteinschaetzung_planung == 'gut' %}🟢 {% if p.selbsteinschaetzung_planung == 'gut' %}🟢
@@ -117,7 +117,7 @@
</div> </div>
<div style="font-size: 0.85rem; margin-top: 0.2rem;">{{ p.selbsteinschaetzung_planung or '—' }}</div> <div style="font-size: 0.85rem; margin-top: 0.2rem;">{{ p.selbsteinschaetzung_planung or '—' }}</div>
</div> </div>
<div style="text-align: center; padding: 0.6rem; background: #F4F6F7; border-radius: 6px;"> <div style="text-align: center; padding: 0.6rem; background: var(--surface-muted); border-radius: 6px;">
<div style="font-size: 0.75rem; color: var(--text-light);">Ausfuehrung</div> <div style="font-size: 0.75rem; color: var(--text-light);">Ausfuehrung</div>
<div style="font-size: 1.4rem; margin-top: 0.2rem;"> <div style="font-size: 1.4rem; margin-top: 0.2rem;">
{% if p.selbsteinschaetzung_ausfuehrung == 'gut' %}🟢 {% if p.selbsteinschaetzung_ausfuehrung == 'gut' %}🟢
@@ -251,7 +251,7 @@
{# Upload-Zone #} {# Upload-Zone #}
<div id="upload-zone" style="margin-top: 1rem; border: 3px dashed var(--border); border-radius: 8px; <div id="upload-zone" style="margin-top: 1rem; border: 3px dashed var(--border); border-radius: 8px;
padding: 1.5rem; text-align: center; cursor: pointer; background: #fafafa;"> padding: 1.5rem; text-align: center; cursor: pointer; background: var(--surface-soft);">
<div style="font-size: 1.1rem; color: var(--text-light);">📁 Dateien hier ablegen</div> <div style="font-size: 1.1rem; color: var(--text-light);">📁 Dateien hier ablegen</div>
<div style="font-size: 0.85rem; color: var(--text-light); margin-top: 0.3rem;"> <div style="font-size: 0.85rem; color: var(--text-light); margin-top: 0.3rem;">
oder klicken — STL, 3MF, JPG, PNG · max. 60 MB pro Datei oder klicken — STL, 3MF, JPG, PNG · max. 60 MB pro Datei
@@ -300,7 +300,7 @@
{% endif %} {% endif %}
</div> </div>
{% if not darf_abschliessen %} {% if not darf_abschliessen %}
<div style="margin-top: 0.6rem; background: #FEF9E7; padding: 0.6rem 0.8rem; border-radius: 6px; font-size: 0.85rem;"> <div style="margin-top: 0.6rem; background: var(--warn-bg); padding: 0.6rem 0.8rem; border-radius: 6px; font-size: 0.85rem;">
<strong>Noch nicht abschliessbar:</strong> <strong>Noch nicht abschliessbar:</strong>
<ul style="margin: 0.3rem 0 0 1.2rem; padding: 0;"> <ul style="margin: 0.3rem 0 0 1.2rem; padding: 0;">
{% for f in abschluss_fehlende %}<li>{{ f }}</li>{% endfor %} {% for f in abschluss_fehlende %}<li>{{ f }}</li>{% endfor %}
@@ -308,17 +308,17 @@
</div> </div>
{% endif %} {% endif %}
{% elif p.freigabe_status == 'wartet_auf_freigabe' %} {% elif p.freigabe_status == 'wartet_auf_freigabe' %}
<div style="background: #FEF9E7; padding: 0.8rem; border-radius: 6px; border-left: 4px solid var(--warning);"> <div style="background: var(--warn-bg); padding: 0.8rem; border-radius: 6px; border-left: 4px solid var(--warning);">
<strong>Wartet auf Freigabe vom Lehrer.</strong> <strong>Wartet auf Freigabe vom Lehrer.</strong>
Sobald er drueber geschaut hat, kannst du ein neues Projekt anfangen. Sobald er drueber geschaut hat, kannst du ein neues Projekt anfangen.
</div> </div>
{% elif p.freigabe_status == 'rueckfrage' %} {% elif p.freigabe_status == 'rueckfrage' %}
<div style="background: #FADBD8; padding: 0.8rem; border-radius: 6px; border-left: 4px solid var(--danger);"> <div style="background: var(--error-bg); padding: 0.8rem; border-radius: 6px; border-left: 4px solid var(--danger);">
<strong>Lehrer hat eine Rueckfrage.</strong> <strong>Lehrer hat eine Rueckfrage.</strong>
Schau ins Cockpit fuer die Details und beantworte sie. Schau ins Cockpit fuer die Details und beantworte sie.
</div> </div>
{% else %} {% else %}
<div style="background: #EAFBF1; padding: 0.8rem; border-radius: 6px; border-left: 4px solid var(--success);"> <div style="background: var(--success-bg); padding: 0.8rem; border-radius: 6px; border-left: 4px solid var(--success);">
<strong>Freigegeben.</strong> <strong>Freigegeben.</strong>
{% if p.freigegeben_am %}Am {{ p.freigegeben_am[:10] }}.{% endif %} {% if p.freigegeben_am %}Am {{ p.freigegeben_am[:10] }}.{% endif %}
Du kannst jetzt ein neues Projekt anfangen. Du kannst jetzt ein neues Projekt anfangen.
@@ -349,16 +349,16 @@
zone.addEventListener('dragover', function(e) { zone.addEventListener('dragover', function(e) {
e.preventDefault(); e.preventDefault();
zone.style.borderColor = 'var(--primary)'; zone.style.borderColor = 'var(--primary)';
zone.style.background = '#EBF5FB'; zone.style.background = 'var(--info-bg)';
}); });
zone.addEventListener('dragleave', function() { zone.addEventListener('dragleave', function() {
zone.style.borderColor = 'var(--border)'; zone.style.borderColor = 'var(--border)';
zone.style.background = '#fafafa'; zone.style.background = 'var(--surface-soft)';
}); });
zone.addEventListener('drop', function(e) { zone.addEventListener('drop', function(e) {
e.preventDefault(); e.preventDefault();
zone.style.borderColor = 'var(--border)'; zone.style.borderColor = 'var(--border)';
zone.style.background = '#fafafa'; zone.style.background = 'var(--surface-soft)';
if (e.dataTransfer.files && e.dataTransfer.files.length) { if (e.dataTransfer.files && e.dataTransfer.files.length) {
dateienHochladen(e.dataTransfer.files); dateienHochladen(e.dataTransfer.files);
} }

View File

@@ -13,7 +13,7 @@
</div> </div>
{% if not darf_neues and sperr_grund %} {% if not darf_neues and sperr_grund %}
<div class="card" style="background:#FEF9E7; border-left: 4px solid var(--warning);"> <div class="card" style="background:var(--warn-bg); border-left: 4px solid var(--warning);">
{{ sperr_grund }} {{ sperr_grund }}
</div> </div>
{% endif %} {% endif %}
@@ -27,7 +27,7 @@
<img src="{{ url_for('api.projekt_cover', projekt_id=p.id) }}" alt="" <img src="{{ url_for('api.projekt_cover', projekt_id=p.id) }}" alt=""
style="width: 100%; height: 160px; object-fit: cover; border-radius: 6px; background: #fff;"> style="width: 100%; height: 160px; object-fit: cover; border-radius: 6px; background: #fff;">
{% else %} {% else %}
<div style="height: 160px; background: linear-gradient(135deg, #ECF0F1, #D5DBDB); border-radius: 6px; <div style="height: 160px; background: linear-gradient(135deg, var(--surface-muted), var(--surface-hover)); border-radius: 6px;
display: flex; align-items: center; justify-content: center; font-size: 2.5rem; color: var(--text-light);"> display: flex; align-items: center; justify-content: center; font-size: 2.5rem; color: var(--text-light);">
🎯 🎯
</div> </div>

View File

@@ -7,7 +7,7 @@
<a href="{{ url_for('profil.cockpit') }}" class="btn btn-secondary">Abbrechen</a> <a href="{{ url_for('profil.cockpit') }}" class="btn btn-secondary">Abbrechen</a>
</div> </div>
<div class="card" style="background:#EBF5FB; border-left: 4px solid var(--primary);"> <div class="card" style="background:var(--info-bg); border-left: 4px solid var(--primary);">
<strong>Commitment.</strong> Mit dem Anlegen entscheidest du dich, dieses Projekt durchzuziehen. <strong>Commitment.</strong> Mit dem Anlegen entscheidest du dich, dieses Projekt durchzuziehen.
Du kannst es spaeter abschliessen und selbst bewerten — und erst dann wieder ein neues anfangen. Du kannst es spaeter abschliessen und selbst bewerten — und erst dann wieder ein neues anfangen.
</div> </div>

View File

@@ -5,11 +5,11 @@
<style> <style>
.kat-tabelle { width: 100%; border-collapse: collapse; } .kat-tabelle { width: 100%; border-collapse: collapse; }
.kat-tabelle th { .kat-tabelle th {
background: #F2F3F4; padding: 0.6rem 0.5rem; background: var(--surface-muted); padding: 0.6rem 0.5rem;
text-align: left; font-size: 0.85rem; cursor: pointer; text-align: left; font-size: 0.85rem; cursor: pointer;
user-select: none; white-space: nowrap; user-select: none; white-space: nowrap;
} }
.kat-tabelle th:hover { background: #E5E7E8; } .kat-tabelle th:hover { background: var(--surface-hover); }
.kat-tabelle th .sort-pfeil { .kat-tabelle th .sort-pfeil {
display: inline-block; margin-left: 0.3rem; opacity: 0.3; font-size: 0.7rem; display: inline-block; margin-left: 0.3rem; opacity: 0.3; font-size: 0.7rem;
} }
@@ -19,16 +19,16 @@
vertical-align: middle; font-size: 0.9rem; vertical-align: middle; font-size: 0.9rem;
} }
.kat-zeile { cursor: pointer; } .kat-zeile { cursor: pointer; }
.kat-zeile:hover { background: #F8F9FA; } .kat-zeile:hover { background: var(--surface-soft); }
.kat-zeile.offen { background: #EBF5FB; } .kat-zeile.offen { background: var(--info-bg); }
.kat-thumb { .kat-thumb {
width: 40px; height: 40px; border-radius: 6px; object-fit: cover; width: 40px; height: 40px; border-radius: 6px; object-fit: cover;
background: linear-gradient(135deg, #ECF0F1, #D5DBDB); background: linear-gradient(135deg, var(--surface-muted), var(--surface-hover));
display: flex; align-items: center; justify-content: center; display: flex; align-items: center; justify-content: center;
font-size: 1.2rem; color: var(--text-light); font-size: 1.2rem; color: var(--text-light);
} }
.kat-thumb img { width: 100%; height: 100%; object-fit: cover; border-radius: 6px; } .kat-thumb img { width: 100%; height: 100%; object-fit: cover; border-radius: 6px; }
.kat-detail { display: none; background: #F8F9FA; } .kat-detail { display: none; background: var(--surface-soft); }
.kat-detail.offen { display: table-row; } .kat-detail.offen { display: table-row; }
.kat-detail-inner { .kat-detail-inner {
display: flex; gap: 1.5rem; padding: 1rem 0.5rem; flex-wrap: wrap; display: flex; gap: 1.5rem; padding: 1rem 0.5rem; flex-wrap: wrap;
@@ -39,7 +39,7 @@
} }
.kat-detail-bild-platzhalter { .kat-detail-bild-platzhalter {
width: 260px; height: 200px; border-radius: 8px; width: 260px; height: 200px; border-radius: 8px;
background: linear-gradient(135deg, #ECF0F1, #D5DBDB); background: linear-gradient(135deg, var(--surface-muted), var(--surface-hover));
display: flex; align-items: center; justify-content: center; display: flex; align-items: center; justify-content: center;
font-size: 3rem; color: var(--text-light); font-size: 3rem; color: var(--text-light);
} }
@@ -54,7 +54,7 @@
padding: 0.2rem 0.6rem; background: #fff; border: 1px solid var(--border); padding: 0.2rem 0.6rem; background: #fff; border: 1px solid var(--border);
border-radius: 4px; text-decoration: none; font-size: 0.85rem; color: var(--text); border-radius: 4px; text-decoration: none; font-size: 0.85rem; color: var(--text);
} }
.kat-dateien a:hover { background: #ECF0F1; } .kat-dateien a:hover { background: var(--surface-muted); }
</style> </style>
<h1>Projekte</h1> <h1>Projekte</h1>

View File

@@ -15,7 +15,7 @@
} }
.sw-karte .bild-platzhalter { .sw-karte .bild-platzhalter {
height: 110px; height: 110px;
background: linear-gradient(135deg, #ECF0F1, #D5DBDB); background: linear-gradient(135deg, var(--surface-muted), var(--surface-hover));
border-radius: 6px; border-radius: 6px;
display: flex; display: flex;
align-items: center; align-items: center;
@@ -49,8 +49,8 @@
gap: 0.3rem; gap: 0.3rem;
font-size: 0.8rem; font-size: 0.8rem;
padding: 0.35rem 0.7rem; padding: 0.35rem 0.7rem;
border-radius: 6px; border-radius: var(--radius-md);
background: #2C3E50; background: var(--color-secondary);
color: #fff; color: #fff;
text-decoration: none; text-decoration: none;
} }