diff --git a/scripts/make-mc-textures.py b/scripts/make-mc-textures.py new file mode 100644 index 0000000..0d015de --- /dev/null +++ b/scripts/make-mc-textures.py @@ -0,0 +1,86 @@ +""" +make-mc-textures.py – erzeugt die 16×16-Kacheln für das Minecraft-Design +(src/assets/design/*.png). Eigene, zufällig erzeugte Muster im Block-Stil – +keine Original-Texturen aus dem Spiel. + +Aufruf: python scripts/make-mc-textures.py +""" +import os +import random +from PIL import Image + +ZIEL = os.path.join(os.path.dirname(__file__), '..', 'src', 'assets', 'design') +os.makedirs(ZIEL, exist_ok=True) + + +def klemme(v): + return max(0, min(255, int(v))) + + +def rauschen(basis, streuung, seed, flecken=None): + """Grundfarbe mit Pixelrauschen; flecken = (anteil, farbe, streuung).""" + rnd = random.Random(seed) + img = Image.new('RGB', (16, 16)) + px = img.load() + for y in range(16): + for x in range(16): + d = rnd.randint(-streuung, streuung) + farbe = basis + if flecken and rnd.random() < flecken[0]: + farbe = flecken[1] + d = rnd.randint(-flecken[2], flecken[2]) + px[x, y] = tuple(klemme(c + d) for c in farbe) + return img + + +def speichere(img, name): + img.save(os.path.join(ZIEL, name)) + print(name) + + +# Hintergrund der Instanzliste: dunkle Erde (wie hinter Menüs im Spiel) +speichere(rauschen((44, 32, 23), 6, 11, (0.16, (31, 22, 15), 4)), 'erde-dunkel.png') + +# Leisten (Werkzeugleiste, Seitenleiste, Statusleiste): dunkler Schiefer +schiefer = rauschen((46, 46, 50), 6, 23, (0.12, (34, 34, 38), 3)) +px = schiefer.load() +rnd = random.Random(5) +for _ in range(5): # ein paar waagerechte Bruchkanten wie bei Tiefenschiefer + y = rnd.randrange(16) + x0 = rnd.randrange(16) + for x in range(x0, min(16, x0 + rnd.randint(3, 7))): + px[x, y] = (30, 30, 33) +speichere(schiefer, 'schiefer.png') + +# Dialoge: Stein +stein = rauschen((78, 78, 80), 8, 37, (0.10, (60, 60, 62), 4)) +speichere(stein, 'stein.png') + +# Holzbretter (z. B. Kopf der Dialoge): vier Bretter zu je 4 Pixeln +bretter = Image.new('RGB', (16, 16)) +px = bretter.load() +rnd = random.Random(41) +farben = [(122, 92, 56), (114, 86, 52), (128, 97, 60), (118, 89, 54)] +fugen = [3, 11, 7, 14] +for brett in range(4): + for y in range(brett * 4, brett * 4 + 4): + for x in range(16): + c = farben[brett] + d = rnd.randint(-5, 5) + if y == brett * 4 + 3: # dunkle Fuge unter jedem Brett + c, d = (74, 55, 33), rnd.randint(-2, 2) + elif x == fugen[brett]: # Stoßfuge + c, d = (88, 66, 40), 0 + px[x, y] = tuple(klemme(v + d) for v in c) +speichere(bretter, 'bretter.png') + +# Grasnarbe: oberer Rand der Werkzeugleiste (16×4, grün mit "Tropfen") +gras = Image.new('RGBA', (16, 4), (0, 0, 0, 0)) +px = gras.load() +rnd = random.Random(53) +tiefe = [2, 3, 2, 2, 4, 3, 2, 3, 2, 2, 3, 4, 2, 3, 2, 3] +for x in range(16): + for y in range(tiefe[x]): + g = rnd.randint(-10, 10) + px[x, y] = (klemme(84 + g), klemme(140 + g), klemme(52 + g // 2), 255) +speichere(gras, 'gras.png') diff --git a/scripts/make-pixelfont.js b/scripts/make-pixelfont.js new file mode 100644 index 0000000..e884c5b --- /dev/null +++ b/scripts/make-pixelfont.js @@ -0,0 +1,270 @@ +'use strict'; + +/* + * make-pixelfont.js – erzeugt src/assets/aeropixel.ttf + * ----------------------------------------------------- + * Eigene Pixel-Schrift für das Minecraft-Design (keine fremde Schrift, also + * keine Lizenzfragen). Jede Glyphe ist ein Raster aus '#' (Pixel) und ' ': + * Zeile 0 ist die Oberkante der Großbuchstaben, Zeile 6 sitzt auf der + * Grundlinie, Zeilen 7–8 sind Unterlängen (g, j, p, q, y, Komma). + * Fehlende Zeichen fallen im Launcher automatisch auf Segoe UI zurück. + * + * Aufruf: node scripts/make-pixelfont.js + */ + +const fs = require('fs'); +const path = require('path'); + +const P = 125; // ein Pixel in Font-Einheiten (8 Pixel = 1 em) +const EM = 1000; +const ASC = 1000; // 7 Zeilen Großbuchstaben + 1 Zeile Luft +const DESC = 250; // 2 Zeilen Unterlänge + +const G = { + A: [' ### ', '# #', '# #', '#####', '# #', '# #', '# #'], + B: ['#### ', '# #', '# #', '#### ', '# #', '# #', '#### '], + C: [' ### ', '# #', '# ', '# ', '# ', '# #', ' ### '], + D: ['#### ', '# #', '# #', '# #', '# #', '# #', '#### '], + E: ['#####', '# ', '# ', '#### ', '# ', '# ', '#####'], + F: ['#####', '# ', '# ', '#### ', '# ', '# ', '# '], + G: [' ####', '# ', '# ', '# ##', '# #', '# #', ' ####'], + H: ['# #', '# #', '# #', '#####', '# #', '# #', '# #'], + I: ['###', ' # ', ' # ', ' # ', ' # ', ' # ', '###'], + J: [' #', ' #', ' #', ' #', ' #', '# #', ' ### '], + K: ['# #', '# # ', '# # ', '## ', '# # ', '# # ', '# #'], + L: ['# ', '# ', '# ', '# ', '# ', '# ', '#####'], + M: ['# #', '## ##', '# # #', '# #', '# #', '# #', '# #'], + N: ['# #', '## #', '# # #', '# ##', '# #', '# #', '# #'], + O: [' ### ', '# #', '# #', '# #', '# #', '# #', ' ### '], + P: ['#### ', '# #', '# #', '#### ', '# ', '# ', '# '], + Q: [' ### ', '# #', '# #', '# #', '# #', '# # ', ' ## #'], + R: ['#### ', '# #', '# #', '#### ', '# # ', '# #', '# #'], + S: [' ####', '# ', '# ', ' ### ', ' #', ' #', '#### '], + T: ['#####', ' # ', ' # ', ' # ', ' # ', ' # ', ' # '], + U: ['# #', '# #', '# #', '# #', '# #', '# #', ' ### '], + V: ['# #', '# #', '# #', '# #', '# #', ' # # ', ' # '], + W: ['# #', '# #', '# #', '# #', '# # #', '## ##', '# #'], + X: ['# #', '# #', ' # # ', ' # ', ' # # ', '# #', '# #'], + Y: ['# #', '# #', ' # # ', ' # ', ' # ', ' # ', ' # '], + Z: ['#####', ' #', ' # ', ' # ', ' # ', '# ', '#####'], + + a: [' ', ' ', ' ### ', ' #', ' ####', '# #', ' ####'], + b: ['# ', '# ', '# ## ', '## #', '# #', '# #', '#### '], + c: [' ', ' ', ' ### ', '# #', '# ', '# #', ' ### '], + d: [' #', ' #', ' ## #', '# ##', '# #', '# #', ' ####'], + e: [' ', ' ', ' ### ', '# #', '#####', '# ', ' ####'], + f: [' ##', ' # ', '####', ' # ', ' # ', ' # ', ' # '], + g: [' ', ' ', ' ####', '# #', '# #', '# #', ' ####', ' #', ' ### '], + h: ['# ', '# ', '# ## ', '## #', '# #', '# #', '# #'], + i: ['#', ' ', '#', '#', '#', '#', '#'], + j: [' #', ' ', ' #', ' #', ' #', ' #', ' #', '# #', ' ## '], + k: ['# ', '# ', '# #', '# # ', '## ', '# # ', '# #'], + l: ['# ', '# ', '# ', '# ', '# ', '# ', ' #'], + m: [' ', ' ', '## # ', '# # #', '# # #', '# #', '# #'], + n: [' ', ' ', '#### ', '# #', '# #', '# #', '# #'], + o: [' ', ' ', ' ### ', '# #', '# #', '# #', ' ### '], + p: [' ', ' ', '# ## ', '## #', '# #', '# #', '#### ', '# ', '# '], + q: [' ', ' ', ' ## #', '# ##', '# #', '# #', ' ####', ' #', ' #'], + r: [' ', ' ', '# ## ', '## #', '# ', '# ', '# '], + s: [' ', ' ', ' ####', '# ', ' ### ', ' #', '#### '], + t: [' # ', ' # ', '###', ' # ', ' # ', ' # ', ' #'], + u: [' ', ' ', '# #', '# #', '# #', '# #', ' ####'], + v: [' ', ' ', '# #', '# #', '# #', ' # # ', ' # '], + w: [' ', ' ', '# #', '# #', '# # #', '# # #', ' ####'], + x: [' ', ' ', '# #', ' # # ', ' # ', ' # # ', '# #'], + y: [' ', ' ', '# #', '# #', '# #', '# #', ' ####', ' #', '#### '], + z: [' ', ' ', '#####', ' # ', ' # ', ' # ', '#####'], + + 0: [' ### ', '# #', '# ##', '# # #', '## #', '# #', ' ### '], + 1: [' # ', ' ## ', ' # ', ' # ', ' # ', ' # ', '#####'], + 2: [' ### ', '# #', ' #', ' ## ', ' # ', '# ', '#####'], + 3: [' ### ', '# #', ' #', ' ## ', ' #', '# #', ' ### '], + 4: [' ##', ' # #', ' # #', '# #', '#####', ' #', ' #'], + 5: ['#####', '# ', '#### ', ' #', ' #', '# #', ' ### '], + 6: [' ## ', ' # ', '# ', '#### ', '# #', '# #', ' ### '], + 7: ['#####', '# #', ' #', ' # ', ' # ', ' # ', ' # '], + 8: [' ### ', '# #', '# #', ' ### ', '# #', '# #', ' ### '], + 9: [' ### ', '# #', '# #', ' ####', ' #', ' # ', ' ## '], + + 'Ä': ['# #', ' ### ', '# #', '# #', '#####', '# #', '# #'], + 'Ö': ['# #', ' ### ', '# #', '# #', '# #', '# #', ' ### '], + 'Ü': ['# #', ' ', '# #', '# #', '# #', '# #', ' ### '], + 'ä': [' # # ', ' ', ' ### ', ' #', ' ####', '# #', ' ####'], + 'ö': [' # # ', ' ', ' ### ', '# #', '# #', '# #', ' ### '], + 'ü': [' # # ', ' ', '# #', '# #', '# #', '# #', ' ####'], + 'ß': [' ### ', '# #', '# # ', '# # ', '# # ', '# #', '# ## '], + 'é': [' # ', ' # ', ' ### ', '# #', '#####', '# ', ' ####'], + + '.': [' ', ' ', ' ', ' ', ' ', ' ', '#'], + ',': [' ', ' ', ' ', ' ', ' ', ' ', '#', '#'], + ':': [' ', ' ', '#', ' ', ' ', ' ', '#'], + ';': [' ', ' ', '#', ' ', ' ', ' ', '#', '#'], + '!': ['#', '#', '#', '#', '#', ' ', '#'], + '?': [' ### ', '# #', ' #', ' # ', ' # ', ' ', ' # '], + '-': [' ', ' ', ' ', '####', ' ', ' ', ' '], + '–': [' ', ' ', ' ', '#####', ' ', ' ', ' '], + '_': [' ', ' ', ' ', ' ', ' ', ' ', ' ', '#####'], + '(': [' #', ' # ', '# ', '# ', '# ', ' # ', ' #'], + ')': ['# ', ' # ', ' #', ' #', ' #', ' # ', '# '], + '[': ['##', '# ', '# ', '# ', '# ', '# ', '##'], + ']': ['##', ' #', ' #', ' #', ' #', ' #', '##'], + '/': [' #', ' # ', ' # ', ' # ', ' # ', ' # ', '# '], + '\\': ['# ', ' # ', ' # ', ' # ', ' # ', ' # ', ' #'], + '+': [' ', ' # ', ' # ', '#####', ' # ', ' # ', ' '], + '=': [' ', ' ', '#####', ' ', '#####', ' ', ' '], + '*': [' ', ' ', '# # #', ' ### ', '# # #', ' ', ' '], + '%': ['# #', ' #', ' # ', ' # ', ' # ', '# ', '# #'], + '&': [' ## ', '# # ', ' ## ', ' ## #', '# # ', '# # ', ' ## #'], + '#': [' # # ', '#####', ' # # ', ' # # ', ' # # ', '#####', ' # # '], + '<': [' #', ' # ', ' # ', '# ', ' # ', ' # ', ' #'], + '>': ['# ', ' # ', ' # ', ' #', ' # ', ' # ', '# '], + "'": ['#', '#'], + '"': ['# #', '# #'], + '|': ['#', '#', '#', '#', '#', '#', '#', '#', '#'], + '·': [' ', ' ', ' ', '#', ' ', ' ', ' '], + '…': [' ', ' ', ' ', ' ', ' ', ' ', '# # #'], + '@': [' ### ', '# #', '# ###', '# # #', '# ###', '# ', ' ####'], +}; + +// ---------- Glyphen in Umrisse umwandeln (waagerechte Pixel-Läufe als Rechtecke) ---------- +function umrisse(zeilen) { + const konturen = []; + zeilen.forEach((zeile, r) => { + const yOben = (7 - r) * P; + const yUnten = yOben - P; + let x = 0; + while (x < zeile.length) { + if (zeile[x] !== '#') { x++; continue; } + let ende = x; + while (ende < zeile.length && zeile[ende] === '#') ende++; + // im Uhrzeigersinn (TrueType-Außenkontur) + konturen.push([[x * P, yUnten], [x * P, yOben], [ende * P, yOben], [ende * P, yUnten]]); + x = ende; + } + }); + return konturen; +} + +const glyphen = [{ name: '.notdef', code: null, breite: 4, konturen: [[[0, 0], [0, 875], [500, 875], [500, 0]], [[125, 125], [375, 125], [375, 750], [125, 750]]] }, + { name: 'space', code: 32, breite: 3, konturen: [] }]; +for (const [zeichen, zeilen] of Object.entries(G)) { + const breite = Math.max(...zeilen.map((z) => z.length)); + glyphen.push({ code: zeichen.codePointAt(0), breite, konturen: umrisse(zeilen) }); +} +const sortiert = [glyphen[0], glyphen[1], ...glyphen.slice(2).sort((a, b) => a.code - b.code)]; + +// ---------- Hilfen zum Schreiben ---------- +class Puffer { + constructor() { this.teile = []; this.laenge = 0; } + u8(v) { const b = Buffer.alloc(1); b.writeUInt8(v); return this.roh(b); } + u16(v) { const b = Buffer.alloc(2); b.writeUInt16BE(v & 0xffff); return this.roh(b); } + i16(v) { const b = Buffer.alloc(2); b.writeInt16BE(v); return this.roh(b); } + u32(v) { const b = Buffer.alloc(4); b.writeUInt32BE(v >>> 0); return this.roh(b); } + i64(v) { const b = Buffer.alloc(8); b.writeBigInt64BE(BigInt(v)); return this.roh(b); } + roh(b) { this.teile.push(b); this.laenge += b.length; return this; } + fertig() { return Buffer.concat(this.teile); } +} +const auf4 = (b) => (b.length % 4 ? Buffer.concat([b, Buffer.alloc(4 - (b.length % 4))]) : b); +function pruefsumme(b) { + const p = auf4(b); + let s = 0; + for (let i = 0; i < p.length; i += 4) s = (s + p.readUInt32BE(i)) >>> 0; + return s; +} + +// ---------- glyf + loca + hmtx ---------- +const glyf = new Puffer(); +const loca = []; +const hmtx = new Puffer(); +let maxPunkte = 0, maxKonturen = 0; +let gxMin = 0, gyMin = 0, gxMax = 0, gyMax = 0; +let maxVorschub = 0, minLsb = 1e9, minRsb = 1e9, maxXAusdehnung = 0; +for (const g of sortiert) { + loca.push(glyf.laenge); + const vorschub = (g.breite + 1) * P; + maxVorschub = Math.max(maxVorschub, vorschub); + if (!g.konturen.length) { hmtx.u16(vorschub).i16(0); continue; } + const punkte = g.konturen.flat(); + const xs = punkte.map((p) => p[0]), ys = punkte.map((p) => p[1]); + const xMin = Math.min(...xs), xMax = Math.max(...xs), yMin = Math.min(...ys), yMax = Math.max(...ys); + gxMin = Math.min(gxMin, xMin); gyMin = Math.min(gyMin, yMin); gxMax = Math.max(gxMax, xMax); gyMax = Math.max(gyMax, yMax); + minLsb = Math.min(minLsb, xMin); minRsb = Math.min(minRsb, vorschub - xMax); maxXAusdehnung = Math.max(maxXAusdehnung, xMax); + maxPunkte = Math.max(maxPunkte, punkte.length); maxKonturen = Math.max(maxKonturen, g.konturen.length); + const b = new Puffer(); + b.i16(g.konturen.length).i16(xMin).i16(yMin).i16(xMax).i16(yMax); + let ende = -1; + for (const k of g.konturen) { ende += k.length; b.u16(ende); } + b.u16(0); // keine Hinting-Anweisungen + for (let i = 0; i < punkte.length; i++) b.u8(0x01); // alle Punkte auf der Kurve, Koordinaten als int16 + let px = 0, py = 0; + for (const [x] of punkte) { b.i16(x - px); px = x; } + for (const [, y] of punkte) { b.i16(y - py); py = y; } + glyf.roh(auf4(b.fertig())); + hmtx.u16(vorschub).i16(xMin); +} +loca.push(glyf.laenge); +const anzahl = sortiert.length; + +const locaB = new Puffer(); +for (const o of loca) locaB.u32(o); + +// ---------- cmap (Format 4, ein Segment je Zeichen) ---------- +const abbildung = sortiert.map((g, i) => [g.code, i]).filter(([c]) => c !== null).sort((a, b) => a[0] - b[0]); +const segmente = abbildung.map(([c, i]) => ({ start: c, ende: c, delta: (i - c) & 0xffff })); +segmente.push({ start: 0xffff, ende: 0xffff, delta: 1 }); +const segX2 = segmente.length * 2; +const suchbereich = 2 * 2 ** Math.floor(Math.log2(segmente.length)); +const sub = new Puffer(); +sub.u16(4).u16(16 + segmente.length * 8).u16(0).u16(segX2).u16(suchbereich) + .u16(Math.log2(suchbereich / 2)).u16(segX2 - suchbereich); +for (const s of segmente) sub.u16(s.ende); +sub.u16(0); +for (const s of segmente) sub.u16(s.start); +for (const s of segmente) sub.u16(s.delta); +for (const s of segmente) sub.u16(0); +const cmap = new Puffer().u16(0).u16(1).u16(3).u16(1).u32(12).roh(sub.fertig()); + +// ---------- head / hhea / maxp / OS/2 / name / post ---------- +const zeit = Math.floor(Date.UTC(2026, 9, 3) / 1000) + 2082844800; // Sekunden seit 1904 +const head = new Puffer().u32(0x00010000).u32(0x00010000).u32(0).u32(0x5f0f3cf5).u16(0x000b).u16(EM) + .i64(zeit).i64(zeit).i16(gxMin).i16(gyMin).i16(gxMax).i16(gyMax).u16(0).u16(8).i16(2).i16(1).i16(0); +const hhea = new Puffer().u32(0x00010000).i16(ASC).i16(-DESC).i16(0).u16(maxVorschub).i16(minLsb).i16(minRsb) + .i16(maxXAusdehnung).i16(1).i16(0).i16(0).i16(0).i16(0).i16(0).i16(0).i16(0).u16(anzahl); +const maxp = new Puffer().u32(0x00010000).u16(anzahl).u16(maxPunkte).u16(maxKonturen).u16(0).u16(0) + .u16(2).u16(0).u16(0).u16(0).u16(0).u16(0).u16(0).u16(0).u16(0); +const codes = abbildung.map(([c]) => c); +const os2 = new Puffer().u16(4).i16(5 * P).u16(400).u16(5).u16(0) + .i16(650).i16(600).i16(0).i16(75).i16(650).i16(600).i16(0).i16(350).i16(P).i16(3 * P) + .i16(0).roh(Buffer.alloc(10)).u32(3).u32(0).u32(0).u32(0).roh(Buffer.from('AERO')) + .u16(0x40).u16(Math.min(...codes)).u16(Math.min(0xffff, Math.max(...codes))) + .i16(ASC).i16(-DESC).i16(0).u16(ASC).u16(DESC).u32(1).u32(0).i16(5 * P).i16(7 * P).u16(0).u16(32).u16(1); +const namen = { 1: 'AeroPixel', 2: 'Regular', 3: 'AeroPixel Regular', 4: 'AeroPixel', 5: 'Version 1.0', 6: 'AeroPixel-Regular' }; +const nameDaten = Object.entries(namen).map(([id, text]) => [Number(id), Buffer.from(text, 'utf16le').swap16()]); +const name = new Puffer().u16(0).u16(nameDaten.length).u16(6 + nameDaten.length * 12); +let versatz = 0; +for (const [id, b] of nameDaten) { name.u16(3).u16(1).u16(0x409).u16(id).u16(b.length).u16(versatz); versatz += b.length; } +for (const [, b] of nameDaten) name.roh(b); +const post = new Puffer().u32(0x00030000).u32(0).i16(-P).i16(P).u32(0).u32(0).u32(0).u32(0).u32(0); + +// ---------- zusammensetzen ---------- +const tabellen = [ + ['OS/2', os2], ['cmap', cmap], ['glyf', glyf], ['head', head], ['hhea', hhea], + ['hmtx', hmtx], ['loca', locaB], ['maxp', maxp], ['name', name], ['post', post], +].map(([tag, p]) => [tag, p.fertig()]); +const n = tabellen.length; +const sb = 16 * 2 ** Math.floor(Math.log2(n)); +const kopf = new Puffer().u32(0x00010000).u16(n).u16(sb).u16(Math.log2(sb / 16)).u16(n * 16 - sb); +let offset = 12 + n * 16; +const verzeichnis = new Puffer(); +for (const [tag, daten] of tabellen) { + verzeichnis.roh(Buffer.from(tag, 'latin1')).u32(pruefsumme(daten)).u32(offset).u32(daten.length); + offset += auf4(daten).length; +} +let schrift = Buffer.concat([kopf.fertig(), verzeichnis.fertig(), ...tabellen.map(([, d]) => auf4(d))]); +// checkSumAdjustment im head-Eintrag setzen +const headOffset = 12 + n * 16 + tabellen.slice(0, 3).reduce((s, [, d]) => s + auf4(d).length, 0); +schrift.writeUInt32BE((0xb1b0afba - pruefsumme(schrift)) >>> 0, headOffset + 8); + +const ziel = path.join(__dirname, '..', 'src', 'assets', 'aeropixel.ttf'); +fs.writeFileSync(ziel, schrift); +console.log(`${ziel}: ${anzahl} Glyphen, ${schrift.length} Bytes`); diff --git a/src/assets/aeropixel.ttf b/src/assets/aeropixel.ttf new file mode 100644 index 0000000..3b1bdc5 Binary files /dev/null and b/src/assets/aeropixel.ttf differ diff --git a/src/assets/design/bretter.png b/src/assets/design/bretter.png new file mode 100644 index 0000000..3754b77 Binary files /dev/null and b/src/assets/design/bretter.png differ diff --git a/src/assets/design/erde-dunkel.png b/src/assets/design/erde-dunkel.png new file mode 100644 index 0000000..1eff5ff Binary files /dev/null and b/src/assets/design/erde-dunkel.png differ diff --git a/src/assets/design/gras.png b/src/assets/design/gras.png new file mode 100644 index 0000000..44ac392 Binary files /dev/null and b/src/assets/design/gras.png differ diff --git a/src/assets/design/schiefer.png b/src/assets/design/schiefer.png new file mode 100644 index 0000000..a13b271 Binary files /dev/null and b/src/assets/design/schiefer.png differ diff --git a/src/assets/design/stein.png b/src/assets/design/stein.png new file mode 100644 index 0000000..2dae791 Binary files /dev/null and b/src/assets/design/stein.png differ diff --git a/src/designs.css b/src/designs.css new file mode 100644 index 0000000..d97f4f3 --- /dev/null +++ b/src/designs.css @@ -0,0 +1,424 @@ +/* + * designs.css – wählbare Designs (Optionen → Darstellung → Design) + * --------------------------------------------------------------- + * Klassisch (hell/dunkel) steht in styles.css. Die Designs hier bauen + * auf den dunklen Regeln auf (data-theme="dark") und überschreiben sie über + * data-design – gleiche Spezifität, deshalb muss diese Datei NACH styles.css + * geladen werden. + */ + +/* ===================== Design-Auswahl in den Optionen ===================== */ +.design-raster{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px} +.settings-card-wide .design-raster{grid-template-columns:repeat(5,minmax(0,1fr))} +@media (max-width:900px){.settings-card-wide .design-raster{grid-template-columns:repeat(2,minmax(0,1fr))}} +.design-wahl{display:flex;flex-direction:column;gap:5px;padding:6px;border:1px solid var(--border);border-radius:8px;background:none;color:var(--text);font-family:inherit;font-size:12px;cursor:pointer;text-align:left} +.design-wahl:hover{border-color:var(--sel-br)} +.design-wahl.on{border-color:var(--sel-br);box-shadow:0 0 0 1px var(--sel-br);background:var(--sel)} +.design-wahl small{font-size:12px;font-weight:600;padding:0 2px} +.dv{position:relative;display:block;width:100%;align-self:stretch;height:58px;border-radius:5px;overflow:hidden;border:1px solid rgba(0,0,0,.25)} +.dv i,.dv b,.dv em{position:absolute;display:block} +.dv i{left:0;right:0;top:0;height:11px} +.dv em{top:11px;right:0;bottom:0;width:24%} +.dv b{left:10px;top:20px;width:22px;height:22px;border-radius:3px} +.dv-dark{background:#242426}.dv-dark i{background:#333337}.dv-dark em{background:#2d2d30;border-left:1px solid #3f3f46}.dv-dark b{background:#0e639c;border:1px solid #1177bb} +.dv-light{background:#e2e2e2}.dv-light i{background:#f0f0f0;border-bottom:1px solid #c4c7cc}.dv-light em{background:#f0f0f0;border-left:1px solid #c4c7cc}.dv-light b{background:#dce8f6;border:1px solid #3a6ea5} +.dv-aero{background:radial-gradient(60px 30px at 35% 10px,rgba(64,126,232,.55),transparent 70%),linear-gradient(to right,rgba(148,175,255,.09) 1px,transparent 1px) 0 0/9px 9px,linear-gradient(to bottom,rgba(148,175,255,.09) 1px,transparent 1px) 0 0/9px 9px,#05070d} +.dv-aero i{background:rgba(10,14,26,.95);border-bottom:1px solid rgba(148,175,255,.18)} +.dv-aero em{background:#0a0e1a;border-left:1px solid rgba(148,175,255,.18)} +.dv-aero b{border-radius:7px;background:linear-gradient(135deg,#8fd8ff,#407ee8 60%,#2658be);box-shadow:0 4px 12px -3px rgba(64,126,232,.9)} +.dv-lila{background:radial-gradient(60px 30px at 35% 10px,rgba(139,92,246,.6),transparent 70%),linear-gradient(to right,rgba(196,165,255,.09) 1px,transparent 1px) 0 0/9px 9px,linear-gradient(to bottom,rgba(196,165,255,.09) 1px,transparent 1px) 0 0/9px 9px,#08050f} +.dv-lila i{background:rgba(15,10,26,.95);border-bottom:1px solid rgba(196,165,255,.18)} +.dv-lila em{background:#0f0a1a;border-left:1px solid rgba(196,165,255,.18)} +.dv-lila b{border-radius:7px;background:linear-gradient(135deg,#e8beff,#8b5cf6 60%,#6d28d9);box-shadow:0 4px 12px -3px rgba(139,92,246,.9)} +.dv-mc{background:url(assets/design/erde-dunkel.png) 0 0/24px 24px;image-rendering:pixelated} +.dv-mc i{height:12px;background:url(assets/design/gras.png) 0 0/16px 4px repeat-x,url(assets/design/schiefer.png) 0 0/24px 24px;border-bottom:1px solid #000} +.dv-mc em{background:url(assets/design/schiefer.png) 0 0/24px 24px;border-left:1px solid #000} +.dv-mc b{border-radius:0;background:#3c8527;border:1px solid #000;box-shadow:inset 1px 1px 0 #6cc349,inset -1px -1px 0 #1d4d13} + +/* ===================================================================== */ +/* ============ Designs: AeroMC (Blau, wie die Webseite) & Nachtlila ===== */ +/* ===================================================================== */ +/* Beide Designs teilen sich alle Regeln unten; sie unterscheiden sich nur in + der Palette. --p-* ohne "#" sind RGB-Tripel, damit rgba(var(--p-…),.5) geht. */ +:root[data-design="aero"]{ + --p-akzent:64,126,232; --p-tief:38,88,190; --p-akzent2:104,196,250; --p-hell:143,216,255; + --p-linie:148,175,255; --p-win:10,14,26; --p-surface:13,20,40; --p-surface2:16,26,53; --p-schatten:2,4,10; + --p-akzent-hover:#4f8df0; --p-tief-hover:#2c63cc; --p-aktiv:#0b1226; --p-konsole:#03050a; + --win:#0a0e1a; --area:#05070d; --bar:#0d1428; --surface:#0d1428; --surface2:#101a35; --input:#070b16; + --text:#e8ecfb; --dim:#93a0c4; --link:#8fd8ff; +} +:root[data-design="lila"]{ + --p-akzent:139,92,246; --p-tief:109,40,217; --p-akzent2:192,132,252; --p-hell:232,190,255; + --p-linie:196,165,255; --p-win:15,10,26; --p-surface:24,15,41; --p-surface2:32,20,56; --p-schatten:6,3,12; + --p-akzent-hover:#9d72ff; --p-tief-hover:#7c3aed; --p-aktiv:#140c24; --p-konsole:#050309; + --win:#0f0a1a; --area:#08050f; --bar:#180f29; --surface:#180f29; --surface2:#201438; --input:#0b0715; + --text:#f0eafb; --dim:#a99cc6; --link:#e8beff; +} +:root:is([data-design="aero"],[data-design="lila"]){ + --border:rgba(var(--p-linie),.14); --border2:rgba(var(--p-linie),.09); + --sel:rgba(var(--p-akzent),.20); --sel-br:var(--p-akzent-hover); --accent:rgb(var(--p-akzent)); + --danger:#ff7a8a; --play:#4ade80; + --cyan:rgb(var(--p-hell)); --cyan-soft:rgb(var(--p-akzent2)); + --stat-bar:rgb(var(--p-akzent2)); + --titel-bg:var(--win); --titel-fg:var(--text); +} +:root:is([data-design="aero"],[data-design="lila"]) ::selection{background:rgb(var(--p-akzent));color:#fff} +:root:is([data-design="aero"],[data-design="lila"]) .titel-text{font-weight:600;background:linear-gradient(120deg,rgb(var(--p-hell)),rgb(var(--p-akzent)) 70%);-webkit-background-clip:text;background-clip:text;color:transparent} +:root:is([data-design="aero"],[data-design="lila"]) body{background:var(--area)} + +/* Werkzeugleiste */ +:root:is([data-design="aero"],[data-design="lila"]) .toolbar{background:rgba(var(--p-win),.94);border-bottom:1px solid var(--border);padding:7px 8px;gap:2px} +:root:is([data-design="aero"],[data-design="lila"]) .tbtn{border-radius:999px;padding:6px 10px;color:var(--text)} +:root:is([data-design="aero"],[data-design="lila"]) .tbtn:hover{background:var(--surface);border-color:var(--border)} +:root:is([data-design="aero"],[data-design="lila"]) .tbtn:active{background:var(--surface2)} +:root:is([data-design="aero"],[data-design="lila"]) .tbtn svg, +:root:is([data-design="aero"],[data-design="lila"]) #btn-new svg,:root:is([data-design="aero"],[data-design="lila"]) #btn-import svg,:root:is([data-design="aero"],[data-design="lila"]) #btn-open-dir svg, +:root:is([data-design="aero"],[data-design="lila"]) #btn-console svg,:root:is([data-design="aero"],[data-design="lila"]) #btn-account svg,:root:is([data-design="aero"],[data-design="lila"]) #btn-settings svg, +:root:is([data-design="aero"],[data-design="lila"]) .acct-av svg{color:var(--cyan-soft)} +:root:is([data-design="aero"],[data-design="lila"]) .tbsep{background:var(--border)} +:root:is([data-design="aero"],[data-design="lila"]) .search-wrap input{border-radius:999px;padding:5px 12px;width:150px} + +/* Instanzliste: Raster und blaues Leuchten wie im Kopf der Webseite */ +:root:is([data-design="aero"],[data-design="lila"]) .workspace{background:var(--area)} +:root:is([data-design="aero"],[data-design="lila"]) .list-area{background: + radial-gradient(520px 260px at 32% -60px,rgba(var(--p-akzent),.30),transparent 70%), + linear-gradient(to right,rgba(var(--p-linie),.05) 1px,transparent 1px) 0 0/44px 44px, + linear-gradient(to bottom,rgba(var(--p-linie),.05) 1px,transparent 1px) 0 0/44px 44px, + var(--area)} +:root:is([data-design="aero"],[data-design="lila"]) .group-header{color:var(--text);padding:8px 4px 4px} +:root:is([data-design="aero"],[data-design="lila"]) .group-header .chev{color:var(--cyan-soft)} +:root:is([data-design="aero"],[data-design="lila"]) .group-header::after{background:linear-gradient(to right,rgba(var(--p-linie),.22),rgba(var(--p-linie),.04))} +:root:is([data-design="aero"],[data-design="lila"]) .group-grid{gap:6px} +:root:is([data-design="aero"],[data-design="lila"]) .card{border-radius:14px;padding:8px 4px 6px;transition:background .15s,border-color .15s,box-shadow .15s} +:root:is([data-design="aero"],[data-design="lila"]) .card:hover{background:rgba(var(--p-surface),.85);border-color:var(--border)} +:root:is([data-design="aero"],[data-design="lila"]) .card.sel{background:linear-gradient(180deg,rgba(var(--p-akzent),.24),rgba(var(--p-tief),.14));border-color:rgba(var(--p-akzent2),.55);box-shadow:0 10px 28px -14px rgba(var(--p-akzent),.95),0 0 0 1px rgba(var(--p-hell),.08) inset} +:root:is([data-design="aero"],[data-design="lila"]) .card.sel .card-name{background:linear-gradient(120deg,rgb(var(--p-akzent2)),rgb(var(--p-akzent)) 60%,rgb(var(--p-tief)));color:#fff;border-radius:999px} +:root:is([data-design="aero"],[data-design="lila"]) .card-icon-img{border-radius:10px} +:root:is([data-design="aero"],[data-design="lila"]) .card-taste{border-radius:999px;background:linear-gradient(120deg,rgb(var(--p-akzent2)),rgb(var(--p-akzent)))} +:root:is([data-design="aero"],[data-design="lila"]) .empty h2{background:linear-gradient(120deg,rgb(var(--p-hell)),rgb(var(--p-akzent)) 60%,rgb(var(--p-tief)));-webkit-background-clip:text;background-clip:text;color:transparent;font-size:26px} + +/* Seitenleiste */ +:root:is([data-design="aero"],[data-design="lila"]) .side{background:var(--win);border-left:1px solid var(--border);padding:10px 6px} +:root:is([data-design="aero"],[data-design="lila"]) .side-ico img{border-radius:12px} +:root:is([data-design="aero"],[data-design="lila"]) .side-grp{color:var(--cyan-soft)} +:root:is([data-design="aero"],[data-design="lila"]) .hr{background:var(--border);margin:8px 4px} +:root:is([data-design="aero"],[data-design="lila"]) .sbtn{border-radius:999px;margin-bottom:1px;padding:5px 2px} +:root:is([data-design="aero"],[data-design="lila"]) .sbtn:hover{background:var(--surface);border-color:var(--border)} +:root:is([data-design="aero"],[data-design="lila"]) .sbtn.play{color:#fff;background:linear-gradient(180deg,rgb(var(--p-akzent)),rgb(var(--p-tief)));border-color:transparent;box-shadow:0 0 0 1px rgba(255,255,255,.08) inset,0 10px 24px -12px rgba(var(--p-akzent),.95);padding:7px 4px} +:root:is([data-design="aero"],[data-design="lila"]) .sbtn.play:hover{background:linear-gradient(180deg,var(--p-akzent-hover),var(--p-tief-hover))} +:root:is([data-design="aero"],[data-design="lila"]) .sbtn.del:hover{color:var(--danger);border-color:rgba(255,122,138,.35)} + +/* Statusleiste */ +:root:is([data-design="aero"],[data-design="lila"]) .statusbar{background:var(--win);border-top:1px solid var(--border)} +:root:is([data-design="aero"],[data-design="lila"]) .st-row{color:var(--dim)} +:root:is([data-design="aero"],[data-design="lila"]) .st-row2{background:var(--input);border-top-color:var(--border2)} + +/* Dialoge */ +:root:is([data-design="aero"],[data-design="lila"]) .modal{background:rgba(var(--p-schatten),.68);backdrop-filter:blur(3px)} +:root:is([data-design="aero"],[data-design="lila"]) .modal-card{background:var(--win);border:1px solid var(--border);border-radius:16px;box-shadow:0 30px 80px -20px rgba(0,0,0,.85),0 0 0 1px rgba(var(--p-hell),.04)} +:root:is([data-design="aero"],[data-design="lila"]) .modal-head{background:linear-gradient(180deg,rgba(var(--p-surface2),.9),rgba(var(--p-win),.9));border-bottom:1px solid var(--border);padding:12px 16px} +:root:is([data-design="aero"],[data-design="lila"]) .modal-body{background:var(--win)} +:root:is([data-design="aero"],[data-design="lila"]) .modal-foot{background:var(--win);border-top:1px solid var(--border);padding:12px 16px} +:root:is([data-design="aero"],[data-design="lila"]) .modal-close{color:var(--dim)} +:root:is([data-design="aero"],[data-design="lila"]) .modal-close:hover{color:var(--cyan)} + +/* Eingabefelder */ +:root:is([data-design="aero"],[data-design="lila"]) .search-wrap input, +:root:is([data-design="aero"],[data-design="lila"]) .field input, +:root:is([data-design="aero"],[data-design="lila"]) .field select, +:root:is([data-design="aero"],[data-design="lila"]) .field textarea, +:root:is([data-design="aero"],[data-design="lila"]) .mods-search input, +:root:is([data-design="aero"],[data-design="lila"]) .mods-search select, +:root:is([data-design="aero"],[data-design="lila"]) .mods-filters select, +:root:is([data-design="aero"],[data-design="lila"]) .mmc-bar select, +:root:is([data-design="aero"],[data-design="lila"]) .clip-length select, +:root:is([data-design="aero"],[data-design="lila"]) .path-row input, +:root:is([data-design="aero"],[data-design="lila"]) .se-farbzeile input[type=text], +:root:is([data-design="aero"],[data-design="lila"]) .se-feld select{background:var(--input);color:var(--text);border-color:var(--border);border-radius:10px} +:root:is([data-design="aero"],[data-design="lila"]) .search-wrap input{border-radius:999px} +:root:is([data-design="aero"],[data-design="lila"]) .search-wrap input:focus, +:root:is([data-design="aero"],[data-design="lila"]) .field input:focus, +:root:is([data-design="aero"],[data-design="lila"]) .field select:focus, +:root:is([data-design="aero"],[data-design="lila"]) .field textarea:focus, +:root:is([data-design="aero"],[data-design="lila"]) .mods-search input:focus, +:root:is([data-design="aero"],[data-design="lila"]) .path-row input:focus{border-color:var(--cyan-soft);box-shadow:0 0 0 3px rgba(var(--p-akzent2),.15)} +:root:is([data-design="aero"],[data-design="lila"]) input[type=checkbox],:root:is([data-design="aero"],[data-design="lila"]) input[type=radio],:root:is([data-design="aero"],[data-design="lila"]) input[type=range]{accent-color:rgb(var(--p-akzent))} +:root:is([data-design="aero"],[data-design="lila"]) .login-usercode{background:var(--input);color:var(--text);border-color:var(--border);border-radius:12px} +:root:is([data-design="aero"],[data-design="lila"]) .upd-notes{background:var(--input);border-radius:10px} + +/* Knöpfe – rund wie auf der Webseite */ +:root:is([data-design="aero"],[data-design="lila"]) .btn{border-radius:999px;padding:7px 15px;background:var(--surface);border-color:var(--border);color:var(--text);transition:background .15s,border-color .15s,transform .15s} +:root:is([data-design="aero"],[data-design="lila"]) .btn:hover{background:var(--surface2);border-color:rgba(var(--p-linie),.32)} +:root:is([data-design="aero"],[data-design="lila"]) .btn:active{background:var(--p-aktiv)} +:root:is([data-design="aero"],[data-design="lila"]) .btn-primary{background:linear-gradient(180deg,rgb(var(--p-akzent)),rgb(var(--p-tief)));border-color:transparent;color:#fff;box-shadow:0 0 0 1px rgba(255,255,255,.08) inset,0 10px 28px -12px rgba(var(--p-akzent),.9)} +:root:is([data-design="aero"],[data-design="lila"]) .btn-primary:hover{background:linear-gradient(180deg,var(--p-akzent-hover),var(--p-tief-hover));transform:translateY(-1px)} +:root:is([data-design="aero"],[data-design="lila"]) .btn-primary:disabled{transform:none} +:root:is([data-design="aero"],[data-design="lila"]) .btn-danger{color:var(--danger);border-color:rgba(255,122,138,.35)} +:root:is([data-design="aero"],[data-design="lila"]) .btn-danger:hover{background:rgba(255,122,138,.10);border-color:rgba(255,122,138,.6)} +:root:is([data-design="aero"],[data-design="lila"]) .btn-mini{padding:4px 10px} +:root:is([data-design="aero"],[data-design="lila"]) .badge{background:var(--surface2);color:var(--dim);border-color:var(--border);border-radius:999px} + +/* Listen, Kacheln, Tabs */ +:root:is([data-design="aero"],[data-design="lila"]) .mods-list, +:root:is([data-design="aero"],[data-design="lila"]) .account-item, +:root:is([data-design="aero"],[data-design="lila"]) .screen-thumb{background:var(--input);border-color:var(--border);border-radius:12px} +:root:is([data-design="aero"],[data-design="lila"]) .mod-icon, +:root:is([data-design="aero"],[data-design="lila"]) .account-av, +:root:is([data-design="aero"],[data-design="lila"]) .icon-preview{background:var(--surface2);border-radius:8px} +:root:is([data-design="aero"],[data-design="lila"]) .mod-item{border-radius:10px} +:root:is([data-design="aero"],[data-design="lila"]) .mod-item+.mod-item{border-color:var(--border2)} +:root:is([data-design="aero"],[data-design="lila"]) .mod-item:hover{background:var(--surface)} +:root:is([data-design="aero"],[data-design="lila"]) .mtab{border-radius:10px 10px 0 0} +:root:is([data-design="aero"],[data-design="lila"]) .mtab.on{background:var(--surface);border-color:var(--border);color:var(--cyan)} +:root:is([data-design="aero"],[data-design="lila"]) .advanced{background:var(--surface);border-color:var(--border);border-radius:12px} +:root:is([data-design="aero"],[data-design="lila"]) .console-out{background:var(--p-konsole);border-color:var(--border);border-radius:12px} +:root:is([data-design="aero"],[data-design="lila"]) .stat-tile, +:root:is([data-design="aero"],[data-design="lila"]) .crash-fund, +:root:is([data-design="aero"],[data-design="lila"]) .share-code-box, +:root:is([data-design="aero"],[data-design="lila"]) .share-preview, +:root:is([data-design="aero"],[data-design="lila"]) .clip-bar, +:root:is([data-design="aero"],[data-design="lila"]) .wahl-option{border-radius:12px;background:var(--surface)} +:root:is([data-design="aero"],[data-design="lila"]) .chat-verlauf{background:var(--input);border-radius:12px} +:root:is([data-design="aero"],[data-design="lila"]) .chat-blase{background:var(--surface2);border-radius:14px} +:root:is([data-design="aero"],[data-design="lila"]) .chat-blase.ich{background:linear-gradient(180deg,rgb(var(--p-akzent)),rgb(var(--p-tief)));border-color:transparent} +:root:is([data-design="aero"],[data-design="lila"]) .stat-bar{border-radius:0 6px 6px 0;background:linear-gradient(90deg,rgb(var(--p-akzent)),rgb(var(--p-akzent2)))} + +/* Einstellungen */ +:root:is([data-design="aero"],[data-design="lila"]) .settings-body{background:var(--area)} +:root:is([data-design="aero"],[data-design="lila"]) .settings-nav{background:var(--win);border-right-color:var(--border)} +:root:is([data-design="aero"],[data-design="lila"]) .snav{border-radius:10px} +:root:is([data-design="aero"],[data-design="lila"]) .snav:hover{background:var(--surface)} +:root:is([data-design="aero"],[data-design="lila"]) .snav.on{background:linear-gradient(120deg,rgba(var(--p-akzent),.30),rgba(var(--p-tief),.18));border-color:rgba(var(--p-akzent2),.40);box-shadow:none} +:root:is([data-design="aero"],[data-design="lila"]) .settings-card{background:var(--surface);border-color:var(--border);border-radius:16px} +:root:is([data-design="aero"],[data-design="lila"]) .settings-kv-row, +:root:is([data-design="aero"],[data-design="lila"]) .about-brand{border-bottom-color:var(--border2)} +:root:is([data-design="aero"],[data-design="lila"]) .appinfo-item{background:rgba(var(--p-linie),.04);border-color:var(--border2);border-radius:12px} +:root:is([data-design="aero"],[data-design="lila"]) .info-meta-link{color:var(--cyan)} +:root:is([data-design="aero"],[data-design="lila"]) .settings-hero h4{background:linear-gradient(120deg,rgb(var(--p-hell)),rgb(var(--p-akzent)) 70%);-webkit-background-clip:text;background-clip:text;color:transparent} + +/* Kontextmenü, Hinweis, Bildlaufleisten */ +:root:is([data-design="aero"],[data-design="lila"]) .ctx{background:var(--surface);border-color:var(--border);border-radius:12px;box-shadow:0 18px 40px -12px rgba(0,0,0,.8)} +:root:is([data-design="aero"],[data-design="lila"]) .ctx-item{border-radius:8px} +:root:is([data-design="aero"],[data-design="lila"]) .ctx-item:hover{background:rgba(var(--p-akzent),.22)} +:root:is([data-design="aero"],[data-design="lila"]) .toast{background:var(--surface2);border:1px solid var(--border);border-radius:999px;padding:10px 18px} +:root:is([data-design="aero"],[data-design="lila"]) ::-webkit-scrollbar-thumb{background:rgba(var(--p-linie),.18);border-color:var(--area)} +:root:is([data-design="aero"],[data-design="lila"]) ::-webkit-scrollbar-thumb:hover{background:rgba(var(--p-linie),.3)} + +/* Skin-Editor */ +:root:is([data-design="aero"],[data-design="lila"]) .se-modus{border-radius:999px;background:var(--surface)} +:root:is([data-design="aero"],[data-design="lila"]) .se-modus-btn.on{background:linear-gradient(180deg,rgb(var(--p-akzent)),rgb(var(--p-tief)))} +:root:is([data-design="aero"],[data-design="lila"]) .se-tool,:root:is([data-design="aero"],[data-design="lila"]) .se-ebene{background:var(--surface)} +:root:is([data-design="aero"],[data-design="lila"]) .se-tool{border-radius:10px} +:root:is([data-design="aero"],[data-design="lila"]) .se-ebenen{border-radius:10px} +:root:is([data-design="aero"],[data-design="lila"]) .se-buehne,:root:is([data-design="aero"],[data-design="lila"]) .se-mini{border-radius:14px;background:var(--input)} +:root:is([data-design="aero"],[data-design="lila"]) .design-wahl{border-radius:12px} + +/* ===================================================================== */ +/* ===================== Design: Minecraft ============================= */ +/* ===================================================================== */ +@font-face{font-family:"AeroPixel";src:url(assets/aeropixel.ttf) format("truetype");font-display:block} +:root[data-design="minecraft"]{ + --win:#313233; --area:#1e1e1f; --bar:#48494a; + --border:#000; --border2:#1a1a1b; + --text:#ffffff; --dim:#b8b9bc; + --sel:#2f6b1f; --sel-br:#6cc349; --link:#86d75e; --accent:#3c8527; + --danger:#ff5555; --play:#6cc349; --input:#000; + --stat-bar:#6cc349; + --pixel:"AeroPixel","Segoe UI",sans-serif; + --mc-schatten:2px 2px 0 #3f3f3f; +} +:root[data-design="minecraft"] body{background:var(--area)} +:root[data-design="minecraft"] ::selection{background:#3c8527;color:#fff} +:root[data-design="minecraft"]{--titel-bg:#1e1e1f;--titel-fg:#ffffff} +:root[data-design="minecraft"] .titel-text{font-family:var(--pixel);font-size:16px;text-shadow:var(--mc-schatten);padding-bottom:2px} + +/* Wiederkehrender Block-Knopf: grauer Stein mit hellem/dunklem Rand */ +:root[data-design="minecraft"] .btn, +:root[data-design="minecraft"] .sbtn, +:root[data-design="minecraft"] .snav, +:root[data-design="minecraft"] .se-tool, +:root[data-design="minecraft"] .wahl-option{ + background:#58595b;color:#fff;border:2px solid #000;border-radius:0; + box-shadow:inset 2px 2px 0 #8b8c8f,inset -2px -2px 0 #36373a; + text-shadow:1px 1px 0 #2a2a2a} +:root[data-design="minecraft"] .btn:hover, +:root[data-design="minecraft"] .sbtn:hover, +:root[data-design="minecraft"] .snav:hover, +:root[data-design="minecraft"] .se-tool:hover:not(:disabled), +:root[data-design="minecraft"] .wahl-option:hover{background:#6a6b6f;border-color:#fff;box-shadow:inset 2px 2px 0 #a3a4a8,inset -2px -2px 0 #3e3f42} +:root[data-design="minecraft"] .btn:active, +:root[data-design="minecraft"] .sbtn:active{background:#48494b;box-shadow:inset -2px -2px 0 #8b8c8f,inset 2px 2px 0 #36373a} +:root[data-design="minecraft"] .btn:disabled, +:root[data-design="minecraft"] .sbtn:disabled{background:#2b2b2c;color:#8b8b8b;box-shadow:none;border-color:#000;text-shadow:none;opacity:1} +:root[data-design="minecraft"] .sbtn:disabled:hover{background:#2b2b2c;border-color:#000} +/* grün wie der Spielen-Knopf */ +:root[data-design="minecraft"] .btn-primary, +:root[data-design="minecraft"] .sbtn.play, +:root[data-design="minecraft"] .snav.on, +:root[data-design="minecraft"] .se-tool.on, +:root[data-design="minecraft"] .wahl-option.an{background:#3c8527;color:#fff;box-shadow:inset 2px 2px 0 #6cc349,inset -2px -2px 0 #1d4d13} +:root[data-design="minecraft"] .btn-primary:hover, +:root[data-design="minecraft"] .sbtn.play:hover{background:#4a9a33;box-shadow:inset 2px 2px 0 #82d65c,inset -2px -2px 0 #24601a;border-color:#fff} +:root[data-design="minecraft"] .btn-danger{background:#8c2b2b;box-shadow:inset 2px 2px 0 #c55050,inset -2px -2px 0 #561616} +:root[data-design="minecraft"] .btn-danger:hover{background:#a33434;border-color:#fff;box-shadow:inset 2px 2px 0 #d86262,inset -2px -2px 0 #651b1b} +:root[data-design="minecraft"] .sbtn.del:hover{background:#8c2b2b;color:#fff;box-shadow:inset 2px 2px 0 #c55050,inset -2px -2px 0 #561616} + +/* Werkzeugleiste: Schiefer mit Grasnarbe */ +:root[data-design="minecraft"] .toolbar{ + background:url(assets/design/gras.png) 0 0/32px 8px repeat-x,url(assets/design/schiefer.png) 0 0/64px 64px; + image-rendering:pixelated;border-bottom:2px solid #000;padding:11px 8px 6px} +:root[data-design="minecraft"] .tbtn{color:#fff;border-radius:0;text-shadow:1px 1px 0 #1a1a1a;image-rendering:auto} +:root[data-design="minecraft"] .tbtn:hover{background:rgba(0,0,0,.35);border-color:#fff} +:root[data-design="minecraft"] .tbtn:active{background:rgba(0,0,0,.5)} +:root[data-design="minecraft"] .tbtn svg,:root[data-design="minecraft"] #btn-console svg,:root[data-design="minecraft"] .acct-av svg{color:#e6e6e6} +:root[data-design="minecraft"] #btn-new svg,:root[data-design="minecraft"] #btn-account svg{color:#7fd858} +:root[data-design="minecraft"] #btn-import svg{color:#6db8ff} +:root[data-design="minecraft"] #btn-open-dir svg{color:#f2c94c} +:root[data-design="minecraft"] #btn-settings svg{color:#d0d0d0} +:root[data-design="minecraft"] .tbsep{background:#000;width:2px} +:root[data-design="minecraft"] .tb-badge{border-radius:0;background:#ff5555;box-shadow:inset -1px -1px 0 #a32a2a} + +/* Eingabefelder: schwarz mit grauem Rand wie im Spiel */ +:root[data-design="minecraft"] .search-wrap input, +:root[data-design="minecraft"] .field input, +:root[data-design="minecraft"] .field select, +:root[data-design="minecraft"] .field textarea, +:root[data-design="minecraft"] .mods-search input, +:root[data-design="minecraft"] .mods-search select, +:root[data-design="minecraft"] .mods-filters select, +:root[data-design="minecraft"] .mmc-bar select, +:root[data-design="minecraft"] .clip-length select, +:root[data-design="minecraft"] .path-row input, +:root[data-design="minecraft"] .login-usercode, +:root[data-design="minecraft"] .upd-notes, +:root[data-design="minecraft"] .se-farbzeile input[type=text], +:root[data-design="minecraft"] .se-feld select{background:#000;color:#fff;border:1px solid #a0a0a0;border-radius:0} +:root[data-design="minecraft"] .search-wrap input:focus, +:root[data-design="minecraft"] .field input:focus, +:root[data-design="minecraft"] .field select:focus, +:root[data-design="minecraft"] .field textarea:focus, +:root[data-design="minecraft"] .mods-search input:focus, +:root[data-design="minecraft"] .path-row input:focus{border-color:#fff;box-shadow:none} +:root[data-design="minecraft"] input[type=checkbox],:root[data-design="minecraft"] input[type=radio],:root[data-design="minecraft"] input[type=range]{accent-color:#3c8527} + +/* Instanzliste auf dunkler Erde */ +:root[data-design="minecraft"] .workspace{background:var(--area)} +:root[data-design="minecraft"] .list-area{background:url(assets/design/erde-dunkel.png) 0 0/64px 64px;image-rendering:pixelated} +:root[data-design="minecraft"] .list-area::after, +:root[data-design="minecraft"] .list{image-rendering:auto} +:root[data-design="minecraft"] .group-header{font-family:var(--pixel);font-size:16px;font-weight:400;color:#fff;text-shadow:var(--mc-schatten);padding:8px 4px 4px} +:root[data-design="minecraft"] .group-count{color:#b8b9bc} +:root[data-design="minecraft"] .group-header .chev{color:#fff;font-family:"Segoe UI",sans-serif;font-size:10px} +:root[data-design="minecraft"] .group-header::after{height:2px;background:rgba(0,0,0,.55);box-shadow:0 1px 0 rgba(255,255,255,.08)} +:root[data-design="minecraft"] .card{border-radius:0} +:root[data-design="minecraft"] .card-name{color:#fff;text-shadow:1px 1px 0 #1a1a1a} +:root[data-design="minecraft"] .card:hover{background:rgba(0,0,0,.35);border-color:rgba(255,255,255,.35)} +:root[data-design="minecraft"] .card.sel{background:rgba(0,0,0,.6);border-color:#fff;outline:1px solid #fff;outline-offset:-2px} +:root[data-design="minecraft"] .card.sel .card-name{background:none;color:#ffff7f;border-radius:0} +:root[data-design="minecraft"] .card-taste{border-radius:0;background:#3c8527;box-shadow:inset -1px -1px 0 #1d4d13} +:root[data-design="minecraft"] .card-icon-img{border-radius:0} +:root[data-design="minecraft"] .empty h2{font-family:var(--pixel);font-weight:400;font-size:24px;color:#fff;text-shadow:3px 3px 0 #3f3f3f} +:root[data-design="minecraft"] .empty p{color:#d0d0d0} + +/* Seitenleiste: Knöpfe gestapelt wie im Pausenmenü */ +:root[data-design="minecraft"] .side{background:url(assets/design/schiefer.png) 0 0/64px 64px;image-rendering:pixelated;border-left:2px solid #000;padding:10px 6px} +:root[data-design="minecraft"] .side>*{image-rendering:auto} +:root[data-design="minecraft"] .side-title{font-family:var(--pixel);font-size:16px;font-weight:400;text-shadow:var(--mc-schatten)} +:root[data-design="minecraft"] .side-grp{color:#86d75e} +:root[data-design="minecraft"] .side-ico img{border-radius:0} +:root[data-design="minecraft"] .side-empty{color:#d0d0d0} +:root[data-design="minecraft"] .hr{background:#000;height:2px;margin:6px 0} +:root[data-design="minecraft"] .sbtn{margin-bottom:3px;padding:5px 2px} +:root[data-design="minecraft"] .sbtn.play{font-family:var(--pixel);font-size:16px;font-weight:400;padding:6px 4px 7px;text-shadow:var(--mc-schatten)} + +/* Statusleiste */ +:root[data-design="minecraft"] .statusbar{background:url(assets/design/schiefer.png) 0 0/64px 64px;image-rendering:pixelated;border-top:2px solid #000} +:root[data-design="minecraft"] .st-row{color:#e6e6e6;text-shadow:1px 1px 0 #1a1a1a} +:root[data-design="minecraft"] .st-row2{background:rgba(0,0,0,.4);border-top:2px solid #000} + +/* Dialoge: dunkles Steinfenster mit Holzbalken als Kopf */ +:root[data-design="minecraft"] .modal{background:rgba(0,0,0,.62)} +:root[data-design="minecraft"] .modal-card{background:#313233;border:2px solid #000;border-radius:0;box-shadow:inset 2px 2px 0 #5a5b5d,inset -2px -2px 0 #1e1e1f,0 10px 30px rgba(0,0,0,.6)} +:root[data-design="minecraft"] .modal-head{background:url(assets/design/bretter.png) 0 0/64px 64px;image-rendering:pixelated;border-bottom:2px solid #000;margin:2px 2px 0} +:root[data-design="minecraft"] .modal-head h3{font-family:var(--pixel);font-size:16px;font-weight:400;color:#fff;text-shadow:var(--mc-schatten)} +:root[data-design="minecraft"] .modal-head>*{image-rendering:auto} +:root[data-design="minecraft"] .modal-body{background:#313233;margin:0 2px} +:root[data-design="minecraft"] .modal-foot{background:#262627;border-top:2px solid #000;margin:0 2px 2px} +:root[data-design="minecraft"] .modal-close{color:#fff;text-shadow:1px 1px 0 #3f3f3f;font-size:16px} +:root[data-design="minecraft"] .modal-close:hover{color:#ffff7f} +:root[data-design="minecraft"] .popout-host .modal-card{box-shadow:inset 2px 2px 0 #5a5b5d,inset -2px -2px 0 #1e1e1f} + +/* Listen, Kacheln, Tabs */ +:root[data-design="minecraft"] .mods-list, +:root[data-design="minecraft"] .account-item, +:root[data-design="minecraft"] .screen-thumb, +:root[data-design="minecraft"] .chat-verlauf, +:root[data-design="minecraft"] .console-out{background:#000;border:2px solid #000;border-radius:0;box-shadow:inset 1px 1px 0 #3a3a3c} +:root[data-design="minecraft"] .account-item{background:#1e1e1f} +:root[data-design="minecraft"] .account-item.active{border-color:#6cc349} +:root[data-design="minecraft"] .mod-icon, +:root[data-design="minecraft"] .account-av, +:root[data-design="minecraft"] .icon-preview{background:#48494a;border-radius:0} +:root[data-design="minecraft"] .mod-item{border-radius:0} +:root[data-design="minecraft"] .mod-item+.mod-item{border-color:#2a2a2b} +:root[data-design="minecraft"] .mod-item:hover{background:#262627;outline:1px solid #8b8b8b;outline-offset:-1px} +:root[data-design="minecraft"] .mods-tabs{border-bottom:2px solid #000} +:root[data-design="minecraft"] .mtab{border-radius:0;color:#c8c8c8;margin-bottom:-2px;border-width:2px} +:root[data-design="minecraft"] .mtab.on{background:#48494a;border-color:#000;color:#fff;text-shadow:1px 1px 0 #2a2a2a} +:root[data-design="minecraft"] .advanced, +:root[data-design="minecraft"] .stat-tile, +:root[data-design="minecraft"] .crash-fund, +:root[data-design="minecraft"] .share-code-box, +:root[data-design="minecraft"] .share-preview, +:root[data-design="minecraft"] .clip-bar, +:root[data-design="minecraft"] .crash-unklar{background:#262627;border:2px solid #000;border-radius:0;box-shadow:inset 1px 1px 0 #48494a} +:root[data-design="minecraft"] .crash-fund{border-left:4px solid #3c8527} +:root[data-design="minecraft"] .badge{border-radius:0;background:#48494a;color:#e6e6e6;border-color:#000} +:root[data-design="minecraft"] .chat-blase{border-radius:0;background:#48494a;border:2px solid #000} +:root[data-design="minecraft"] .chat-blase.ich{background:#3c8527;border-color:#000} +:root[data-design="minecraft"] .stat-bar{border-radius:0;box-shadow:inset 0 -2px 0 #3c8527} +:root[data-design="minecraft"] .mod-new{border-radius:0} +:root[data-design="minecraft"] .friend-avatar{border-radius:0} + +/* Einstellungen */ +:root[data-design="minecraft"] .settings-body{background:url(assets/design/erde-dunkel.png) 0 0/64px 64px;image-rendering:pixelated} +:root[data-design="minecraft"] .settings-body>*{image-rendering:auto} +:root[data-design="minecraft"] .settings-nav{background:rgba(0,0,0,.45);border-right:2px solid #000;gap:4px} +:root[data-design="minecraft"] .settings-nav-label{color:#d0d0d0;text-shadow:1px 1px 0 #1a1a1a} +:root[data-design="minecraft"] .snav{padding:8px 12px} +:root[data-design="minecraft"] .settings-hero h4{font-family:var(--pixel);font-size:24px;font-weight:400;text-shadow:3px 3px 0 #3f3f3f} +:root[data-design="minecraft"] .settings-hero p{color:#d0d0d0} +:root[data-design="minecraft"] .settings-card{background:#313233;border:2px solid #000;border-radius:0;box-shadow:inset 2px 2px 0 #5a5b5d,inset -2px -2px 0 #1e1e1f} +:root[data-design="minecraft"] .settings-card h5{font-family:var(--pixel);font-size:16px;font-weight:400;text-shadow:var(--mc-schatten)} +:root[data-design="minecraft"] .settings-kv-row, +:root[data-design="minecraft"] .about-brand{border-bottom-color:#1a1a1b} +:root[data-design="minecraft"] .appinfo-item{background:#262627;border:2px solid #000;border-radius:0} +:root[data-design="minecraft"] .info-meta-link{color:#86d75e} +:root[data-design="minecraft"] .spane h4{font-family:var(--pixel);font-size:16px;font-weight:400;text-shadow:var(--mc-schatten)} + +/* Kontextmenü, Hinweis, Bildlaufleisten */ +:root[data-design="minecraft"] .ctx{background:#1e1e1f;border:2px solid #000;border-radius:0;box-shadow:inset 1px 1px 0 #48494a,0 8px 24px rgba(0,0,0,.5)} +:root[data-design="minecraft"] .ctx-item{border-radius:0;text-shadow:1px 1px 0 #000} +:root[data-design="minecraft"] .ctx-item:hover{background:#3c8527} +:root[data-design="minecraft"] .ctx-danger:hover{background:#8c2b2b} +:root[data-design="minecraft"] .ctx-sep{background:#000;height:2px} +:root[data-design="minecraft"] .toast{background:#212122;border:2px solid #000;border-radius:0;box-shadow:inset 2px 2px 0 #4a4a4c,inset -2px -2px 0 #111,0 6px 20px rgba(0,0,0,.5);text-shadow:1px 1px 0 #000} +:root[data-design="minecraft"] .toast.err{background:#5c1a1a} +:root[data-design="minecraft"] ::-webkit-scrollbar-thumb{background:#8b8b8b;border:3px solid var(--area);border-radius:0;box-shadow:inset -2px -2px 0 #555} +:root[data-design="minecraft"] ::-webkit-scrollbar-thumb:hover{background:#a8a8a8} + +/* Skin-Editor */ +:root[data-design="minecraft"] .se-modus{border:2px solid #000;border-radius:0;background:#2b2b2c} +:root[data-design="minecraft"] .se-modus-btn{color:#d0d0d0;text-shadow:1px 1px 0 #000} +:root[data-design="minecraft"] .se-modus-btn+.se-modus-btn{border-left:2px solid #000} +:root[data-design="minecraft"] .se-modus-btn.on{background:#3c8527;color:#fff;box-shadow:inset 2px 2px 0 #6cc349,inset -2px -2px 0 #1d4d13} +:root[data-design="minecraft"] .se-ebenen{border:2px solid #000;border-radius:0} +:root[data-design="minecraft"] .se-ebene{background:#2b2b2c;color:#d0d0d0} +:root[data-design="minecraft"] .se-ebene+.se-ebene{border-left:2px solid #000} +:root[data-design="minecraft"] .se-ebene.on{background:#3c8527;color:#fff} +:root[data-design="minecraft"] .se-buehne,:root[data-design="minecraft"] .se-mini{border:2px solid #000;border-radius:0;background:#1e1e1f} +:root[data-design="minecraft"] .se-farbfeld{border-radius:0;border-color:#000} +:root[data-design="minecraft"] .se-titel{color:#d0d0d0} +:root[data-design="minecraft"] .design-wahl{border-radius:0;border:2px solid #000;background:#262627} +:root[data-design="minecraft"] .design-wahl.on{border-color:#fff;box-shadow:none;background:#2f6b1f} +:root[data-design="minecraft"] .dv{border-radius:0} diff --git a/src/index.html b/src/index.html index 2670726..a3208fe 100644 --- a/src/index.html +++ b/src/index.html @@ -6,8 +6,15 @@ content="default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self'; img-src 'self' data: https:; connect-src 'self';" /> AeroMC + + +
+ + AeroMC +
+
@@ -250,14 +257,7 @@
-
Oberfläche
- +
Instanzliste
+ Ein Klick zeigt das Design sofort an – mit „Speichern“ gilt es in allen Fenstern. + +
Icons
+