feat(ui): Hintergrundgrafiken fuer Leiste und Seitenleiste je Theme
Pixel Art, Outdoor und Cyberpunk legen jetzt eine Grafik hinter die obere Leiste und die Seitenleiste: 8-bit-Himmel mit Wolken und Huegelkante sowie eine Steinmauer, blauer Himmel mit Schleierwolken sowie eine Wiese, Neonroehren im Regen sowie eine regnerische Gasse. perinco bleibt einfarbig. Sechs SVG in public/themes/, von Hand gezeichnet - stilisierte Grafik statt Foto, damit sie in jeder Aufloesung scharf bleibt; zusammen 36 kB. Die Pixel-Grafiken haben einen absichtlich winzigen viewBox (eine Einheit = ein Bildpunkt) und shape-rendering="crispEdges", damit die Kanten beim Hochskalieren hart bleiben; die Mauer blendet nach oben stufenweise aus und nicht mit einem Verlauf - Pixelgrafik kennt keine Zwischentoene. Im Markup nur zwei Anker: app-header und app-sidebar. Den Rest machen zwei Variablen mit Rueckfall auf none, weshalb perinco unberuehrt bleibt. Die Variable enthaelt zwei Ebenen: einen Schleier aus der Flaechenfarbe des Themes und darunter die Grafik. Das erledigt zwei Dinge zugleich - derselbe blaue Himmel wird im Dunkelmodus zur Nacht (keine zweite Datei noetig), und die Schrift bleibt lesbar, weil der Schleier in der Leiste an den Raendern dicht liegt und in der Seitenleiste oben ueber den Menuepunkten. Aus dem ersten Versuch gelernt: die Cyberpunk-Grafik hatte eine deckende Nachtflaeche. Im hellen Modus wurde daraus unter dem weissen Schleier ein grauer Schmutzstreifen. Sie ist jetzt durchsichtig und zeigt nur Licht - ueber Dunkel leuchtet das Neon, ueber Weiss bleiben blasse farbige Linien. Ebenso zurueckgenommen wurde der Schleier ueber der Steinmauer: "Einstellungen" und der Benutzername stehen darauf. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
93fe8cfd73
commit
dc701f8522
@@ -169,6 +169,49 @@ Augenblick das Design des ersten.
|
||||
Der `ThemeProvider` steht deshalb in `main.tsx` **unter** dem `AuthProvider` -
|
||||
er liest den Benutzer.
|
||||
|
||||
### Hintergrundbilder in Leiste und Seitenleiste
|
||||
|
||||
Alle Themes außer perinco legen eine Grafik hinter die obere Leiste und die
|
||||
Seitenleiste: 8-bit-Himmel und Steinmauer, blauer Himmel und Wiese,
|
||||
Neonröhren und regnerische Gasse. Die Dateien liegen als **SVG** in
|
||||
`public/themes/` und sind von Hand gezeichnet - stilisierte Grafik statt Foto,
|
||||
damit sie in jeder Auflösung scharf bleibt und wenige Kilobyte wiegt.
|
||||
|
||||
Zwei Anker im Markup: `app-header` an `<header>` und `app-sidebar` an `<aside>`.
|
||||
Mehr braucht es nicht, den Rest machen zwei Variablen:
|
||||
|
||||
```css
|
||||
.app-header { background-image: var(--theme-header-image, none); background-size: cover; }
|
||||
.app-sidebar { background-image: var(--theme-sidebar-image, none); background-position: bottom center; }
|
||||
```
|
||||
|
||||
Ohne Theme steht in den Variablen nichts, der Rückfall `none` greift, und
|
||||
perinco bleibt einfarbig. `bg-surface` bleibt an beiden Elementen: die Farbe
|
||||
liegt unter dem Bild und trägt, solange es lädt oder fehlt.
|
||||
|
||||
Die Variable enthält **zwei Ebenen** - einen Schleier aus der Flächenfarbe des
|
||||
Themes und darunter die Grafik:
|
||||
|
||||
```css
|
||||
--theme-header-image: linear-gradient(90deg, rgb(26 32 22 / .95) 0%, rgb(26 32 22 / .6) 55%, …),
|
||||
url('/themes/outdoor-header.svg');
|
||||
```
|
||||
|
||||
Das ist kein Umweg, sondern erledigt zwei Dinge zugleich:
|
||||
|
||||
1. **Eine Grafik für beide Modi.** Der dunkle Schleier des Dunkelmodus tönt
|
||||
denselben blauen Himmel zur Nacht ab - es braucht keine zweite Datei.
|
||||
2. **Lesbarkeit.** In der oberen Leiste liegt der Schleier an den Rändern dicht
|
||||
(Titel links, Schalter rechts) und lässt die Grafik nur in der leeren Mitte
|
||||
durch; in der Seitenleiste deckt er oben über den Menüpunkten und gibt nach
|
||||
unten frei, wo die Leiste ohnehin leer ist.
|
||||
|
||||
> **Eine Lehre aus dem ersten Versuch:** Die Cyberpunk-Grafik hatte zuerst eine
|
||||
> deckende Nachtfläche. Im **hellen** Modus wurde daraus unter dem weissen
|
||||
> Schleier ein grauer Schmutzstreifen. Seither ist sie durchsichtig und zeigt
|
||||
> nur Licht - über Dunkel leuchtet das Neon, über Weiss bleiben blasse farbige
|
||||
> Linien. Wer eine Grafik ergänzt: **keine deckenden Flächen**, nur Motiv.
|
||||
|
||||
### Was ein neues Theme können muss
|
||||
|
||||
Die Rollen der Skalen sind über die ganze App gleich; ein Theme, das sie
|
||||
|
||||
@@ -85,6 +85,12 @@ die Scanner-Einstellungen. Alles andere ist für beide Rollen gleich.
|
||||
haben bis zu acht Spalten, und eine Pixelschrift wäre darin nicht mehr zu
|
||||
lesen.
|
||||
|
||||
Die drei Designs neben perinco haben zusätzlich eine **Grafik** hinter der
|
||||
oberen Leiste und der Seitenleiste: 8-bit-Himmel und Steinmauer, blauer Himmel
|
||||
und Wiese, Neonröhren und Regen. Sie liegt hinter einem Schleier, damit die
|
||||
Schrift darauf lesbar bleibt, und ist dort am deutlichsten, wo die Leisten frei
|
||||
sind - in der Mitte oben und unten links. perinco bleibt einfarbig.
|
||||
|
||||

