From bb135cd962906335b38c674b2c1829d3b25cf9c2 Mon Sep 17 00:00:00 2001 From: Serverlele30 <46974281+Serverlele30@users.noreply.github.com> Date: Tue, 10 Feb 2026 15:38:23 +0100 Subject: [PATCH] Add files via upload --- CHANGELOG.md | 631 ++++++++++++++++++-- index.html | 16 +- package-lock.json | 42 ++ script.js | 307 ++++++---- styles.css | 1444 ++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 2194 insertions(+), 246 deletions(-) create mode 100644 package-lock.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 608218e..4221ead 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,84 @@ Alle wichtigen Änderungen an diesem Projekt werden in dieser Datei dokumentiert Das Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.0.0/), und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/). +## [31.0.0] - 2026-02-10 + +### Developer View & Auto-Changelog System + +#### Added +- **Developer View mit Tab-System**: Neue Entwickler-Ansicht mit 3 Tabs + - Changelog: Automatisch geladene Versionshistorie + - Info: App-Informationen, Statistiken, Status + - Features: Detaillierte Feature-Beschreibungen mit Collapsibles +- **Automatisches Changelog-Loading**: CHANGELOG.md wird automatisch gefetcht und gerendert +- **Markdown-zu-HTML Konverter**: Vollständiger Parser für Markdown-Syntax + - Überschriften (h1-h6) + - Fettdruck (**bold**) und Kursiv (*italic*) + - Code-Blöcke (``` ```) und Inline-Code (`code`) + - Listen (geordnet und ungeordnet) + - Links [text](url) + - Blockquotes (>) + - Horizontale Linien (---) + - Tabellen +- **GitHub-Style Formatierung**: Changelog sieht aus wie auf GitHub + - Hierarchische Überschriften mit Border-Bottom + - Gelbe Highlights für wichtige Begriffe + - Grüner Code-Text auf schwarzem Hintergrund + - Responsive Typography +- **Mobile-Optimierungen für Developer View**: + - Kompaktere Layouts für kleine Bildschirme + - Touch-optimierte Tab-Navigation (min 44px) + - Horizontal scrollbare Tabs mit Scroll-Hint Animation + - Bessere Lesbarkeit durch angepasste Font-Größen + - Stack-Layout für Info-Boxen + - Full-Width GitHub-Link Button + - Landscape-Mode Support + +#### Changed +- **Changelog-Verwaltung**: Nur noch CHANGELOG.md pflegen - keine HTML-Duplikate mehr +- **Developer-Tabs Design**: Premium-Look mit Gradienten und Animationen + - 3D-Button-Effekt mit Schatten + - Smooth Transform-Animationen + - Aktiver Tab hebt sich durch Gold-Gradient ab + - Hover-Effekte auf Desktop +- **Tab-Content Animation**: Fade-in beim Tab-Wechsel (0.4s cubic-bezier) +- **Info-Boxen**: 2-Spalten-Layout auf Desktop, Stack auf Mobile +- **Typography**: Optimierte Font-Größen für alle Breakpoints + - Mobile: 12-14px + - Tablet: 14-16px + - Desktop: 15-18px + +#### Fixed +- **CSS Duplikat-Fehler**: Doppelte Mobile Media Query (Zeile 2040-2130) entfernt +- **Markdown Parsing**: Korrekte Konvertierung von verschachtelten Listen +- **UTF-8 Encoding**: CHANGELOG.md ohne Zeichenfehler (ä, ö, ü) +- **Tab-Switching**: Changelog lädt nur einmal beim ersten Öffnen +- **Touch-Feedback**: Optimierte :active States für Mobile +- **Scroll-Verhalten**: Smooth horizontal scrolling für Tabs mit -webkit-overflow-scrolling + +#### Technical Details +- **Neue JavaScript-Funktionen**: + - `loadChangelog()`: Fetcht und rendert CHANGELOG.md + - `markdownToHtml()`: Konvertiert Markdown zu HTML (230 Zeilen) + - `parseInline()`: Konvertiert inline Markdown (bold, italic, code, links) + - `escapeHtml()`: Sicheres HTML-Escaping für Code-Blöcke +- **CSS-Ergänzungen**: +200 Zeilen für Markdown-Formatierung +- **Responsive Breakpoints**: + - Mobile: < 768px + - Tablet: 768-1023px + - Desktop: 1024px+ + - Extra Small: < 360px + - Landscape Mobile: < 768px & orientation: landscape +- **Performance**: Changelog cached nach erstem Load +- **Browser-Support**: Chrome 80+, Safari 12+, Firefox 75+ + +--- + ## [30.0.0] - 2026-02-10 -### 🎉 Major Release - Code-Trennung & Desktop-Optimierung +### Major Release - Code-Trennung & Desktop-Optimierung -### Added +#### Added - **Modulare Dateistruktur**: Projekt in separate HTML, CSS und JS Dateien aufgeteilt - **Desktop-Optimierungen**: Responsive Layouts für verschiedene Bildschirmgrößen - Tablet/Desktop (768px+): 900px Container @@ -25,7 +98,7 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/). - **README.md**: Umfassende Dokumentation der Projektstruktur - **CHANGELOG.md**: Versionsverwaltung und Änderungsprotokoll -### Changed +#### Changed - **Dateistruktur**: - `index.html`: Von 4.698 auf 390 Zeilen reduziert - `styles.css`: 2.467 Zeilen (vorher inline) @@ -34,13 +107,13 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/). - Vorher: 1200px (zu breit) - Jetzt: 900px (Tablet), 1100px (Desktop), 1400px (XL) - **Navigation-Menü**: Von 280px auf 320px verbreitert -- **Header-Schrift**: Desktop-Größen erhöht (36px → 38px) +- **Header-Schrift**: Desktop-Größen erhöht (36px -> 38px) - **Detail-Modal**: Responsive Breiten je nach Bildschirmgröße - Tablet: 900px - Desktop: 1100px - Extra Large: 1300px -### Fixed +#### Fixed - **Z-Index Issue**: Popups und Modals werden jetzt korrekt über dem Header angezeigt - Header: z-index 10000 - Detail-Modal: z-index 10005 @@ -49,7 +122,7 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/). - **Desktop-Layout**: Fehlende Optimierungen für große Bildschirme korrigiert - **Live-Map Controls**: Bessere Positionierung auf Desktop -### Technical Details +#### Technical Details - CSS-Dateigröße: 2.467 Zeilen (inkl. Desktop-Optimierungen) - JavaScript unverändert: 1.992 Zeilen - HTML-Struktur: Sauber getrennt, 390 Zeilen @@ -60,25 +133,499 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/). ## [29.0.0] - 2026-02-09 ### Vorherige Version (Monolithisch) + - Alle Code in einer `index.html` Datei - 4.698 Zeilen insgesamt - Funktionale PWA mit allen Features - Optimiert für Mobile -### Features (bereits vorhanden) -- ✅ Echtzeit-Abfahrten VBB/BVG -- ✅ Routenplanung -- ✅ Live-Fahrzeugverfolgung (Radar) -- ✅ Service Worker (Offline-Fähigkeit) -- ✅ PWA Manifest (Installierbar) -- ✅ HTTPS Development Server -- ✅ DotMatrix Font Integration -- ✅ Dark Mode Design -- ✅ Touch-optimiert für Mobile -- ✅ Pull-to-Refresh -- ✅ Leaflet.js Karten-Integration -- ✅ BVG-Linienfarben -- ✅ Fahrzeug-Filter (U-Bahn, Bus, Tram, S-Bahn, Regional) +#### Features (bereits vorhanden) + +- Echtzeit-Abfahrten VBB/BVG +- Routenplanung +- Live-Fahrzeugverfolgung (Radar) +- Service Worker (Offline-Fähigkeit) +- PWA Manifest (Installierbar) +- HTTPS Development Server +- DotMatrix Font Integration +- Dark Mode Design +- Touch-optimiert für Mobile +- Pull-to-Refresh +- Leaflet.js Karten-Integration +- BVG-Linienfarben +- Fahrzeug-Filter (U-Bahn, Bus, Tram, S-Bahn, Regional) + +--- + +## [28.0.0] - 2026-02-08 + +### Live-Map Feature + +#### Added +- **Live-Fahrzeugverfolgung**: Echtzeit-Karte mit Leaflet.js +- **Fahrzeug-Marker**: Farbcodierte Marker für verschiedene Verkehrsmittel + - U-Bahn: Blau + - S-Bahn: Grün + - Bus: Rot/Rosa + - Tram: Orange + - Regional: Grau +- **Fahrzeug-Filter**: Toggle für verschiedene Verkehrsmitteltypen +- **Live-Updates**: Automatisches Refresh alle 10 Sekunden +- **Popup-Informationen**: Linie, Richtung, Verspätung beim Klick auf Marker +- **Map Controls**: Filter-Buttons über der Karte + +#### Changed +- **Navigation**: Neuer "Radar" Menüpunkt +- **API-Calls**: Optimiert für Live-Daten (radar endpoint) +- **Performance**: Marker-Clustering für bessere Performance + +#### Fixed +- **Memory Leaks**: Alte Marker werden korrekt entfernt +- **Map-Rendering**: Korrekte Tile-Layer Initialisierung + +--- + +## [27.0.0] - 2026-02-07 + +### Journey Planner Enhancements + +#### Added +- **Umsteigezeiten-Warnung**: Farbcodierte Hinweise bei knappen Umstiegen + - Grün: Ausreichend Zeit (5+ Minuten) + - Orange: Knapp (3-5 Minuten) + - Rot: Sehr knapp (< 3 Minuten) +- **Zwischenstopps**: Anzeige aller Haltestellen auf der Route +- **Platform-Informationen**: Gleis/Steig-Anzeige für alle Stops +- **Journey-Details Modal**: Detaillierte Ansicht mit allen Informationen +- **Swap-Button**: Von/Nach Felder tauschen per Button + +#### Changed +- **Journey-Layout**: Verbesserte Darstellung der Verbindungen +- **Icon-System**: Einheitliche Verkehrsmittel-Icons +- **Touch-Targets**: Größere Buttons für bessere Bedienbarkeit + +#### Fixed +- **Zeitberechnung**: Korrekte Berechnung von Umsteigezeiten +- **API-Parsing**: Robusteres Parsing von Journey-Daten + +--- + +## [26.0.0] - 2026-02-06 + +### Departure Filters + +#### Added +- **Verkehrsmittel-Filter**: Filter nach U-Bahn, S-Bahn, Bus, Tram +- **Linien-Filter**: Filter nach spezifischen Linien (U1, U2, etc.) +- **Filter-Persistenz**: Einstellungen werden gespeichert +- **Filter-Counter**: Anzeige der gefilterten Abfahrten + +#### Changed +- **Filter-UI**: Neue Filter-Leiste unter der Suche +- **Performance**: Optimiertes Filtern ohne neu zu laden + +--- + +## [25.0.0] - 2026-02-05 + +### BVG Line Colors + +#### Added +- **Original BVG-Farben**: Authentische Linienfarben + - U-Bahn: Linienspezifische Farben (U1-U9) + - S-Bahn: Grün + - Bus: Rot/Rosa + - Tram: Orange + - RE/RB: Grau +- **Color-Mapping**: Vollständige Farbtabelle für alle Linien +- **Badge-Design**: Farbige Linien-Badges + +#### Changed +- **Line-Badge Styling**: Größere, besser lesbare Badges +- **Contrast**: Optimierter Kontrast für alle Farben + +--- + +## [24.0.0] - 2026-02-04 + +### Pull-to-Refresh + +#### Added +- **Pull-to-Refresh Gesture**: Native-ähnliche Aktualisierung +- **Refresh-Spinner**: Visuelles Feedback beim Aktualisieren +- **Touch-Events**: touchstart, touchmove, touchend Handler +- **Haptic Feedback**: Vibration bei erfolgreicher Aktualisierung + +#### Changed +- **Scroll-Verhalten**: -webkit-overflow-scrolling für smoothes Scrolling +- **Performance**: Debounced Refresh-Events + +--- + +## [23.0.0] - 2026-02-03 + +### Platform Information + +#### Added +- **Gleis/Steig-Anzeige**: Anzeige der Abfahrtsplattform +- **Platform-Icon**: Symbol für Gleis/Steig +- **Platform-Badge**: Formatierte Darstellung + +#### Changed +- **Departure-Layout**: Mehr Platz für Platform-Info +- **API-Integration**: Korrekte Platform-Daten von VBB API + +--- + +## [22.0.0] - 2026-02-02 + +### Journey Planner + +#### Added +- **Routenplaner**: Von/Nach Suche implementiert +- **Journey-Results**: Anzeige von Verbindungen +- **Journey-Legs**: Detaillierte Anzeige aller Teilstrecken +- **Time-Display**: Abfahrts- und Ankunftszeiten +- **Duration**: Gesamtdauer der Verbindung +- **Transfers**: Anzahl der Umstiege + +#### Changed +- **Navigation**: Neuer "Route" Menüpunkt +- **API-Calls**: Integration von journeys endpoint + +--- + +## [21.0.0] - 2026-02-01 + +### Departure Details Modal + +#### Added +- **Detail-View**: Modal mit ausführlichen Informationen +- **Trip-Informationen**: Linie, Richtung, Betreiber +- **Stop-Sequence**: Alle folgenden Haltestellen +- **Remarks**: Hinweise und Störungen +- **Close-Button**: Einfaches Schließen des Modals + +#### Changed +- **Modal-Styling**: Fullscreen-Modal mit z-index Optimierung +- **Scroll-Verhalten**: Smooth scrolling in Stop-List + +--- + +## [20.0.0] - 2026-01-31 + +### Auto-Refresh + +#### Added +- **Automatische Aktualisierung**: Abfahrten refreshen alle 30 Sekunden +- **Last-Update Timestamp**: Anzeige der letzten Aktualisierung +- **Pause on Background**: Refresh stoppt bei Hintergrund-Tab +- **Visual-Indicator**: Animierter Refresh-Status + +#### Changed +- **Performance**: Optimierte API-Calls (nur Diffs laden) +- **Battery-Saving**: Intelligentes Refresh-Verhalten + +--- + +## [19.0.0] - 2026-01-30 + +### Delay Information + +#### Added +- **Verspätungsanzeige**: Rot hervorgehobene Delays +- **Delay-Badge**: Minute-genaue Verspätung +- **Cancelled-Status**: Markierung ausgefallener Fahrten +- **On-Time Badge**: Grüner Badge bei pünktlichen Fahrten + +#### Changed +- **Color-Scheme**: Rot für Delays, Grün für On-Time +- **Departure-Layout**: Mehr Platz für Delay-Info + +--- + +## [18.0.0] - 2026-01-29 + +### GPS Location Search + +#### Added +- **GPS-Button**: Automatische Standorterkennung +- **Nearby-Stops**: Nächstgelegene Haltestellen finden +- **Distance-Display**: Entfernung in Metern +- **Permission-Handling**: Browser-Berechtigungen für Standort +- **Loading-State**: Visuelles Feedback während GPS-Suche + +#### Changed +- **Search-Layout**: GPS-Button neben Suchfeld +- **API-Integration**: nearby endpoint + +#### Fixed +- **Permission-Errors**: Bessere Fehlerbehandlung bei verweigerten Berechtigungen + +--- + +## [17.0.0] - 2026-01-28 + +### Station Autocomplete + +#### Added +- **Live-Suche**: Autocomplete während der Eingabe +- **Fuzzy-Search**: Fehlertolerante Suche +- **Product-Tags**: Anzeige verfügbarer Verkehrsmittel +- **Keyboard-Navigation**: Arrow-Keys für Auswahl +- **Click-Outside**: Schließen bei Klick außerhalb + +#### Changed +- **Suggestions-UI**: Besseres Dropdown-Design +- **API-Calls**: Debounced requests (300ms) +- **Performance**: Caching von Search-Results + +--- + +## [16.0.0] - 2026-01-27 + +### Real-time Departures + +#### Added +- **VBB API Integration**: Anbindung an v6.vbb.transport.rest +- **Departure-List**: Chronologische Abfahrtsliste +- **Line-Badges**: Farbige Linien-Anzeige +- **Direction-Display**: Fahrtrichtung/Endhaltestelle +- **Time-Display**: Abfahrtszeit in Minuten oder absolut + +#### Changed +- **API-Endpoint**: Wechsel zu VBB Transport REST API v6 +- **Data-Structure**: Neue JSON-Struktur + +--- + +## [15.0.0] - 2026-01-26 + +### DotMatrix Font + +#### Added +- **DotMatrix Font**: Original BVG-Schriftart integriert +- **Font-Loading**: @font-face mit Fallback +- **Typography**: Einheitliche Schrift in gesamter App + +#### Changed +- **Font-Stack**: 'DotMatrix', 'Courier New', monospace +- **Letter-Spacing**: Optimiert für Lesbarkeit + +--- + +## [14.0.0] - 2026-01-25 + +### Dark Mode Design + +#### Added +- **Dark Theme**: Schwarzer Hintergrund (#000) +- **BVG Yellow**: Primärfarbe #FFED00 +- **Color-Scheme**: Vollständiges Farbkonzept +- **Contrast**: WCAG-konforme Kontraste + +#### Changed +- **Gesamtes UI**: Umstellung auf Dark Mode +- **Button-Styles**: Gelb auf Schwarz +- **Input-Fields**: Schwarzer Hintergrund + +--- + +## [13.0.0] - 2026-01-24 + +### Navigation System + +#### Added +- **Sidebar-Navigation**: Slide-out Menu +- **View-Switching**: Navigation zwischen verschiedenen Ansichten +- **Active-States**: Hervorhebung aktiver View +- **Smooth-Transitions**: Animierte View-Wechsel +- **Overlay**: Backdrop beim geöffneten Menu + +#### Changed +- **App-Structure**: Multi-View Architecture +- **Menu-Icon**: Hamburger-Button im Header + +--- + +## [12.0.0] - 2026-01-23 + +### PWA Manifest + +#### Added +- **manifest.json**: PWA Manifest-Datei +- **App-Icons**: Icons in verschiedenen Größen +- **Standalone-Mode**: App läuft ohne Browser-UI +- **Theme-Color**: #FFED00 (BVG Yellow) +- **Background-Color**: #000000 (Black) +- **Display**: standalone +- **Orientation**: portrait-primary + +#### Changed +- **HTML Meta-Tags**: PWA-spezifische Meta-Tags + +--- + +## [11.0.0] - 2026-01-22 + +### Service Worker + +#### Added +- **Service Worker**: Offline-Fähigkeit +- **Cache-First Strategy**: Schnelle Ladezeiten +- **Offline-Page**: Custom Offline-Seite +- **Cache-Update**: Automatische Cache-Updates +- **Background-Sync**: Sync bei Netzwerk-Reconnect + +#### Changed +- **Loading-Performance**: Deutlich schnellere App + +--- + +## [10.0.0] - 2026-01-21 + +### HTTPS Development Server + +#### Added +- **HTTPS-Server**: Node.js Server mit SSL +- **Auto-SSL**: Automatische Zertifikatserstellung +- **Mobile-Testing**: Echter HTTPS-Zugriff vom Handy +- **Hot-Reload**: Automatisches Neuladen bei Änderungen + +#### Changed +- **Development-Workflow**: Einfacheres Mobile-Testing + +--- + +## [9.0.0] - 2026-01-20 + +### Touch Optimizations + +#### Added +- **Touch-Targets**: Minimum 44x44px für alle interaktiven Elemente +- **Tap-Highlights**: Custom Highlight-Colors +- **Touch-Feedback**: Active-States für Touch +- **Gesture-Support**: Grundlegende Touch-Gesten + +#### Changed +- **Button-Sizes**: Größere Buttons für Touch +- **Spacing**: Mehr Abstand zwischen Elementen + +--- + +## [8.0.0] - 2026-01-19 + +### Responsive Design + +#### Added +- **Mobile-First**: Optimierung für Smartphones +- **Breakpoints**: 768px, 1024px, 1200px +- **Fluid-Typography**: Skalierbare Schriftgrößen +- **Flexible-Layouts**: CSS Grid & Flexbox + +#### Changed +- **Gesamtes Layout**: Responsive für alle Bildschirmgrößen + +--- + +## [7.0.0] - 2026-01-18 + +### Station Search + +#### Added +- **Search-Input**: Textfeld für Stationssuche +- **Search-Button**: Suche-Button +- **Clear-Button**: X zum Leeren des Suchfelds +- **Loading-State**: Spinner während der Suche + +#### Changed +- **UI-Layout**: Suchfeld prominent im Header + +--- + +## [6.0.0] - 2026-01-17 + +### Error Handling + +#### Added +- **Error-Messages**: Benutzerfreundliche Fehlermeldungen +- **API-Error-Handling**: Try-Catch für API-Calls +- **Network-Error-Detection**: Offline-Erkennung +- **Retry-Logic**: Automatisches Wiederholen bei Fehler + +#### Changed +- **User-Experience**: Besseres Feedback bei Problemen + +--- + +## [5.0.0] - 2026-01-16 + +### Loading States + +#### Added +- **Loading-Spinner**: Animierter Lade-Indikator +- **Skeleton-Screens**: Platzhalter während des Ladens +- **Progressive-Loading**: Schrittweises Laden von Daten + +#### Changed +- **UX**: Klares Feedback während Ladezeiten + +--- + +## [4.0.0] - 2026-01-15 + +### API Integration + +#### Added +- **Fetch-API**: Integration von VBB API +- **CORS-Handling**: Cross-Origin Requests +- **Rate-Limiting**: Respektierung von API-Limits +- **Error-Responses**: Handling von API-Fehlern + +#### Changed +- **Data-Flow**: Asynchrone Datenverarbeitung + +--- + +## [3.0.0] - 2026-01-14 + +### Basic Styling + +#### Added +- **CSS-Framework**: Custom CSS ohne Framework +- **Color-Variables**: CSS Custom Properties +- **Typography**: Schrift-Hierarchie +- **Button-Styles**: Einheitliche Button-Designs + +#### Changed +- **Visual-Design**: Erste Styling-Implementierung + +--- + +## [2.0.0] - 2026-01-13 + +### HTML Structure + +#### Added +- **Semantic-HTML**: Header, Main, Footer +- **Meta-Tags**: Viewport, Description, etc. +- **HTML5-Elements**: Article, Section, Nav +- **Accessibility**: ARIA-Labels wo nötig + +#### Changed +- **Document-Structure**: Semantisches HTML + +--- + +## [1.0.0] - 2026-01-12 + +### Initial Release + +#### Added +- **Project-Setup**: Initiales Git-Repository +- **Basic-HTML**: Einfache HTML-Struktur +- **README**: Projekt-Dokumentation +- **License**: MIT-Lizenz --- @@ -86,29 +633,32 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/). **Entwickelt von:** Aaron K. & Claude (Anthropic) **Lizenz:** MIT -**Repository:** https://github.com/Serverlele30/VBB-Status-Web-App +**Repository:** [github.com/Serverlele30/VBB-Status-Web-App](https://github.com/Serverlele30/VBB-Status-Web-App) ### Mitwirkende -- Aaron K. - Projektleitung, Konzept, Testing -- Claude (Anthropic) - Entwicklung, Code-Optimierung + +- **Aaron K.** - Projektleitung, Konzept, Testing, Entwicklung +- **Claude (Anthropic)** - Entwicklung, Code-Optimierung --- ## Geplante Features / Roadmap -### v31.0.0 (geplant) -- [ ] API-Error Handling verbessern -- [ ] Favoriten-Stationen speichern -- [ ] Benachrichtigungen bei Verspätungen -- [ ] Dunkles/Helles Theme umschaltbar -- [ ] Historische Daten und Statistiken +### v32.0.0 (geplant) -### v32.0.0 (Ideen) -- [ ] Barrierefreiheit (A11y) Audit -- [ ] Mehrsprachigkeit (Englisch) -- [ ] Export von Routen als iCal/PDF -- [ ] Teilen-Funktion für Verbindungen -- [ ] Integration mit Kalender-Apps +- API-Error Handling verbessern +- Favoriten-Stationen speichern +- Benachrichtigungen bei Verspätungen +- Dark/Light Mode Toggle + +### v33.0.0 (Ideen) + +- Barrierefreiheit (A11y) Audit +- Mehrsprachigkeit (Englisch) +- Export von Routen als iCal/PDF +- Teilen-Funktion für Verbindungen +- Integration mit Kalender-Apps +- Offline-Modus mit Service Worker Cache --- @@ -116,17 +666,18 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/). Dieses Projekt verwendet [Semantic Versioning](https://semver.org/lang/de/): -- **MAJOR** (X.0.0): Breaking Changes, große Architekturänderungen -- **MINOR** (0.X.0): Neue Features, abwärtskompatibel -- **PATCH** (0.0.X): Bugfixes, kleine Verbesserungen +- **MAJOR** (z.B. 31.x.x): Grundlegende Änderungen, neue Features +- **MINOR** (z.B. x.1.x): Neue Features, abwärtskompatibel +- **PATCH** (z.B. x.x.1): Bug-Fixes, kleine Verbesserungen --- ## Support & Feedback Bei Fragen oder Problemen: -1. GitHub Issues: https://github.com/Serverlele30/VBB-Status-Web-App/issues + +1. [GitHub Issues](https://github.com/Serverlele30/VBB-Status-Web-App/issues) 2. README konsultieren 3. Code-Kommentare lesen -**Viel Erfolg mit der VBB Netz Status App! 🚇🚌🚊** +**Viel Erfolg mit der VBB Netz Status App!** \ No newline at end of file diff --git a/index.html b/index.html index 1045f7d..01b56b6 100644 --- a/index.html +++ b/index.html @@ -94,7 +94,7 @@

