diff --git a/docs/architecture/backend.md b/docs/architecture/backend.md
index 146d4df..1c28ecd 100644
--- a/docs/architecture/backend.md
+++ b/docs/architecture/backend.md
@@ -29,23 +29,33 @@ Das Backend ist in Node.js/Express geschrieben und in **Services** aufgeteilt, d
### Zustandsübergänge
+
+
```mermaid
-stateDiagram-v2
- [*] --> IDLE
- IDLE --> ANALYZING: analyzeDisc()
- ANALYZING --> METADATA_SELECTION: MakeMKV fertig
- METADATA_SELECTION --> READY_TO_START: selectMetadata()
- READY_TO_START --> RIPPING: startJob()
- RIPPING --> MEDIAINFO_CHECK: MKV erstellt
- MEDIAINFO_CHECK --> READY_TO_ENCODE: Tracks analysiert
- READY_TO_ENCODE --> ENCODING: confirmEncode()
- ENCODING --> FINISHED: HandBrake fertig
- ENCODING --> ERROR: Fehler
- RIPPING --> ERROR: Fehler
- ERROR --> IDLE: retryJob() / cancel
- FINISHED --> IDLE: cancel / neue Disc
+flowchart LR
+ START(( )) --> IDLE
+ IDLE -->|analyzeDisc()| ANALYZING[ANALYZING]
+ ANALYZING -->|MakeMKV fertig| META[METADATA\nSELECTION]
+ META -->|selectMetadata()| RTS[READY_TO\nSTART]
+ RTS -->|startJob()| RIP[RIPPING]
+ RIP -->|MKV erstellt| MIC[MEDIAINFO\nCHECK]
+ MIC -->|Tracks analysiert| RTE[READY_TO\nENCODE]
+ RTE -->|confirmEncode()| ENC[ENCODING]
+ ENC -->|HandBrake fertig| FIN([FINISHED])
+ ENC -->|Fehler| ERR([ERROR])
+ RIP -->|Fehler| ERR
+ ERR -->|retryJob() / cancel| IDLE
+ FIN -->|cancel / neue Disc| IDLE
+
+ style FIN fill:#e8f5e9,stroke:#66bb6a,color:#2e7d32
+ style ERR fill:#ffebee,stroke:#ef5350,color:#c62828
+ style ENC fill:#f3e5f5,stroke:#ab47bc,color:#6a1b9a
+ style RIP fill:#e3f2fd,stroke:#42a5f5,color:#1565c0
+ style MIC fill:#e3f2fd,stroke:#42a5f5,color:#1565c0
```
+
+
---
## diskDetectionService.js
diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md
index 4531c6d..ccaaca9 100644
--- a/docs/getting-started/quickstart.md
+++ b/docs/getting-started/quickstart.md
@@ -6,24 +6,106 @@ Nach der [Installation](installation.md) und [Konfiguration](configuration.md) f
## Übersicht: Pipeline-Zustände
-```mermaid
-stateDiagram-v2
- direction LR
- [*] --> IDLE
- IDLE --> DISC_DETECTED: Disc eingelegt
- DISC_DETECTED --> METADATA_SELECTION: Analyse gestartet
- METADATA_SELECTION --> READY_TO_START: Metadaten bestätigt\n(keine Obfuskierung)
- METADATA_SELECTION --> WAITING_FOR_USER_DECISION: Obfuskierung erkannt\n→ Playlist wählen
- WAITING_FOR_USER_DECISION --> READY_TO_START: Playlist bestätigt
- READY_TO_START --> MEDIAINFO_CHECK: Vorhandene Raw-Datei\ngefunden
- READY_TO_START --> RIPPING: Ripping starten
- RIPPING --> MEDIAINFO_CHECK: MakeMKV fertig
- MEDIAINFO_CHECK --> READY_TO_ENCODE: Track-Review bereit
- READY_TO_ENCODE --> ENCODING: Encode bestätigt
- ENCODING --> FINISHED: Erfolg
- ENCODING --> ERROR: Fehler
- RIPPING --> ERROR: Fehler
-```
+
+
+
+
1
+
DISC_DETECTED
+
Disc erkannt
+
+
+
2
+
METADATA_SELECTION
+
Scan & Metadaten
+
+
+
⚠
+
WAITING_FOR_USER_DECISION
+
Playlist wählen
(nur bei Obfusk.)
+
+
+
3
+
READY_TO_START
+
Bereit
+
+
+
4
+
RIPPING
+
MakeMKV
+
+
+
5
+
MEDIAINFO_CHECK
+
HandBrake-Scan
+
+
+
6
+
READY_TO_ENCODE
+
Track-Review
+
+
+
7
+
ENCODING
+
HandBrake
+
+
+
8
+
POST_ENCODE_SCRIPTS
+
Skripte
(optional)
+
+
+
✓
+
FINISHED
+
Fertig
+
+
+
+**Legende:** ● Warten | ■ Läuft automatisch | ■ Benutzeraktion | ⚠ Optional | ■ Encodierung | ✓ Fertig
+
+??? note "Vollständiges Zustandsdiagramm (inkl. Fehler- & Alternativpfade)"
+
+
+
+ ```mermaid
+ flowchart LR
+ START(( )) --> IDLE
+
+ IDLE -->|Disc erkannt| DD[DISC_DETECTED]
+ DD -->|Analyse starten| META[METADATA\nSELECTION]
+
+ META -->|1 Kandidat| RTS[READY_TO\nSTART]
+ META -->|mehrere Kandidaten| WUD[WAITING_FOR\nUSER_DECISION]
+ WUD -->|Playlist bestätigt| RTS
+
+ RTS -->|Raw vorhanden| MIC[MEDIAINFO\nCHECK]
+ RTS -->|Ripping starten| RIP[RIPPING]
+ RIP -->|MKV fertig| MIC
+ RIP -->|Fehler| ERR
+
+ MIC --> RTE[READY_TO\nENCODE]
+ RTE -->|bestätigt| ENC[ENCODING]
+
+ ENC -->|mit Skripten| PES[POST_ENCODE\nSCRIPTS]
+ ENC -->|ohne Skripte| FIN([FINISHED])
+ ENC -->|Fehler| ERR
+
+ PES -->|Erfolg| FIN
+ PES -->|Fehler| ERR
+
+ ERR([ERROR]) -->|Retry / Cancel| IDLE
+
+ style FIN fill:#e8f5e9,stroke:#66bb6a,color:#2e7d32
+ style ERR fill:#ffebee,stroke:#ef5350,color:#c62828
+ style WUD fill:#fff8e1,stroke:#ffa726,color:#e65100
+ style PES fill:#f3e5f5,stroke:#ab47bc,color:#6a1b9a
+ style ENC fill:#f3e5f5,stroke:#ab47bc,color:#6a1b9a
+ ```
+
+
---
diff --git a/docs/index.md b/docs/index.md
index 3947fa9..7a5b7fd 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -112,19 +112,31 @@ open http://localhost:5173
## Pipeline-Überblick
+
+
```mermaid
-stateDiagram-v2
- [*] --> IDLE
- IDLE --> ANALYZING: Disc erkannt
- ANALYZING --> METADATA_SELECTION: Analyse abgeschlossen
- METADATA_SELECTION --> READY_TO_START: Metadaten bestätigt
- READY_TO_START --> RIPPING: Start gedrückt
- RIPPING --> MEDIAINFO_CHECK: MKV erstellt
- MEDIAINFO_CHECK --> READY_TO_ENCODE: Tracks analysiert
- READY_TO_ENCODE --> ENCODING: Encode bestätigt
- ENCODING --> FINISHED: Encoding fertig
- ENCODING --> ERROR: Fehler
- RIPPING --> ERROR: Fehler
- ERROR --> [*]
- FINISHED --> [*]
+flowchart LR
+ IDLE --> DD[DISC_DETECTED]
+ DD --> META[METADATA\nSELECTION]
+ META -->|1 Kandidat| RTS[READY_TO\nSTART]
+ META -->|Obfuskierung| WUD[WAITING_FOR\nUSER_DECISION]
+ WUD --> RTS
+ RTS --> RIP[RIPPING]
+ RTS -->|Raw vorhanden| MIC
+ RIP --> MIC[MEDIAINFO\nCHECK]
+ MIC --> RTE[READY_TO\nENCODE]
+ RTE --> ENC[ENCODING]
+ ENC --> PES[POST_ENCODE\nSCRIPTS]
+ ENC -->|keine Skripte| FIN([FINISHED])
+ PES --> FIN
+ ENC --> ERR([ERROR])
+ RIP --> ERR
+
+ style FIN fill:#e8f5e9,stroke:#66bb6a,color:#2e7d32
+ style ERR fill:#ffebee,stroke:#ef5350,color:#c62828
+ style WUD fill:#fff8e1,stroke:#ffa726,color:#e65100
+ style PES fill:#f3e5f5,stroke:#ab47bc,color:#6a1b9a
+ style ENC fill:#f3e5f5,stroke:#ab47bc,color:#6a1b9a
```
+
+
diff --git a/docs/pipeline/workflow.md b/docs/pipeline/workflow.md
index 69de26a..abcacd1 100644
--- a/docs/pipeline/workflow.md
+++ b/docs/pipeline/workflow.md
@@ -6,40 +6,48 @@ Der Ripping-Workflow von Ripster ist als **State Machine** implementiert. Jeder
## Zustandsdiagramm
+
+
```mermaid
-stateDiagram-v2
- direction TB
- [*] --> IDLE
+flowchart LR
+ START(( )) --> IDLE
- IDLE --> DISC_DETECTED: Disc erkannt
- DISC_DETECTED --> METADATA_SELECTION: Analyse starten
+ IDLE -->|Disc erkannt| DD[DISC_DETECTED]
+ DD -->|Analyse starten| META[METADATA\nSELECTION]
- METADATA_SELECTION --> READY_TO_START: Kein Obfuskierungsverdacht\n(ein Kandidat)
- METADATA_SELECTION --> WAITING_FOR_USER_DECISION: Mehrere Playlist-Kandidaten\n→ manuelle Auswahl nötig
+ META -->|1 Kandidat| RTS[READY_TO\nSTART]
+ META -->|mehrere Kandidaten| WUD[WAITING_FOR\nUSER_DECISION]
+ WUD -->|Playlist bestätigt| RTS
- WAITING_FOR_USER_DECISION --> READY_TO_START: Playlist bestätigt
+ RTS -->|Raw vorhanden| MIC[MEDIAINFO\nCHECK]
+ RTS -->|Ripping starten| RIP[RIPPING]
+ RIP -->|MKV fertig| MIC
+ RIP -->|Fehler| ERR
- READY_TO_START --> RIPPING: Starten\n(kein Raw vorhanden)
- READY_TO_START --> MEDIAINFO_CHECK: Starten\n(Raw bereits vorhanden)
+ MIC --> RTE[READY_TO\nENCODE]
+ RTE -->|Tracks + Skripte\nbestätigt| ENC[ENCODING]
- RIPPING --> MEDIAINFO_CHECK: MKV/Backup erstellt
+ ENC -->|mit Skripten| PES[POST_ENCODE\nSCRIPTS]
+ ENC -->|ohne Skripte| FIN([FINISHED])
+ ENC -->|Fehler| ERR
- MEDIAINFO_CHECK --> READY_TO_ENCODE: Track-Scan\nabgeschlossen
+ PES -->|Erfolg| FIN
+ PES -->|Fehler| ERR
- READY_TO_ENCODE --> ENCODING: Tracks + Skripte\nbestätigt
+ ERR([ERROR]) -->|Retry / Cancel| IDLE
+ FIN -->|Neue Disc| IDLE
- ENCODING --> POST_ENCODE_SCRIPTS: Erfolg\n(Skripte konfiguriert)
- ENCODING --> FINISHED: Erfolg\n(keine Skripte)
- POST_ENCODE_SCRIPTS --> FINISHED: Alle Skripte\nerfolgt
-
- RIPPING --> ERROR: Fehler
- ENCODING --> ERROR: Fehler
- POST_ENCODE_SCRIPTS --> ERROR: Skript-Fehler
-
- ERROR --> IDLE: Abbrechen / Retry
- FINISHED --> IDLE: Neue Disc
+ style FIN fill:#e8f5e9,stroke:#66bb6a,color:#2e7d32
+ style ERR fill:#ffebee,stroke:#ef5350,color:#c62828
+ style WUD fill:#fff8e1,stroke:#ffa726,color:#e65100
+ style PES fill:#f3e5f5,stroke:#ab47bc,color:#6a1b9a
+ style ENC fill:#f3e5f5,stroke:#ab47bc,color:#6a1b9a
+ style RIP fill:#e3f2fd,stroke:#42a5f5,color:#1565c0
+ style MIC fill:#e3f2fd,stroke:#42a5f5,color:#1565c0
```
+
+
---
## Zustandsbeschreibungen
diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css
index cdfd134..9c24353 100644
--- a/docs/stylesheets/extra.css
+++ b/docs/stylesheets/extra.css
@@ -37,13 +37,99 @@
font-size: 0.85em;
}
-/* Mermaid diagrams */
+/* Mermaid diagrams – standard */
.md-typeset .mermaid {
display: flex;
justify-content: center;
margin: 1.5rem 0;
}
+/* Large pipeline flowchart: horizontal scroll + min-height */
+.pipeline-diagram {
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+ margin: 1.5rem 0;
+ padding-bottom: 0.5rem;
+}
+
+.pipeline-diagram .mermaid {
+ min-width: 900px;
+ justify-content: flex-start;
+}
+
+.pipeline-diagram .mermaid svg {
+ min-width: 900px;
+ height: auto;
+}
+
+/* Pipeline step track */
+.pipeline-steps {
+ display: flex;
+ flex-wrap: nowrap;
+ gap: 0;
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+ padding: 1rem 0 1.5rem 0;
+ margin: 1.5rem 0;
+ scrollbar-width: thin;
+}
+
+.pipeline-step {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ min-width: 110px;
+ flex: 0 0 auto;
+ position: relative;
+}
+
+.pipeline-step:not(:last-child)::after {
+ content: '→';
+ position: absolute;
+ right: -14px;
+ top: 22px;
+ font-size: 1.2rem;
+ color: var(--md-default-fg-color--light);
+ z-index: 1;
+}
+
+.pipeline-step-badge {
+ width: 44px;
+ height: 44px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 0.75rem;
+ font-weight: 700;
+ margin-bottom: 0.5rem;
+ border: 2px solid transparent;
+}
+
+.pipeline-step-label {
+ font-size: 0.7rem;
+ text-align: center;
+ line-height: 1.2;
+ max-width: 90px;
+ color: var(--md-default-fg-color);
+}
+
+.pipeline-step-sub {
+ font-size: 0.6rem;
+ color: var(--md-default-fg-color--light);
+ text-align: center;
+ margin-top: 0.2rem;
+}
+
+/* Step colors */
+.step-idle { background: #eceff1; color: #546e7a; border-color: #90a4ae; }
+.step-user { background: #e8eaf6; color: #3949ab; border-color: #7986cb; }
+.step-running { background: #e3f2fd; color: #1565c0; border-color: #42a5f5; }
+.step-wait { background: #fff8e1; color: #e65100; border-color: #ffa726; }
+.step-encode { background: #f3e5f5; color: #6a1b9a; border-color: #ab47bc; }
+.step-done { background: #e8f5e9; color: #2e7d32; border-color: #66bb6a; }
+.step-error { background: #ffebee; color: #c62828; border-color: #ef5350; }
+
/* Table improvements */
.md-typeset table:not([class]) {
width: 100%;