|
||||
* Die Menüpunkte **Akquise**, **Opportunities**, **Kontakte**, **Mails** und
|
||||
**Scanner** klappen beim Anklicken ihre Unterpunkte auf. Hinter einigen steht
|
||||
|
||||
@@ -247,7 +247,7 @@ Uhrzeit, dieses Jahr Tag und Monat, sonst mit Jahr.
|
||||
| Datei | Hält | Eigenheit |
|
||||
| --- | --- | --- |
|
||||
| `auth.tsx` | Benutzer, `isAdmin`, `login`, `logout`, `updateUser` | prüft beim Start das gespeicherte Token gegen `/auth/me` |
|
||||
| `theme.tsx` | Farbwelt (perinco/Pixel Art/Outdoor/Cyberpunk) und Modus (hell/dunkel/System) | Beides gehört dem Benutzer und steht in `crm_users`; `localStorage` ist nur der Zwischenspeicher fürs Inline-Skript in `index.html`. Doppelklick auf den Modus-Schalter folgt wieder dem System |
|
||||
| `theme.tsx` | Farbwelt (perinco/Pixel Art/Outdoor/Cyberpunk, Hintergrundgrafiken in `public/themes/`) und Modus (hell/dunkel/System) | Beides gehört dem Benutzer und steht in `crm_users`; `localStorage` ist nur der Zwischenspeicher fürs Inline-Skript in `index.html`. Doppelklick auf den Modus-Schalter folgt wieder dem System |
|
||||
| `navigation.tsx` | `currentView`, `goTo(view, { tab, leadId })` | erspart es, Callbacks durch vier Ebenen zu reichen; `leadId` öffnet den Kontakt direkt |
|
||||
| `whisper.tsx` | Modellstatus, Worker, Fortschritt, `transcribe` | ein Worker für die ganze App |
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 80" width="1600" height="80" preserveAspectRatio="xMidYMid slice">
|
||||
<!--
|
||||
Cyberpunk, obere Leiste: Neonroehren hinter Regen.
|
||||
|
||||
Die Roehren sind doppelt gezeichnet - einmal breit und unscharf (der Schein),
|
||||
einmal duenn und hell (das Glas). Genau daraus besteht der Neoneffekt; eine
|
||||
einzelne farbige Linie sieht nur nach Linie aus.
|
||||
|
||||
Der Regen faellt schraeg und ist bewusst blass: er soll Bewegung andeuten,
|
||||
nicht die Schrift der Leiste stoeren. Die Deckung darueber kommt aus dem
|
||||
Theme (index.css), damit dieselbe Grafik im hellen Modus blass bleibt.
|
||||
-->
|
||||
<defs>
|
||||
<filter id="schein" x="-60%" y="-200%" width="220%" height="500%">
|
||||
<feGaussianBlur stdDeviation="7" />
|
||||
</filter>
|
||||
<filter id="weiterSchein" x="-80%" y="-300%" width="260%" height="700%">
|
||||
<feGaussianBlur stdDeviation="18" />
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
<!--
|
||||
Bewusst KEINE deckende Nachtflaeche: die Grafik ist durchsichtig und zeigt
|
||||
nur Licht. Ueber der dunklen Flaeche des Dunkelmodus ergibt das leuchtendes
|
||||
Neon, ueber der weissen des hellen Modus blasse farbige Linien. Mit einer
|
||||
dunklen Grundflaeche wurde daraus im hellen Modus ein grauer Schmutzstreifen.
|
||||
-->
|
||||
|
||||
<!-- Ferne Fensterreihen: die Stadt im Hintergrund -->
|
||||
<g fill="#4a6fa8" opacity="0.35">
|
||||
<rect x="120" y="18" width="3" height="5" /><rect x="130" y="30" width="3" height="4" />
|
||||
<rect x="148" y="12" width="3" height="6" /><rect x="160" y="26" width="3" height="5" />
|
||||
<rect x="420" y="22" width="3" height="5" /><rect x="432" y="14" width="3" height="4" />
|
||||
<rect x="446" y="34" width="3" height="5" /><rect x="458" y="20" width="3" height="6" />
|
||||
<rect x="980" y="16" width="3" height="5" /><rect x="992" y="28" width="3" height="4" />
|
||||
<rect x="1006" y="20" width="3" height="6" /><rect x="1018" y="34" width="3" height="4" />
|
||||
<rect x="1320" y="24" width="3" height="5" /><rect x="1332" y="14" width="3" height="6" />
|
||||
<rect x="1346" y="30" width="3" height="4" />
|
||||
</g>
|
||||
|
||||
<!-- Waagerechte Neonroehren -->
|
||||
<g>
|
||||
<!-- Magenta, lang -->
|
||||
<rect x="180" y="26" width="300" height="8" fill="#c026d3" opacity="0.5" filter="url(#weiterSchein)" />
|
||||
<rect x="180" y="28" width="300" height="4" fill="#e879f9" opacity="0.85" filter="url(#schein)" />
|
||||
<rect x="180" y="29" width="300" height="2" fill="#fbe3ff" opacity="0.95" />
|
||||
|
||||
<!-- Cyan, kurz -->
|
||||
<rect x="620" y="50" width="180" height="8" fill="#0891b2" opacity="0.5" filter="url(#weiterSchein)" />
|
||||
<rect x="620" y="52" width="180" height="4" fill="#22d3ee" opacity="0.85" filter="url(#schein)" />
|
||||
<rect x="620" y="53" width="180" height="2" fill="#d6feff" opacity="0.95" />
|
||||
|
||||
<!-- Violett, mittig -->
|
||||
<rect x="900" y="20" width="240" height="8" fill="#7326d6" opacity="0.5" filter="url(#weiterSchein)" />
|
||||
<rect x="900" y="22" width="240" height="4" fill="#a24cff" opacity="0.85" filter="url(#schein)" />
|
||||
<rect x="900" y="23" width="240" height="2" fill="#ecdcff" opacity="0.95" />
|
||||
|
||||
<!-- Cyan, rechts -->
|
||||
<rect x="1260" y="46" width="220" height="8" fill="#0891b2" opacity="0.45" filter="url(#weiterSchein)" />
|
||||
<rect x="1260" y="48" width="220" height="4" fill="#22d3ee" opacity="0.8" filter="url(#schein)" />
|
||||
<rect x="1260" y="49" width="220" height="2" fill="#d6feff" opacity="0.9" />
|
||||
</g>
|
||||
|
||||
<!-- Senkrechte Roehren: setzen Takt in die Breite -->
|
||||
<g>
|
||||
<rect x="540" y="0" width="6" height="80" fill="#c026d3" opacity="0.35" filter="url(#weiterSchein)" />
|
||||
<rect x="542" y="0" width="2" height="80" fill="#f0a6ff" opacity="0.7" filter="url(#schein)" />
|
||||
<rect x="1180" y="0" width="6" height="80" fill="#0891b2" opacity="0.35" filter="url(#weiterSchein)" />
|
||||
<rect x="1182" y="0" width="2" height="80" fill="#7ce9f7" opacity="0.7" filter="url(#schein)" />
|
||||
</g>
|
||||
|
||||
<!-- Regen: schraege Striche, unterschiedlich lang und blass -->
|
||||
<g stroke="#a5c8ff" stroke-linecap="round">
|
||||
<g stroke-width="1.2" opacity="0.3">
|
||||
<path d="M40 -6 l-8 26" /><path d="M96 4 l-8 26" /><path d="M152 -8 l-8 26" />
|
||||
<path d="M214 10 l-8 26" /><path d="M268 -4 l-8 26" /><path d="M330 16 l-8 26" />
|
||||
<path d="M392 2 l-8 26" /><path d="M452 20 l-8 26" /><path d="M512 -2 l-8 26" />
|
||||
<path d="M574 14 l-8 26" /><path d="M636 4 l-8 26" /><path d="M698 22 l-8 26" />
|
||||
<path d="M760 -6 l-8 26" /><path d="M822 12 l-8 26" /><path d="M884 0 l-8 26" />
|
||||
<path d="M946 18 l-8 26" /><path d="M1008 6 l-8 26" /><path d="M1070 24 l-8 26" />
|
||||
<path d="M1132 -4 l-8 26" /><path d="M1194 14 l-8 26" /><path d="M1256 2 l-8 26" />
|
||||
<path d="M1318 20 l-8 26" /><path d="M1380 8 l-8 26" /><path d="M1442 26 l-8 26" />
|
||||
<path d="M1504 -2 l-8 26" /><path d="M1566 16 l-8 26" />
|
||||
</g>
|
||||
<g stroke-width="1.6" opacity="0.22">
|
||||
<path d="M70 34 l-10 34" /><path d="M186 40 l-10 34" /><path d="M302 30 l-10 34" />
|
||||
<path d="M418 44 l-10 34" /><path d="M534 36 l-10 34" /><path d="M650 46 l-10 34" />
|
||||
<path d="M766 32 l-10 34" /><path d="M882 42 l-10 34" /><path d="M998 34 l-10 34" />
|
||||
<path d="M1114 48 l-10 34" /><path d="M1230 36 l-10 34" /><path d="M1346 44 l-10 34" />
|
||||
<path d="M1462 32 l-10 34" /><path d="M1578 42 l-10 34" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
@@ -0,0 +1,106 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 260 900" width="260" height="900" preserveAspectRatio="xMidYMax slice">
|
||||
<!--
|
||||
Cyberpunk, Seitenleiste: Blick durch ein Fenster in eine regnerische Gasse.
|
||||
|
||||
Aufbau von hinten nach vorn: Fensterreihen der Haeuser, senkrechte
|
||||
Neonroehren, eine Pfuetze mit Spiegelung, der Regen davor. Die Roehren sind
|
||||
wieder doppelt gezeichnet - breit und unscharf als Schein, duenn und hell
|
||||
als Glas.
|
||||
|
||||
Die obere Haelfte bleibt ruhig: dort stehen die Menuepunkte. Die Gasse steht
|
||||
in den unteren rund 350 px, wo die Leiste frei ist.
|
||||
-->
|
||||
<defs>
|
||||
<filter id="schein" x="-100%" y="-40%" width="300%" height="180%">
|
||||
<feGaussianBlur stdDeviation="6" />
|
||||
</filter>
|
||||
<filter id="weiterSchein" x="-200%" y="-60%" width="500%" height="220%">
|
||||
<feGaussianBlur stdDeviation="16" />
|
||||
</filter>
|
||||
<!--
|
||||
Kein Schwarz: ein farbiger Dunst statt einer dunklen Flaeche. Ueber der
|
||||
dunklen Flaeche des Dunkelmodus wirkt er wie Tiefe, ueber der weissen des
|
||||
hellen Modus wie ein kuehler Schleier - grau wird er in keinem von beiden.
|
||||
-->
|
||||
<linearGradient id="tiefe" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#3a4a80" stop-opacity="0" />
|
||||
<stop offset="0.4" stop-color="#33407a" stop-opacity="0.16" />
|
||||
<stop offset="1" stop-color="#2b3a72" stop-opacity="0.3" />
|
||||
</linearGradient>
|
||||
<linearGradient id="pfuetze" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#22d3ee" stop-opacity="0.35" />
|
||||
<stop offset="1" stop-color="#22d3ee" stop-opacity="0" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Die Gasse wird nach unten dichter -->
|
||||
<rect y="450" width="260" height="450" fill="url(#tiefe)" />
|
||||
|
||||
<!-- Fensterreihen: warm und kalt gemischt, wie bewohnte Haeuser -->
|
||||
<g opacity="0.5">
|
||||
<g fill="#f0b356">
|
||||
<rect x="18" y="612" width="5" height="7" /><rect x="34" y="648" width="5" height="7" />
|
||||
<rect x="18" y="700" width="5" height="7" /><rect x="50" y="676" width="5" height="7" />
|
||||
<rect x="208" y="624" width="5" height="7" /><rect x="224" y="668" width="5" height="7" />
|
||||
<rect x="240" y="708" width="5" height="7" />
|
||||
</g>
|
||||
<g fill="#7cc4ef">
|
||||
<rect x="34" y="588" width="5" height="7" /><rect x="18" y="664" width="5" height="7" />
|
||||
<rect x="50" y="628" width="5" height="7" /><rect x="224" y="596" width="5" height="7" />
|
||||
<rect x="208" y="688" width="5" height="7" /><rect x="240" y="640" width="5" height="7" />
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Senkrechte Neonroehren links und rechts, wie Schilder an den Haeusern -->
|
||||
<g>
|
||||
<rect x="26" y="520" width="10" height="180" fill="#c026d3" opacity="0.4" filter="url(#weiterSchein)" />
|
||||
<rect x="29" y="520" width="4" height="180" fill="#e879f9" opacity="0.8" filter="url(#schein)" />
|
||||
<rect x="30" y="520" width="2" height="180" fill="#fbe3ff" opacity="0.9" />
|
||||
|
||||
<rect x="222" y="580" width="10" height="230" fill="#0891b2" opacity="0.4" filter="url(#weiterSchein)" />
|
||||
<rect x="225" y="580" width="4" height="230" fill="#22d3ee" opacity="0.8" filter="url(#schein)" />
|
||||
<rect x="226" y="580" width="2" height="230" fill="#d6feff" opacity="0.9" />
|
||||
|
||||
<rect x="126" y="700" width="8" height="120" fill="#7326d6" opacity="0.35" filter="url(#weiterSchein)" />
|
||||
<rect x="128" y="700" width="4" height="120" fill="#a24cff" opacity="0.75" filter="url(#schein)" />
|
||||
</g>
|
||||
|
||||
<!-- Waagerechtes Schild, quer zur Gasse -->
|
||||
<g>
|
||||
<rect x="60" y="756" width="140" height="8" fill="#c026d3" opacity="0.4" filter="url(#weiterSchein)" />
|
||||
<rect x="60" y="758" width="140" height="4" fill="#f0a6ff" opacity="0.8" filter="url(#schein)" />
|
||||
</g>
|
||||
|
||||
<!-- Nasser Boden mit Spiegelung: die Roehren strahlen nach unten aus -->
|
||||
<rect y="828" width="260" height="72" fill="#243060" opacity="0.3" />
|
||||
<g>
|
||||
<rect x="26" y="828" width="10" height="60" fill="url(#pfuetze)" filter="url(#schein)" />
|
||||
<rect x="222" y="828" width="10" height="60" fill="url(#pfuetze)" filter="url(#schein)" />
|
||||
<rect x="126" y="828" width="8" height="46" fill="url(#pfuetze)" filter="url(#schein)" />
|
||||
</g>
|
||||
<!-- Zwei Lichtstreifen als nasser Glanz -->
|
||||
<g fill="#7ce9f7" opacity="0.16">
|
||||
<rect x="0" y="846" width="260" height="2" />
|
||||
<rect x="0" y="872" width="260" height="1.5" />
|
||||
</g>
|
||||
|
||||
<!-- Regen ueber die ganze Hoehe, oben blasser -->
|
||||
<g stroke="#a5c8ff" stroke-linecap="round">
|
||||
<g stroke-width="1.2" opacity="0.12">
|
||||
<path d="M20 60 l-6 40" /><path d="M78 20 l-6 40" /><path d="M140 90 l-6 40" />
|
||||
<path d="M198 40 l-6 40" /><path d="M246 110 l-6 40" /><path d="M46 150 l-6 40" />
|
||||
<path d="M112 130 l-6 40" /><path d="M176 170 l-6 40" /><path d="M228 200 l-6 40" />
|
||||
</g>
|
||||
<g stroke-width="1.3" opacity="0.2">
|
||||
<path d="M32 300 l-7 46" /><path d="M96 340 l-7 46" /><path d="M158 310 l-7 46" />
|
||||
<path d="M214 360 l-7 46" /><path d="M62 420 l-7 46" /><path d="M128 400 l-7 46" />
|
||||
<path d="M190 440 l-7 46" /><path d="M244 410 l-7 46" />
|
||||
</g>
|
||||
<g stroke-width="1.6" opacity="0.3">
|
||||
<path d="M24 520 l-9 56" /><path d="M88 560 l-9 56" /><path d="M150 530 l-9 56" />
|
||||
<path d="M206 580 l-9 56" /><path d="M54 640 l-9 56" /><path d="M118 620 l-9 56" />
|
||||
<path d="M182 660 l-9 56" /><path d="M240 630 l-9 56" /><path d="M40 740 l-9 56" />
|
||||
<path d="M104 760 l-9 56" /><path d="M168 730 l-9 56" /><path d="M232 770 l-9 56" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.3 KiB |
@@ -0,0 +1,57 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 80" width="1600" height="80" preserveAspectRatio="xMidYMid slice">
|
||||
<!--
|
||||
Outdoor, obere Leiste: blauer Himmel mit Schleierwolken.
|
||||
|
||||
Die Leiste ist nur 80 px hoch und traegt Text - deshalb keine kraeftigen
|
||||
Kontraste, sondern ein weicher Verlauf und Wolken aus unscharfen Ellipsen.
|
||||
Der Schleier darueber kommt aus dem Theme (index.css), nicht aus dieser
|
||||
Datei: so tont derselbe Himmel im Dunkelmodus zur Nacht ab.
|
||||
-->
|
||||
<defs>
|
||||
<linearGradient id="himmel" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#5eb3e4" />
|
||||
<stop offset="0.55" stop-color="#8fcdec" />
|
||||
<stop offset="1" stop-color="#cfe8f5" />
|
||||
</linearGradient>
|
||||
<filter id="weich" x="-30%" y="-120%" width="160%" height="340%">
|
||||
<feGaussianBlur stdDeviation="9" />
|
||||
</filter>
|
||||
<filter id="sehrWeich" x="-40%" y="-200%" width="180%" height="500%">
|
||||
<feGaussianBlur stdDeviation="20" />
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
<rect width="1600" height="80" fill="url(#himmel)" />
|
||||
|
||||
<!-- Sonnenschein oben links, gerade so sichtbar -->
|
||||
<ellipse cx="240" cy="4" rx="260" ry="60" fill="#fff6d8" opacity="0.5" filter="url(#sehrWeich)" />
|
||||
|
||||
<!-- Wolkenbaenke: je drei bis vier Ellipsen, damit die Kanten unregelmaessig sind -->
|
||||
<g fill="#ffffff" filter="url(#weich)">
|
||||
<g opacity="0.85">
|
||||
<ellipse cx="150" cy="52" rx="120" ry="20" />
|
||||
<ellipse cx="230" cy="44" rx="80" ry="16" />
|
||||
<ellipse cx="86" cy="58" rx="70" ry="14" />
|
||||
</g>
|
||||
<g opacity="0.6">
|
||||
<ellipse cx="520" cy="30" rx="150" ry="17" />
|
||||
<ellipse cx="610" cy="24" rx="90" ry="13" />
|
||||
</g>
|
||||
<g opacity="0.8">
|
||||
<ellipse cx="880" cy="58" rx="170" ry="22" />
|
||||
<ellipse cx="960" cy="50" rx="110" ry="16" />
|
||||
<ellipse cx="800" cy="62" rx="90" ry="15" />
|
||||
</g>
|
||||
<g opacity="0.55">
|
||||
<ellipse cx="1240" cy="26" rx="140" ry="16" />
|
||||
<ellipse cx="1330" cy="34" rx="100" ry="14" />
|
||||
</g>
|
||||
<g opacity="0.78">
|
||||
<ellipse cx="1520" cy="56" rx="150" ry="20" />
|
||||
<ellipse cx="1440" cy="62" rx="90" ry="14" />
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Dunstband am unteren Rand: laesst die Leiste sauber in den Inhalt uebergehen -->
|
||||
<rect y="60" width="1600" height="20" fill="#ffffff" opacity="0.28" filter="url(#weich)" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,70 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 260 900" width="260" height="900" preserveAspectRatio="xMidYMax slice">
|
||||
<!--
|
||||
Outdoor, Seitenleiste: Wiese, die von unten hereinwaechst.
|
||||
|
||||
Der obere Teil ist absichtlich leer (durchsichtig): dort stehen die
|
||||
Menuepunkte. Das Gras sitzt in den unteren rund 300 px, wo die Leiste
|
||||
ohnehin frei ist, und wird nach oben hin blasser.
|
||||
|
||||
Gezeichnet mit quadratischen Bezierkurven statt Bildpunkten - die Halme
|
||||
bleiben damit in jeder Hoehe scharf.
|
||||
-->
|
||||
<defs>
|
||||
<linearGradient id="wiese" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#7bbf5a" stop-opacity="0" />
|
||||
<stop offset="0.45" stop-color="#6fb350" stop-opacity="0.55" />
|
||||
<stop offset="1" stop-color="#4e8f39" stop-opacity="0.95" />
|
||||
</linearGradient>
|
||||
<linearGradient id="dunst" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#a8d68f" stop-opacity="0" />
|
||||
<stop offset="1" stop-color="#a8d68f" stop-opacity="0.35" />
|
||||
</linearGradient>
|
||||
<filter id="weich" x="-20%" y="-20%" width="140%" height="140%">
|
||||
<feGaussianBlur stdDeviation="14" />
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
<!-- Gruener Schein, der den Uebergang traegt -->
|
||||
<rect y="520" width="260" height="380" fill="url(#dunst)" filter="url(#weich)" />
|
||||
|
||||
<!-- Erdreich und Wiesenflaeche -->
|
||||
<path d="M0 760 C 60 742 120 754 180 744 C 216 738 240 746 260 740 L260 900 L0 900 Z" fill="url(#wiese)" />
|
||||
|
||||
<!-- Hintere Halmreihe: hell, duenn, hoch -->
|
||||
<g stroke="#8fca6e" stroke-width="2.4" stroke-linecap="round" fill="none" opacity="0.5">
|
||||
<path d="M12 772 Q 6 720 20 686" />
|
||||
<path d="M34 768 Q 40 716 30 676" />
|
||||
<path d="M58 774 Q 52 726 66 692" />
|
||||
<path d="M84 766 Q 92 714 82 680" />
|
||||
<path d="M110 772 Q 104 722 118 690" />
|
||||
<path d="M136 764 Q 144 712 134 678" />
|
||||
<path d="M162 770 Q 156 720 170 688" />
|
||||
<path d="M190 766 Q 198 716 188 684" />
|
||||
<path d="M216 772 Q 210 724 224 694" />
|
||||
<path d="M242 768 Q 250 718 240 686" />
|
||||
</g>
|
||||
|
||||
<!-- Vordere Halmreihe: dunkler, kraeftiger, kuerzer -->
|
||||
<g stroke="#3f7d2e" stroke-width="3.6" stroke-linecap="round" fill="none" opacity="0.85">
|
||||
<path d="M0 830 Q 8 786 24 758" />
|
||||
<path d="M24 836 Q 18 792 6 764" />
|
||||
<path d="M48 828 Q 58 784 74 756" />
|
||||
<path d="M72 838 Q 66 794 54 766" />
|
||||
<path d="M98 830 Q 108 786 124 760" />
|
||||
<path d="M122 840 Q 116 796 104 768" />
|
||||
<path d="M148 828 Q 158 784 174 758" />
|
||||
<path d="M172 838 Q 166 794 154 764" />
|
||||
<path d="M198 832 Q 208 788 224 760" />
|
||||
<path d="M222 840 Q 216 796 204 768" />
|
||||
<path d="M248 830 Q 258 786 260 764" />
|
||||
</g>
|
||||
|
||||
<!-- Ein paar Blueten, damit es nicht nach Rasenteppich aussieht -->
|
||||
<g opacity="0.8">
|
||||
<circle cx="42" cy="742" r="4" fill="#f7e07a" />
|
||||
<circle cx="128" cy="726" r="3.4" fill="#f7f3e0" />
|
||||
<circle cx="206" cy="748" r="3.8" fill="#f7e07a" />
|
||||
<circle cx="88" cy="800" r="3" fill="#f7f3e0" />
|
||||
<circle cx="186" cy="812" r="3.4" fill="#f7e07a" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
@@ -0,0 +1,68 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 20" width="400" height="20" shape-rendering="crispEdges" preserveAspectRatio="xMidYMid slice">
|
||||
<!--
|
||||
Pixel Art, obere Leiste: 8-bit-Himmel mit Wolken und Huegelkante.
|
||||
|
||||
Der viewBox ist absichtlich winzig (400 x 20): eine Einheit ist ein
|
||||
Bildpunkt, und die Grafik wird von der Leiste hochskaliert. Zusammen mit
|
||||
shape-rendering="crispEdges" bleiben die Kanten hart - genau das, was ein
|
||||
Pixelbild ausmacht. Ein feiner Verlauf waere hier ein Stilbruch, deshalb
|
||||
liegen die Himmelstoene in Baendern uebereinander.
|
||||
-->
|
||||
|
||||
<!-- Himmel in Stufen statt Verlauf -->
|
||||
<rect width="400" height="6" fill="#7ec0e8" />
|
||||
<rect y="6" width="400" height="5" fill="#96cfee" />
|
||||
<rect y="11" width="400" height="4" fill="#b3dcf3" />
|
||||
<rect y="15" width="400" height="5" fill="#cbe8f7" />
|
||||
|
||||
<!-- Sonne: ein Quadrat mit abgesetzter Ecke, wie in alten Spielen -->
|
||||
<g fill="#ffe98a">
|
||||
<rect x="26" y="2" width="8" height="8" />
|
||||
<rect x="24" y="4" width="12" height="4" />
|
||||
<rect x="28" y="0" width="4" height="12" />
|
||||
</g>
|
||||
|
||||
<!-- Wolken: Bloecke, keine Rundungen -->
|
||||
<g fill="#ffffff">
|
||||
<rect x="70" y="4" width="16" height="3" />
|
||||
<rect x="74" y="2" width="9" height="3" />
|
||||
<rect x="66" y="7" width="24" height="3" />
|
||||
|
||||
<rect x="150" y="8" width="20" height="3" />
|
||||
<rect x="156" y="6" width="10" height="3" />
|
||||
<rect x="146" y="11" width="28" height="2" />
|
||||
|
||||
<rect x="248" y="3" width="14" height="3" />
|
||||
<rect x="252" y="1" width="8" height="3" />
|
||||
<rect x="244" y="6" width="22" height="3" />
|
||||
|
||||
<rect x="330" y="7" width="18" height="3" />
|
||||
<rect x="335" y="5" width="9" height="3" />
|
||||
<rect x="326" y="10" width="26" height="2" />
|
||||
</g>
|
||||
|
||||
<!-- Vogelschwarm: je zwei Bildpunkte -->
|
||||
<g fill="#4a5a66">
|
||||
<rect x="200" y="4" width="2" height="1" />
|
||||
<rect x="203" y="3" width="2" height="1" />
|
||||
<rect x="290" y="6" width="2" height="1" />
|
||||
<rect x="293" y="5" width="2" height="1" />
|
||||
</g>
|
||||
|
||||
<!-- Huegelkante am unteren Rand, treppenfoermig -->
|
||||
<g fill="#5fa83f">
|
||||
<rect y="17" width="400" height="3" />
|
||||
<rect x="0" y="16" width="40" height="1" />
|
||||
<rect x="52" y="15" width="34" height="2" />
|
||||
<rect x="60" y="14" width="18" height="1" />
|
||||
<rect x="120" y="16" width="46" height="1" />
|
||||
<rect x="196" y="15" width="40" height="2" />
|
||||
<rect x="206" y="14" width="20" height="1" />
|
||||
<rect x="280" y="16" width="52" height="1" />
|
||||
<rect x="348" y="15" width="36" height="2" />
|
||||
</g>
|
||||
<!-- Grasspitzen als hellere Kante -->
|
||||
<g fill="#7ec957">
|
||||
<rect x="0" y="17" width="400" height="1" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1,66 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 65 225" width="65" height="225" shape-rendering="crispEdges" preserveAspectRatio="xMidYMax slice">
|
||||
<!--
|
||||
Pixel Art, Seitenleiste: Steinmauer, von unten aufgemauert.
|
||||
|
||||
Der viewBox ist winzig (65 x 225, eine Einheit = ein Bildpunkt), damit die
|
||||
Mauer beim Hochskalieren blockig bleibt; shape-rendering="crispEdges" haelt
|
||||
die Kanten hart. Oben ist die Grafik leer - dort stehen die Menuepunkte.
|
||||
|
||||
Nach oben hin wird die Mauer **stufenweise** durchsichtig, Reihe um Reihe.
|
||||
Ein weicher Verlauf waere hier ein Stilbruch: Pixelgrafik kennt keine
|
||||
Zwischentoene, sie staffelt.
|
||||
|
||||
Jeder Stein ist 12 x 6 Punkte, versetzt gemauert, mit heller Kante oben und
|
||||
dunkler unten - damit taeuscht Pixelgrafik Tiefe vor.
|
||||
-->
|
||||
<defs>
|
||||
<g id="stein">
|
||||
<rect width="12" height="6" fill="#8a8f7a" />
|
||||
<rect width="12" height="1" fill="#a8ad96" />
|
||||
<rect y="5" width="12" height="1" fill="#5f6553" />
|
||||
<rect x="11" width="1" height="6" fill="#5f6553" />
|
||||
</g>
|
||||
<!-- Eine ganze Reihe; der Versatz kommt beim Aufruf -->
|
||||
<g id="reihe">
|
||||
<use href="#stein" x="0" /><use href="#stein" x="13" /><use href="#stein" x="26" />
|
||||
<use href="#stein" x="39" /><use href="#stein" x="52" />
|
||||
</g>
|
||||
</defs>
|
||||
|
||||
<!-- Reihen von unten nach oben, jede zweite um einen halben Stein versetzt -->
|
||||
<use href="#reihe" y="219" opacity="1" />
|
||||
<use href="#reihe" x="-6" y="212" opacity="1" />
|
||||
<use href="#reihe" y="205" opacity="1" />
|
||||
<use href="#reihe" x="-6" y="198" opacity="1" />
|
||||
<use href="#reihe" y="191" opacity="0.9" />
|
||||
<use href="#reihe" x="-6" y="184" opacity="0.8" />
|
||||
<use href="#reihe" y="177" opacity="0.7" />
|
||||
<use href="#reihe" x="-6" y="170" opacity="0.6" />
|
||||
<use href="#reihe" y="163" opacity="0.5" />
|
||||
<use href="#reihe" x="-6" y="156" opacity="0.4" />
|
||||
<use href="#reihe" y="149" opacity="0.32" />
|
||||
<use href="#reihe" x="-6" y="142" opacity="0.24" />
|
||||
<use href="#reihe" y="135" opacity="0.18" />
|
||||
<use href="#reihe" x="-6" y="128" opacity="0.13" />
|
||||
<use href="#reihe" y="121" opacity="0.09" />
|
||||
<use href="#reihe" x="-6" y="114" opacity="0.06" />
|
||||
<use href="#reihe" y="107" opacity="0.03" />
|
||||
|
||||
<!-- Moos in den Fugen: sonst wirkt die Mauer steril -->
|
||||
<g fill="#6f9c4a">
|
||||
<rect x="4" y="218" width="3" height="1" />
|
||||
<rect x="30" y="211" width="4" height="1" />
|
||||
<rect x="17" y="204" width="2" height="1" />
|
||||
<rect x="46" y="197" width="3" height="1" />
|
||||
<rect x="9" y="190" width="4" height="1" opacity="0.9" />
|
||||
<rect x="55" y="183" width="3" height="1" opacity="0.8" />
|
||||
<rect x="24" y="176" width="2" height="1" opacity="0.7" />
|
||||
<rect x="38" y="162" width="3" height="1" opacity="0.5" />
|
||||
</g>
|
||||
|
||||
<!-- Zwei ausgebrochene Steine, damit die Mauer nicht zu regelmaessig ist -->
|
||||
<g fill="#5f6553">
|
||||
<rect x="26" y="219" width="12" height="6" />
|
||||
<rect x="7" y="170" width="12" height="6" opacity="0.6" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
@@ -17,8 +17,13 @@ export const Header: React.FC<HeaderProps> = ({ title, subtitle, onToggleSidebar
|
||||
const { theme, preference, toggle, useSystem, palette, setPalette } = useTheme();
|
||||
const isDark = theme === 'dark';
|
||||
|
||||
/*
|
||||
* `app-header` ist keine Utility-Klasse, sondern ein Anker: darueber legt ein
|
||||
* Theme ein Hintergrundbild hinter die Leiste (siehe index.css). `relative`
|
||||
* haelt den Inhalt darueber.
|
||||
*/
|
||||
return (
|
||||
<header className="flex shrink-0 items-center gap-4 border-b border-ink-200 bg-surface px-4 py-4 md:px-6">
|
||||
<header className="app-header relative flex shrink-0 items-center gap-4 border-b border-ink-200 bg-surface px-4 py-4 md:px-6">
|
||||
<button
|
||||
onClick={onToggleSidebar}
|
||||
className="rounded-lg p-2 text-ink-500 transition hover:bg-ink-100 hover:text-ink-800"
|
||||
|
||||
@@ -352,7 +352,8 @@ export const Sidebar: React.FC<SidebarProps> = ({
|
||||
)}
|
||||
|
||||
<aside
|
||||
className={`fixed inset-y-0 left-0 z-30 flex h-full flex-col overflow-hidden border-r border-ink-200 bg-surface transition-all duration-300 lg:static ${
|
||||
// `app-sidebar` ist der Anker fuer das Hintergrundbild des Themes.
|
||||
className={`app-sidebar fixed inset-y-0 left-0 z-30 flex h-full flex-col overflow-hidden border-r border-ink-200 bg-surface transition-all duration-300 lg:static ${
|
||||
isOpen ? 'w-64 translate-x-0' : 'w-0 -translate-x-full lg:w-[76px] lg:translate-x-0'
|
||||
}`}
|
||||
>
|
||||
|
||||
+144
@@ -160,6 +160,24 @@
|
||||
* kaputt - genau das ist der Grund fuer die Schreibweise in allen Themes.
|
||||
* =========================================================================== */
|
||||
html.theme-outdoor:not(.dark) {
|
||||
/* Blauer Himmel oben, Wiese links. Heller Schleier aus der Flaechenfarbe. */
|
||||
--theme-header-image: linear-gradient(
|
||||
90deg,
|
||||
rgb(253 251 246 / 0.94) 0%,
|
||||
rgb(253 251 246 / 0.38) 30%,
|
||||
rgb(253 251 246 / 0.3) 55%,
|
||||
rgb(253 251 246 / 0.94) 100%
|
||||
),
|
||||
url('/themes/outdoor-header.svg');
|
||||
--theme-sidebar-image: linear-gradient(
|
||||
180deg,
|
||||
rgb(253 251 246 / 0.97) 0%,
|
||||
rgb(253 251 246 / 0.88) 45%,
|
||||
rgb(253 251 246 / 0.44) 78%,
|
||||
rgb(253 251 246 / 0.58) 100%
|
||||
),
|
||||
url('/themes/outdoor-sidebar.svg');
|
||||
|
||||
--color-canvas: #f2eee3;
|
||||
--color-surface: #fdfbf6;
|
||||
|
||||
@@ -210,6 +228,25 @@ html.theme-outdoor:not(.dark) {
|
||||
* nach kaltem Terminal aussieht.
|
||||
*/
|
||||
html.theme-outdoor.dark {
|
||||
/* Dieselben Grafiken, dunkler Schleier: aus dem Himmel wird Nacht, aus der
|
||||
Wiese eine Silhouette. */
|
||||
--theme-header-image: linear-gradient(
|
||||
90deg,
|
||||
rgb(26 32 22 / 0.95) 0%,
|
||||
rgb(26 32 22 / 0.68) 30%,
|
||||
rgb(26 32 22 / 0.6) 55%,
|
||||
rgb(26 32 22 / 0.95) 100%
|
||||
),
|
||||
url('/themes/outdoor-header.svg');
|
||||
--theme-sidebar-image: linear-gradient(
|
||||
180deg,
|
||||
rgb(26 32 22 / 0.97) 0%,
|
||||
rgb(26 32 22 / 0.9) 45%,
|
||||
rgb(26 32 22 / 0.62) 78%,
|
||||
rgb(26 32 22 / 0.72) 100%
|
||||
),
|
||||
url('/themes/outdoor-sidebar.svg');
|
||||
|
||||
--color-canvas: #12170f;
|
||||
--color-surface: #1a2016;
|
||||
|
||||
@@ -268,6 +305,24 @@ html.theme-outdoor.dark {
|
||||
* schlechtes Design.
|
||||
* =========================================================================== */
|
||||
html.theme-pixel:not(.dark) {
|
||||
/* 8-bit-Himmel oben, Steinmauer links. */
|
||||
--theme-header-image: linear-gradient(
|
||||
90deg,
|
||||
rgb(246 248 241 / 0.95) 0%,
|
||||
rgb(246 248 241 / 0.45) 30%,
|
||||
rgb(246 248 241 / 0.38) 55%,
|
||||
rgb(246 248 241 / 0.95) 100%
|
||||
),
|
||||
url('/themes/pixel-header.svg');
|
||||
--theme-sidebar-image: linear-gradient(
|
||||
180deg,
|
||||
rgb(246 248 241 / 0.97) 0%,
|
||||
rgb(246 248 241 / 0.92) 48%,
|
||||
rgb(246 248 241 / 0.72) 80%,
|
||||
rgb(246 248 241 / 0.84) 100%
|
||||
),
|
||||
url('/themes/pixel-sidebar.svg');
|
||||
|
||||
/* Deutlich dunkler als die Karten: Pixelgrafik lebt von harten Kanten, und
|
||||
bei zu aehnlichen Toenen verschwimmen Karte und Grund. */
|
||||
--color-canvas: #cdd8c2;
|
||||
@@ -319,6 +374,24 @@ html.theme-pixel:not(.dark) {
|
||||
* schwarzem Grund unsichtbar), das Gruen der Knoepfe leuchtet kraeftiger.
|
||||
*/
|
||||
html.theme-pixel.dark {
|
||||
/* Nachtvariante: derselbe Himmel unter dunklem Schleier. */
|
||||
--theme-header-image: linear-gradient(
|
||||
90deg,
|
||||
rgb(21 26 34 / 0.96) 0%,
|
||||
rgb(21 26 34 / 0.7) 30%,
|
||||
rgb(21 26 34 / 0.62) 55%,
|
||||
rgb(21 26 34 / 0.96) 100%
|
||||
),
|
||||
url('/themes/pixel-header.svg');
|
||||
--theme-sidebar-image: linear-gradient(
|
||||
180deg,
|
||||
rgb(21 26 34 / 0.97) 0%,
|
||||
rgb(21 26 34 / 0.92) 48%,
|
||||
rgb(21 26 34 / 0.78) 80%,
|
||||
rgb(21 26 34 / 0.88) 100%
|
||||
),
|
||||
url('/themes/pixel-sidebar.svg');
|
||||
|
||||
--color-canvas: #0d0f14;
|
||||
--color-surface: #151a22;
|
||||
|
||||
@@ -374,6 +447,25 @@ html.theme-pixel.dark {
|
||||
* plus weicher Halo in der Markenfarbe.
|
||||
* =========================================================================== */
|
||||
html.theme-cyberpunk.dark {
|
||||
/* Neonroehren oben, regnerische Gasse links - hier ist die Grafik zu Hause,
|
||||
der Schleier darf duenner sein. */
|
||||
--theme-header-image: linear-gradient(
|
||||
90deg,
|
||||
rgb(15 17 32 / 0.94) 0%,
|
||||
rgb(15 17 32 / 0.5) 28%,
|
||||
rgb(15 17 32 / 0.42) 55%,
|
||||
rgb(15 17 32 / 0.94) 100%
|
||||
),
|
||||
url('/themes/cyberpunk-header.svg');
|
||||
--theme-sidebar-image: linear-gradient(
|
||||
180deg,
|
||||
rgb(15 17 32 / 0.96) 0%,
|
||||
rgb(15 17 32 / 0.86) 45%,
|
||||
rgb(15 17 32 / 0.45) 78%,
|
||||
rgb(15 17 32 / 0.6) 100%
|
||||
),
|
||||
url('/themes/cyberpunk-sidebar.svg');
|
||||
|
||||
--color-canvas: #07080f;
|
||||
--color-surface: #0f1120;
|
||||
|
||||
@@ -439,6 +531,25 @@ html.theme-cyberpunk.dark {
|
||||
* Schatten: ein Halo auf hellem Grund sieht nach Fehler aus, nicht nach Neon.
|
||||
*/
|
||||
html.theme-cyberpunk:not(.dark) {
|
||||
/* Am Tag bleibt vom Neon nur ein Nachklang: heller Schleier, dicht genug,
|
||||
dass aus den Roehren blasse Linien werden statt dunkler Flecken. */
|
||||
--theme-header-image: linear-gradient(
|
||||
90deg,
|
||||
rgb(255 255 255 / 0.96) 0%,
|
||||
rgb(255 255 255 / 0.62) 30%,
|
||||
rgb(255 255 255 / 0.55) 55%,
|
||||
rgb(255 255 255 / 0.96) 100%
|
||||
),
|
||||
url('/themes/cyberpunk-header.svg');
|
||||
--theme-sidebar-image: linear-gradient(
|
||||
180deg,
|
||||
rgb(255 255 255 / 0.98) 0%,
|
||||
rgb(255 255 255 / 0.9) 45%,
|
||||
rgb(255 255 255 / 0.68) 78%,
|
||||
rgb(255 255 255 / 0.78) 100%
|
||||
),
|
||||
url('/themes/cyberpunk-sidebar.svg');
|
||||
|
||||
--color-canvas: #eceff7;
|
||||
--color-surface: #ffffff;
|
||||
|
||||
@@ -518,6 +629,39 @@ html.theme-cyberpunk:not(.dark) {
|
||||
font-family: var(--font-display);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hintergrundbilder der oberen Leiste und der Seitenleiste.
|
||||
*
|
||||
* Ohne Theme steht in den Variablen nichts, dann greift der Rueckfall `none`
|
||||
* und beide Flaechen bleiben einfarbig - perinco sieht also aus wie immer.
|
||||
*
|
||||
* Die Variable enthaelt **zwei** Ebenen: einen Schleier aus der Flaechenfarbe
|
||||
* des Themes und darunter die Grafik. Das ist kein Umweg, sondern der Grund,
|
||||
* dass eine Grafik in beiden Modi funktioniert - der Schleier des
|
||||
* Dunkelmodus toent den blauen Himmel zur Nacht ab. Er ist ausserdem die
|
||||
* Bedingung dafuer, dass die Schrift lesbar bleibt: in der oberen Leiste
|
||||
* steht er an den Raendern dicht (Titel links, Knoepfe rechts) und laesst die
|
||||
* Grafik nur in der leeren Mitte durch, in der Seitenleiste liegt er oben
|
||||
* ueber den Menuepunkten und gibt nach unten frei.
|
||||
*
|
||||
* `bg-surface` an den Elementen bleibt: die Farbe liegt unter dem Bild und
|
||||
* traegt, solange die Grafik laedt oder fehlt.
|
||||
*/
|
||||
.app-header {
|
||||
background-image: var(--theme-header-image, none);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.app-sidebar {
|
||||
background-image: var(--theme-sidebar-image, none);
|
||||
background-repeat: no-repeat;
|
||||
/* Unten verankert: dort sitzt in allen drei Grafiken das Motiv. */
|
||||
background-position: bottom center;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pixelschrift hat eine feste Zeichenbreite und traegt ihre Sperrung selbst;
|
||||
* die negative Laufweite der Ueberschriften wuerde die Buchstaben ineinander
|
||||
|
||||
Reference in New Issue
Block a user