VBB NETZ STATUS

Live-Nahverkehr für Berlin & Brandenburg

-
v29.0
+
v30.0
@@ -234,12 +234,12 @@
Verkehrsmittel:
- - - - - - + + + + + +
@@ -294,7 +294,7 @@

🚀 Version Info

- + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..6dc5f12 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,42 @@ +{ + "name": "vbb-netz-status", + "version": "29.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "vbb-netz-status", + "version": "29.0.0", + "license": "MIT", + "dependencies": { + "mime-types": "^2.1.35" + }, + "devDependencies": {}, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + } + } +} diff --git a/script.js b/script.js index 43ae2cc..684e316 100644 --- a/script.js +++ b/script.js @@ -2103,149 +2103,240 @@ document.addEventListener('DOMContentLoaded', () => { // UPDATES VIEW - CHANGELOG LOADER // ========================================== + +// ========================================== +// CHANGELOG LOADER - VERBESSERT +// Fetcht CHANGELOG.md und konvertiert Markdown zu HTML +// ========================================== + async function loadChangelog() { const container = document.getElementById('changelogContent'); try { + // Lade CHANGELOG.md const response = await fetch('CHANGELOG.md'); - if (!response.ok) throw new Error('CHANGELOG nicht gefunden'); + if (!response.ok) throw new Error('CHANGELOG.md nicht gefunden'); const markdown = await response.text(); - const html = parseChangelog(markdown); - container.innerHTML = html; - // Accordion-Funktionalität - document.querySelectorAll('.version-header').forEach(header => { - header.addEventListener('click', () => { - const versionBox = header.parentElement; - versionBox.classList.toggle('open'); - - // Vibration Feedback - if (navigator.vibrate) navigator.vibrate(5); - }); - }); + // Konvertiere Markdown zu HTML + const html = markdownToHtml(markdown); + + // Wrapper mit changelog-container Klasse + container.innerHTML = `
${html}
`; } catch (error) { console.error('Changelog Fehler:', error); container.innerHTML = ` -
-

⚠️ Changelog konnte nicht geladen werden

-

${error.message}

+
+
+

⚠️ Changelog konnte nicht geladen werden

+

${error.message}

+
`; } } -function parseChangelog(markdown) { - const lines = markdown.split('\n'); +// ========================================== +// MARKDOWN TO HTML CONVERTER +// ========================================== + +function markdownToHtml(markdown) { let html = ''; - let currentVersion = null; - let currentCategory = null; - let changes = {}; + const lines = markdown.split('\n'); + let inList = false; + let inOrderedList = false; + let inCodeBlock = false; + let codeBlockContent = ''; - // Parse Markdown for (let i = 0; i < lines.length; i++) { - const line = lines[i].trim(); + let line = lines[i]; - // Version Header: ## [30.0.0] - 2026-02-10 - if (line.match(/^## \[(\d+\.\d+\.\d+)\] - (.+)$/)) { - // Speichere vorherige Version - if (currentVersion) { - html += renderVersion(currentVersion, changes); - changes = {}; + // Code-Block Start/Ende (```) + if (line.trim().startsWith('```')) { + if (!inCodeBlock) { + inCodeBlock = true; + codeBlockContent = ''; + continue; + } else { + inCodeBlock = false; + html += `
${escapeHtml(codeBlockContent)}
`; + codeBlockContent = ''; + continue; + } + } + + // Innerhalb Code-Block + if (inCodeBlock) { + codeBlockContent += line + '\n'; + continue; + } + + // Leere Zeile - Schließe Listen + if (line.trim() === '') { + if (inList) { + html += ''; + inList = false; + } + if (inOrderedList) { + html += ''; + inOrderedList = false; + } + continue; + } + + // Überschriften (# ## ### ####) + if (line.match(/^(#{1,6})\s+(.+)$/)) { + const match = line.match(/^(#{1,6})\s+(.+)$/); + const level = match[1].length; + const text = parseInline(match[2]); + + if (inList) { + html += ''; + inList = false; + } + if (inOrderedList) { + html += ''; + inOrderedList = false; } - const match = line.match(/^## \[(\d+\.\d+\.\d+)\] - (.+)$/); - currentVersion = { - number: match[1], - date: match[2] - }; + html += `${text}`; + continue; } - // Kategorie: ### Added - else if (line.match(/^### (.+)$/)) { - const match = line.match(/^### (.+)$/); - currentCategory = match[1]; - if (!changes[currentCategory]) { - changes[currentCategory] = []; + // Horizontale Linie (--- oder ***) + if (line.match(/^(---+|\*\*\*+)$/)) { + if (inList) { + html += ''; + inList = false; } + if (inOrderedList) { + html += ''; + inOrderedList = false; + } + html += '
'; + continue; } - // Change Item: - Feature xyz - else if (line.match(/^[-*] (.+)$/) && currentCategory) { - const match = line.match(/^[-*] (.+)$/); - changes[currentCategory].push(match[1]); + // Ungeordnete Liste (- oder *) + if (line.match(/^[-*]\s+(.+)$/)) { + const match = line.match(/^[-*]\s+(.+)$/); + const text = parseInline(match[1]); + + if (inOrderedList) { + html += ''; + inOrderedList = false; + } + + if (!inList) { + html += ''; + inList = false; + } + + if (!inOrderedList) { + html += '
    '; + inOrderedList = true; + } + + html += `
  1. ${text}
  2. `; + continue; + } + + // Blockquote (>) + if (line.match(/^>\s+(.+)$/)) { + const match = line.match(/^>\s+(.+)$/); + const text = parseInline(match[1]); + + if (inList) { + html += ''; + inList = false; + } + if (inOrderedList) { + html += '
'; + inOrderedList = false; + } + + html += `
${text}
`; + continue; + } + + // Normaler Paragraph + if (line.trim() !== '') { + if (inList) { + html += ''; + inList = false; + } + if (inOrderedList) { + html += ''; + inOrderedList = false; + } + + const text = parseInline(line); + html += `

