diff --git a/LICENSE.mit b/LICENSE similarity index 100% rename from LICENSE.mit rename to LICENSE diff --git a/LICENSE.gnu b/LICENSE.gnu deleted file mode 100644 index 77791b4..0000000 --- a/LICENSE.gnu +++ /dev/null @@ -1,26 +0,0 @@ -GNU AFFERO GENERAL PUBLIC LICENSE -Version 3, 19 November 2007 - ---- - -Copyright © Patrick Asmus (scriptos) - -Name: Patrick Asmus (scriptos) -Email: support@techniverse.net -Website: https://www.patrick-asmus.de -Blog: https://www.cleveradmin.de - ---- - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . diff --git a/README.md b/README.md index dc14603..43eca71 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,10 @@

-

Name des Projekts

+

Kutt Dark Mode CSS

- Kurzbeschreibung des Projekts/Anwendung, um die es geht + Ein sauberes Dark-Mode-Theme für Kutt, den selbst gehosteten URL-Shortener.

@@ -22,7 +22,170 @@

-CONTENT BEREICH +## Vorschau + +![Kutt Dark Mode CSS Vorschau](assets/screenshot1.png) + +- Hintergrund: Dunkles Blaugrau (`#0f1419`) +- Akzentfarbe: Blau (`#1D6397`) +- Alle Icons (Edit, Delete, QR-Code, Stats, Ban) bleiben sichtbar und funktional + +## Installation + +### 1. Volume in `docker-compose.yaml` einrichten + +Der Kutt-Container braucht ein Volume, das den Custom-Ordner einbindet: + +```yaml +services: + kutt-app: + image: kutt/kutt:latest + volumes: + - ./data/app/custom:/kutt/custom +``` + +### 2. CSS-Datei kopieren + +Die Datei `custom.css` in den CSS-Ordner innerhalb des Custom-Verzeichnisses legen: + +```bash +mkdir -p ./data/app/custom/css +cp custom.css ./data/app/custom/css/custom.css +``` + +### 3. Container neu starten + +```bash +docker restart kutt-app +``` + +### 4. Im Browser prüfen + +Die Seite mit `Ctrl + Shift + R` (Hard-Reload) neu laden, damit der Browser-Cache das neue CSS holt. + +![Kutt Dark Mode CSS Vorschau](assets/screenshot2.png) + +## Logo anpassen + +Kutt unterstützt ein eigenes Logo über das Custom-Verzeichnis: + +```bash +mkdir -p ./data/app/custom/images +cp dein-logo.png ./data/app/custom/images/logo.png +``` + +Das Logo wird automatisch von Kutt geladen. Das CSS sorgt dafür, dass es als 32x32px Kreis dargestellt wird: + +```css +img[src*="logo"] { + width: 32px; + height: 32px; + object-fit: contain; + border-radius: 50%; +} +``` + +Wenn du ein eckiges Logo bevorzugst, einfach `border-radius: 50%;` entfernen oder auf z.B. `border-radius: 6px;` ändern. + +### Weitere anpassbare Bilder + +| Datei | Zweck | +|---|---| +| `images/logo.png` | Logo im Header | +| `images/favicon.ico` | Browser-Tab-Icon | +| `images/favicon-16x16.png` | Favicon 16px | +| `images/favicon-32x32.png` | Favicon 32px | +| `images/favicon-196x196.png` | Favicon groß (Android etc.) | +| `images/card.png` | Social-Media-Vorschaubild (Open Graph) | + +Alle Dateien kommen in `./data/app/custom/images/`. + +## Wichtige CSS-Variablen + +Die wichtigsten Farben werden über CSS Custom Properties gesteuert. Sie stehen ganz oben in der `custom.css` im `:root`-Block und können dort einfach angepasst werden: + +### Akzentfarbe + +```css +--color-primary: #1D6397; /* Hauptfarbe für Links und Buttons */ +--outline-color: #1D6397; /* Fokus-Rahmen */ +--focus-outline-color: rgba(29, 99, 151, 0.5); +--checkbox-bg-color: #1D6397; /* Checkbox-Farbe */ +``` + +Um die Akzentfarbe zu ändern, diese vier Werte plus die Button-Gradients anpassen: + +```css +--button-bg-primary: linear-gradient(to right, #1a5a8a, #1D6397); +--button-bg-primary-box-shadow-color: rgba(29, 99, 151, 0.35); +``` + +### Hintergründe + +```css +--bg-color: #0f1419; /* Seiten-Hintergrund */ +--table-bg-color: #151d28; /* Tabellen-Header/Footer */ +--table-tr-hover-bg-color: #1a2535; /* Zeile beim Hover */ +``` + +Für Tabellen und Karten wird `#141c26` als Hintergrund und `#1a2332` für erhöhte Elemente (Inputs, Buttons) verwendet. Diese Werte stehen direkt in den CSS-Regeln (nicht als Variable). + +### Text + +```css +--text-color: #dce0e8; /* Haupttext */ +--secondary-text-color: #8b95a5; /* Gedämpfter Text */ +--input-label-color: #c8cdd5; /* Label-Text */ +``` + +## Custom Footer + +Kutt erlaubt einen eigenen Footer über eine Handlebars-Vorlage: + +```bash +mkdir -p ./data/app/custom/views/partials +``` + +Dort eine Datei `footer.hbs` anlegen, z.B.: + +```html + +``` + +Das CSS enthält bereits passende Styles für `.site-footer`. + +## Verzeichnisstruktur + +So sollte das Custom-Verzeichnis am Ende aussehen: + +``` +data/app/custom/ + css/ + custom.css + images/ + logo.png + favicon.ico + favicon-16x16.png + favicon-32x32.png + favicon-196x196.png + card.png + views/ + partials/ + footer.hbs +``` + +## Hinweise + +- Das CSS überschreibt Kutts eingebaute CSS-Variablen. Bei einem Kutt-Update könnten sich Klassennamen ändern — nach Updates kurz prüfen. +- Die Icons (Edit, Delete, QR, Stats, Ban) werden bewusst nicht über `color`-Overrides verändert, sondern behalten ihre originalen `stroke`/`fill`-Werte. Nur die Hintergründe der Action-Buttons werden dezent angepasst. +- Getestet mit Kutt `latest` (Stand Juli 2025). +

