Compare commits

..

10 Commits

Author SHA1 Message Date
ab58cde4d6 docs: delete README 2026-02-23 09:05:43 +00:00
b5d526f18b docs: delete IT_Abteilung/Willkomen 2026-02-23 09:05:23 +00:00
5922dafa17 docs: create IT_Abteilung/wiki 2026-02-23 09:04:59 +00:00
c4e78bc400 docs: update IT_Abteilung/n8n 2026-02-23 08:50:39 +00:00
ca3bad7f62 docs: create IT_Abteilung/n8n 2026-02-23 08:44:22 +00:00
Jane Doe
f49fb7715e docs: add all untracked content 2026-02-19 08:13:19 +00:00
590f1323c7 docs: create home 2026-02-17 12:49:52 +00:00
8772fab75c docs: create IT_Abteilung/Willkomen 2026-02-17 12:41:54 +00:00
b4363897fe Update home.md 2026-02-17 12:33:47 +00:00
484f494fc9 docs: upload appicon_1024x1024-01.png 2026-02-17 12:32:53 +00:00
5 changed files with 337 additions and 703 deletions

146
IT_Abteilung/n8n.md Normal file
View File

@@ -0,0 +1,146 @@
---
title: n8n Dokumentation
description:
published: true
date: 2026-02-23T08:50:38.634Z
tags:
editor: markdown
dateCreated: 2026-02-23T08:44:20.329Z
---
# 🛠️ n8n Instanz-Dokumentation: n8n.profice.de
Diese Dokumentation beschreibt die Konfiguration, den Betrieb und die Nutzung der n8n-Automatisierungsinstanz unter der Domain **n8n.profice.de**.
---
## 1. Architektur-Übersicht
Die n8n-Instanz ist in einer hochsicheren Umgebung isoliert. Sie ist **nicht** über das öffentliche Internet erreichbar.
* **Host:** `n8n.profice.de`
* **Bereitstellung:** Docker & Docker Compose
* **Reverse Proxy:** Traefik (mit automatischer TLS-Verschlüsselung)
* **Netzwerksicherheit:** Zugriff ausschließlich über **WireGuard VPN**
---
## 2. Sicherheitskonzept (Zero-Exposure)
Um maximale Sicherheit für unsere Workflows zu gewährleisten, folgt das System dem Prinzip des "Least Privilege Access":
1. **VPN-Tunnel:** Der Server akzeptiert Pakete für den Traefik-Proxy nur, wenn diese über das virtuelle WireGuard-Interface eingehen.
2. **IP-Whitelisting:** In der Firewall (UFW/Iptables) sind die Ports 80 und 443 für das öffentliche Interface gesperrt und nur für das VPN-Subnetz (z.B. `10.8.0.0/24`) freigegeben.
3. **End-to-End Verschlüsselung:** Trotz VPN wird der Verkehr innerhalb des Tunnels zusätzlich via HTTPS (Let's Encrypt) verschlüsselt.
---
## 3. Installation & Konfiguration
### 3.1 Docker Compose Setup
Die Instanz wird über eine `docker-compose.yml` Datei verwaltet. Hier ist die Konfiguration, die mit Traefik kommuniziert:
```yaml
version: '3.8'
services:
n8n:
image: n8nio/n8n:latest
container_name: n8n_app
restart: always
environment:
- N8N_HOST=n8n.profice.de
- N8N_PORT=5678
- N8N_PROTOCOL=https
- NODE_ENV=production
- WEBHOOK_URL=[https://n8n.profice.de/](https://n8n.profice.de/)
- GENERIC_TIMEZONE=Europe/Berlin
volumes:
- /opt/n8n/data:/home/node/.n8n
networks:
- traefik_network
labels:
- "traefik.enable=true"
- "traefik.http.routers.n8n.rule=Host(`n8n.profice.de`)"
- "traefik.http.routers.n8n.entrypoints=websecure"
- "traefik.http.routers.n8n.tls.certresolver=myresolver"
- "traefik.http.services.n8n.loadbalancer.server.port=5678"
networks:
traefik_network:
external: true
```
### 3.2 Traefik Integration
Traefik fungiert als zentraler Edge-Router und übernimmt die SSL-Terminierung. Da die Instanz hinter einem VPN liegt und nicht über das öffentliche Internet für eine HTTP-01-Challenge erreichbar ist, wird die **DNS-01-Challenge** empfohlen, um gültige Let's Encrypt Zertifikate zu erhalten.
* **Automatische Erkennung:** Durch Docker-Labels erkennt Traefik den n8n-Container automatisch.
* **Sicherheit:** Traefik leitet Anfragen nur weiter, wenn der Host-Header exakt `n8n.profice.de` entspricht.
---
## 4. Nutzung und Zugriff
Um die n8n-Plattform zu nutzen, müssen die folgenden Schritte auf dem Endgerät des Benutzers durchgeführt werden:
### 4.1 VPN-Verbindung (WireGuard)
Ein Zugriff ohne aktiven VPN-Tunnel ist technisch ausgeschlossen.
1. Öffnen Sie den **WireGuard Client**.
2. Aktivieren Sie den Tunnel für das Profil `profice-intern`.
3. Vergewissern Sie sich, dass der Status auf "Aktiv" steht.
### 4.2 Web-Interface
1. Öffnen Sie einen Browser Ihrer Wahl.
2. Rufen Sie die Adresse [https://n8n.profice.de](https://n8n.profice.de) auf.
3. Melden Sie sich mit Ihren Benutzerdaten an.
> [!IMPORTANT]
> Sollten Sie eine Fehlermeldung wie "DNS_PROBE_FINISHED_NXDOMAIN" erhalten, prüfen Sie bitte, ob Ihr WireGuard-Tunnel die DNS-Anfragen korrekt an den internen DNS-Server weiterleitet.
---
## 5. Wartung und Updates
### 5.1 n8n aktualisieren
Da n8n in einem Docker-Container läuft, ist der Update-Prozess standardisiert:
```bash
# Zum Installationsverzeichnis navigieren
cd /opt/n8n-docker
# Neueste Version vom Docker Hub beziehen
docker-compose pull
# Container mit der neuen Version neu starten
docker-compose up -d
```
### 5.2 Backup-Strategie
Der Schutz Ihrer Automatisierungsdaten ist essenziell. Da n8n alle Konfigurationen, Anmeldedaten und Workflows lokal speichert, muss das Datenverzeichnis regelmäßig gesichert werden.
* **Datenverzeichnis:** `/opt/n8n/data` (enthält die SQLite-Datenbank `database.sqlite`, Verschlüsselungs-Keys und binäre Anhänge).
* **Häufigkeit:** Es wird ein tägliches Backup dieses Verzeichnisses empfohlen.
* **Vorgehensweise:** Sichern Sie das Verzeichnis idealerweise im gestoppten Zustand der Container oder nutzen Sie Dateisystem-Snapshots.
* **Manueller Export:** Einzelne Workflows können jederzeit über die n8n-Benutzeroberfläche als `.json` Dateien exportiert und in einem Git-Repository (z.B. GitLab/GitHub) versioniert werden.
---
## 6. Fehlerbehebung (Troubleshooting)
Sollten Probleme beim Zugriff auf **n8n.profice.de** auftreten, nutzen Sie bitte die folgende Tabelle zur ersten Diagnose:
| Symptom | Mögliche Ursache | Lösung |
| :--- | :--- | :--- |
| **Seite lädt unendlich / Timeout** | WireGuard-Tunnel ist inaktiv. | Prüfen Sie Ihren WireGuard-Client und die Verbindung zum VPN-Server. |
| **504 Gateway Timeout** | Der n8n-Dienst reagiert nicht oder der Container ist abgestürzt. | Prüfen Sie den Status mit `docker ps`. Starten Sie ggf. mit `docker-compose restart n8n` neu. |
| **403 Forbidden** | Zugriff erfolgt von einer nicht autorisierten IP-Adresse. | Stellen Sie sicher, dass Ihr Traffic korrekt durch den VPN-Tunnel geroutet wird (IP-Check). |
| **DNS_PROBE_FINISHED_NXDOMAIN** | Die Domain kann intern nicht aufgelöst werden. | Prüfen Sie, ob der im WireGuard-Profil hinterlegte DNS-Server erreichbar ist. |
| **Workflows werden nicht ausgeführt** | Datenbank-Lock oder fehlende Ressourcen. | Prüfen Sie die Logs mittels `docker logs --tail 50 n8n_app`. |
---
**Dokumentationsstatus:** Aktiv ✅
**Verantwortlich:** IT-Abteilung / DevOps
**Letzte Aktualisierung:** 23.02.2026

152
IT_Abteilung/wiki.md Normal file
View File

@@ -0,0 +1,152 @@
---
title: Wiki.js Profice Dokumentation
description:
published: true
date: 2026-02-23T09:04:58.250Z
tags:
editor: markdown
dateCreated: 2026-02-23T09:04:58.250Z
---
# 📚 Wiki.js Instanz-Dokumentation: wiki.profice.de
Diese Dokumentation beschreibt die Einrichtung, den Betrieb und die Synchronisations-Logik der zentralen Wissensdatenbank **wiki.profice.de**.
---
## 1. Architektur-Überblick
Wiki.js dient als zentrales Dokumentations-Tool und ist tief in unsere Infrastruktur integriert. Die Datenhaltung erfolgt redundant durch eine Kopplung mit unserem internen Git-System.
* **Domain:** `wiki.profice.de`
* **Plattform:** Wiki.js (Node.js Applikation)
* **Datenbank:** PostgreSQL (Docker)
* **Reverse Proxy:** Traefik
* **Versionskontrolle:** Gitea (`git.profice.de`)
* **Netzwerk:** Zugriff nur via **WireGuard VPN**
---
## 2. Sicherheits- und Netzwerkzugriff
### 2.1 VPN-Beschränkung (WireGuard)
Die Instanz `wiki.profice.de` ist **nicht** öffentlich erreichbar. Der Zugriff wird durch den Traefik-Proxy streng auf Anfragen aus dem WireGuard-Tunnel beschränkt.
* **Voraussetzung:** Ein aktiver WireGuard-Tunnel mit Zugriff auf das Netzsegment von `profice.de`.
* **DNS:** Die interne Auflösung der Domain erfolgt nur bei bestehender VPN-Verbindung.
### 2.2 TLS-Verschlüsselung
Obwohl die Verbindung über einen verschlüsselten VPN-Tunnel erfolgt, wird der Traffic zusätzlich durch **TLS-Zertifikate** (via Let's Encrypt / Traefik) gesichert, um "Man-in-the-Middle"-Angriffe innerhalb des Netzwerks zu verhindern.
---
## 3. Technische Konfiguration (Docker)
Die Bereitstellung erfolgt über Docker Compose. Wiki.js benötigt eine PostgreSQL-Datenbank für den Betrieb.
### 3.1 Docker Compose Beispiel
```yaml
version: "3.8"
services:
db:
image: postgres:15-alpine
container_name: wikijs_db
environment:
- POSTGRES_DB=wiki
- POSTGRES_USER=wikijs
- POSTGRES_PASSWORD=dein_sicheres_passwort
volumes:
- /opt/wiki/db-data:/var/lib/postgresql/data
networks:
- internal_network
wiki:
image: requarks/wiki:2
container_name: wikijs_app
depends_on:
- db
environment:
- DB_TYPE=postgres
- DB_HOST=db
- DB_PORT=5432
- DB_USER=wikijs
- DB_PASS=dein_sicheres_passwort
- DB_NAME=wiki
volumes:
- /opt/wiki/config:/wiki/config
networks:
- internal_network
- traefik_network
labels:
- "traefik.enable=true"
- "traefik.http.routers.wiki.rule=Host(`wiki.profice.de`)"
- "traefik.http.routers.wiki.entrypoints=websecure"
- "traefik.http.routers.wiki.tls.certresolver=myresolver"
networks:
traefik_network:
external: true
internal_network:
external: false
```
## 4. Gitea-Integration (Git Storage)
Ein wesentliches Merkmal dieser Instanz ist die bidirektionale Synchronisation mit unserem internen Gitea-Server. Dies stellt sicher, dass alle Dokumente als reine Markdown-Dateien versioniert und auch bei einem Datenbankausfall gesichert sind.
* **Repository-URL:** `https://git.profice.de/it-docs/wiki-storage.git`
* **Synchronisations-Modus:** Bidirektional (Push bei Änderungen im Wiki / Pull bei Änderungen im Repository).
* **Authentifizierung:** Die Kopplung erfolgt über einen **Personal Access Token**, der in Gitea für den Dokumentations-Account generiert wurde.
### Konfigurationsschritte im Wiki:
1. Navigieren Sie zu **Administration > Storage**.
2. Wählen Sie **Git** aus der Liste der verfügbaren Storage-Module.
3. Tragen Sie die URL von `git.profice.de` und die entsprechenden Anmeldedaten ein.
4. Stellen Sie das Synchronisations-Intervall ein (Standard: 5 Minuten).
---
## 5. Verwendung und Best Practices
### 5.1 Editor-Wahl
Für technische Dokumentationen ist zwingend der **Markdown-Editor** zu verwenden. Dies gewährleistet die volle Kompatibilität mit dem Gitea-Storage und ermöglicht eine saubere Versionskontrolle.
### 5.2 Medien und Anhänge
Bilder sollten direkt per Drag-and-Drop in den Editor gezogen werden. Wiki.js speichert diese im lokalen `/assets` Verzeichnis, welches automatisch mit in das Git-Repository übertragen wird.
### 5.3 Zugriffsschutz
Da das Wiki sensible Infrastruktur-Details enthält (wie z.B. n8n-Konfigurationen), ist der Zugriff strikt auf Benutzer innerhalb des **WireGuard-VPN-Tunnels** beschränkt. Traefik blockiert alle Anfragen, die von externen (öffentlichen) IP-Adressen kommen.
---
## 6. Wartung und Fehlerbehebung
### 6.1 System-Updates
Die Wartung erfolgt über Docker. Vor jedem Update wird ein Snapshot der PostgreSQL-Datenbank empfohlen.
```bash
# Verzeichnis der Docker-Installation aufrufen
cd /opt/wiki-js
# Neue Images ziehen und Container neu starten
docker-compose pull
docker-compose up -d
```
### 6.2 Troubleshooting-Guide
Falls Probleme mit der Instanz **wiki.profice.de** auftreten, nutzen Sie bitte die folgende Übersicht zur Fehlerbehebung:
| Symptom | Mögliche Ursache | Lösung |
| :--- | :--- | :--- |
| **Gitea-Sync schlägt fehl** | Der Personal Access Token ist abgelaufen oder die Repository-Berechtigungen wurden geändert. | Erzeugen Sie einen neuen Token auf `git.profice.de` und aktualisieren Sie diesen in den Wiki.js Storage-Einstellungen. |
| **Seite nicht erreichbar** | Die WireGuard-Verbindung ist inaktiv oder der Client befindet sich im falschen IP-Bereich. | Prüfen Sie Ihren VPN-Status. Stellen Sie sicher, dass der DNS-Server die IP korrekt auflöst. |
| **Bilder laden nicht** | Die Git-Synchronisation hat einen Konflikt in den `/assets` erzeugt. | Überprüfen Sie das Repository auf `git.profice.de` auf Merge-Konflikte und führen Sie diese ggf. manuell zusammen. |
| **"Bad Gateway" (502)** | Der Wiki.js-Container oder der Postgres-Container ist abgestürzt. | Prüfen Sie den Status mit `docker ps`. Starten Sie die Container mit `docker-compose restart` neu. |
| **Änderungen fehlen** | Die bidirektionale Synchronisation ist verzögert. | Erzwingen Sie einen manuellen "Import" über das Administrations-Panel unter "Storage". |
---
**Dokumentationsstatus:** Aktiv ✅
**Verantwortlich:** IT-Administration / DevOps
**Letzte Aktualisierung:** 23.02.2026

BIN
appicon_1024x1024-01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

39
home.md Normal file
View File

@@ -0,0 +1,39 @@
---
title: Start Seite
description:
published: true
date: 2026-02-17T12:49:51.801Z
tags:
editor: markdown
dateCreated: 2026-02-17T12:49:50.713Z
---
<div class="profice-wrapper">
<div class="hero-container">
<div class="hero-text">
<h1>Profice <span>Wiki</span></h1>
<div class="info-card">
Willkommen im offiziellen Portal für Dokumentation und Wissensmanagement der <strong>Profice</strong>. <br><br>
Dieser Hub dient als zentrale Quelle für technische Leitfäden, Prozessabläufe und die gesamte interne Wissensdatenbank.
</div>
<div class="btn-row">
<a href="/new" class="btn-profice outline">Durchsuchen</a>
<a href="/new" class="btn-profice outline">Erstellen</a>
</div>
</div>
<div class="hex-visual">
<div class="hex-shape">
<div style="font-size: 40px; margin-bottom: 10px;">📄</div>
<div style="font-weight: 800; letter-spacing: 2px;">DOCUMENTATION</div>
</div>
</div>
</div>
</div>
---
### HYPERLINKS
| 📁 Abteilung | 🛠 Support | 📈 Projekte |
| :--- | :--- | :--- |
| [Entwicklung](/dev) | [IT-Hilfe](/it) | [Aktivitäten](/projects) |
| [Marketing](/marketing) | [Onboarding](/hr) | [Archiv](/archive) |

View File

@@ -1,703 +0,0 @@
/* ==========================================================================
Wiki.js Custom Theme - Profice Corporate Design
Optimized CSS Injection with Light/Dark Mode Support
========================================================================== */
/* ===== CSS VARIABLES - LIGHT MODE (Default) ===== */
:root {
/* Core Colors */
--pf-bg-body: #F7F7F0;
--pf-bg-content: #FFFFFF;
--pf-bg-sidebar: #4F4747;
--pf-bg-header: #4F4747;
/* Text Colors */
--pf-text-primary: #4F4747;
--pf-text-secondary: #6B6363;
--pf-text-muted: #8A8A7A;
--pf-text-inverse: #F7F7F0;
/* Accent Colors */
--pf-accent-teal: #5A9E96;
--pf-accent-teal-hover: #4A8E86;
--pf-accent-orange: #D4864A;
--pf-accent-green: #7FB882;
/* UI Elements */
--pf-border-light: rgba(79, 71, 71, 0.1);
--pf-border-medium: rgba(79, 71, 71, 0.2);
--pf-shadow-soft: 0 2px 12px rgba(79, 71, 71, 0.08);
--pf-shadow-medium: 0 4px 20px rgba(79, 71, 71, 0.12);
--pf-shadow-card: 0 1px 3px rgba(79, 71, 71, 0.06), 0 4px 16px rgba(79, 71, 71, 0.06);
/* Transitions */
--pf-transition: 0.2s ease;
--pf-transition-slow: 0.3s ease;
/* Spacing */
--pf-radius-sm: 6px;
--pf-radius-md: 10px;
--pf-radius-lg: 16px;
--pf-radius-pill: 50px;
}
/* ===== CSS VARIABLES - DARK MODE ===== */
.theme--dark,
[data-theme="dark"],
.dark-mode {
--pf-bg-body: #1E1E1E;
--pf-bg-content: #2D2D2D;
--pf-bg-sidebar: #252525;
--pf-bg-header: #252525;
--pf-text-primary: #E8E8E8;
--pf-text-secondary: #B0B0B0;
--pf-text-muted: #888888;
--pf-text-inverse: #1E1E1E;
--pf-border-light: rgba(255, 255, 255, 0.08);
--pf-border-medium: rgba(255, 255, 255, 0.15);
--pf-shadow-soft: 0 2px 12px rgba(0, 0, 0, 0.3);
--pf-shadow-medium: 0 4px 20px rgba(0, 0, 0, 0.4);
--pf-shadow-card: 0 1px 3px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.2);
}
/* ===== GLOBAL RESET & BASE ===== */
body {
background-color: var(--pf-bg-body) !important;
color: var(--pf-text-primary) !important;
font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, Roboto, sans-serif !important;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* ===== HEADER / APP BAR ===== */
header,
.v-app-bar,
.v-toolbar,
.application--wrap > header {
background-color: var(--pf-bg-header) !important;
border-bottom: none !important;
box-shadow: var(--pf-shadow-soft) !important;
}
.v-toolbar__content {
background: transparent !important;
border: none !important;
}
/* Header elements */
.v-app-bar .v-toolbar__title,
.v-toolbar__title,
header .v-btn,
header .v-icon,
.v-app-bar .v-icon {
color: var(--pf-text-inverse) !important;
}
/* Header buttons - clean circular style */
header .v-btn,
.v-app-bar .v-btn {
background: rgba(255, 255, 255, 0.1) !important;
border-radius: 50% !important;
box-shadow: none !important;
min-width: 40px !important;
width: 40px !important;
height: 40px !important;
padding: 0 !important;
transition: var(--pf-transition) !important;
}
header .v-btn:hover,
.v-app-bar .v-btn:hover {
background: rgba(255, 255, 255, 0.2) !important;
transform: none !important;
}
/* ===== SEARCH BAR - Clean Pill Style ===== */
.v-app-bar .v-text-field,
header .search-box,
.v-toolbar .v-input,
.v-app-bar .v-input {
background: rgba(255, 255, 255, 0.12) !important;
border: none !important;
border-radius: var(--pf-radius-pill) !important;
box-shadow: none !important;
max-width: 400px !important;
}
.v-app-bar .v-text-field input,
.v-app-bar .v-input input {
color: var(--pf-text-inverse) !important;
padding: 8px 16px !important;
}
.v-app-bar .v-text-field input::placeholder,
.v-app-bar .v-input input::placeholder {
color: rgba(255, 255, 255, 0.5) !important;
}
/* Remove search field underlines and outlines */
.v-app-bar .v-text-field .v-input__slot::before,
.v-app-bar .v-text-field .v-input__slot::after,
.v-app-bar .v-input .v-input__slot::before,
.v-app-bar .v-input .v-input__slot::after {
display: none !important;
border: none !important;
}
.v-app-bar .v-text-field .v-input__slot,
.v-app-bar .v-input .v-input__slot {
background: transparent !important;
box-shadow: none !important;
border: none !important;
}
.v-app-bar .v-text-field.v-input--is-focused .v-input__slot,
.v-app-bar .v-input.v-input--is-focused .v-input__slot {
background: rgba(255, 255, 255, 0.18) !important;
}
/* ===== SIDEBAR / NAVIGATION DRAWER ===== */
.v-navigation-drawer,
.v-navigation-drawer__content {
background-color: var(--pf-bg-sidebar) !important;
border-right: none !important;
}
/* Sidebar text */
.v-navigation-drawer .v-list-item__title,
.v-navigation-drawer .v-list-item__subtitle,
.v-navigation-drawer .v-icon {
color: var(--pf-text-inverse) !important;
}
/* Sidebar navigation items */
.v-navigation-drawer .v-list-item {
margin: 4px 8px !important;
border-radius: var(--pf-radius-sm) !important;
transition: var(--pf-transition) !important;
border: none !important;
min-height: 40px !important;
}
.v-navigation-drawer .v-list-item:hover {
background: rgba(255, 255, 255, 0.08) !important;
}
/* Active sidebar item - subtle highlight, no thick border */
.v-navigation-drawer .v-list-item--active,
.v-navigation-drawer .v-list-item.v-list-item--active {
background: rgba(90, 158, 150, 0.25) !important;
border: none !important;
}
.v-navigation-drawer .v-list-item--active .v-list-item__title,
.v-navigation-drawer .v-list-item--active .v-icon {
color: #FFFFFF !important;
font-weight: 600 !important;
}
/* Sidebar section headers */
.v-navigation-drawer .v-subheader {
color: var(--pf-accent-orange) !important;
font-size: 11px !important;
font-weight: 700 !important;
text-transform: uppercase !important;
letter-spacing: 0.5px !important;
}
/* ===== MAIN CONTENT AREA ===== */
main,
.v-main,
.v-main__wrap {
background-color: var(--pf-bg-body) !important;
}
/* Content container - Clean white card */
.container,
.v-container,
.page-col-content,
.contents {
background: var(--pf-bg-content) !important;
border-radius: var(--pf-radius-lg) !important;
box-shadow: var(--pf-shadow-card) !important;
padding: 32px !important;
margin: 24px !important;
border: 1px solid var(--pf-border-light) !important;
}
/* Remove any glass morphism / backdrop filter */
.container,
.v-container,
.page-col-content,
.contents {
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
}
/* ===== BREADCRUMBS ===== */
.v-breadcrumbs {
background: transparent !important;
padding: 8px 0 16px 0 !important;
display: flex !important;
align-items: center !important;
}
.v-breadcrumbs__item,
.v-breadcrumbs a {
color: var(--pf-text-muted) !important;
font-size: 13px !important;
text-decoration: none !important;
transition: var(--pf-transition) !important;
}
.v-breadcrumbs a:hover {
color: var(--pf-accent-teal) !important;
}
.v-breadcrumbs__divider {
color: var(--pf-text-muted) !important;
padding: 0 8px !important;
}
/* ===== TYPOGRAPHY ===== */
h1, h2, h3, h4, h5, h6 {
color: var(--pf-text-primary) !important;
font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, Roboto, sans-serif !important;
font-weight: 600 !important;
line-height: 1.3 !important;
}
h1 {
font-size: 2rem !important;
margin-bottom: 20px !important;
padding-bottom: 12px !important;
border-bottom: 2px solid var(--pf-accent-teal) !important;
}
h2 {
font-size: 1.5rem !important;
margin-top: 32px !important;
margin-bottom: 16px !important;
color: var(--pf-text-primary) !important;
}
h3 {
font-size: 1.25rem !important;
color: var(--pf-accent-teal) !important;
margin-top: 24px !important;
margin-bottom: 12px !important;
}
p {
color: var(--pf-text-secondary) !important;
line-height: 1.7 !important;
margin-bottom: 16px !important;
}
a {
color: var(--pf-accent-teal) !important;
text-decoration: none !important;
transition: var(--pf-transition) !important;
}
a:hover {
color: var(--pf-accent-teal-hover) !important;
text-decoration: underline !important;
}
/* ===== BUTTONS - Standardized Teal Gradient ===== */
.v-btn,
button:not(.v-app-bar .v-btn),
input[type="submit"],
input[type="button"] {
background: linear-gradient(135deg, var(--pf-accent-teal), var(--pf-accent-green)) !important;
color: #FFFFFF !important;
border: none !important;
border-radius: var(--pf-radius-md) !important;
padding: 10px 20px !important;
font-weight: 600 !important;
font-size: 14px !important;
text-transform: none !important;
letter-spacing: 0 !important;
box-shadow: 0 2px 8px rgba(90, 158, 150, 0.3) !important;
transition: var(--pf-transition) !important;
}
.v-btn:hover,
button:not(.v-app-bar .v-btn):hover,
input[type="submit"]:hover,
input[type="button"]:hover {
box-shadow: 0 4px 16px rgba(90, 158, 150, 0.4) !important;
transform: translateY(-1px) !important;
}
/* Secondary / Outlined buttons */
.v-btn--outlined {
background: transparent !important;
color: var(--pf-text-primary) !important;
border: 2px solid var(--pf-border-medium) !important;
box-shadow: none !important;
}
.v-btn--outlined:hover {
background: var(--pf-bg-body) !important;
border-color: var(--pf-accent-teal) !important;
color: var(--pf-accent-teal) !important;
transform: none !important;
}
/* Icon buttons in content area */
.v-btn--icon {
background: transparent !important;
box-shadow: none !important;
}
.v-btn--icon:hover {
background: var(--pf-border-light) !important;
}
/* ===== CARDS ===== */
.v-card {
background: var(--pf-bg-content) !important;
border-radius: var(--pf-radius-md) !important;
box-shadow: var(--pf-shadow-card) !important;
border: 1px solid var(--pf-border-light) !important;
transition: var(--pf-transition-slow) !important;
overflow: hidden !important;
position: relative !important;
}
.v-card:hover {
box-shadow: var(--pf-shadow-medium) !important;
transform: none !important;
border-color: var(--pf-border-medium) !important;
}
/* Remove the top gradient bar from cards */
.v-card::before {
display: none !important;
}
/* ===== FORMS & INPUTS ===== */
.v-text-field .v-input__slot,
.v-input .v-input__slot,
input:not([type="submit"]):not([type="button"]),
textarea,
select {
background: var(--pf-bg-body) !important;
border: 1px solid var(--pf-border-medium) !important;
border-radius: var(--pf-radius-sm) !important;
transition: var(--pf-transition) !important;
}
.v-text-field.v-input--is-focused .v-input__slot,
.v-input.v-input--is-focused .v-input__slot,
input:focus,
textarea:focus,
select:focus {
border-color: var(--pf-accent-teal) !important;
box-shadow: 0 0 0 3px rgba(90, 158, 150, 0.15) !important;
outline: none !important;
}
/* ===== CODE BLOCKS ===== */
pre,
code {
font-family: 'Consolas', 'Monaco', 'Fira Code', monospace !important;
}
pre {
background: #2D2D2D !important;
color: #E8E8E8 !important;
border-radius: var(--pf-radius-md) !important;
padding: 20px !important;
margin: 16px 0 !important;
border-left: 4px solid var(--pf-accent-teal) !important;
overflow-x: auto !important;
}
code:not(pre code) {
background: rgba(90, 158, 150, 0.1) !important;
color: var(--pf-accent-teal) !important;
padding: 2px 6px !important;
border-radius: 4px !important;
font-size: 0.9em !important;
}
/* ===== BLOCKQUOTES ===== */
blockquote {
background: rgba(90, 158, 150, 0.08) !important;
border-left: 4px solid var(--pf-accent-teal) !important;
border-radius: 0 var(--pf-radius-sm) var(--pf-radius-sm) 0 !important;
padding: 16px 20px !important;
margin: 16px 0 !important;
color: var(--pf-text-secondary) !important;
}
/* ===== ALERTS ===== */
.v-alert {
border-radius: var(--pf-radius-md) !important;
padding: 16px 20px !important;
border: none !important;
margin: 16px 0 !important;
}
.v-alert.success,
.v-alert--success {
background: rgba(127, 184, 130, 0.15) !important;
border-left: 4px solid var(--pf-accent-green) !important;
}
.v-alert.info,
.v-alert--info {
background: rgba(90, 158, 150, 0.15) !important;
border-left: 4px solid var(--pf-accent-teal) !important;
}
.v-alert.warning,
.v-alert--warning {
background: rgba(212, 134, 74, 0.15) !important;
border-left: 4px solid var(--pf-accent-orange) !important;
}
.v-alert.error,
.v-alert--error {
background: rgba(220, 80, 80, 0.15) !important;
border-left: 4px solid #DC5050 !important;
}
/* ===== TABLES ===== */
table {
width: 100% !important;
border-collapse: collapse !important;
border-radius: var(--pf-radius-md) !important;
overflow: hidden !important;
box-shadow: var(--pf-shadow-soft) !important;
margin: 16px 0 !important;
}
table th {
background: var(--pf-bg-sidebar) !important;
color: var(--pf-text-inverse) !important;
font-weight: 600 !important;
padding: 14px 16px !important;
text-align: left !important;
}
table td {
padding: 12px 16px !important;
border-bottom: 1px solid var(--pf-border-light) !important;
color: var(--pf-text-secondary) !important;
}
table tr:hover td {
background: rgba(90, 158, 150, 0.04) !important;
}
/* ===== TAGS / CHIPS ===== */
.v-chip {
background: linear-gradient(135deg, var(--pf-accent-teal), var(--pf-accent-green)) !important;
color: #FFFFFF !important;
border-radius: var(--pf-radius-pill) !important;
font-size: 12px !important;
font-weight: 500 !important;
padding: 4px 12px !important;
}
/* ===== DIALOGS / MODALS ===== */
.v-dialog {
border-radius: var(--pf-radius-lg) !important;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2) !important;
overflow: hidden !important;
}
.v-dialog .v-card {
border-radius: var(--pf-radius-lg) !important;
box-shadow: none !important;
}
/* ===== TOOLTIPS ===== */
.v-tooltip__content {
background: var(--pf-bg-sidebar) !important;
color: var(--pf-text-inverse) !important;
border-radius: var(--pf-radius-sm) !important;
padding: 8px 12px !important;
font-size: 13px !important;
box-shadow: var(--pf-shadow-medium) !important;
}
/* ===== SCROLLBAR ===== */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: var(--pf-bg-body);
}
::-webkit-scrollbar-thumb {
background: var(--pf-text-muted);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--pf-text-secondary);
}
/* ===== SELECTION ===== */
::selection {
background: var(--pf-accent-teal);
color: #FFFFFF;
}
/* ===== WIKI.JS SPECIFIC FIXES ===== */
/* Page title styling */
.page-header h1,
.contents > h1:first-child {
font-size: 2rem !important;
color: var(--pf-text-primary) !important;
border-bottom: 2px solid var(--pf-accent-teal) !important;
padding-bottom: 12px !important;
margin-bottom: 24px !important;
}
/* Sidebar tree view */
.v-treeview {
background: transparent !important;
}
.v-treeview-node__root {
border-radius: var(--pf-radius-sm) !important;
margin: 2px 0 !important;
}
.v-treeview-node__root:hover {
background: rgba(255, 255, 255, 0.06) !important;
}
/* Comments section */
.comments-container {
background: var(--pf-bg-content) !important;
border-radius: var(--pf-radius-md) !important;
padding: 20px !important;
border: 1px solid var(--pf-border-light) !important;
}
/* Editor */
.editor,
.ProseMirror,
.CodeMirror {
background: var(--pf-bg-content) !important;
border-radius: var(--pf-radius-md) !important;
border: 1px solid var(--pf-border-medium) !important;
}
.editor:focus-within,
.ProseMirror:focus,
.CodeMirror-focused {
border-color: var(--pf-accent-teal) !important;
box-shadow: 0 0 0 3px rgba(90, 158, 150, 0.15) !important;
}
/* Page info sidebar cards */
.page-col-sd .v-card {
background: var(--pf-bg-content) !important;
border: 1px solid var(--pf-border-light) !important;
margin-bottom: 16px !important;
}
/* Dividers */
hr,
.v-divider {
border-color: var(--pf-border-light) !important;
margin: 24px 0 !important;
}
/* Lists */
ul, ol {
padding-left: 24px !important;
margin: 12px 0 !important;
}
li {
margin-bottom: 8px !important;
color: var(--pf-text-secondary) !important;
}
li::marker {
color: var(--pf-accent-teal) !important;
}
/* Images */
.contents img {
border-radius: var(--pf-radius-md) !important;
box-shadow: var(--pf-shadow-soft) !important;
max-width: 100% !important;
height: auto !important;
}
/* Loading states */
.v-progress-circular {
color: var(--pf-accent-teal) !important;
}
/* ===== RESPONSIVE ===== */
@media (max-width: 960px) {
.container,
.v-container,
.page-col-content,
.contents {
padding: 20px !important;
margin: 12px !important;
border-radius: var(--pf-radius-md) !important;
}
h1 {
font-size: 1.75rem !important;
}
h2 {
font-size: 1.35rem !important;
}
}
@media (max-width: 600px) {
.container,
.v-container,
.page-col-content,
.contents {
padding: 16px !important;
margin: 8px !important;
}
.v-btn {
padding: 8px 16px !important;
font-size: 13px !important;
}
}
/* ===== PRINT ===== */
@media print {
header,
.v-app-bar,
.v-navigation-drawer,
footer {
display: none !important;
}
body {
background: #FFFFFF !important;
}
.container,
.v-container {
box-shadow: none !important;
border: none !important;
margin: 0 !important;
padding: 0 !important;
}
}