${text}

`; } } - // Speichere letzte Version - if (currentVersion) { - html += renderVersion(currentVersion, changes); - } - - // GitHub Link Button - html += ` - - 💻 Alle Updates & Code auf GitHub - - `; + // Schließe offene Listen am Ende + if (inList) html += ''; + if (inOrderedList) html += ''; return html; } -function renderVersion(version, changes) { - const categoryIcons = { - 'Added': '✨', - 'Changed': '🔄', - 'Fixed': '🐛', - 'Removed': '🗑️', - 'Deprecated': '⚠️', - 'Security': '🔒' - }; +// ========================================== +// INLINE MARKDOWN PARSER +// ========================================== + +function parseInline(text) { + // Links [text](url) + text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '$1'); - let categoriesHtml = ''; + // Inline Code `code` + text = text.replace(/`([^`]+)`/g, '$1'); - for (const [category, items] of Object.entries(changes)) { - if (items.length === 0) continue; - - const icon = categoryIcons[category] || '📝'; - const itemsHtml = items.map(item => `
  • ${item}
  • `).join(''); - - categoriesHtml += ` -
    -
    ${icon} ${category}
    -
      - ${itemsHtml} -
    -
    - `; - } + // Bold **text** oder __text__ + text = text.replace(/\*\*([^*]+)\*\*/g, '$1'); + text = text.replace(/__([^_]+)__/g, '$1'); - return ` -
    -
    -
    - v${version.number} - ${version.date} -
    - ▼ -
    -
    -
    - ${categoriesHtml} -
    -
    -
    - `; + // Italic *text* oder _text_ (aber nicht ** oder __) + text = text.replace(/(?$1'); + text = text.replace(/(?$1'); + + // Strikethrough ~~text~~ + text = text.replace(/~~([^~]+)~~/g, '$1'); + + return text; } -// Changelog laden wenn Updates-View geöffnet wird +function escapeHtml(text) { + const div = document.createElement('div'); + div.textContent = text; + return div.innerHTML; +} + +// Changelog laden wenn Developer-View geöffnet wird document.addEventListener('DOMContentLoaded', () => { - // Wenn direkt Updates-View aktiv ist - if (document.getElementById('view-developer')?.classList.contains('active')) { - loadChangelog(); + const developerView = document.getElementById('view-developer'); + if (developerView?.classList.contains('active')) { + const changelogContent = document.getElementById('changelogContent'); + if (changelogContent && !changelogContent.querySelector('.changelog-container')) { + loadChangelog(); + } } // Beim View-Wechsel @@ -2253,21 +2344,23 @@ document.addEventListener('DOMContentLoaded', () => { mutations.forEach((mutation) => { if (mutation.target.id === 'view-developer' && mutation.target.classList.contains('active')) { - // Nur laden wenn noch nicht geladen const content = document.getElementById('changelogContent'); - if (content.innerHTML.includes('Lade Changelog')) { + if (content && !content.querySelector('.changelog-container')) { loadChangelog(); } } }); }); - const updatesView = document.getElementById('view-developer'); - if (updatesView) { - observer.observe(updatesView, { attributes: true, attributeFilter: ['class'] }); + if (developerView) { + observer.observe(developerView, { + attributes: true, + attributeFilter: ['class'] + }); } }); + // ========================================== // MOBILE DETECTION - GPS NUR AUF MOBILE // ========================================== diff --git a/styles.css b/styles.css index 36263aa..0a4d93a 100644 --- a/styles.css +++ b/styles.css @@ -1,4 +1,4 @@ - /* DotMatrix Font by NikBLN - https://github.com/NikBLN/weilSieDichLieben */ +/* DotMatrix Font by NikBLN - https://github.com/NikBLN/weilSieDichLieben */ @font-face { font-family: 'DotMatrix'; src: url('./DotMatrix.ttf') format('truetype'); @@ -1591,60 +1591,6 @@ } } - .journey-leg { - padding: 10px; - gap: 10px; - } - - .journey-leg-icon { - font-size: 18px; - } - - .journey-leg-line { - font-size: 13px; - } - - .journey-leg-stations { - font-size: 11px; - } - - .journey-leg-time { - font-size: 10px; - min-width: 50px; - } - - .journey-transfer { - padding: 10px 12px; - font-size: 13px; - } - - .journey-transfer-time { - font-size: 15px; - } - - .journey-label { - font-size: 14px; - } - - .swap-btn { - margin: 10px 0; - font-size: 18px; - } - - body { - overflow-x: hidden; - } - - /* Text truncation für lange Namen */ - .departure-destination { - overflow: hidden; - text-overflow: ellipsis; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - } - } - /* Extra Small Mobile (SE, kleine Geräte) */ @media (max-width: 360px) { .header h1 { @@ -2365,45 +2311,1361 @@ .filter-btn:active, .transport-filter-btn:active { transform: scale(0.95); } -/* Developer Tabs */ - .developer-tabs { - display: flex; - gap: 8px; - margin-bottom: 20px; - overflow-x: auto; - padding: 0 10px; - } +/* ========================================== + DEVELOPER VIEW - PREMIUM DESIGN (NO GLOW) + Ersetze die bestehenden .developer-* und .dev-* Regeln + ========================================== */ - .dev-tab { - background-color: #1a1a1a; - border: 2px solid #333; - color: #FFED00; - padding: 12px 20px; - border-radius: 8px 8px 0 0; - font-family: var(--font-stack); - font-size: 14px; - cursor: pointer; - transition: all 0.2s; - white-space: nowrap; - flex-shrink: 0; - } +/* Developer Header - Schöner Gradient */ +.developer-header { + text-align: center; + padding: 30px 20px; + margin-bottom: 25px; + background: linear-gradient(135deg, #000 0%, #1a1a00 50%, #000 100%); + border: 3px solid #FFED00; + border-radius: 16px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5); +} - .dev-tab.active { - background-color: #000; - border-color: #FFED00; - border-bottom-color: #000; - } +.developer-header h2 { + font-size: 32px; + color: #FFED00; + margin: 0 0 10px 0; + font-family: 'DotMatrix', 'Courier New', monospace; + letter-spacing: 2px; +} - .dev-tab:hover { - background-color: #0a0a0a; - } +.developer-subtitle { + font-size: 15px; + color: #aaa; + margin: 0; + opacity: 0.9; +} - .dev-tab-content { - display: none; - padding: 10px; - } +/* Developer Tabs - Premium Look */ +.developer-tabs { + display: flex; + gap: 10px; + margin-bottom: 0; + overflow-x: auto; + padding: 15px; + background: linear-gradient(180deg, #0a0a0a 0%, #000 100%); + border-radius: 12px 12px 0 0; + border: 2px solid #222; + border-bottom: none; + -webkit-overflow-scrolling: touch; + scrollbar-width: thin; + scrollbar-color: #FFED00 #1a1a1a; + box-shadow: inset 0 2px 10px rgba(0, 0, 0, 0.5); +} - .dev-tab-content.active { - display: block; - } +.developer-tabs::-webkit-scrollbar { + height: 8px; +} +.developer-tabs::-webkit-scrollbar-track { + background: #0a0a0a; + border-radius: 4px; +} + +.developer-tabs::-webkit-scrollbar-thumb { + background: linear-gradient(90deg, #FFED00 0%, #FFD700 100%); + border-radius: 4px; +} + +.developer-tabs::-webkit-scrollbar-thumb:hover { + background: #FFED00; +} + +/* Developer Tab - Schöne 3D Buttons */ +.dev-tab { + background: linear-gradient(180deg, #1a1a1a 0%, #0a0a0a 100%); + border: 2px solid #333; + color: #FFED00; + padding: 14px 24px; + border-radius: 10px 10px 0 0; + font-family: 'DotMatrix', 'Courier New', monospace; + font-size: 14px; + cursor: pointer; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + white-space: nowrap; + flex-shrink: 0; + min-width: 130px; + text-align: center; + -webkit-tap-highlight-color: transparent; + position: relative; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.4); +} + +/* Tab Hover Effect */ +.dev-tab::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(180deg, rgba(255, 237, 0, 0) 0%, rgba(255, 237, 0, 0.05) 100%); + border-radius: 10px 10px 0 0; + opacity: 0; + transition: opacity 0.3s ease; +} + +.dev-tab:hover::before { + opacity: 1; +} + +/* Active Tab */ +.dev-tab.active { + background: linear-gradient(180deg, #FFED00 0%, #FFD700 100%); + color: #000; + border-color: #FFED00; + border-bottom-color: transparent; + font-weight: bold; + transform: translateY(3px); + box-shadow: 0 2px 15px rgba(0, 0, 0, 0.3); +} + +.dev-tab.active::before { + display: none; +} + +.dev-tab:active { + transform: scale(0.97) translateY(1px); +} + +/* Tab Content */ +.dev-tab-content { + display: none; + padding: 25px 15px; + background: linear-gradient(180deg, #0a0a0a 0%, #000 100%); + border: 2px solid #222; + border-top: 3px solid #FFED00; + border-radius: 0 0 12px 12px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5); + position: relative; +} + +.dev-tab-content.active { + display: block; + animation: fadeInContent 0.4s cubic-bezier(0.4, 0, 0.2, 1); +} + +@keyframes fadeInContent { + from { + opacity: 0; + transform: translateY(-15px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* ========================================== + CHANGELOG - VERBESSERTE FORMATIERUNG + ========================================== */ + +.changelog-container { + padding: 0; +} + +/* Changelog Item - Große Card */ +.changelog-item { + background: linear-gradient(135deg, #0a0a0a 0%, #000 100%); + border: 2px solid #333; + border-radius: 12px; + padding: 0; + margin-bottom: 20px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4); + overflow: hidden; + transition: all 0.3s ease; +} + +.changelog-item:hover { + transform: translateY(-2px); + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5); + border-color: #444; +} + +.changelog-item.latest { + border: 3px solid #FFED00; + background: linear-gradient(135deg, #0a0a00 0%, #000 100%); +} + +/* Changelog Header - Gelber Top-Bar */ +.changelog-header { + background: linear-gradient(90deg, #1a1a1a 0%, #0a0a0a 100%); + padding: 15px 20px; + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 2px solid #333; +} + +.changelog-item.latest .changelog-header { + background: linear-gradient(90deg, #FFED00 0%, #FFD700 100%); +} + +.changelog-version { + background: #000; + color: #FFED00; + padding: 6px 16px; + border-radius: 20px; + font-weight: bold; + font-size: 14px; + border: 2px solid #FFED00; +} + +.changelog-item.latest .changelog-version { + background: #000; + color: #FFED00; + border-color: #000; + animation: pulse 2s ease-in-out infinite; +} + +@keyframes pulse { + 0%, 100% { transform: scale(1); } + 50% { transform: scale(1.05); } +} + +.changelog-date { + color: #888; + font-size: 13px; + font-weight: bold; +} + +.changelog-item.latest .changelog-date { + color: #000; +} + +/* Changelog Body */ +.changelog-body { + padding: 20px; +} + +.changelog-title { + font-size: 20px; + color: #FFED00; + margin: 0 0 15px 0; + font-weight: bold; + padding-bottom: 10px; + border-bottom: 1px solid #222; +} + +/* Changelog Changes - Grid Layout */ +.changelog-changes { + margin: 0; + padding: 0; + list-style: none; + display: grid; + gap: 12px; +} + +.changelog-changes li { + background: #0a0a0a; + padding: 12px 15px; + border-radius: 8px; + border-left: 4px solid #555; + font-size: 14px; + line-height: 1.6; + color: #ccc; + display: flex; + align-items: flex-start; + gap: 10px; + transition: all 0.2s ease; +} + +.changelog-changes li:hover { + background: #111; + border-left-color: #FFED00; + transform: translateX(3px); +} + +/* Change Type Icons */ +.changelog-changes li::before { + content: '✓'; + display: inline-block; + width: 20px; + height: 20px; + background: #FFED00; + color: #000; + border-radius: 50%; + text-align: center; + line-height: 20px; + font-weight: bold; + font-size: 12px; + flex-shrink: 0; + margin-top: 2px; +} + +.changelog-changes li strong { + color: #FFED00; + font-weight: bold; +} + +/* Spezielle Change Types */ +.changelog-changes li[data-type="new"]::before { + content: '★'; + background: #FFED00; +} + +.changelog-changes li[data-type="fix"]::before { + content: '🔧'; + background: none; + font-size: 16px; +} + +.changelog-changes li[data-type="improve"]::before { + content: '↑'; + background: #00cc00; +} + +.changelog-changes li[data-type="remove"]::before { + content: '✗'; + background: #cc0000; +} + +/* Info Boxes */ +.dev-info-container { + display: grid; + grid-template-columns: 1fr; + gap: 18px; +} + +.dev-info-box { + background: linear-gradient(135deg, #0a0a0a 0%, #000 100%); + border: 1px solid #333; + border-radius: 12px; + padding: 20px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4); + transition: all 0.3s ease; +} + +.dev-info-box:hover { + transform: translateY(-3px); + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5); + border-color: #FFED00; +} + +.dev-info-box h3 { + font-size: 19px; + color: #FFED00; + margin: 0 0 15px 0; + padding-bottom: 12px; + border-bottom: 2px solid #333; + font-family: 'DotMatrix', 'Courier New', monospace; +} + +.dev-info-table { + width: 100%; + border-collapse: collapse; +} + +.dev-info-table tr { + border-bottom: 1px solid #1a1a1a; + transition: background-color 0.2s ease; +} + +.dev-info-table tr:hover { + background-color: #0a0a0a; +} + +.dev-info-table tr:last-child { + border-bottom: none; +} + +.dev-info-table td { + padding: 12px 0; + font-size: 13px; + color: #ccc; +} + +.dev-info-table td:first-child { + color: #888; + width: 40%; +} + +.dev-info-table td:last-child { + color: #fff; + font-weight: bold; +} + +.status-badge-dev { + display: inline-block; + padding: 4px 12px; + border-radius: 20px; + font-size: 11px; + font-weight: bold; + background: linear-gradient(135deg, #00cc00 0%, #00aa00 100%); +} + +/* GitHub Link Button */ +.github-link-btn { + display: block; + text-align: center; + padding: 16px 28px; + margin: 25px 0 0 0; + background: linear-gradient(135deg, #1a1a1a 0%, #0a0a0a 100%); + color: #FFED00; + text-decoration: none; + border-radius: 12px; + border: 2px solid #FFED00; + font-size: 16px; + font-weight: bold; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + font-family: 'DotMatrix', 'Courier New', monospace; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4); + position: relative; + overflow: hidden; +} + +.github-link-btn::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 237, 0, 0.1), transparent); + transition: left 0.5s ease; +} + +.github-link-btn:hover::before { + left: 100%; +} + +.github-link-btn:hover { + background: linear-gradient(135deg, #FFED00 0%, #FFD700 100%); + color: #000; + transform: translateY(-3px); + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5); +} + +.github-link-btn:active { + transform: translateY(-1px); +} + +/* Features Details */ +.dev-features-container { + padding: 0; +} + +.feature-detail { + background: linear-gradient(135deg, #0a0a0a 0%, #000 100%); + border: 1px solid #333; + border-radius: 12px; + margin-bottom: 15px; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4); + transition: all 0.3s ease; +} + +.feature-detail:hover { + border-color: #444; + box-shadow: 0 6px 25px rgba(0, 0, 0, 0.5); +} + +.feature-detail[open] { + border-color: #FFED00; + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5); +} + +.feature-detail summary { + background: linear-gradient(135deg, #1a1a1a 0%, #0a0a0a 100%); + padding: 16px 20px; + cursor: pointer; + font-size: 16px; + font-weight: bold; + color: #FFED00; + user-select: none; + transition: all 0.3s ease; + -webkit-tap-highlight-color: transparent; + list-style: none; + position: relative; +} + +.feature-detail summary::-webkit-details-marker { + display: none; +} + +.feature-detail summary::after { + content: '▼'; + position: absolute; + right: 20px; + transition: transform 0.3s ease; + font-size: 12px; +} + +.feature-detail[open] summary::after { + transform: rotate(180deg); +} + +.feature-detail summary:hover { + background: linear-gradient(135deg, #222 0%, #111 100%); + padding-left: 25px; + box-shadow: inset 4px 0 0 #FFED00; +} + +.feature-detail[open] summary { + background: linear-gradient(135deg, #000 0%, #0a0a0a 100%); + border-bottom: 1px solid #333; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); +} + +.feature-content { + padding: 18px 20px; + animation: expandContent 0.3s ease; +} + +@keyframes expandContent { + from { + opacity: 0; + transform: translateY(-10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.feature-content p { + margin: 0 0 14px 0; + color: #ccc; + font-size: 14px; + line-height: 1.6; +} + +.feature-content strong { + color: #FFED00; +} + +.feature-content ul { + margin: 0 0 16px 0; + padding-left: 22px; + color: #ccc; +} + +.feature-content li { + margin-bottom: 8px; + font-size: 13px; + line-height: 1.6; +} + +.feature-api { + background: linear-gradient(135deg, #0a0a0a 0%, #000 100%); + padding: 12px 15px; + border-radius: 8px; + border-left: 4px solid #FFED00; + font-size: 12px; + margin: 0; + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.5); +} + +.feature-api code { + font-family: 'Courier New', monospace; + color: #0f0; + background-color: #000; + padding: 3px 8px; + border-radius: 4px; +} + +/* ========================================== + RESPONSIVE - MOBILE (max-width: 767px) + ========================================== */ +@media (max-width: 767px) { + .developer-header { + padding: 20px 15px; + margin-bottom: 20px; + } + + .developer-header h2 { + font-size: 24px; + } + + .developer-subtitle { + font-size: 13px; + } + + .developer-tabs { + padding: 12px 10px; + gap: 8px; + } + + .dev-tab { + padding: 11px 18px; + font-size: 13px; + min-width: 110px; + } + + .dev-tab-content { + padding: 18px 12px; + } + + .changelog-item { + margin-bottom: 18px; + } + + .changelog-header { + padding: 12px 15px; + flex-direction: column; + gap: 8px; + align-items: flex-start; + } + + .changelog-version { + font-size: 12px; + padding: 4px 12px; + } + + .changelog-date { + font-size: 11px; + } + + .changelog-body { + padding: 15px; + } + + .changelog-title { + font-size: 17px; + margin-bottom: 12px; + } + + .changelog-changes { + gap: 10px; + } + + .changelog-changes li { + padding: 10px 12px; + font-size: 13px; + } + + .dev-info-box { + padding: 16px; + } + + .dev-info-box h3 { + font-size: 17px; + } + + .github-link-btn { + padding: 14px 24px; + font-size: 15px; + } + + .feature-detail summary { + font-size: 15px; + padding: 14px 18px; + } + + .feature-content { + padding: 15px 16px; + } +} + +/* ========================================== + RESPONSIVE - TABLET (768px - 1023px) + ========================================== */ +@media (min-width: 768px) and (max-width: 1023px) { + .developer-header { + padding: 25px 20px; + } + + .developer-header h2 { + font-size: 30px; + } + + .developer-tabs { + padding: 14px 12px; + gap: 10px; + } + + .dev-tab { + padding: 13px 24px; + font-size: 14px; + min-width: 140px; + } + + .dev-tab-content { + padding: 22px 16px; + } + + .dev-info-container { + grid-template-columns: repeat(2, 1fr); + gap: 18px; + } + + .github-link-btn { + grid-column: 1 / -1; + } + + .changelog-changes { + gap: 14px; + } +} + +/* ========================================== + RESPONSIVE - DESKTOP (min-width: 1024px) + ========================================== */ +@media (min-width: 1024px) { + .developer-header { + padding: 35px 25px; + } + + .developer-header h2 { + font-size: 36px; + } + + .developer-subtitle { + font-size: 16px; + } + + .developer-tabs { + padding: 16px 15px; + gap: 12px; + } + + .dev-tab { + padding: 15px 30px; + font-size: 15px; + min-width: 160px; + } + + .dev-tab:hover { + transform: translateY(-3px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.5); + } + + .dev-tab.active:hover { + transform: translateY(3px); + } + + .dev-tab-content { + padding: 30px 25px; + } + + .dev-info-container { + grid-template-columns: repeat(2, 1fr); + gap: 20px; + } + + .dev-info-box { + padding: 24px; + } + + .github-link-btn { + grid-column: 1 / -1; + padding: 18px 32px; + font-size: 17px; + } + + .changelog-item { + margin-bottom: 24px; + } + + .changelog-header { + padding: 18px 24px; + } + + .changelog-version { + font-size: 15px; + padding: 7px 18px; + } + + .changelog-body { + padding: 24px; + } + + .changelog-title { + font-size: 22px; + margin-bottom: 18px; + } + + .changelog-changes { + gap: 14px; + } + + .changelog-changes li { + padding: 14px 18px; + font-size: 15px; + } + + .feature-detail summary { + font-size: 17px; + padding: 18px 24px; + } + + .feature-content { + padding: 20px 24px; + } +} + +/* Extra Small Mobile */ +@media (max-width: 360px) { + .developer-header h2 { + font-size: 22px; + } + + .dev-tab { + padding: 9px 14px; + font-size: 12px; + min-width: 95px; + } + + .changelog-changes li { + font-size: 12px; + padding: 8px 10px; + } +} +/* ========================================== + CHANGELOG - MARKDOWN-STYLE FORMATIERUNG + Für automatisches Rendering von CHANGELOG.md + ========================================== */ + +/* Changelog Container für Markdown Content */ +.changelog-container { + font-family: 'DotMatrix', 'Courier New', monospace; + line-height: 1.6; + color: #ccc; + padding: 0; +} + +/* Überschriften - GitHub Style */ +.changelog-container h1 { + font-size: 28px; + color: #FFED00; + font-weight: bold; + margin: 0 0 20px 0; + padding-bottom: 10px; + border-bottom: 3px solid #FFED00; + letter-spacing: 1px; +} + +.changelog-container h2 { + font-size: 22px; + color: #FFED00; + font-weight: bold; + margin: 30px 0 15px 0; + padding-bottom: 8px; + border-bottom: 2px solid #333; + letter-spacing: 0.5px; +} + +.changelog-container h3 { + font-size: 18px; + color: #fff; + font-weight: bold; + margin: 20px 0 12px 0; +} + +.changelog-container h4 { + font-size: 16px; + color: #fff; + font-weight: bold; + margin: 15px 0 10px 0; +} + +/* Absätze */ +.changelog-container p { + margin: 0 0 15px 0; + color: #ccc; + font-size: 14px; + line-height: 1.7; +} + +/* Fetter Text */ +.changelog-container strong, +.changelog-container b { + color: #FFED00; + font-weight: bold; +} + +/* Kursiver Text */ +.changelog-container em, +.changelog-container i { + font-style: italic; + color: #ddd; +} + +/* Listen */ +.changelog-container ul { + margin: 0 0 15px 0; + padding-left: 25px; + list-style-type: disc; +} + +.changelog-container ol { + margin: 0 0 15px 0; + padding-left: 25px; +} + +.changelog-container li { + margin-bottom: 8px; + color: #ccc; + font-size: 14px; + line-height: 1.6; +} + +/* Nested Listen */ +.changelog-container ul ul, +.changelog-container ul ol, +.changelog-container ol ul, +.changelog-container ol ol { + margin-top: 8px; + margin-bottom: 0; +} + +.changelog-container ul ul { + list-style-type: circle; +} + +.changelog-container ul ul ul { + list-style-type: square; +} + +/* Links */ +.changelog-container a { + color: #FFED00; + text-decoration: none; + border-bottom: 1px solid transparent; + transition: border-color 0.2s; +} + +.changelog-container a:hover { + border-bottom-color: #FFED00; +} + +/* Code-Blöcke */ +.changelog-container code { + background-color: #0a0a0a; + color: #0f0; + padding: 2px 6px; + border-radius: 3px; + font-family: 'Courier New', monospace; + font-size: 13px; + border: 1px solid #222; +} + +.changelog-container pre { + background-color: #0a0a0a; + padding: 12px; + border-radius: 6px; + border: 1px solid #222; + overflow-x: auto; + margin: 0 0 15px 0; +} + +.changelog-container pre code { + background: none; + border: none; + padding: 0; + color: #0f0; +} + +/* Horizontale Linie */ +.changelog-container hr { + border: none; + border-top: 2px solid #333; + margin: 30px 0; +} + +/* Blockquote */ +.changelog-container blockquote { + border-left: 4px solid #FFED00; + padding-left: 15px; + margin: 15px 0; + color: #aaa; + font-style: italic; +} + +/* Tabellen */ +.changelog-container table { + width: 100%; + border-collapse: collapse; + margin: 0 0 15px 0; +} + +.changelog-container th, +.changelog-container td { + border: 1px solid #333; + padding: 8px 12px; + text-align: left; +} + +.changelog-container th { + background-color: #1a1a1a; + color: #FFED00; + font-weight: bold; +} + +.changelog-container tr:hover { + background-color: #0a0a0a; +} + +/* Checkboxen in Listen (für Task Lists) */ +.changelog-container input[type="checkbox"] { + margin-right: 8px; + cursor: pointer; +} + +/* Responsive - Markdown Changelog */ +@media (max-width: 767px) { + .changelog-container h1 { + font-size: 24px; + } + + .changelog-container h2 { + font-size: 20px; + } + + .changelog-container h3 { + font-size: 17px; + } + + .changelog-container h4 { + font-size: 15px; + } + + .changelog-container p, + .changelog-container li { + font-size: 13px; + } + + .changelog-container pre { + font-size: 12px; + padding: 10px; + } +} + +@media (min-width: 1024px) { + .changelog-container h1 { + font-size: 32px; + } + + .changelog-container h2 { + font-size: 26px; + } + + .changelog-container h3 { + font-size: 20px; + } + + .changelog-container h4 { + font-size: 18px; + } + + .changelog-container p, + .changelog-container li { + font-size: 15px; + } +} +/* ========================================== + DEVELOPER VIEW - MOBILE OPTIMIERUNGEN + Füge diese Regeln zu styles-complete.css hinzu + ========================================== */ + +/* Mobile-First Verbesserungen */ +@media (max-width: 767px) { + /* Developer Header - Kompakter auf Mobile */ + .developer-header { + padding: 20px 15px; + margin: 15px 10px 20px 10px; + border-radius: 12px; + } + + .developer-header h2 { + font-size: 22px; + letter-spacing: 1px; + margin-bottom: 8px; + } + + .developer-subtitle { + font-size: 12px; + } + + /* Tabs - Besseres Touch-Target */ + .developer-tabs { + padding: 10px 8px; + gap: 6px; + border-radius: 10px 10px 0 0; + } + + .dev-tab { + padding: 12px 16px; + font-size: 13px; + min-width: 100px; + border-radius: 8px 8px 0 0; + } + + /* Tab Content - Mehr Padding für Lesbarkeit */ + .dev-tab-content { + padding: 20px 12px; + border-radius: 0 0 10px 10px; + } + + /* Changelog Container - Bessere Lesbarkeit */ + .changelog-container { + font-size: 14px; + line-height: 1.7; + } + + .changelog-container h1 { + font-size: 22px; + margin-bottom: 16px; + padding-bottom: 8px; + } + + .changelog-container h2 { + font-size: 18px; + margin: 25px 0 12px 0; + padding-bottom: 6px; + } + + .changelog-container h3 { + font-size: 16px; + margin: 16px 0 10px 0; + } + + .changelog-container h4 { + font-size: 14px; + margin: 12px 0 8px 0; + } + + .changelog-container p { + font-size: 13px; + margin-bottom: 12px; + line-height: 1.6; + } + + .changelog-container ul, + .changelog-container ol { + padding-left: 20px; + margin-bottom: 12px; + } + + .changelog-container li { + font-size: 13px; + margin-bottom: 6px; + line-height: 1.5; + } + + .changelog-container code { + font-size: 12px; + padding: 2px 5px; + } + + .changelog-container pre { + padding: 10px; + font-size: 11px; + overflow-x: auto; + } + + .changelog-container hr { + margin: 20px 0; + } + + /* Info Boxes - Stack on Mobile */ + .dev-info-container { + grid-template-columns: 1fr; + gap: 12px; + } + + .dev-info-box { + padding: 15px; + } + + .dev-info-box h3 { + font-size: 16px; + margin-bottom: 12px; + padding-bottom: 10px; + } + + .dev-info-table td { + padding: 10px 0; + font-size: 12px; + } + + .dev-info-table td:first-child { + width: 45%; + } + + /* GitHub Link - Full Width auf Mobile */ + .github-link-btn { + padding: 14px 20px; + font-size: 14px; + margin: 20px 0; + } + + /* Feature Details - Kompakter */ + .feature-detail { + margin-bottom: 12px; + border-radius: 10px; + } + + .feature-detail summary { + padding: 14px 16px; + font-size: 14px; + } + + .feature-detail summary::after { + right: 16px; + font-size: 11px; + } + + .feature-content { + padding: 14px 16px; + } + + .feature-content p { + font-size: 13px; + margin-bottom: 12px; + } + + .feature-content li { + font-size: 12px; + margin-bottom: 6px; + } + + .feature-api { + padding: 10px 12px; + font-size: 11px; + } + + .feature-api code { + font-size: 11px; + padding: 2px 6px; + } + + /* Links - Größere Touch-Targets */ + .changelog-container a { + display: inline-block; + padding: 2px 0; + min-height: 30px; + line-height: 1.5; + } + + /* Blockquotes - Kompakter */ + .changelog-container blockquote { + padding-left: 12px; + margin: 12px 0; + font-size: 13px; + border-left-width: 3px; + } + + /* Tabellen - Horizontal Scroll */ + .changelog-container table { + display: block; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } + + .changelog-container th, + .changelog-container td { + padding: 8px 10px; + font-size: 12px; + white-space: nowrap; + } + + /* Bessere Touch-Feedback */ + .dev-tab:active { + transform: scale(0.96) translateY(1px); + background-color: #222; + } + + .feature-detail summary:active { + background: linear-gradient(135deg, #222 0%, #111 100%); + } + + /* Scroll-Hint für Tabs */ + .developer-tabs::after { + content: '→'; + position: absolute; + right: 5px; + top: 50%; + transform: translateY(-50%); + color: #FFED00; + font-size: 20px; + opacity: 0.5; + pointer-events: none; + animation: scrollHint 2s ease-in-out infinite; + } + + @keyframes scrollHint { + 0%, 100% { opacity: 0.5; transform: translateY(-50%) translateX(0); } + 50% { opacity: 0.8; transform: translateY(-50%) translateX(5px); } + } + + /* Verstecke Scroll-Hint wenn am Ende */ + .developer-tabs::-webkit-scrollbar-thumb:hover ~ .developer-tabs::after { + opacity: 0; + } +} + +/* Extra Small Mobile - Weitere Anpassungen */ +@media (max-width: 360px) { + .developer-header h2 { + font-size: 20px; + } + + .developer-subtitle { + font-size: 11px; + } + + .dev-tab { + padding: 10px 14px; + font-size: 12px; + min-width: 90px; + } + + .dev-tab-content { + padding: 16px 10px; + } + + .changelog-container h1 { + font-size: 20px; + } + + .changelog-container h2 { + font-size: 16px; + } + + .changelog-container h3 { + font-size: 15px; + } + + .changelog-container h4 { + font-size: 13px; + } + + .changelog-container p, + .changelog-container li { + font-size: 12px; + } + + .dev-info-box { + padding: 12px; + } + + .github-link-btn { + font-size: 13px; + padding: 12px 16px; + } +} + +/* Landscape Mobile - Horizontal Optimierung */ +@media (max-width: 767px) and (orientation: landscape) { + .developer-header { + padding: 15px; + margin: 10px; + } + + .developer-header h2 { + font-size: 20px; + } + + .dev-tab-content { + max-height: calc(100vh - 200px); + overflow-y: auto; + -webkit-overflow-scrolling: touch; + } +} \ No newline at end of file
    Version:30.0.0
    Version:30.0
    Release:10.02.2026
    Lizenz:MIT
    Status:✅ Stabil