@@ -34,4 +197,4 @@ CONTENT BEREICH © Patrick Asmus · Techniverse Network · Lizenz -

\ No newline at end of file +

diff --git a/assets/screenshot1.png b/assets/screenshot1.png new file mode 100644 index 0000000..e516ff0 Binary files /dev/null and b/assets/screenshot1.png differ diff --git a/assets/screenshot2.png b/assets/screenshot2.png new file mode 100644 index 0000000..4aedb3a Binary files /dev/null and b/assets/screenshot2.png differ diff --git a/custom.css b/custom.css new file mode 100644 index 0000000..57d3ddf --- /dev/null +++ b/custom.css @@ -0,0 +1,419 @@ +/* ========================================================== + Kutt Dark Mode – Techniverse + Accent: #1D6397 + ========================================================== */ + + +/* ---------------------------------------------------------- + 1. CSS-VARIABLEN ÜBERSCHREIBEN + ---------------------------------------------------------- */ + +:root { + --bg-color: #0f1419; + --text-color: #dce0e8; + --color-primary: #1D6397; + --outline-color: #1D6397; + --button-bg: linear-gradient(to right, #2a3545, #1e2a38); + --button-bg-box-shadow-color: rgba(0, 0, 0, 0.4); + --button-bg-primary: linear-gradient(to right, #1a5a8a, #1D6397); + --button-bg-primary-box-shadow-color: rgba(29, 99, 151, 0.35); + --button-bg-secondary: linear-gradient(to right, hsl(262, 47%, 45%), hsl(265, 80%, 40%)); + --button-bg-secondary-box-shadow-color: hsla(258, 58%, 35%, 0.4); + --button-bg-danger: linear-gradient(to right, hsl(0, 70%, 45%), hsl(0, 65%, 40%)); + --button-bg-danger-box-shadow-color: hsla(0, 58%, 35%, 0.4); + --button-bg-success: linear-gradient(to right, hsl(130, 50%, 38%), hsl(130, 55%, 35%)); + --button-bg-success-box-shadow-color: hsla(128, 60%, 35%, 0.4); + --button-action-shadow-color: rgba(0, 0, 0, 0.25); + --underline-color: #4a5568; + --secondary-text-color: #8b95a5; + --send-icon-hover-color: #1D6397; + --send-spinner-icon-color: #4a5568; + --success-icon-color: hsl(144, 45%, 50%); + --error-icon-color: hsl(0, 70%, 55%); + --copy-icon-color: hsl(144, 45%, 50%); + --copy-icon-bg-color: hsla(144, 40%, 30%, 0.3); + --copy-icon-shadow-color: rgba(0, 0, 0, 0.2); + --focus-outline-color: rgba(29, 99, 151, 0.5); + --checkbox-bg-color: #1D6397; + --input-shadow-color: rgba(0, 0, 0, 0.25); + --input-hover-shadow-color: rgba(0, 0, 0, 0.4); + --input-label-color: #c8cdd5; + --table-bg-color: #151d28; + --table-shadow-color: rgba(0, 0, 0, 0.35); + --table-tr-border-color: #1e2a38; + --table-tr-hover-bg-color: #1a2535; + --table-head-tr-border-color: #253342; + --table-status-gray-bg-color: #1a2332; +} + + +/* ---------------------------------------------------------- + 2. GLOBALE GRUNDLAGEN + ---------------------------------------------------------- */ + +body { + background-color: var(--bg-color) !important; + color: var(--text-color) !important; +} + +hr { + background-color: #1e2a38 !important; +} + +span.underline { + border-bottom-color: #4a5568 !important; +} + + +/* ---------------------------------------------------------- + 3. BUTTONS + ---------------------------------------------------------- */ + +a.button, +button { + color: #c8cdd5; +} + +a.button.primary, +button.primary, +a.button.secondary, +button.secondary, +a.button.danger, +button.danger, +a.button.success, +button.success { + color: white; +} + +button.nav { + background-color: #1a2332; + box-shadow: 0 0px 10px rgba(0, 0, 0, 0.2); + color: #c8cdd5; +} + +button.nav:disabled { + background-color: #141c26; + box-shadow: 0 0px 5px rgba(0, 0, 0, 0.15); + color: #4a5568; +} + +/* Action-Button Hintergründe für Dark Mode anpassen */ +a.button.action.delete, +button.action.delete { + background: hsla(0, 60%, 40%, 0.2); +} + +a.button.action.edit, +button.action.edit { + background: hsla(46, 70%, 40%, 0.2); +} + +a.button.action.qrcode, +button.action.qrcode { + background: hsla(0, 0%, 50%, 0.15); +} + +a.button.action.stats, +button.action.stats { + background: hsla(260, 60%, 50%, 0.2); +} + +a.button.action.ban, +button.action.ban { + background: hsla(10, 60%, 40%, 0.2); +} + + +/* ---------------------------------------------------------- + 4. INPUTS & SELECTS + ---------------------------------------------------------- */ + +input[type="text"], +input[type="email"], +input[type="password"] { + color: #dce0e8; + background-color: #1a2332; + border-bottom-color: #253342; +} + +input[type="text"]::placeholder, +input[type="email"]::placeholder, +input[type="password"]::placeholder { + color: #5a6577; +} + +.error input[type="text"], +.error input[type="email"], +.error input[type="password"] { + border-bottom-color: rgba(220, 50, 50, 0.6); + box-shadow: 0 10px 15px hsla(0, 70%, 40%, 0.15); +} + +select { + color: #dce0e8; + background-color: #1a2332; + border-bottom-color: #253342; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='48' height='48' viewBox='0 0 24 24' fill='none' stroke='%238b95a5' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E"); +} + +.error select { + border-bottom-color: rgba(220, 50, 50, 0.6); + box-shadow: 0 10px 15px hsla(0, 70%, 40%, 0.15); +} + +select:has(option[value=""]:checked) { + color: #5a6577; +} + +select option { + background-color: #1a2332; + color: #dce0e8; +} + +input[type="checkbox"] { + background-color: #1a2332; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); +} + +label { + color: var(--input-label-color); +} + +p.error { color: #e5534b; } +p.success { color: #2ea043; } + + +/* ---------------------------------------------------------- + 5. TABELLEN + ---------------------------------------------------------- */ + +table { + background-color: #141c26; +} + +table thead { + background-color: var(--table-bg-color); +} + +table tfoot { + background-color: var(--table-bg-color); +} + +table .tab a { + color: var(--text-color); + background-color: #1a2332; + box-shadow: 0 0px 10px rgba(0, 0, 0, 0.2); +} + +table .tab a.active { + background-color: #111920; + box-shadow: 0 0px 5px rgba(0, 0, 0, 0.15); + color: #4a5568; +} + +#main-table-wrapper table td .description { + color: #6b7585; +} +#main-table-wrapper table td .description a { + color: #5a6577; + border-bottom-color: #5a6577; +} +#main-table-wrapper table td .description span { + color: #5a6577; +} + +#main-table-wrapper table .status.gray { + background-color: var(--table-status-gray-bg-color); +} +#main-table-wrapper table .status.green { + background-color: hsla(130, 50%, 30%, 0.3); + color: #2ea043; +} +#main-table-wrapper table .status.red { + background-color: hsla(0, 50%, 30%, 0.3); + color: #e5534b; +} + +/* Fade-Gradient für abgeschnittene Texte */ +#main-table-wrapper table tbody td.right-fade:after { + background: linear-gradient(to left, #141c26, rgba(20, 28, 38, 0.001)); +} + +#main-table-wrapper table tbody tr:hover td.right-fade:after { + background: linear-gradient(to left, var(--table-tr-hover-bg-color), rgba(26, 37, 53, 0.001)); +} + +/* Edit-Zeile */ +#main-table-wrapper table tr.edit { + background-color: #111920; +} + + +/* ---------------------------------------------------------- + 6. DIALOGE + ---------------------------------------------------------- */ + +.dialog { + background-color: rgba(0, 0, 0, 0.75); +} + +.dialog .box { + background-color: #1a2332; +} + + +/* ---------------------------------------------------------- + 7. HEADER + ---------------------------------------------------------- */ + +header a.logo:hover { + color: inherit; +} + + +/* ---------------------------------------------------------- + 8. SHORTENER (Hauptseite) + ---------------------------------------------------------- */ + +main #shorturl h1 span { + border-bottom-color: #4a5568; +} + +main form button.submit svg.send { + fill: #5a6577; +} + + +/* ---------------------------------------------------------- + 9. TOOLTIPS + ---------------------------------------------------------- */ + +[data-tooltip]:before { + border-top-color: #1a2332; +} + +[data-tooltip]:after { + background: #1a2332; + color: #dce0e8; + box-shadow: 0 1em 2em -0.5em rgba(0, 0, 0, 0.5); +} + + +/* ---------------------------------------------------------- + 10. STATISTIKEN + ---------------------------------------------------------- */ + +#stats { + background-color: #141c26; +} + +.stats-head { + background-color: var(--table-bg-color); +} + +svg.map path { + fill: #1a2332; + stroke: #0f1419; +} + +svg.map path.color-1 { fill: hsla(207, 50%, 30%, 0.4); } +svg.map path.color-2 { fill: hsla(207, 50%, 35%, 0.5); } +svg.map path.color-3 { fill: hsla(207, 50%, 40%, 0.6); } +svg.map path.color-4 { fill: hsla(207, 50%, 45%, 0.7); } +svg.map path.color-5 { fill: hsla(207, 50%, 50%, 0.8); } +svg.map path.color-6 { fill: hsla(207, 50%, 55%, 0.9); } +svg.map path.active { stroke: #1D6397; } + +#map-tooltip:before { + border-top-color: #1a2332; +} + +#map-tooltip:after { + background: rgba(26, 35, 50, 0.95); + color: #dce0e8; + box-shadow: 0 1em 2em -0.5em rgba(0, 0, 0, 0.4); +} + + +/* ---------------------------------------------------------- + 11. SETTINGS + ---------------------------------------------------------- */ + +h1.settings-welcome span { + border-bottom-color: #4a5568; +} + +#apikey p { + border-bottom-color: #4a5568; +} + + +/* ---------------------------------------------------------- + 12. SONSTIGES + ---------------------------------------------------------- */ + +a.wrapper-only { + color: inherit; +} + +/* Scrollbar */ +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + background: #0f1419; +} + +::-webkit-scrollbar-thumb { + background: #2a3545; + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: #3a4a5d; +} + + +/* ========================================================== + LOGO & FOOTER (Techniverse Branding) + ========================================================== */ + +/* Logo proportional (Kreis) */ +img[src*="logo"] { + width: 32px; + height: 32px; + object-fit: contain; + border-radius: 50%; +} + +/* Footer */ +.site-footer { + margin-top: 3rem; + text-align: center; +} +.site-footer p { + font-size: 1rem; +} +.site-footer a { + font-weight: 600; + font-size: 1.05rem; + text-decoration: none; +} +.site-footer a:hover { + text-decoration: underline; +} +.site-footer span[aria-hidden="true"] { + opacity: 0.5; + margin: 0 0.5rem; +} +.site-footer .link { + background: none; + border: none; + font-weight: 600; + font-size: 1.05rem; +} +.site-footer .link:hover { + text-decoration: underline; +}