diff --git a/backend/VERSION.md b/backend/VERSION.md
new file mode 100644
index 0000000..e1e9cf4
--- /dev/null
+++ b/backend/VERSION.md
@@ -0,0 +1,70 @@
+# Version Management
+
+## Current Version: 0.1.30
+
+The backend version is managed in `/backend/config/version.go`.
+
+## Updating the Version
+
+To update the application version:
+
+1. Edit `/backend/config/version.go`
+2. Change the `Version` constant:
+ ```go
+ const Version = "0.1.31" // Update this
+ ```
+
+## Git Commit Information
+
+The git commit hash is automatically detected at runtime from:
+
+1. `GIT_COMMIT` environment variable (preferred for Docker)
+2. Git command output (works in development)
+3. Falls back to "unknown" if neither is available
+
+## Setting Git Commit in Docker
+
+### Development Environment
+
+Add to `docker/.env`:
+```bash
+GIT_COMMIT=$(git rev-parse --short HEAD)
+```
+
+Then restart the container:
+```bash
+cd docker
+docker-compose -f docker-compose.dev.yml up -d backend-dev
+```
+
+### Production Build
+
+Use build-time variable:
+```bash
+docker build --build-arg GIT_COMMIT=$(git rev-parse --short HEAD) .
+```
+
+Or set in docker-compose.yml:
+```yaml
+environment:
+ - GIT_COMMIT=${GIT_COMMIT:-unknown}
+```
+
+## API Endpoints
+
+- **Public**: `GET /api/public/version` (no authentication)
+- **Protected**: `GET /api/version` (requires JWT token)
+
+Both return:
+```json
+{
+ "version": "0.1.30",
+ "gitCommit": "d0c177b"
+}
+```
+
+## Frontend Integration
+
+The landing page automatically fetches version information from `/api/public/version` and displays it.
+
+To see the version in the frontend, visit: http://localhost:5173
diff --git a/backend/cmd/main.go b/backend/cmd/main.go
index ca6de1b..fe775e3 100644
--- a/backend/cmd/main.go
+++ b/backend/cmd/main.go
@@ -82,9 +82,11 @@ func main() {
importer.RegisterRoutes(protected)
pdfrender.RegisterRoutes(protected)
transfer.RegisterRoutes(protected)
+ config.RegisterRoutes(protected)
// Register public routes (no authentication)
pdfrender.RegisterPublicRoutes(r)
+ config.RegisterPublicRoutes(r)
logger.Info("API-Routen erfolgreich registriert")
diff --git a/backend/config/handlers.go b/backend/config/handlers.go
new file mode 100644
index 0000000..ba75953
--- /dev/null
+++ b/backend/config/handlers.go
@@ -0,0 +1,10 @@
+package config
+
+import (
+ "github.com/gin-gonic/gin"
+)
+
+// Versionsinfo returns version and git commit information
+func Versionsinfo(c *gin.Context) {
+ c.JSON(200, GetInfo())
+}
diff --git a/backend/config/routes.go b/backend/config/routes.go
new file mode 100644
index 0000000..d09a4fe
--- /dev/null
+++ b/backend/config/routes.go
@@ -0,0 +1,15 @@
+package config
+
+import "github.com/gin-gonic/gin"
+
+// RegisterRoutes registers config-related routes (protected)
+func RegisterRoutes(r *gin.RouterGroup) {
+ r.GET("/version", Versionsinfo)
+}
+
+// RegisterPublicRoutes registers public config routes (no auth required)
+func RegisterPublicRoutes(r *gin.Engine) {
+ // Public version endpoint - no authentication required
+ public := r.Group("/api/public")
+ public.GET("/version", Versionsinfo)
+}
diff --git a/backend/config/version.go b/backend/config/version.go
new file mode 100644
index 0000000..f22469e
--- /dev/null
+++ b/backend/config/version.go
@@ -0,0 +1,60 @@
+package config
+
+// Version is the application version
+const Version = "0.1.30"
+
+var (
+ // GitCommit will be set by build flags or detected at runtime
+ GitCommit = "unknown"
+)
+
+// init detects git commit if not set during build
+func init() {
+ /*
+ if GitCommit == "" {
+ // Try environment variable first
+ if envCommit := os.Getenv("GIT_COMMIT"); envCommit != "" {
+ GitCommit = envCommit
+ } else {
+ // Try to detect from git command
+ GitCommit = detectGitCommit()
+ }
+ }
+ */
+}
+
+/*
+// detectGitCommit tries to get the current git commit hash
+func detectGitCommit() string {
+ cmd := exec.Command("git", "rev-parse", "--short", "HEAD")
+ output, err := cmd.Output()
+ if err != nil {
+ return "unknown"
+ }
+ return strings.TrimSpace(string(output))
+}
+*/
+// GetVersion returns the current application version
+func GetVersion() string {
+ return Version
+}
+
+/*
+// GetGitCommit returns the git commit hash
+func GetGitCommit() string {
+ return GitCommit
+}
+*/
+// Info contains version information
+type Info struct {
+ Version string `json:"version"`
+ GitCommit string `json:"gitCommit"`
+}
+
+// GetInfo returns version information as a struct
+func GetInfo() Info {
+ return Info{
+ Version: Version,
+ GitCommit: GitCommit,
+ }
+}
diff --git a/backend/config/version_test.go b/backend/config/version_test.go
new file mode 100644
index 0000000..62f702a
--- /dev/null
+++ b/backend/config/version_test.go
@@ -0,0 +1,43 @@
+package config
+
+import (
+ "testing"
+)
+
+func TestGetVersion(t *testing.T) {
+ version := GetVersion()
+ if version == "" {
+ t.Error("Version should not be empty")
+ }
+ if version != Version {
+ t.Errorf("Expected version %s, got %s", Version, version)
+ }
+}
+
+/*
+ func TestGetGitCommit(t *testing.T) {
+ commit := GetGitCommit()
+ if commit == "" {
+ t.Error("GitCommit should not be empty")
+ }
+ // Should be either "unknown" or a valid git hash
+ if commit != "unknown" && len(commit) < 7 {
+ t.Errorf("Invalid git commit format: %s", commit)
+ }
+ }
+*/
+func TestGetInfo(t *testing.T) {
+ info := GetInfo()
+
+ if info.Version == "" {
+ t.Error("Info.Version should not be empty")
+ }
+
+ if info.GitCommit == "" {
+ t.Error("Info.GitCommit should not be empty")
+ }
+
+ if info.Version != Version {
+ t.Errorf("Expected info.Version %s, got %s", Version, info.Version)
+ }
+}
diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml
index f13867b..1a2d930 100644
--- a/docker/docker-compose.dev.yml
+++ b/docker/docker-compose.dev.yml
@@ -14,6 +14,7 @@ services:
- API_PORT=${API_PORT:-8180}
- TEMPLATES_DIR=${TEMPLATES_DIR:-./templatesx}
- EXPORT_TEMP_DIR=${EXPORT_TEMP_DIR:-./export_tempx}
+ - GIT_COMMIT=${GIT_COMMIT:-unknown}
depends_on:
mariadb-dev:
condition: service_healthy
diff --git a/docker/start-dev.sh b/docker/start-dev.sh
index 8aaf104..255c0b3 100755
--- a/docker/start-dev.sh
+++ b/docker/start-dev.sh
@@ -11,6 +11,10 @@ fi
# Gehe ins Docker-Verzeichnis
cd "$(dirname "$0")"
+# Get current git commit
+export GIT_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
+echo "📝 Git Commit: $GIT_COMMIT"
+
echo "📦 Building and starting development containers..."
# Stoppe vorhandene Container
diff --git a/frontend/VERSION.md b/frontend/VERSION.md
new file mode 100644
index 0000000..b4835d2
--- /dev/null
+++ b/frontend/VERSION.md
@@ -0,0 +1,87 @@
+# Frontend Version Management
+
+## Current Version: 0.1.30
+
+The frontend version is managed independently from the backend.
+
+## Version Locations
+
+1. **Primary source**: `/frontend/src/version.js`
+ - Contains the VERSION constant
+ - Exports version info functions
+
+2. **Package metadata**: `/frontend/package.json`
+ - Standard npm version field
+ - Should match version.js
+
+## Updating the Version
+
+### Option 1: Using the update script (Recommended)
+```bash
+# Updates both backend and frontend
+./scripts/update-version.sh 0.1.31
+```
+
+### Option 2: Manual update
+Edit `/frontend/src/version.js`:
+```javascript
+export const VERSION = '0.1.31' // Update this
+```
+
+And `/frontend/package.json`:
+```json
+{
+ "version": "0.1.31" // Update this
+}
+```
+
+## Git Commit Information
+
+The git commit is injected via environment variable:
+- Set `VITE_GIT_COMMIT` in `.env` or at build time
+- Falls back to "unknown" if not set
+
+Example `.env`:
+```bash
+VITE_GIT_COMMIT=d0c177b
+```
+
+## Usage in Components
+
+```javascript
+import { getVersion, getGitCommit, getVersionInfo } from '@/version'
+
+// Get version string
+const version = getVersion() // "0.1.30"
+
+// Get git commit
+const commit = getGitCommit() // "d0c177b" or "unknown"
+
+// Get full info object
+const info = getVersionInfo() // { version: "0.1.30", gitCommit: "d0c177b" }
+```
+
+## Landing Page Display
+
+The landing page shows both:
+- **Frontend Version**: From `/frontend/src/version.js`
+- **Backend Version**: Fetched from `/api/public/version`
+
+This allows users to see if frontend and backend are in sync.
+
+## Build-time Version Injection
+
+To inject git commit at build time, update `vite.config.js`:
+
+```javascript
+import { defineConfig } from 'vite'
+import { execSync } from 'child_process'
+
+const gitCommit = execSync('git rev-parse --short HEAD').toString().trim()
+
+export default defineConfig({
+ define: {
+ 'import.meta.env.VITE_GIT_COMMIT': JSON.stringify(gitCommit)
+ }
+})
+```
diff --git a/frontend/package.json b/frontend/package.json
index d83539a..faae845 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,6 +1,6 @@
{
- "name": "my-app",
- "version": "0.0.0",
+ "name": "bamort-frontend",
+ "version": "0.1.21",
"private": true,
"type": "module",
"scripts": {
diff --git a/frontend/public/Abgrund-DD2.jpg b/frontend/public/Abgrund-DD2.jpg
new file mode 100644
index 0000000..adfde2b
Binary files /dev/null and b/frontend/public/Abgrund-DD2.jpg differ
diff --git a/frontend/public/Drache.png b/frontend/public/Drache.png
new file mode 100644
index 0000000..aafd311
Binary files /dev/null and b/frontend/public/Drache.png differ
diff --git a/frontend/src/assets/main.css b/frontend/src/assets/main.css
index 473d551..9352e08 100644
--- a/frontend/src/assets/main.css
+++ b/frontend/src/assets/main.css
@@ -1467,4 +1467,2421 @@ a,
.spells-grid, .available-spells .spells-grid {
grid-template-columns: repeat(5, 1fr);
}
+}
+
+/* ========================================
+ CONSOLIDATED MODAL STYLES
+ ======================================== */
+
+/* Modal overlay - covers entire viewport */
+.modal-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.5);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 1000;
+}
+
+/* Modal content container */
+.modal-content {
+ background: white;
+ border-radius: 8px;
+ width: 90%;
+ max-width: 500px;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+ display: flex;
+ flex-direction: column;
+ max-height: 80vh;
+ animation: modalSlideIn 0.3s ease-out;
+}
+
+/* Modal header */
+.modal-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20px;
+ border-bottom: 1px solid #dee2e6;
+ flex-shrink: 0;
+}
+
+.modal-header h3 {
+ margin: 0;
+ color: #333;
+ font-size: 1.25rem;
+}
+
+/* Modal body */
+.modal-body {
+ padding: 20px;
+ overflow-y: auto;
+ flex: 1;
+ min-height: 0;
+}
+
+/* Modal footer */
+.modal-footer {
+ display: flex;
+ justify-content: flex-end;
+ gap: 10px;
+ padding: 20px;
+ border-top: 1px solid #dee2e6;
+ flex-shrink: 0;
+}
+
+/* Modal actions (alternative to footer) */
+.modal-actions {
+ display: flex;
+ justify-content: flex-end;
+ gap: 10px;
+ margin-top: 20px;
+ padding-top: 15px;
+ border-top: 1px solid #eee;
+}
+
+/* Close button */
+.close-button {
+ background: none;
+ border: none;
+ font-size: 1.5rem;
+ color: #999;
+ cursor: pointer;
+ padding: 0;
+ width: 30px;
+ height: 30px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: color 0.2s ease;
+}
+
+.close-button:hover {
+ color: #333;
+}
+
+/* Modal slide in animation */
+@keyframes modalSlideIn {
+ from {
+ opacity: 0;
+ transform: scale(0.9) translateY(-20px);
+ }
+ to {
+ opacity: 1;
+ transform: scale(1) translateY(0);
+ }
+}
+
+/* ========================================
+ CONSOLIDATED BUTTON STYLES
+ ======================================== */
+
+/* Cancel button */
+.btn-cancel {
+ padding: 10px 20px;
+ border: 1px solid #dee2e6;
+ border-radius: 6px;
+ background: #f8f9fa;
+ color: #495057;
+ cursor: pointer;
+ font-weight: 500;
+ transition: all 0.2s ease;
+}
+
+.btn-cancel:hover {
+ background: #e9ecef;
+ border-color: #adb5bd;
+}
+
+/* Confirm button (success/submit) */
+.btn-confirm {
+ padding: 10px 20px;
+ border: none;
+ border-radius: 6px;
+ background: #1da766;
+ color: white;
+ cursor: pointer;
+ font-weight: 600;
+ transition: all 0.2s ease;
+}
+
+.btn-confirm:hover:not(:disabled) {
+ background: #16a085;
+}
+
+.btn-confirm:disabled {
+ background: #ccc;
+ cursor: not-allowed;
+ opacity: 0.6;
+}
+
+/* Export button */
+.btn-export {
+ padding: 10px 20px;
+ border: 1px solid #007bff;
+ border-radius: 6px;
+ background: #007bff;
+ color: white;
+ cursor: pointer;
+ font-weight: 500;
+ transition: all 0.2s ease;
+}
+
+.btn-export:hover:not(:disabled) {
+ background: #0056b3;
+ border-color: #0056b3;
+}
+
+.btn-export:disabled {
+ opacity: 0.6;
+ cursor: not-allowed;
+}
+
+/* Small export button with icon */
+.export-button-small {
+ width: 40px;
+ height: 40px;
+ padding: 0;
+ border: 1px solid #007bff;
+ border-radius: 8px;
+ background: #007bff;
+ color: white;
+ font-size: 1.2rem;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ flex-shrink: 0;
+}
+
+.export-button-small:hover {
+ background: #0056b3;
+ border-color: #0056b3;
+ transform: scale(1.05);
+}
+
+/* Delete button */
+.btn-delete {
+ background: none;
+ border: none;
+ cursor: pointer;
+ font-size: 1.2rem;
+ padding: 4px 8px;
+ transition: transform 0.2s ease;
+ color: #dc3545;
+}
+
+.btn-delete:hover {
+ transform: scale(1.2);
+}
+
+/* Edit button */
+.btn-edit {
+ background: none;
+ border: none;
+ cursor: pointer;
+ font-size: 1.2rem;
+ padding: 4px 8px;
+ transition: transform 0.2s ease;
+ color: #007bff;
+}
+
+.btn-edit:hover {
+ transform: scale(1.2);
+}
+
+/* Add button */
+.btn-add,
+.btn-add-equipment,
+.btn-add-weapon,
+.btn-add-inline,
+.btn-add-spell {
+ padding: 8px 16px;
+ background: #1da766;
+ color: white;
+ border: none;
+ border-radius: 6px;
+ cursor: pointer;
+ font-weight: bold;
+ transition: background 0.2s ease;
+}
+
+.btn-add:hover,
+.btn-add-equipment:hover,
+.btn-add-weapon:hover,
+.btn-add-inline:hover,
+.btn-add-spell:hover {
+ background: #16a085;
+}
+
+/* Action button small (for table actions) */
+.btn-action {
+ background: none;
+ border: none;
+ cursor: pointer;
+ padding: 4px 8px;
+ transition: all 0.2s ease;
+ font-size: 1rem;
+}
+
+.btn-action:hover {
+ transform: scale(1.1);
+}
+
+.icon {
+ font-size: 14px;
+}
+
+.btn-improve-small {
+ font-size: 1.2rem;
+}
+
+/* ========================================
+ CONSOLIDATED FORM STYLES
+ ======================================== */
+
+/* Form group container */
+.form-group {
+ margin-bottom: 20px;
+}
+
+.form-group label {
+ display: block;
+ margin-bottom: 8px;
+ font-weight: 500;
+ color: #495057;
+ font-size: 0.95rem;
+}
+
+/* Form control (input, select, textarea) */
+.form-control,
+.template-select,
+.form-group input[type="text"],
+.form-group input[type="email"],
+.form-group input[type="password"],
+.form-group input[type="number"],
+.form-group select,
+.form-group textarea {
+ width: 100%;
+ padding: 10px 12px;
+ border: 1px solid #dee2e6;
+ border-radius: 6px;
+ background: white;
+ color: #495057;
+ font-size: 0.95rem;
+ box-sizing: border-box;
+ transition: border-color 0.2s ease, box-shadow 0.2s ease;
+}
+
+.form-control:focus,
+.template-select:focus,
+.form-group input:focus,
+.form-group select:focus,
+.form-group textarea:focus {
+ outline: none;
+ border-color: #007bff;
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+
+.form-control:disabled,
+.template-select:disabled,
+.form-group input:disabled,
+.form-group select:disabled,
+.form-group textarea:disabled {
+ opacity: 0.6;
+ cursor: not-allowed;
+ background: #e9ecef;
+}
+
+/* Form row */
+.form-row {
+ display: flex;
+ gap: 15px;
+ align-items: flex-start;
+ margin-bottom: 15px;
+}
+
+@media (max-width: 768px) {
+ .form-row {
+ flex-direction: column;
+ }
+}
+
+/* Checkbox label */
+.checkbox-label {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ cursor: pointer;
+ user-select: none;
+ font-weight: normal;
+ margin: 0;
+}
+
+.checkbox-label input[type="checkbox"] {
+ width: 18px;
+ height: 18px;
+ cursor: pointer;
+ margin: 0;
+}
+
+/* Help text */
+.help-text {
+ display: block;
+ margin-top: 5px;
+ font-size: 12px;
+ color: #6c757d;
+ font-style: italic;
+}
+
+/* ========================================
+ CONSOLIDATED LOADING INDICATORS
+ ======================================== */
+
+/* Loading overlay (absolute positioned within container) */
+.loading-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(255, 255, 255, 0.95);
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ z-index: 10;
+ border-radius: 8px;
+}
+
+.loading-overlay p {
+ color: #007bff;
+ font-weight: 500;
+ margin: 0;
+}
+
+/* Spinner animation */
+.spinner {
+ border: 4px solid #f3f3f3;
+ border-top: 4px solid #007bff;
+ border-radius: 50%;
+ width: 50px;
+ height: 50px;
+ animation: spin 1s linear infinite;
+ margin-bottom: 15px;
+}
+
+/* Loading message (text only) */
+.loading-message {
+ text-align: center;
+ padding: 20px;
+ color: #6c757d;
+ font-style: italic;
+}
+
+/* ========================================
+ CONSOLIDATED TABLE STYLES
+ ======================================== */
+
+/* Table header cell */
+.cd-table-header {
+ background-color: #1da766;
+ color: white;
+ font-weight: bold;
+ padding: 8px;
+ text-align: left;
+}
+
+/* Empty state for tables/lists */
+.empty-state {
+ text-align: center;
+ color: #999;
+ font-style: italic;
+ padding: 2rem;
+}
+
+.empty-state h3 {
+ color: #333;
+ margin-bottom: 10px;
+ font-size: 1.5rem;
+}
+
+/* Action cell */
+.action-cell {
+ text-align: center;
+ vertical-align: middle;
+}
+
+/* ========================================
+ CONSOLIDATED HEADER/LAYOUT STYLES
+ ======================================== */
+
+/* Header section */
+.header-section {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 1rem;
+ flex-wrap: wrap;
+ gap: 10px;
+}
+
+/* Header content */
+.header-content {
+ display: flex;
+ align-items: center;
+ gap: 15px;
+ flex: 1;
+}
+
+/* Character header */
+.character-header {
+ margin-bottom: 20px;
+}
+
+.character-header h2 {
+ margin: 0;
+ color: #333;
+ font-size: 1.5rem;
+ border-bottom: 2px solid #007bff;
+ padding-bottom: 10px;
+ flex: 1;
+}
+
+/* ========================================
+ COMPONENT-SPECIFIC STYLES (EXTRACTED FROM COMPONENTS)
+ ======================================== */
+
+/* SkillView - Tables Container */
+.tables-container {
+ display: flex;
+ gap: 1rem;
+ width: 100%;
+}
+
+.table-wrapper-left {
+ flex: 6;
+ min-width: 0;
+}
+
+.table-wrapper-right {
+ flex: 4;
+ min-width: 0;
+}
+
+/* Learning Mode Controls */
+.learning-mode-controls {
+ display: flex;
+ align-items: center;
+ gap: 15px;
+}
+
+.resources-display {
+ display: flex;
+ gap: 15px;
+ animation: slideIn 0.3s ease;
+}
+
+.resource-item {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ padding: 6px 12px;
+ background: #f8f9fa;
+ border: 1px solid #dee2e6;
+ border-radius: 6px;
+ font-weight: bold;
+ color: #495057;
+}
+
+.resource-value {
+ font-size: 14px;
+ white-space: nowrap;
+}
+
+/* Learning Mode Buttons */
+.btn-learning-mode {
+ padding: 8px 16px;
+ border: 2px solid #1da766;
+ background: white;
+ color: #1da766;
+ border-radius: 6px;
+ cursor: pointer;
+ font-weight: bold;
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ transition: all 0.3s ease;
+ position: relative;
+}
+
+.btn-learning-mode:hover {
+ background: #1da766;
+ color: white;
+}
+
+.btn-learning-mode.active {
+ background: #1da766;
+ color: white;
+}
+
+.learning-actions {
+ display: flex;
+ gap: 5px;
+ animation: slideIn 0.3s ease;
+}
+
+.btn-learn-new {
+ width: 40px;
+ height: 40px;
+ border: 2px solid #007bff;
+ background: white;
+ border-radius: 6px;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 16px;
+ transition: all 0.2s ease;
+ position: relative;
+}
+
+.btn-learn-new:hover {
+ background: #007bff;
+ color: white;
+}
+
+.btn-improve {
+ width: 40px;
+ height: 40px;
+ border: 2px solid #28a745;
+ background: white;
+ border-radius: 6px;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 16px;
+ transition: all 0.2s ease;
+ position: relative;
+}
+
+.btn-improve:hover {
+ background: #28a745;
+ color: white;
+}
+
+/* Practice Points Controls */
+.pp-cell {
+ padding: 4px 8px;
+}
+
+.pp-container {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 2px;
+}
+
+.pp-btn {
+ width: 20px;
+ height: 20px;
+ border: 1px solid #007bff;
+ background: white;
+ color: #007bff;
+ border-radius: 3px;
+ cursor: pointer;
+ font-size: 14px;
+ font-weight: bold;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: all 0.2s ease;
+ line-height: 1;
+ padding: 0;
+}
+
+.pp-btn:hover:not(:disabled) {
+ background: #007bff;
+ color: white;
+}
+
+.pp-btn:disabled {
+ border-color: #ccc;
+ color: #ccc;
+ cursor: not-allowed;
+ opacity: 0.5;
+}
+
+.pp-btn-plus {
+ border-color: #28a745;
+ color: #28a745;
+}
+
+.pp-btn-plus:hover:not(:disabled) {
+ background: #28a745;
+ color: white;
+}
+
+.pp-btn-minus {
+ border-color: #dc3545;
+ color: #dc3545;
+}
+
+.pp-btn-minus:hover:not(:disabled) {
+ background: #dc3545;
+ color: white;
+}
+
+.pp-value {
+ min-width: 20px;
+ text-align: center;
+ font-weight: bold;
+ color: #495057;
+ font-size: 13px;
+}
+
+/* Spell/Skill Dialog Styles */
+.modal-wide {
+ max-width: 700px;
+}
+
+.current-resources {
+ display: flex;
+ gap: 15px;
+ margin-bottom: 20px;
+ flex-wrap: wrap;
+}
+
+.resource-display-card {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 12px 16px;
+ background: #f8f9fa;
+ border: 1px solid #dee2e6;
+ border-radius: 8px;
+ flex: 1;
+ min-width: 160px;
+}
+
+.resource-display-card .resource-icon {
+ font-size: 20px;
+}
+
+.resource-remaining {
+ margin-top: 4px;
+}
+
+.resource-remaining small {
+ color: #6c757d;
+ font-weight: normal;
+}
+
+.text-warning {
+ color: #f0ad4e !important;
+}
+
+.text-danger {
+ color: #d9534f !important;
+}
+
+/* Selection Summary */
+.selection-summary {
+ background: #e7f3ff;
+ padding: 12px;
+ border-radius: 6px;
+ margin-bottom: 10px;
+ border-left: 4px solid #007bff;
+}
+
+.cost-summary {
+ color: #28a745;
+ font-weight: bold;
+}
+
+/* Learning Levels List */
+.learning-levels {
+ border: 1px solid #dee2e6;
+ border-radius: 6px;
+ max-height: 300px;
+ overflow-y: auto;
+}
+
+.level-option {
+ padding: 12px 16px;
+ border-bottom: 1px solid #f1f1f1;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.level-option:last-child {
+ border-bottom: none;
+}
+
+.level-option:hover:not(.disabled) {
+ background: #f8f9fa;
+}
+
+.level-option.selected {
+ background: #e7f3ff;
+ border-left: 4px solid #007bff;
+}
+
+.level-option.in-sequence:not(.selected) {
+ background: #f0f8ff;
+ border-left: 2px solid #87ceeb;
+}
+
+.level-option.disabled {
+ background: #f8f9fa;
+ color: #6c757d;
+ cursor: not-allowed;
+ opacity: 0.6;
+}
+
+.level-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ font-weight: 500;
+}
+
+.level-target {
+ color: #495057;
+}
+
+.level-cost {
+ color: #28a745;
+ font-weight: bold;
+}
+
+.level-option.disabled .level-cost {
+ color: #dc3545;
+}
+
+.level-details {
+ margin-top: 4px;
+ color: #6c757d;
+}
+
+/* Form Column Layouts */
+.form-col {
+ flex: 1;
+ min-width: 0;
+}
+
+.form-col-main {
+ flex: 2;
+ min-width: 200px;
+}
+
+.form-col-input {
+ flex: 1;
+ min-width: 140px;
+}
+
+/* School Buttons */
+.school-buttons {
+ display: flex;
+ gap: 8px;
+ flex-wrap: wrap;
+ margin-top: 5px;
+}
+
+.school-btn {
+ padding: 6px 12px;
+ border: 1px solid #dee2e6;
+ border-radius: 4px;
+ background: white;
+ color: #495057;
+ cursor: pointer;
+ font-size: 14px;
+ transition: all 0.2s ease;
+}
+
+.school-btn:hover {
+ background: #f8f9fa;
+ border-color: #007bff;
+}
+
+.school-btn.active {
+ background: #007bff;
+ color: white;
+ border-color: #007bff;
+}
+
+/* Spell/Skill Container and Sections */
+.spells-container {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 20px;
+ margin-bottom: 15px;
+}
+
+@media (max-width: 1024px) {
+ .spells-container {
+ grid-template-columns: 1fr;
+ }
+}
+
+.available-spells-section,
+.learning-list-section {
+ min-height: 300px;
+}
+
+.learning-item {
+ background: #f0f8ff !important;
+ border-left: 3px solid #007bff !important;
+}
+
+.learning-item .level-header {
+ position: relative;
+}
+
+.remove-btn {
+ position: absolute;
+ right: 0;
+ top: 50%;
+ transform: translateY(-50%);
+ background: #dc3545;
+ color: white;
+ border: none;
+ border-radius: 50%;
+ width: 24px;
+ height: 24px;
+ cursor: pointer;
+ font-size: 16px;
+ line-height: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.remove-btn:hover {
+ background: #c82333;
+}
+
+.already-selected {
+ opacity: 0.5;
+ pointer-events: none;
+}
+
+.spell-actions-inline {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.btn-add-inline {
+ background: #28a745;
+ color: white;
+ border: none;
+ border-radius: 50%;
+ width: 28px;
+ height: 28px;
+ cursor: pointer;
+ font-size: 14px;
+ font-weight: bold;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: all 0.2s ease;
+ flex-shrink: 0;
+}
+
+.btn-add-inline:hover:not(:disabled) {
+ background: #218838;
+ transform: scale(1.1);
+}
+
+.btn-add-inline:disabled {
+ background: #6c757d;
+ cursor: not-allowed;
+ transform: none;
+}
+
+.already-selected .btn-add-inline {
+ background: #17a2b8;
+}
+
+/* Total Costs Display */
+.total-costs {
+ margin-top: 10px;
+ padding: 10px;
+ background: #e7f3ff;
+ border-radius: 4px;
+ border-left: 4px solid #007bff;
+}
+
+/* Spell Details */
+.spell-details-section {
+ background: #e7f3ff;
+ padding: 16px;
+ border-radius: 6px;
+ margin-bottom: 10px;
+ border-left: 4px solid #007bff;
+}
+
+.loading-spell-details {
+ text-align: center;
+ padding: 20px;
+ color: #6c757d;
+ font-style: italic;
+}
+
+.spell-details-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+ gap: 15px;
+ margin-top: 15px;
+}
+
+.spell-detail-card {
+ background: white;
+ border: 1px solid #dee2e6;
+ border-radius: 6px;
+ padding: 12px;
+}
+
+.spell-detail-card h4 {
+ margin: 0 0 10px 0;
+ color: #495057;
+ font-size: 14px;
+ font-weight: bold;
+ border-bottom: 1px solid #e9ecef;
+ padding-bottom: 5px;
+}
+
+.detail-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 6px;
+ font-size: 13px;
+}
+
+.detail-row:last-child {
+ margin-bottom: 0;
+}
+
+.detail-label {
+ color: #6c757d;
+ font-weight: 500;
+ flex: 0 0 auto;
+ margin-right: 10px;
+}
+
+.detail-value {
+ color: #495057;
+ text-align: right;
+ flex: 1 1 auto;
+}
+
+.spell-description {
+ background: white;
+ border: 1px solid #dee2e6;
+ border-radius: 6px;
+ padding: 12px;
+ margin-top: 15px;
+}
+
+.spell-description h4 {
+ margin: 0 0 8px 0;
+ color: #495057;
+ font-size: 14px;
+ font-weight: bold;
+}
+
+.spell-description p {
+ margin: 0;
+ color: #495057;
+ font-size: 13px;
+ line-height: 1.4;
+}
+
+/* Spell Actions */
+.spell-actions {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ flex-wrap: wrap;
+}
+
+.cost-info {
+ color: #28a745;
+ font-weight: bold;
+}
+
+.btn-add-spell {
+ padding: 4px 12px;
+ background: #28a745;
+ color: white;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+ font-size: 12px;
+ transition: background 0.2s ease;
+}
+
+.btn-add-spell:hover:not(:disabled) {
+ background: #218838;
+}
+
+.btn-add-spell:disabled {
+ background: #6c757d;
+ cursor: not-allowed;
+}
+
+/* No Spells Message */
+.no-spells {
+ text-align: center;
+ padding: 20px;
+ color: #6c757d;
+ font-style: italic;
+}
+
+/* Modal Content Headers */
+.modal-content h3 {
+ margin-top: 0;
+ margin-bottom: 20px;
+ color: #333;
+ border-bottom: 2px solid #1da766;
+ padding-bottom: 10px;
+}
+
+/* ========================================
+ SKILL LEARN DIALOG STYLES
+ ======================================== */
+
+/* Dialog Header */
+.dialog-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20px 24px;
+ border-bottom: 2px solid #1da766;
+ background: #f8f9fa;
+ border-radius: 0;
+ flex-shrink: 0;
+ z-index: 10;
+}
+
+.dialog-header h3 {
+ margin: 0;
+ color: #333;
+ font-size: 1.5rem;
+}
+
+.btn-close {
+ background: none;
+ border: none;
+ font-size: 24px;
+ cursor: pointer;
+ color: #666;
+ padding: 0;
+ width: 30px;
+ height: 30px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: all 0.2s ease;
+}
+
+.btn-close:hover {
+ background: #e9ecef;
+ color: #333;
+}
+
+/* Resources Section */
+.resources-section {
+ padding: 20px 24px;
+ background: #f8f9fa;
+ border-bottom: 1px solid #dee2e6;
+ flex-shrink: 0;
+}
+
+.resources-section h4 {
+ margin: 0 0 15px 0;
+ color: #495057;
+ font-size: 1.1rem;
+}
+
+.text-info {
+ color: #17a2b8 !important;
+}
+
+/* Reward Method Section */
+.reward-method-section {
+ margin-top: 20px;
+ padding-top: 20px;
+ border-top: 1px solid #dee2e6;
+}
+
+.reward-method-section label {
+ display: block;
+ margin-bottom: 8px;
+ font-weight: 600;
+ color: #495057;
+ font-size: 0.95rem;
+}
+
+.reward-method-section .form-select {
+ width: 100%;
+ padding: 12px 16px;
+ border: 2px solid #dee2e6;
+ border-radius: 8px;
+ font-size: 14px;
+ font-family: inherit;
+ transition: border-color 0.2s ease, box-shadow 0.2s ease;
+ box-sizing: border-box;
+ background: white;
+}
+
+.reward-method-section .form-select:focus {
+ outline: none;
+ border-color: #1da766;
+ box-shadow: 0 0 0 3px rgba(29, 167, 102, 0.1);
+}
+
+.reward-method-section .form-hint {
+ display: block;
+ margin-top: 4px;
+ font-size: 0.85rem;
+ color: #6c757d;
+ font-style: italic;
+}
+
+/* Form Section */
+.form-section {
+ padding: 24px;
+ flex: 1;
+ overflow-y: auto;
+}
+
+.form-input,
+.form-select,
+.form-textarea {
+ width: 100%;
+ padding: 12px 16px;
+ border: 2px solid #dee2e6;
+ border-radius: 8px;
+ font-size: 14px;
+ font-family: inherit;
+ transition: border-color 0.2s ease, box-shadow 0.2s ease;
+ box-sizing: border-box;
+}
+
+.form-input:focus,
+.form-select:focus,
+.form-textarea:focus {
+ outline: none;
+ border-color: #1da766;
+ box-shadow: 0 0 0 3px rgba(29, 167, 102, 0.1);
+}
+
+.form-textarea {
+ resize: vertical;
+ min-height: 80px;
+}
+
+.form-hint {
+ display: block;
+ margin-top: 4px;
+ font-size: 0.85rem;
+ color: #6c757d;
+ font-style: italic;
+}
+
+/* Costs Preview */
+.costs-preview {
+ padding: 20px 24px;
+ background: #fff3cd;
+ border-top: 1px solid #ffeaa7;
+ border-bottom: 1px solid #ffeaa7;
+ flex-shrink: 0;
+}
+
+.costs-preview h4 {
+ margin: 0 0 12px 0;
+ color: #856404;
+ font-size: 1rem;
+}
+
+.cost-item {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.cost-label {
+ color: #856404;
+ font-weight: 500;
+}
+
+.cost-value {
+ font-weight: bold;
+ color: #495057;
+ background: white;
+ padding: 4px 8px;
+ border-radius: 4px;
+ border: 1px solid #ffeaa7;
+}
+
+/* Action Info */
+.action-info {
+ flex: 1;
+}
+
+.selection-count {
+ font-size: 0.9rem;
+ color: #6c757d;
+ font-weight: 500;
+}
+
+.action-buttons {
+ display: flex;
+ gap: 12px;
+}
+
+/* Skills Selection Container */
+.skills-selection-container {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 20px;
+ margin-bottom: 20px;
+}
+
+@media (max-width: 1024px) {
+ .skills-selection-container {
+ grid-template-columns: 1fr;
+ gap: 16px;
+ }
+}
+
+.skills-available,
+.skills-selected {
+ border: 2px solid #dee2e6;
+ border-radius: 8px;
+ overflow: hidden;
+}
+
+.skills-available h4,
+.skills-selected h4 {
+ margin: 0;
+ padding: 12px 16px;
+ background: #f8f9fa;
+ border-bottom: 1px solid #dee2e6;
+ font-size: 1rem;
+ color: #495057;
+}
+
+/* Category Filters */
+.category-filters {
+ padding: 12px 16px;
+ border-bottom: 1px solid #dee2e6;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ background: #f8f9fa;
+}
+
+.category-filter-btn {
+ padding: 6px 12px;
+ background: white;
+ border: 2px solid #dee2e6;
+ border-radius: 20px;
+ font-size: 0.85rem;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ white-space: nowrap;
+ font-weight: 500;
+ color: #495057;
+}
+
+.category-filter-btn:hover {
+ border-color: #1da766;
+ color: #1da766;
+}
+
+.category-filter-btn.active {
+ background: #1da766;
+ border-color: #1da766;
+ color: white;
+ font-weight: 600;
+}
+
+.category-filter-btn:first-child {
+ font-weight: 600;
+ background: #e9ecef;
+ border-color: #adb5bd;
+}
+
+.category-filter-btn:first-child.active {
+ background: #495057;
+ border-color: #495057;
+ color: white;
+}
+
+/* Sort and Search Controls */
+.search-input {
+ margin: 0;
+ font-size: 13px;
+}
+
+.sort-and-search-controls {
+ padding: 12px 16px;
+ border-bottom: 1px solid #dee2e6;
+ display: flex;
+ align-items: center;
+ gap: 20px;
+ background: #f8f9fa;
+ flex-wrap: wrap;
+}
+
+.sort-controls {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ flex: 0 0 auto;
+}
+
+.skills-search {
+ flex: 1;
+ min-width: 200px;
+}
+
+.sort-label {
+ font-size: 0.9rem;
+ color: #495057;
+ font-weight: 500;
+}
+
+.sort-btn {
+ padding: 6px 12px;
+ background: white;
+ border: 2px solid #dee2e6;
+ border-radius: 6px;
+ font-size: 0.85rem;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ white-space: nowrap;
+ font-weight: 500;
+ color: #495057;
+ display: flex;
+ align-items: center;
+ gap: 4px;
+}
+
+.sort-btn:hover {
+ border-color: #1da766;
+ color: #1da766;
+}
+
+.sort-btn.active {
+ background: #1da766;
+ border-color: #1da766;
+ color: white;
+ font-weight: 600;
+}
+
+.sort-icon {
+ font-size: 0.8rem;
+ font-weight: bold;
+}
+
+/* Skills List */
+.skills-list {
+ max-height: 60vh;
+ overflow-y: auto;
+ background: white;
+}
+
+.skill-item {
+ padding: 12px 16px;
+ border-bottom: 1px solid #f8f9fa;
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ cursor: grab;
+ transition: all 0.2s ease;
+}
+
+.skill-item:hover {
+ background: #f8f9fa;
+}
+
+.skill-item:active {
+ cursor: grabbing;
+}
+
+.skill-item.skill-affordable {
+ border-left: 4px solid #1da766;
+}
+
+.skill-item:not(.skill-affordable) {
+ opacity: 0.6;
+ cursor: not-allowed;
+}
+
+.skill-info {
+ flex: 1;
+}
+
+.skill-main-line {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ flex-wrap: wrap;
+}
+
+.skill-name {
+ font-weight: 600;
+ color: #333;
+ font-size: 0.95rem;
+ min-width: 120px;
+}
+
+.skill-category {
+ font-size: 0.8rem;
+ color: #6c757d;
+ font-style: italic;
+ min-width: 100px;
+}
+
+.skill-costs {
+ display: flex;
+ gap: 8px;
+ font-size: 0.85rem;
+ margin-left: auto;
+}
+
+.cost-ep {
+ color: #1da766;
+ font-weight: 600;
+}
+
+.cost-gold {
+ color: #ffc107;
+ font-weight: 600;
+}
+
+.skill-actions {
+ display: flex;
+ gap: 8px;
+}
+
+.btn-select {
+ width: 32px;
+ height: 32px;
+ border: 2px solid #1da766;
+ background: white;
+ color: #1da766;
+ border-radius: 50%;
+ cursor: pointer;
+ font-weight: bold;
+ font-size: 14px;
+ transition: all 0.2s ease;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.btn-select:hover:not(:disabled) {
+ background: #1da766;
+ color: white;
+ transform: scale(1.1);
+}
+
+.btn-select:disabled {
+ border-color: #6c757d;
+ color: #6c757d;
+ cursor: not-allowed;
+ transform: none;
+}
+
+/* Skills Drop Zone */
+.skills-drop-zone {
+ min-height: 60vh;
+ padding: 16px;
+ background: white;
+ border: 2px dashed #dee2e6;
+ margin: 16px;
+ border-radius: 8px;
+ transition: all 0.2s ease;
+}
+
+.skills-drop-zone.drag-over {
+ border-color: #1da766;
+ background: rgba(29, 167, 102, 0.05);
+}
+
+.drop-zone-placeholder {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ min-height: 200px;
+ color: #6c757d;
+ text-align: center;
+}
+
+.placeholder-icon {
+ font-size: 48px;
+ margin-bottom: 16px;
+ opacity: 0.7;
+}
+
+.placeholder-text {
+ font-size: 0.9rem;
+ line-height: 1.4;
+ max-width: 200px;
+}
+
+/* Selected Skills List */
+.selected-skills-list {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+.selected-skill-item {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ padding: 12px;
+ background: #f8f9fa;
+ border: 1px solid #dee2e6;
+ border-radius: 6px;
+ transition: all 0.2s ease;
+}
+
+.selected-skill-item:hover {
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.selected-skill-info {
+ flex: 1;
+}
+
+.selected-skill-name {
+ font-weight: 600;
+ color: #333;
+ margin-bottom: 4px;
+}
+
+.selected-skill-costs {
+ display: flex;
+ gap: 12px;
+ font-size: 0.85rem;
+}
+
+/* Total Costs */
+.total-costs-header {
+ font-weight: 600;
+ color: #856404;
+ margin-bottom: 8px;
+}
+
+.total-costs-breakdown {
+ display: flex;
+ gap: 16px;
+ margin-bottom: 8px;
+}
+
+.total-ep,
+.total-gold {
+ font-weight: 600;
+ font-size: 0.9rem;
+}
+
+.total-ep {
+ color: #1da766;
+}
+
+.total-gold {
+ color: #ffc107;
+}
+
+.affordability-check {
+ font-size: 0.85rem;
+ font-weight: 600;
+}
+
+.text-success {
+ color: #28a745;
+}
+
+.loading-skills {
+ padding: 20px;
+ text-align: center;
+ color: #6c757d;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+}
+
+.simple-input-section {
+ margin-bottom: 20px;
+ padding: 16px;
+ background: #fff3cd;
+ border: 1px solid #ffeaa7;
+ border-radius: 8px;
+}
+
+.simple-input-section .form-group {
+ margin-bottom: 0;
+}
+
+/* ========================================
+ AUDIT LOG VIEW STYLES
+ ======================================== */
+.audit-log-view {
+ padding: 20px;
+ background: #f8f9fa;
+ border-radius: 8px;
+ margin-top: 20px;
+}
+
+.audit-log-view h4 {
+ color: #333;
+ margin-bottom: 20px;
+ padding-bottom: 10px;
+ border-bottom: 2px solid #007bff;
+}
+
+.filter-controls {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 15px;
+ align-items: center;
+ margin-bottom: 20px;
+ padding: 15px;
+ background: white;
+ border-radius: 6px;
+ border: 1px solid #e9ecef;
+}
+
+.filter-group {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.date-range-group {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ margin-left: 10px;
+}
+
+.filter-select, .date-input {
+ padding: 8px 12px;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ background: white;
+}
+
+.btn-refresh {
+ padding: 8px 16px;
+ background: #007bff;
+ color: white;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ gap: 5px;
+}
+
+.btn-refresh:hover:not(:disabled) {
+ background: #0056b3;
+}
+
+.stats-section {
+ margin-bottom: 25px;
+ padding: 15px;
+ background: white;
+ border-radius: 6px;
+ border: 1px solid #e9ecef;
+}
+
+.stats-section h5 {
+ margin-bottom: 15px;
+ color: #555;
+}
+
+.stats-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+ gap: 15px;
+}
+
+.stat-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 10px;
+ background: #f8f9fa;
+ border-radius: 4px;
+}
+
+.stat-label {
+ font-weight: 500;
+ color: #666;
+}
+
+.stat-value {
+ font-weight: bold;
+ font-size: 1.1em;
+}
+
+.stat-value.positive {
+ color: #28a745;
+}
+
+.stat-value.negative {
+ color: #dc3545;
+}
+
+.audit-entries {
+ background: white;
+ border-radius: 6px;
+ border: 1px solid #e9ecef;
+}
+
+.loading, .no-entries {
+ padding: 40px;
+ text-align: center;
+ color: #666;
+ font-style: italic;
+}
+
+.audit-entry {
+ padding: 15px;
+ border-bottom: 1px solid #e9ecef;
+ transition: background-color 0.2s;
+}
+
+.audit-entry:last-child {
+ border-bottom: none;
+}
+
+.audit-entry:hover {
+ background-color: #f8f9fa;
+}
+
+.audit-entry.positive-change {
+ border-left: 4px solid #28a745;
+}
+
+.audit-entry.negative-change {
+ border-left: 4px solid #dc3545;
+}
+
+.entry-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 10px;
+}
+
+.entry-field {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ font-weight: bold;
+}
+
+.field-icon {
+ font-size: 1.2em;
+}
+
+.entry-timestamp {
+ color: #666;
+ font-size: 0.9em;
+ text-align: right;
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+}
+
+.timestamp-date {
+ font-weight: 500;
+ color: #555;
+}
+
+.timestamp-time {
+ font-size: 0.85em;
+ color: #888;
+ font-family: monospace;
+}
+
+.timestamp-relative {
+ font-size: 0.8em;
+ color: #999;
+ font-style: italic;
+}
+
+.entry-content {
+ margin-left: 20px;
+}
+
+.value-change {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ margin-bottom: 8px;
+ font-family: monospace;
+ font-size: 1.1em;
+}
+
+.old-value {
+ color: #666;
+}
+
+.arrow {
+ color: #007bff;
+ font-weight: bold;
+}
+
+.new-value {
+ font-weight: bold;
+}
+
+.difference {
+ font-weight: bold;
+ font-size: 0.9em;
+}
+
+.difference.positive {
+ color: #28a745;
+}
+
+.difference.negative {
+ color: #dc3545;
+}
+
+.entry-reason, .entry-notes {
+ display: flex;
+ gap: 8px;
+ margin-bottom: 5px;
+ font-size: 0.9em;
+}
+
+.reason-label, .notes-label {
+ font-weight: 500;
+ color: #666;
+ min-width: 50px;
+}
+
+.reason-value {
+ background: #e9ecef;
+ padding: 2px 8px;
+ border-radius: 12px;
+ font-size: 0.85em;
+ font-weight: 500;
+}
+
+.notes-value {
+ color: #555;
+ font-style: italic;
+}
+
+.date-group {
+ margin-bottom: 25px;
+}
+
+.date-group-header {
+ background: #007bff;
+ color: white;
+ padding: 8px 15px;
+ margin: 0 0 10px 0;
+ border-radius: 4px;
+ font-weight: 500;
+ font-size: 0.9em;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.checkbox-input {
+ margin-right: 8px;
+}
+
+/* ========================================
+ EQUIPMENT VIEW STYLES
+ ======================================== */
+.btn-add-equipment {
+ padding: 8px 16px;
+ background: #1da766;
+ color: white;
+ border: none;
+ border-radius: 6px;
+ cursor: pointer;
+ font-weight: bold;
+ transition: background 0.2s ease;
+}
+
+.btn-add-equipment:hover {
+ background: #16a085;
+}
+
+.empty-state {
+ text-align: center;
+ color: #999;
+ font-style: italic;
+ padding: 2rem !important;
+}
+
+.btn-delete {
+ background: none;
+ border: none;
+ cursor: pointer;
+ font-size: 1.2rem;
+ padding: 4px 8px;
+ transition: transform 0.2s ease;
+}
+
+.btn-delete:hover {
+ transform: scale(1.2);
+}
+
+.equipment-list {
+ max-height: 300px;
+ overflow-y: auto;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ margin-bottom: 15px;
+}
+
+.equipment-item {
+ padding: 12px;
+ border-bottom: 1px solid #eee;
+ cursor: pointer;
+ transition: background 0.2s ease;
+}
+
+.equipment-item:hover {
+ background: #f5f5f5;
+}
+
+.equipment-item.selected {
+ background: #e8f5e9;
+ border-left: 3px solid #1da766;
+}
+
+.equipment-name {
+ font-weight: bold;
+ color: #333;
+ margin-bottom: 4px;
+}
+
+.equipment-details {
+ font-size: 0.9em;
+ color: #666;
+}
+
+.no-results {
+ text-align: center;
+ padding: 2rem;
+ color: #999;
+ font-style: italic;
+}
+
+.selected-equipment-details {
+ background: #f8f9fa;
+ padding: 15px;
+ border-radius: 4px;
+ margin-top: 15px;
+}
+
+.selected-equipment-details h4 {
+ margin-top: 0;
+ color: #1da766;
+}
+
+.selected-equipment-details p {
+ margin: 8px 0;
+}
+
+.btn-confirm {
+ padding: 8px 20px;
+ background: #1da766;
+ color: white;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+ font-weight: bold;
+ transition: background 0.2s ease;
+}
+
+.btn-confirm:hover:not(:disabled) {
+ background: #16a085;
+}
+
+.btn-confirm:disabled {
+ background: #ccc;
+ cursor: not-allowed;
+}
+
+.btn-cancel {
+ padding: 8px 20px;
+ background: #6c757d;
+ color: white;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+ transition: background 0.2s ease;
+}
+
+.btn-cancel:hover {
+ background: #5a6268;
+}
+
+/* ========================================
+ CHARACTER CREATION STYLES
+ ======================================== */
+.character-creation {
+ width: 100%;
+ max-width: none;
+ margin: 0;
+ padding: 10px;
+}
+
+.creation-content {
+ width: 100%;
+ background: white;
+ border-radius: 8px;
+ padding: 30px;
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+ margin-bottom: 20px;
+}
+
+.creation-header {
+ margin-bottom: 30px;
+}
+
+.creation-header h1 {
+ text-align: center;
+ margin-bottom: 20px;
+ color: #333;
+}
+
+.progress-indicator {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 20px;
+ margin-bottom: 20px;
+}
+
+.step {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 10px;
+ border-radius: 8px;
+ transition: all 0.3s ease;
+}
+
+.step.active {
+ background-color: #e3f2fd;
+ border: 2px solid #2196f3;
+}
+
+.step.completed {
+ background-color: #e8f5e8;
+ border: 2px solid #4caf50;
+}
+
+.step-number {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 30px;
+ height: 30px;
+ border-radius: 50%;
+ background-color: #ddd;
+ color: #666;
+ font-weight: bold;
+ margin-bottom: 5px;
+}
+
+.step.active .step-number {
+ background-color: #2196f3;
+ color: white;
+}
+
+.step.completed .step-number {
+ background-color: #4caf50;
+ color: white;
+}
+
+.step.clickable {
+ cursor: pointer;
+ transition: all 0.3s ease;
+}
+
+.step.clickable:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
+}
+
+.step.completed:hover .step-number {
+ background-color: #45a049;
+}
+
+.step.active:hover .step-number {
+ background-color: #1976d2;
+}
+
+.step-title {
+ font-size: 12px;
+ color: #666;
+ text-align: center;
+}
+
+.session-info {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 15px;
+ background-color: #f5f5f5;
+ border-radius: 4px;
+ font-size: 14px;
+ color: #666;
+}
+
+.delete-btn {
+ background-color: #f44336;
+ color: white;
+ padding: 8px 16px;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+ font-size: 14px;
+}
+
+.delete-btn:hover {
+ background-color: #d32f2f;
+}
+
+/* ========================================
+ DATASHEET VIEW STYLES
+ ======================================== */
+.datasheet-container {
+ padding-top: 10px;
+}
+
+.character-overview {
+ margin-bottom: 30px;
+ margin-top: 0;
+}
+
+.character-image {
+ position: relative;
+}
+
+.character-image .image-upload-container {
+ position: absolute;
+ bottom: 10px;
+ right: 10px;
+}
+
+.character-info {
+ margin-top: 20px;
+}
+
+.info-section {
+ max-width: none;
+ white-space: normal;
+ line-height: 1.6;
+}
+
+.info-section p {
+ margin: 15px 0;
+ padding: 0;
+}
+
+.editable-value {
+ cursor: pointer;
+ padding: 2px 4px;
+ border-radius: 3px;
+ transition: background-color 0.2s;
+}
+
+.editable-value:hover {
+ background-color: rgba(0, 123, 255, 0.1);
+}
+
+.edit-input {
+ width: 60px;
+ padding: 2px 4px;
+ font-size: inherit;
+ font-weight: bold;
+ border: 2px solid var(--primary-color);
+ border-radius: 3px;
+ text-align: center;
+}
+
+.edit-input:focus {
+ outline: none;
+ border-color: #0056b3;
+}
+
+.editable-prop {
+ cursor: pointer;
+ padding: 1px 3px;
+ border-radius: 2px;
+ transition: background-color 0.2s;
+ display: inline-block;
+ min-width: 20px;
+}
+
+.editable-prop:hover {
+ background-color: rgba(0, 123, 255, 0.1);
+}
+
+.prop-input {
+ padding: 1px 4px;
+ font-size: inherit;
+ border: 1px solid var(--primary-color);
+ border-radius: 3px;
+ min-width: 60px;
+}
+
+.prop-input:focus {
+ outline: none;
+ border-color: #0056b3;
+}
+
+/* ===================================
+ LANDING PAGE STYLES
+ =================================== */
+
+.landing-page {
+ width: 100vw;
+ height: 100vh;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ background-image: url('/Abgrund-DD2.jpg');
+ background-size: cover;
+ background-position: center;
+ background-repeat: no-repeat;
+ background-attachment: fixed;
+ position: relative;
+ overflow: hidden;
+}
+
+.landing-page::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(0, 0, 0, 0.5);
+ z-index: 1;
+}
+
+.landing-content {
+ position: relative;
+ z-index: 2;
+ max-width: 800px;
+ padding: 2rem;
+ text-align: center;
+ color: white;
+}
+
+.dragon-container {
+ margin-bottom: 2rem;
+}
+
+.dragon-image {
+ max-width: 300px;
+ width: 100%;
+ height: auto;
+ filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3));
+ animation: float 3s ease-in-out infinite;
+}
+
+@keyframes float {
+ 0%, 100% {
+ transform: translateY(0);
+ }
+ 50% {
+ transform: translateY(-10px);
+ }
+}
+
+.info-container h1 {
+ font-size: 2.5rem;
+ margin-bottom: 1.5rem;
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
+ line-height: 1.2;
+}
+
+.info-container .description {
+ font-size: 1.2rem;
+ line-height: 1.6;
+ margin-bottom: 2rem;
+ text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7);
+}
+
+.version-info {
+ margin-bottom: 2rem;
+ font-size: 0.9rem;
+ opacity: 0.9;
+}
+
+.version-info p {
+ margin: 0.5rem 0;
+ line-height: 1.4;
+}
+
+.action-links {
+ display: flex;
+ gap: 1rem;
+ justify-content: center;
+ flex-wrap: wrap;
+}
+
+.action-links .btn {
+ min-width: 150px;
+ font-size: 1.1rem;
+ padding: 12px 24px;
+}
+
+@media (max-width: 768px) {
+ .landing-content {
+ padding: 1rem;
+ }
+
+ .dragon-image {
+ max-width: 200px;
+ }
+
+ .info-container h1 {
+ font-size: 1.8rem;
+ }
+
+ .info-container .description {
+ font-size: 1rem;
+ }
+
+ .action-links {
+ flex-direction: column;
+ align-items: center;
+ }
+
+ .action-links .btn {
+ width: 100%;
+ max-width: 300px;
+ }
}
\ No newline at end of file
diff --git a/frontend/src/components/AuditLogView.vue b/frontend/src/components/AuditLogView.vue
index c32b016..af2030a 100644
--- a/frontend/src/components/AuditLogView.vue
+++ b/frontend/src/components/AuditLogView.vue
@@ -431,276 +431,6 @@ export default {
};
-
diff --git a/frontend/src/components/AusruestungForm.vue b/frontend/src/components/AusruestungForm.vue
index 0db9227..fe387e1 100644
--- a/frontend/src/components/AusruestungForm.vue
+++ b/frontend/src/components/AusruestungForm.vue
@@ -35,3 +35,7 @@ export default {
},
}
+
+
diff --git a/frontend/src/components/AusruestungList.vue b/frontend/src/components/AusruestungList.vue
index f78556e..b397174 100644
--- a/frontend/src/components/AusruestungList.vue
+++ b/frontend/src/components/AusruestungList.vue
@@ -38,3 +38,7 @@ export default {
},
}
+
+
diff --git a/frontend/src/components/CharacterCreation.vue b/frontend/src/components/CharacterCreation.vue
index 8e816fc..26fa0db 100644
--- a/frontend/src/components/CharacterCreation.vue
+++ b/frontend/src/components/CharacterCreation.vue
@@ -359,132 +359,6 @@ export default {
}
-
diff --git a/frontend/src/components/CharacterCreation/CharacterAttributes.vue b/frontend/src/components/CharacterCreation/CharacterAttributes.vue
index 2ec184d..cc1087d 100644
--- a/frontend/src/components/CharacterCreation/CharacterAttributes.vue
+++ b/frontend/src/components/CharacterCreation/CharacterAttributes.vue
@@ -336,22 +336,8 @@ export default {
}
-
diff --git a/frontend/src/components/CharacterCreation/CharacterBasicInfo.vue b/frontend/src/components/CharacterCreation/CharacterBasicInfo.vue
index fda5b8b..f4f2666 100644
--- a/frontend/src/components/CharacterCreation/CharacterBasicInfo.vue
+++ b/frontend/src/components/CharacterCreation/CharacterBasicInfo.vue
@@ -390,49 +390,8 @@ export default {
}
-
diff --git a/frontend/src/components/CharacterCreation/CharacterSkills.vue b/frontend/src/components/CharacterCreation/CharacterSkills.vue
index e433139..86b5798 100644
--- a/frontend/src/components/CharacterCreation/CharacterSkills.vue
+++ b/frontend/src/components/CharacterCreation/CharacterSkills.vue
@@ -705,10 +705,9 @@ export default {
}
-
+
\ No newline at end of file
diff --git a/frontend/src/components/CharacterList.vue b/frontend/src/components/CharacterList.vue
index b741f4e..441dcec 100644
--- a/frontend/src/components/CharacterList.vue
+++ b/frontend/src/components/CharacterList.vue
@@ -132,8 +132,9 @@ export default {
}
-
-
+
diff --git a/frontend/src/components/EquipmentView.vue b/frontend/src/components/EquipmentView.vue
index 0785770..85549cc 100644
--- a/frontend/src/components/EquipmentView.vue
+++ b/frontend/src/components/EquipmentView.vue
@@ -119,272 +119,12 @@
-
diff --git a/frontend/src/components/ExperianceView.vue b/frontend/src/components/ExperianceView.vue
index 1509c36..72dea8a 100644
--- a/frontend/src/components/ExperianceView.vue
+++ b/frontend/src/components/ExperianceView.vue
@@ -93,8 +93,8 @@
-
+
+
diff --git a/frontend/src/components/ForgotPasswordForm.vue b/frontend/src/components/ForgotPasswordForm.vue
index a8b1069..c1f276b 100644
--- a/frontend/src/components/ForgotPasswordForm.vue
+++ b/frontend/src/components/ForgotPasswordForm.vue
@@ -95,6 +95,6 @@ export default {
}
-
diff --git a/frontend/src/components/ImageUploadCropper.vue b/frontend/src/components/ImageUploadCropper.vue
index 60ae4ed..791c049 100644
--- a/frontend/src/components/ImageUploadCropper.vue
+++ b/frontend/src/components/ImageUploadCropper.vue
@@ -74,7 +74,10 @@
-
-
diff --git a/frontend/src/components/Menu.vue b/frontend/src/components/Menu.vue
index 1e20def..1fc86be 100644
--- a/frontend/src/components/Menu.vue
+++ b/frontend/src/components/Menu.vue
@@ -1,6 +1,9 @@
diff --git a/frontend/src/components/SkillLearnDialog.vue b/frontend/src/components/SkillLearnDialog.vue
index ca9012c..13e6a43 100644
--- a/frontend/src/components/SkillLearnDialog.vue
+++ b/frontend/src/components/SkillLearnDialog.vue
@@ -740,17 +740,9 @@ export default {
-
-
diff --git a/frontend/src/components/WeaponView.vue b/frontend/src/components/WeaponView.vue
index 1812e17..2b32f3f 100644
--- a/frontend/src/components/WeaponView.vue
+++ b/frontend/src/components/WeaponView.vue
@@ -191,7 +191,9 @@
-
diff --git a/frontend/src/views/UserProfileView.vue b/frontend/src/views/UserProfileView.vue
index 92619ed..fd615cf 100644
--- a/frontend/src/views/UserProfileView.vue
+++ b/frontend/src/views/UserProfileView.vue
@@ -95,7 +95,9 @@
-