From 419d200bf9440e3a5222a01c943f9f4f49ed4121 Mon Sep 17 00:00:00 2001 From: guyg1474 <340572510+guyg1474@users.noreply.github.com> Date: Thu, 15 Oct 2026 18:28:58 +0200 Subject: [PATCH] =?UTF-8?q?CSS=20nach=20Bereichen=20aufgeteilt,=20doppelte?= =?UTF-8?q?=20Regeln=20zusammengef=C3=BChrt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - styles.css (1757 Zeilen) und themes.css → frontend/src/styles/: base, layout, components, start, projekte (inkl. Artikel), monitoring, haushalt, reisen, kanban, konto, grundschicht, responsive und designs/ (gemeinsam, blackwall, fabrik); index.css legt die Reihenfolge fest - Die spätere "Moderne Grundschicht" ist in die Regeln der Bereiche eingearbeitet (z. B. .segmented, .household-item, .tile, .board-column stehen jeweils nur noch an einer Stelle); übrig bleiben nur bereichsübergreifende Regeln (einheitliche Eingabefelder, Hover, Bewegung) - .link-picker (Auswahllisten in Dialogen) zu den allgemeinen Bausteinen - Optisch unverändert: 54 Seiten-Screenshots (9 Seiten × 3 Designs × Desktop/Handy) und 18 Dialog-/Zustandsbilder pixelgleich zum Stand davor Co-Authored-By: Claude Opus 5.5 --- README.md | 8 +- docs/BRIEF.md | 2 +- frontend/src/main.jsx | 3 +- frontend/src/styles.css | 1757 ----------------- frontend/src/styles/base.css | 189 ++ frontend/src/styles/components.css | 190 ++ frontend/src/styles/designs/blackwall.css | 325 +++ .../{themes.css => styles/designs/fabrik.css} | 375 ---- frontend/src/styles/designs/gemeinsam.css | 46 + frontend/src/styles/grundschicht.css | 50 + frontend/src/styles/haushalt.css | 282 +++ frontend/src/styles/index.css | 17 + frontend/src/styles/kanban.css | 203 ++ frontend/src/styles/konto.css | 27 + frontend/src/styles/layout.css | 116 ++ frontend/src/styles/monitoring.css | 124 ++ frontend/src/styles/projekte.css | 198 ++ frontend/src/styles/reisen.css | 198 ++ frontend/src/styles/responsive.css | 21 + frontend/src/styles/start.css | 102 + 20 files changed, 2096 insertions(+), 2137 deletions(-) delete mode 100644 frontend/src/styles.css create mode 100644 frontend/src/styles/base.css create mode 100644 frontend/src/styles/components.css create mode 100644 frontend/src/styles/designs/blackwall.css rename frontend/src/{themes.css => styles/designs/fabrik.css} (53%) create mode 100644 frontend/src/styles/designs/gemeinsam.css create mode 100644 frontend/src/styles/grundschicht.css create mode 100644 frontend/src/styles/haushalt.css create mode 100644 frontend/src/styles/index.css create mode 100644 frontend/src/styles/kanban.css create mode 100644 frontend/src/styles/konto.css create mode 100644 frontend/src/styles/layout.css create mode 100644 frontend/src/styles/monitoring.css create mode 100644 frontend/src/styles/projekte.css create mode 100644 frontend/src/styles/reisen.css create mode 100644 frontend/src/styles/responsive.css create mode 100644 frontend/src/styles/start.css diff --git a/README.md b/README.md index 6545e8a..d3c708b 100644 --- a/README.md +++ b/README.md @@ -250,8 +250,12 @@ frontend/ src/main.jsx Routen src/api.js API-Aufrufe, Bild-Upload src/auth.jsx Anmeldestatus - src/styles.css Grund-Styling und Matrix-Design (responsiv, volle Breite) - src/themes.css Blackwall und Fabrik (überschreiben styles.css) + src/styles/index.css Bindet alle Styles in fester Reihenfolge ein (Kommentar dort beachten) + src/styles/base.css Tokens (Farben, Schrift, Form) und Matrix als Standard-Design + src/styles/.css layout, components, start, projekte, monitoring, haushalt, reisen, kanban, konto + src/styles/grundschicht.css Bereichsübergreifend: einheitliche Eingabefelder, Hover, Bewegung (kommt nach den Bereichen) + src/styles/responsive.css Handy-Anpassungen, weniger Bewegung + src/styles/designs/ Blackwall und Fabrik (überschreiben vor allem Tokens) src/theme.js, motion.js Design-Auswahl, Animations-Schalter src/useLiveData.js Laden, regelmäßiges Nachladen und Speichern einer Seite (gemeinsamer Hook) src/storage.js Kleine Einstellungen pro Browser (localStorage) diff --git a/docs/BRIEF.md b/docs/BRIEF.md index fdfaf07..d65ec68 100644 --- a/docs/BRIEF.md +++ b/docs/BRIEF.md @@ -19,7 +19,7 @@ Darstellung: gleiche Seiten, gleiche Bedienung, gleiche Reihenfolge der Inhalte. ## Modernisierung (zweite Runde) Ziel: wie eine durchdachte Alltags-Oberfläche wirken statt wie eine Film-Requisite, das Vorbild -bleibt erkennbar. Umsetzung über ein gemeinsames Token-System in `styles.css` (Farbrollen, Radien, +bleibt erkennbar. Umsetzung über ein gemeinsames Token-System in `frontend/src/styles/base.css` (Farbrollen, Radien, Schatten, Fokusring, Schriftrollen für Text/Titel/Beschriftung, Bewegung); jedes Design setzt vor allem diese Werte. Ruhige Fließtext-Schriften, Display-Schrift nur für Seitentitel, weiche Fokusringe, Status als Pillen, Kacheln mit Icon-Feld, Hintergründe zur Mitte hin ausgeblendet, diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx index 8b1d28c..0262572 100644 --- a/frontend/src/main.jsx +++ b/frontend/src/main.jsx @@ -30,8 +30,7 @@ import NotFound from './pages/NotFound.jsx'; import Projects from './pages/Projects.jsx'; import Users from './pages/Users.jsx'; import './theme.js'; -import './styles.css'; -import './themes.css'; +import './styles/index.css'; // Artikelseite inkl. Editor erst bei Bedarf laden, damit die Startseite schnell bleibt const Project = lazy(() => import('./pages/Project.jsx')); diff --git a/frontend/src/styles.css b/frontend/src/styles.css deleted file mode 100644 index 0443961..0000000 --- a/frontend/src/styles.css +++ /dev/null @@ -1,1757 +0,0 @@ -/* ============================================================ - P42 Dashboard – Retro-Terminal in Rot ("Matrix in Rot") - Volle Breite, responsiv (Handy → Tablet → PC → Ultrawide) - ============================================================ */ - -/* Token-System: Farbrollen, Form, Bewegung, Schrift. Die Designs in themes.css setzen vor allem diese Werte. */ -:root { - /* Farbrollen (für Glow & Transparenzen: --accent-rgb; der Matrix-Regen liest sie mit) */ - --accent-rgb: 255 70 70; - --bg: #080203; - --surface: rgb(20 6 7 / 0.84); - --surface-hover: rgb(34 9 10 / 0.92); - --surface-2: #180607; - --border: rgb(var(--accent-rgb) / 0.22); /* feine Linie */ - --line-strong: rgb(var(--accent-rgb) / 0.55); /* betonte Linie */ - --accent: rgb(var(--accent-rgb)); - --accent-ink: #140203; /* Schrift auf Akzentgrund */ - --accent-soft: rgb(var(--accent-rgb) / 0.13); - --text: #f1c3c3; - --read: #f6d8d8; /* langer Fließtext */ - --bright: #fff1f1; - --muted: #d08e8e; /* getönt, nicht grau */ - --ok: #fff1f1; - --warn: #ffa66e; - --bad: #ff3d3d; - --bad-glow: rgb(255 61 61 / 0.6); - /* Diagramm-Reihen (geprüft auf Farbenblindheit vor --surface): 1 = Akzent, 2 = Gegenfarbe */ - --series-1: #ff4646; - --series-2: #9b7fe0; - --topbar-bg: rgb(8 2 3 / 0.76); - --glow: 0 0 6px rgb(var(--accent-rgb) / 0.55), 0 0 20px rgb(var(--accent-rgb) / 0.2); - --heading-glow: 0 0 6px rgb(var(--accent-rgb) / 0.55), 0 0 26px rgb(var(--accent-rgb) / 0.25); - --text-glow: none; - - /* Flächen, die Designs überschreiben können */ - --input-bg: rgb(4 1 1 / 0.85); - --card-inner: rgb(12 3 4 / 0.9); - --panel: rgb(12 3 4 / 0.96); - --overlay: rgb(6 1 2 / 0.86); - --backdrop: rgb(0 0 0 / 0.72); - --editor-bg: rgb(4 1 1 / 0.9); - --map-ocean: #050102; - --map-land: #1a0506; - --map-land-hover: #3a0b0c; - /* Reise-Karte: Punkte anderer Konten, je Person eine Farbe (deutlich anders als die eigenen Punkte) */ - --other-1: #9b7fe0; - --other-2: #4fd1a5; - --other-3: #ffd84a; - --other-4: #5fb4ff; - --other-5: #c6ff5c; - --other-6: #ff9f43; - - /* Form */ - --radius-s: 4px; - --radius-m: 8px; - --radius-l: 12px; - --radius-pill: 999px; - --shadow-1: inset 0 1px 0 rgb(255 255 255 / 0.035), 0 12px 32px -20px rgb(0 0 0 / 0.95); - --shadow-2: 0 32px 80px -24px rgb(0 0 0 / 0.95), 0 0 0 1px rgb(var(--accent-rgb) / 0.1); - --focus-ring: 0 0 0 3px rgb(var(--accent-rgb) / 0.3); - --blur: blur(14px) saturate(1.15); - --control-h: 40px; - - /* Bewegung (nur transform/opacity) */ - --ease-out: cubic-bezier(0.16, 1, 0.3, 1); - --dur: 0.2s; - --lift: -2px; - - /* Schrift: Text, Display (Marke/Seitentitel), Überschriften, Beschriftungen */ - --font: 'IBM Plex Mono', ui-monospace, 'Cascadia Mono', Menlo, monospace; - --font-display: 'VT323', 'IBM Plex Mono', monospace; - --font-heading: var(--font); - --font-label: var(--font); - --body-size: clamp(14.5px, 0.86rem + 0.15vw, 15.5px); - --h1-font: var(--font-display); - --h1-size: clamp(2.4rem, 3.8vw, 3.6rem); - --h1-weight: 400; - --h1-tracking: 0.04em; - --h2-size: 1.05rem; - --h3-size: 1rem; - --heading-weight: 600; - --heading-tracking: 0.05em; - --heading-case: uppercase; - --label-size: 0.72rem; - --label-tracking: 0.12em; - --tile-font: var(--font-display); - --tile-size: 1.55rem; - - --gutter: clamp(16px, 3vw, 56px); - --topbar-h: 64px; - color-scheme: dark; -} - -* { box-sizing: border-box; } - -html { background: var(--bg); -webkit-text-size-adjust: 100%; } - -body { - margin: 0; - background: transparent; - color: var(--text); - font-family: var(--font); - font-size: var(--body-size); - line-height: 1.6; - text-shadow: var(--text-glow); - caret-color: var(--accent); - -webkit-font-smoothing: antialiased; - text-rendering: optimizeLegibility; -} -p { text-wrap: pretty; } - -/* Röhrenmonitor: Scanlines + abgedunkelte Ränder */ -body::after { - content: ''; - position: fixed; - inset: 0; - z-index: 100; - pointer-events: none; - background: - repeating-linear-gradient(to bottom, transparent 0 2px, rgb(0 0 0 / 0.07) 2px 3px), - radial-gradient(ellipse at center, transparent 62%, rgb(0 0 0 / 0.32) 100%); -} - -.matrix-rain { - position: fixed; - inset: 0; - z-index: -1; - width: 100%; - height: 100%; - opacity: 0.2; - pointer-events: none; - /* In der Mitte, wo der Inhalt steht, fast unsichtbar; an den Rändern deutlich */ - mask-image: radial-gradient(ellipse 70% 75% at 50% 45%, rgb(0 0 0 / 0.18) 0 45%, #000 100%); -} -.calm .matrix-rain { display: none; } - -::selection { background: var(--accent); color: var(--accent-ink); text-shadow: none; } - -* { scrollbar-color: var(--line-strong) transparent; scrollbar-width: thin; } - -#root { min-height: 100vh; display: flex; flex-direction: column; } - -a { color: var(--bright); text-decoration-style: dotted; text-underline-offset: 3px; } -a:hover { color: var(--accent); } -img { max-width: 100%; } -strong, b { color: var(--bright); } -code { font-family: var(--font); color: var(--bright); } - -/* Überschriften: Seitentitel in der Display-Schrift, alles darunter ruhig und klar */ -h1, h2, h3 { - font-family: var(--font-heading); - font-weight: var(--heading-weight); - text-transform: var(--heading-case); - letter-spacing: var(--heading-tracking); - color: var(--bright); - text-wrap: balance; -} -h1 { - font-family: var(--h1-font); - font-weight: var(--h1-weight); - font-size: var(--h1-size); - letter-spacing: var(--h1-tracking); - line-height: 1.02; - margin: 0 0 6px; - text-shadow: var(--heading-glow); -} -h2 { font-size: var(--h2-size); line-height: 1.25; } -h3 { font-size: var(--h3-size); line-height: 1.3; } -/* Kleine Beschriftungen (Eyebrows): weit gesperrt, klein */ -.eyebrow, .fact dt, .aside-facts dt, .monitor-facts dt, .info-facts dt, .form label, .menu-label { - font-family: var(--font-label); -} - -/* Blinkender Cursor hinter Seitenüberschriften */ -.page-head h1::after, .hero h1::after { - content: '_'; - margin-left: 0.1em; - animation: blink 1.1s steps(1) infinite; -} -@keyframes blink { 50% { opacity: 0; } } - -.lead { color: var(--muted); margin: 0 0 28px; } -.lead::before { content: '// '; } -.hint { color: var(--muted); font-size: 0.88rem; margin: 12px 0 0; } -.error { color: var(--bad); margin: 0; text-shadow: 0 0 4px var(--bad-glow); } -.error::before { content: '! '; font-weight: 700; } -.success { color: var(--ok); margin: 0; } -.success::before { content: '✓ '; } -.center { text-align: center; } - -/* ---------- Kopfzeile + Menü ---------- */ -.topbar { - position: sticky; - top: 0; - z-index: 20; - height: var(--topbar-h); - display: flex; - align-items: center; - justify-content: space-between; - gap: 16px; - padding: 0 var(--gutter); - border-bottom: 1px solid var(--border); - background: var(--topbar-bg); - backdrop-filter: var(--blur); - -webkit-backdrop-filter: var(--blur); -} -.brand { - font-family: var(--font-display); - font-size: 1.85rem; - letter-spacing: 0.06em; - text-transform: uppercase; - color: var(--bright); - text-decoration: none; - text-shadow: var(--heading-glow); - white-space: nowrap; -} -.brand::before { content: '>_ '; color: var(--accent); } -.brand span { color: var(--accent); } - -.menu { position: relative; } -.menu-btn { - display: grid; - place-items: center; - width: var(--control-h); - height: var(--control-h); - border: 1px solid var(--line-strong); - border-radius: var(--radius-s); - background: transparent; - color: var(--accent); - cursor: pointer; -} -.menu-btn:hover, .menu-btn[aria-expanded='true'] { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); } -.menu-btn svg { width: 22px; height: 22px; } -.menu-panel { - position: absolute; - right: 0; - top: calc(100% + 10px); - min-width: 260px; - display: flex; - flex-direction: column; - padding: 6px; - background: var(--panel); - border: 1px solid var(--border); - border-radius: var(--radius-m); - box-shadow: var(--shadow-2); - backdrop-filter: var(--blur); - -webkit-backdrop-filter: var(--blur); -} -.menu-panel a, .menu-item { - font: inherit; - text-align: left; - padding: 9px 12px; - border: 0; - border-radius: var(--radius-s); - background: none; - color: var(--text); - text-decoration: none; - text-transform: uppercase; - letter-spacing: 0.06em; - font-size: 0.88rem; - cursor: pointer; - text-shadow: inherit; -} -.menu-panel a::before, .menu-item::before { content: ' '; white-space: pre; } -.menu-panel a:hover, .menu-item:hover { background: var(--accent-soft); color: var(--bright); } -.menu-panel a:hover::before, .menu-item:hover::before { content: '> '; } -.menu-panel a.active { background: var(--accent); color: var(--accent-ink); text-shadow: none; } -.menu-panel a.active::before { content: '> '; } -.menu-panel hr { border: 0; border-top: 1px solid var(--border); margin: 6px 4px; } -.menu-user { padding: 6px 12px 4px; font-size: 0.78rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; } - -/* Hauptnavigation in der Kopfzeile (ab Tablet), darunter im Menü */ -.topnav { display: flex; gap: 4px; margin-left: auto; } -.topnav a { - padding: 8px 14px; - color: var(--muted); - text-decoration: none; - text-transform: uppercase; - letter-spacing: 0.08em; - font-size: 0.82rem; - border: 1px solid transparent; - border-radius: var(--radius-s); -} -.topnav a:hover { color: var(--bright); background: var(--accent-soft); } -.topnav a.active { color: var(--bright); border-color: var(--line-strong); background: var(--accent-soft); } -.topnav a.active::before { content: '> '; color: var(--accent); } -.menu-primary { display: none; flex-direction: column; } -@media (max-width: 999px) { - .topnav { display: none; } - .menu-primary { display: flex; } -} - -/* ---------- Seitenrahmen: volle Breite ---------- */ -.page { flex: 1; width: 100%; padding: clamp(24px, 4vw, 48px) var(--gutter) 64px; } -.footer { text-align: center; color: var(--muted); font-size: 0.75rem; padding: 24px 20px; letter-spacing: 0.14em; text-transform: uppercase; } - -.page-head { - display: flex; - justify-content: space-between; - align-items: flex-end; - gap: 16px 24px; - flex-wrap: wrap; - margin-bottom: 20px; -} -.page-head .lead { margin-bottom: 0; } -.page-actions { display: flex; gap: 8px; flex-wrap: wrap; } - -/* ---------- Bausteine ---------- */ -.card { - background: var(--surface); - border: 1px solid var(--border); - border-radius: var(--radius-m); - box-shadow: var(--shadow-1); - padding: clamp(16px, 1.6vw, 22px); -} - -.btn { - display: inline-flex; - align-items: center; - justify-content: center; - gap: 8px; - min-height: var(--control-h); - font: inherit; - font-family: var(--font-label); - font-size: 0.82rem; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.08em; - padding: 0 20px; - border: 1px solid var(--accent); - border-radius: var(--radius-s); - background: var(--accent); - color: var(--accent-ink); - text-shadow: none; - cursor: pointer; - white-space: nowrap; - transition: transform var(--dur) var(--ease-out); -} -.btn:hover:not(:disabled) { background: var(--bright); border-color: var(--bright); transform: translateY(-1px); } -.btn:active:not(:disabled) { transform: translateY(0); } -.btn:disabled { opacity: 0.5; cursor: wait; } -.btn.ghost { background: transparent; color: var(--accent); border-color: var(--line-strong); } -.btn.ghost:hover:not(:disabled) { background: var(--accent-soft); border-color: var(--accent); color: var(--bright); } -.btn.ghost.danger-btn { color: var(--bad); border-color: rgb(255 61 61 / 0.5); } -.btn.ghost.danger-btn:hover:not(:disabled) { background: var(--bad); border-color: var(--bad); color: var(--accent-ink); } -.btn.small { min-height: 30px; padding: 0 12px; font-size: 0.74rem; } -.btn.full { width: 100%; } -:focus-visible { - outline: 2px solid var(--bright); - outline-offset: 2px; -} - -.link-btn { - font: inherit; - font-size: 0.82rem; - border: 0; - background: none; - padding: 0; - color: var(--muted); - text-transform: uppercase; - letter-spacing: 0.06em; - cursor: pointer; - text-shadow: inherit; -} -.link-btn:hover { color: var(--bright); } -.link-btn.danger:hover { color: var(--bad); } - -/* Status-Chips: getönte Pillen; "bad" gefüllt, damit es sofort auffällt */ -.badge { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 2px 10px; - border-radius: var(--radius-pill); - font-family: var(--font-label); - font-size: 0.72rem; - font-weight: 600; - line-height: 1.5; - text-transform: uppercase; - letter-spacing: 0.08em; - white-space: nowrap; - color: var(--accent); - background: color-mix(in oklab, currentColor 13%, transparent); - box-shadow: inset 0 0 0 1px color-mix(in oklab, currentColor 32%, transparent); - text-shadow: none; -} -.badge::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; } -.badge.ok { color: var(--ok); } -.badge.warn { color: var(--warn); } -.badge.bad { color: var(--accent-ink); background: var(--bad); box-shadow: none; } -.badge.muted { color: var(--muted); } -.badge.muted::before { opacity: 0.5; } - -.chip { - font: inherit; - font-size: 0.78rem; - padding: 4px 12px; - border: 1px solid var(--border); - border-radius: var(--radius-pill); - background: var(--card-inner); - color: var(--text); - cursor: pointer; - text-shadow: inherit; - text-decoration: none; -} -.chip:hover { color: var(--bright); border-color: var(--line-strong); background: var(--accent-soft); } - -.notice { border: 1px solid var(--border); border-left: 3px solid var(--accent); border-radius: var(--radius-m); padding: 14px 18px; color: var(--text); margin-bottom: 24px; background: var(--surface); } -.notice::before { content: '# '; color: var(--accent); } - -.meta { display: flex; gap: 8px; align-items: center; margin-top: 14px; font-size: 0.8rem; color: var(--muted); } -.dot { width: 10px; height: 10px; border-radius: 50%; background: var(--muted); display: inline-block; flex: none; } -.dot.ok { background: var(--ok); box-shadow: 0 0 6px var(--ok); } -.dot.warn { background: var(--warn); box-shadow: 0 0 6px var(--warn); } -.dot.bad { background: var(--bad); box-shadow: 0 0 6px var(--bad); animation: blink 1.1s steps(1) infinite; } - -.grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); - gap: clamp(14px, 1.5vw, 24px); -} -.grid h3 { margin: 0; } - -/* ---------- Formulare & Dialoge ---------- */ -.form { display: flex; flex-direction: column; gap: 14px; } -.form h2 { margin: 0 0 4px; } -.form label { - display: flex; - flex-direction: column; - gap: 6px; - font-size: var(--label-size); - font-weight: 600; - color: var(--muted); - text-transform: uppercase; - letter-spacing: var(--label-tracking); -} -.form label small { font-weight: 400; color: var(--muted); text-transform: none; letter-spacing: 0; } -.form label.checkbox { flex-direction: row; align-items: center; gap: 10px; } -.form label.checkbox input { width: 18px; height: 18px; accent-color: var(--accent); } - -.form input:not([type='checkbox']), .form select, .aside-card select, .title-input, .lead-input, .track-form input { - font: inherit; - font-weight: 400; - text-transform: none; - letter-spacing: normal; - color: var(--bright); - background: var(--input-bg); - border: 1px solid var(--border); - border-radius: 0; - padding: 10px 12px; - width: 100%; - text-shadow: none; -} -.form input:focus, .form select:focus, .aside-card select:focus, .title-input:focus, .lead-input:focus, .track-form input:focus { - outline: none; - border-color: var(--accent); - box-shadow: var(--glow); -} -::placeholder { color: var(--muted); opacity: 0.8; } -.form-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; } - -.modal { - width: min(520px, calc(100% - 32px)); - border: 1px solid var(--line-strong); - border-radius: var(--radius-l); - background: var(--panel); - color: var(--text); - padding: clamp(20px, 3vw, 28px); - box-shadow: var(--shadow-2); -} -.modal::backdrop, .lightbox::backdrop { background: var(--backdrop); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); } - -.lightbox { border: 1px solid var(--accent); padding: 0; background: var(--input-bg); max-width: 96vw; max-height: 96vh; cursor: zoom-out; } -.lightbox img { display: block; max-width: 96vw; max-height: 96vh; object-fit: contain; } - -/* ---------- Anmeldung ---------- */ -.auth-page { min-height: 100vh; display: grid; place-items: center; padding: 24px var(--gutter); } -.auth-card { - width: min(440px, 100%); - padding: clamp(22px, 4vw, 34px); - display: flex; - flex-direction: column; - gap: 14px; - border-color: var(--line-strong); - border-radius: var(--radius-l); - box-shadow: var(--shadow-2); - backdrop-filter: var(--blur); - -webkit-backdrop-filter: var(--blur); -} -.auth-brand { margin-bottom: 4px; } - -/* ---------- Startseite: Sendungsverfolgung ---------- */ -.hero { text-align: center; } - -.track-form { display: flex; gap: 8px; max-width: 820px; margin: 0 auto; } -.prompt-input { flex: 1; min-width: 0; position: relative; } -.prompt-input::before { - content: '>'; - position: absolute; - left: 16px; - top: 50%; - transform: translateY(-50%); - color: var(--accent); - font-size: 1.15rem; - pointer-events: none; -} -.track-form input { font-size: 1.1rem; padding: 14px 18px 14px 38px; border-color: var(--accent); } -.track-form .btn { padding: 14px 26px; } - -.recent { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin-top: 12px; } - -.result { margin: 24px auto 0; max-width: 1280px; text-align: left; } -.result .card { border-color: var(--accent); } -.result-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; flex-wrap: wrap; } -.carrier { font-family: var(--h1-font); font-size: calc(var(--h1-size) * 0.6); line-height: 1.05; text-transform: uppercase; color: var(--bright); text-shadow: var(--heading-glow); } -.number { color: var(--muted); font-size: 0.88rem; word-break: break-all; } - -.tracking-result { display: grid; gap: 24px; } -@media (min-width: 900px) { - .tracking-result { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); gap: 36px; } - .tracking-events { border-left: 1px dashed var(--border); padding-left: 32px; } -} - -.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; margin: 18px 0 4px; } -.fact { border: 1px solid var(--border); border-radius: var(--radius-s); padding: 10px 14px; background: var(--card-inner); } -.fact dt, .aside-facts dt, .monitor-facts dt { - font-size: var(--label-size); - color: var(--muted); - text-transform: uppercase; - letter-spacing: var(--label-tracking); -} -.fact dd { margin: 2px 0 0; font-weight: 600; color: var(--bright); } - -.timeline { list-style: none; margin: 0; padding: 0; } -.timeline li { position: relative; padding: 0 0 16px 22px; border-left: 1px dashed var(--border); margin-left: 5px; } -.timeline li:last-child { border-left-color: transparent; padding-bottom: 0; } -.timeline li::before { - content: ''; - position: absolute; - left: -6px; - top: 5px; - width: 11px; - height: 11px; - background: var(--bg); - border: 1px solid var(--accent); -} -.timeline li:first-child::before { background: var(--accent); box-shadow: var(--glow); } -.timeline .when { font-size: 0.78rem; color: var(--muted); } -.timeline .what { color: var(--bright); } -.timeline .where { font-size: 0.82rem; color: var(--muted); } -.more { margin-top: 10px; } - -.links { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; } -.links a { font-size: 0.8rem; padding: 5px 12px; border: 1px solid var(--border); border-radius: var(--radius-pill); text-decoration: none; text-transform: uppercase; letter-spacing: 0.05em; } -.links a:hover { border-color: var(--accent); background: var(--accent); color: var(--accent-ink); text-shadow: none; } - -/* ---------- Startseite: Kacheln ---------- */ -.tiles-section { margin-top: clamp(40px, 6vw, 72px); } -.tiles-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 6px 12px; margin-bottom: 14px; } -.tiles-head .link-btn { white-space: nowrap; } -.section-title { margin: 0; white-space: nowrap; } -.section-title::before { content: '// '; color: var(--accent); } -/* Flex statt festem Raster: jede Zeile wird ganz gefüllt, egal wie viele Kacheln */ -.tiles { display: flex; flex-wrap: wrap; gap: clamp(14px, 1.5vw, 24px); } -.tiles > * { flex: 1 1 210px; min-width: 0; } -.tile { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 10px; - padding: clamp(18px, 2vw, 28px); - border: 1px solid var(--border); - background: var(--surface); - color: var(--text); - font: inherit; - text-align: left; - text-decoration: none; - text-shadow: inherit; - cursor: pointer; - transition: border-color 0.12s, box-shadow 0.12s, background 0.12s; -} -.tile:hover { border-color: var(--accent); box-shadow: var(--glow); background: var(--surface-hover); color: var(--text); } -.tile:hover strong { color: var(--bright); } -.tile svg { width: 34px; height: 34px; color: var(--accent); filter: drop-shadow(0 0 4px rgb(var(--accent-rgb) / 0.6)); } -.tile strong { font-family: var(--tile-font); font-size: var(--tile-size); font-weight: 400; line-height: 1.05; text-transform: uppercase; letter-spacing: 0.04em; } -.tile small { color: var(--muted); font-size: 0.8rem; } -.tile-empty { border-style: dashed; background: transparent; } -.tile-empty svg { color: var(--muted); filter: none; } -.tile-empty strong { color: var(--muted); } - - -/* ---------- Projektübersicht ---------- */ -.projects-grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr)); } -.project-card { - padding: 0; - overflow: hidden; - display: flex; - flex-direction: column; - color: var(--text); - text-decoration: none; - transition: border-color 0.12s, box-shadow 0.12s; -} -.project-card:hover { border-color: var(--accent); box-shadow: var(--glow); color: var(--text); } -.project-cover-wrap { position: relative; } -.project-cover-wrap .badge { position: absolute; left: 12px; top: 12px; background: var(--overlay); padding: 3px 8px; } -.project-cover-wrap .badge.ok { background: var(--accent); color: var(--accent-ink); text-shadow: none; } -.project-body h3 { overflow-wrap: anywhere; } -.project-cover { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border-bottom: 1px solid var(--border); filter: saturate(0.8) contrast(1.05); } -.project-card:hover .project-cover { filter: none; } -.project-cover.empty { - background: repeating-linear-gradient(45deg, transparent 0 10px, rgb(var(--accent-rgb) / 0.07) 10px 20px), var(--input-bg); -} -.project-body { padding: 16px 18px 18px; display: flex; flex-direction: column; flex: 1; } -.project-body .meta { margin-top: auto; padding-top: 14px; } -.project-meta { flex-direction: column; align-items: flex-start; gap: 2px; } -.project-title-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; } -.project-teaser { - display: -webkit-box; - -webkit-line-clamp: 3; - -webkit-box-orient: vertical; - overflow: hidden; - margin: 8px 0 0; - color: var(--muted); - font-size: 0.9rem; -} - -/* ---------- Monitoring ---------- */ -.monitor-summary { - display: flex; - align-items: center; - flex-wrap: wrap; - gap: 10px; - margin: 0 0 16px; - padding: 10px 14px; - border: 1px solid var(--border); - background: var(--surface); - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.08em; -} -.monitor-summary-time { margin-left: auto; font-weight: 400; color: var(--muted); font-size: 0.8rem; } -.monitor-card { display: flex; flex-direction: column; border-left: 4px solid var(--border); } -.monitor-card.ok { border-left-color: var(--ok); } -.monitor-card.bad { border-color: var(--bad); border-left-color: var(--bad); box-shadow: inset 4px 0 12px -6px var(--bad), 0 0 14px rgb(255 43 43 / 0.25); } -.monitor-card.ok h3 { color: var(--ok); } -.monitor-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; } -.monitor-target { margin: 6px 0 0; color: var(--muted); font-size: 0.85rem; word-break: break-all; } -.monitor-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 12px 16px; margin: 16px 0 0; padding-top: 14px; border-top: 1px dashed var(--border); } -.monitor-facts dd { margin: 2px 0 0; color: var(--bright); font-size: 0.88rem; } -.monitor-foot { justify-content: space-between; margin-top: auto; padding-top: 16px; flex-wrap: wrap; } -.monitor-actions { display: flex; gap: 14px; } - -/* Server-Auslastung (P42-S.M.): Karte → große Ansicht */ -.monitor-card.clickable { cursor: pointer; transition: transform var(--dur) var(--ease-out), border-color var(--dur); } -.monitor-card.clickable:hover { transform: translateY(var(--lift)); border-color: var(--line-strong); } -.monitor-card.clickable:focus-visible { outline: none; box-shadow: var(--focus-ring); } -.monitor-card.clickable .monitor-target { word-break: normal; overflow-wrap: anywhere; } -.agent-summary { display: grid; gap: 10px; margin-top: 14px; } -.agent-summary .monitor-facts { margin-top: 4px; } - -.meter { display: grid; gap: 4px; min-width: 0; } -.meter-label { display: flex; justify-content: space-between; gap: 8px; font-size: 0.82rem; color: var(--text); } -.meter-label span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } -.meter-label strong { color: var(--bright); font-weight: 600; white-space: nowrap; } -.meter small { color: var(--muted); font-size: 0.76rem; } -.meter-bar { display: block; height: 6px; border-radius: var(--radius-pill); background: var(--accent-soft); overflow: hidden; } -.meter-bar i { display: block; height: 100%; border-radius: inherit; background: var(--accent); transition: width 0.6s var(--ease-out); } -.meter.warn .meter-bar i, .server-tile.warn .meter-bar i { background: var(--warn); } -.meter.bad .meter-bar i, .server-tile.bad .meter-bar i { background: var(--bad); } -.meter.bad .meter-label strong { color: var(--bad); } -.meter.compact .meter-label { font-size: 0.74rem; } - -.server-modal { width: min(1280px, calc(100% - 24px)); max-height: calc(100vh - 24px); overflow-y: auto; padding: clamp(16px, 2.4vw, 30px); } -.server-detail { display: grid; gap: 18px; } -.server-detail-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; } -.server-detail-head h2 { margin: 0; } -.server-detail-sub { margin: 6px 0 0; color: var(--muted); font-size: 0.84rem; line-height: 1.6; } -.server-detail-actions { display: flex; align-items: center; gap: 10px; } -.server-detail-actions .btn { padding: 0 14px; } - -.server-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; } -.server-tile { display: grid; gap: 4px; align-content: start; padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius-m); background: var(--card-inner); } -.server-tile strong { font-family: var(--tile-font); font-size: var(--tile-size); font-weight: 400; color: var(--bright); line-height: 1.1; } -.server-tile small { color: var(--muted); font-size: 0.76rem; } -.server-tile .meter-bar { margin-top: 4px; } -.server-tile.bad strong { color: var(--bad); } -.sr-flag { font-family: var(--font-label); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.08em; } - -.server-range { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; } -.server-range .eyebrow { margin-right: 4px; } -.server-range .hint { margin: 0 0 0 auto; font-size: 0.8rem; } - -.server-charts { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; } -@media (min-width: 900px) { .server-charts { grid-template-columns: repeat(2, minmax(0, 1fr)); } } - -.chart { margin: 0; padding: 12px 14px 8px; border: 1px solid var(--border); border-radius: var(--radius-m); background: var(--card-inner); min-width: 0; transition: opacity var(--dur); } -.chart.is-loading { opacity: 0.6; } -.chart-head { display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap; gap: 6px 14px; margin-bottom: 6px; } -.chart-title { font-family: var(--font-label); font-size: var(--label-size); letter-spacing: var(--label-tracking); text-transform: uppercase; color: var(--text); } -.chart-legend { display: flex; gap: 14px; flex-wrap: wrap; font-size: 0.78rem; color: var(--text); } -.chart-key { display: inline-flex; align-items: center; gap: 6px; } -.chart-key i, .chart-tip-row i { width: 14px; height: 2px; border-radius: 1px; display: inline-block; flex: none; } -.chart-plot { position: relative; width: 100%; } -.chart-plot svg { display: block; touch-action: pan-y; outline: none; } -.chart-plot svg:focus-visible { box-shadow: var(--focus-ring); } -.chart-grid { stroke: var(--border); stroke-width: 1; shape-rendering: crispEdges; } -.chart-axis { fill: var(--muted); font-size: 10.5px; font-family: var(--font); } -.chart-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; } -.chart-dot { stroke: var(--card-inner); stroke-width: 2; } -.chart-cross { stroke: var(--line-strong); stroke-width: 1; } -.chart-empty { margin: 0; height: 190px; display: grid; place-items: center; color: var(--muted); font-size: 0.85rem; text-align: center; } -.chart-tip { - position: absolute; - top: 4px; - transform: translateX(-50%); - min-width: 160px; - padding: 8px 10px; - border: 1px solid var(--line-strong); - border-radius: var(--radius-s); - background: var(--panel); - box-shadow: var(--shadow-2); - pointer-events: none; - font-size: 0.78rem; - z-index: 2; -} -.chart-tip-time { color: var(--muted); margin-bottom: 4px; } -.chart-tip-row { display: flex; align-items: center; gap: 8px; } -.chart-tip-row strong { color: var(--bright); font-weight: 600; } -.chart-tip-row span { color: var(--muted); } - -.server-table summary, .server-sections details summary { cursor: pointer; } -.server-table summary { color: var(--muted); font-size: 0.85rem; } -.server-table-scroll { max-height: 320px; overflow: auto; margin-top: 8px; border: 1px solid var(--border); } -.server-table table { width: 100%; border-collapse: collapse; font-size: 0.78rem; white-space: nowrap; } -.server-table th, .server-table td { padding: 5px 10px; text-align: right; border-bottom: 1px solid var(--border); } -.server-table th:first-child, .server-table td:first-child { text-align: left; } -.server-table th { position: sticky; top: 0; background: var(--panel); color: var(--muted); font-weight: 600; } - -.server-sections { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; } -@media (min-width: 900px) { .server-sections { grid-template-columns: repeat(2, minmax(0, 1fr)); } } -.server-sections section { display: grid; gap: 10px; align-content: start; padding: 14px; border: 1px solid var(--border); border-radius: var(--radius-m); background: var(--card-inner); min-width: 0; } -.server-sections h3 { margin: 0; } -.server-sections .hint { margin: 0; font-size: 0.8rem; } -.server-cores { display: grid; grid-template-columns: repeat(auto-fill, minmax(90px, 1fr)); gap: 8px 12px; } -.server-list { display: grid; gap: 6px; margin: 0; } -.server-list div { display: flex; justify-content: space-between; gap: 12px; font-size: 0.84rem; border-bottom: 1px solid var(--border); padding-bottom: 5px; } -.server-list dt { color: var(--muted); overflow-wrap: anywhere; } -.server-list dd { margin: 0; color: var(--bright); text-align: right; } -.server-list small { color: var(--muted); } - -/* ---------- Vorrat & Einkauf ---------- */ -.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } - -.household-error { margin-bottom: 16px; } -.household { display: grid; gap: clamp(14px, 1.5vw, 24px); align-items: start; } -@media (min-width: 900px) { - .household { grid-template-columns: repeat(2, minmax(0, 1fr)); } -} - -/* Handy: Umschalter, nur die gewählte Liste zeigen */ -.segmented { display: none; margin-bottom: 14px; border: 1px solid var(--accent); } -@media (max-width: 899px) { - .segmented { display: flex; } - .household-panel[data-hidden] { display: none; } -} -.segmented button { - flex: 1; - font: inherit; - font-size: 0.88rem; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.08em; - padding: 11px 8px; - border: 0; - background: transparent; - color: var(--text); - cursor: pointer; -} -.segmented button[aria-selected='true'] { background: var(--accent); color: var(--accent-ink); } -.segmented .count { opacity: 0.75; } -.segmented .count::before { content: '['; } -.segmented .count::after { content: ']'; } - -.household-panel { display: flex; flex-direction: column; gap: 16px; } -.household-panel.einkauf { border-color: var(--accent); } -.shopping-lists { display: flex; flex-direction: column; gap: 8px; margin-bottom: 18px; } -.shopping-lists-label { color: var(--muted); font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.08em; margin-right: 2px; } -.shopping-lists .chip-list { align-items: center; } -.shopping-visibility { margin: 0; font-size: 0.8rem; } -.list-delete { margin-right: auto; } -.household-head { display: flex; align-items: baseline; justify-content: space-between; gap: 6px 12px; flex-wrap: wrap; } -.household-head h2 { margin: 0; } -.household-head h2::before { content: '// '; color: var(--accent); } -.household-head .hint { margin: 0; } -.household-empty { margin: 0; } - -.household-add { display: flex; gap: 8px; } -.household-add .combo { flex: 1; min-width: 0; } -.household-add input { - font: inherit; - color: var(--bright); - background: var(--input-bg); - border: 1px solid var(--border); - padding: 10px 12px; - width: 100%; -} -.household-add input:focus { outline: none; border-color: var(--accent); box-shadow: var(--glow); } -.household-add { flex-wrap: wrap; } -.household-add .household-qty-input { width: 4.5em; flex: none; text-align: center; } -.household-add-error { flex-basis: 100%; } -[aria-invalid='true'] { border-color: var(--bad) !important; box-shadow: 0 0 6px var(--bad-glow) !important; } - -/* Menge + Einheit als zusammenhängender Block */ -.qty-unit { display: flex; flex: none; } -.qty-unit > input { border-right: 0 !important; } -.unit-select { - font: inherit; - font-size: 0.85rem; - color: var(--bright); - background: var(--input-bg); - border: 1px solid var(--border); - padding: 0 6px; - min-height: 34px; - cursor: pointer; -} -.unit-select:focus { outline: none; border-color: var(--accent); box-shadow: var(--glow); } -.unit-select:disabled { opacity: 0.4; cursor: default; } -.household-item > .unit-select { flex: none; width: 4.4em; margin-left: -12px; border-left: 0; } - -/* Vorschlagsliste */ -.combo { position: relative; } -.combo-list { - position: absolute; - z-index: 12; - left: 0; - right: 0; - top: calc(100% + 4px); - margin: 0; - padding: 4px; - list-style: none; - background: var(--bg); - border: 1px solid var(--accent); - box-shadow: var(--glow); - max-height: 300px; - overflow-y: auto; -} -.combo-list li { - display: flex; - justify-content: space-between; - align-items: baseline; - gap: 12px; - padding: 8px 10px; - cursor: pointer; - color: var(--text); -} -.combo-list li::before { content: ' '; white-space: pre; } -.combo-list li > span { flex: 1; } -.combo-list li:hover, .combo-list li.active { background: var(--accent-soft); color: var(--bright); } -.combo-list li.active::before { content: '> '; color: var(--accent); } -.combo-list small { color: var(--muted); font-size: 0.75rem; white-space: nowrap; } - -.household-list { list-style: none; margin: 0; padding: 0; } -.household-item { - display: flex; - align-items: center; - gap: 12px; - padding: 10px 0; - border-top: 1px dashed var(--border); -} -.household-name { flex: 1; min-width: 0; display: flex; flex-direction: column; } -.household-name strong { overflow-wrap: anywhere; } -.household-name small { color: var(--muted); font-size: 0.75rem; } - -.household-check { - appearance: none; - flex: none; - width: 24px; - height: 24px; - margin: 0; - border: 1px solid var(--accent); - background: var(--input-bg); - cursor: pointer; - display: grid; - place-items: center; -} -.household-check::after { content: '✓'; color: var(--accent); opacity: 0; font-weight: 700; } -.household-check:hover::after { opacity: 0.6; } -.household-check:checked::after { opacity: 1; } - -/* Einkauf: abgehakt = im Wagen, unten in der Liste */ -.household-cart-head { - margin: 14px 0 4px; - font-size: var(--label-size); - letter-spacing: var(--label-tracking); - text-transform: uppercase; - color: var(--muted); -} -.household-item.checked .household-name strong { text-decoration: line-through; text-decoration-thickness: 2px; color: var(--muted); } -.household-item.checked .stepper, -.household-item.checked > .unit-select, -.household-item.checked .household-actions { opacity: 0.55; } -.household-finish { display: flex; align-items: center; justify-content: space-between; gap: 8px 12px; flex-wrap: wrap; padding-top: 12px; border-top: 1px solid var(--border); } -.household-finish .hint { margin: 0; } -/* Gleiten beim Abhaken/Einkauf beenden (nur während des Übergangs benannt, damit Designwechsel unberührt bleibt) */ -html.vt-items .household-item { view-transition-name: var(--vt); } -::view-transition-group(*) { animation-duration: 0.32s; animation-timing-function: var(--ease-out); } - -.stepper { display: flex; align-items: stretch; flex: none; border: 1px solid var(--border); } -.stepper button { - font: inherit; - width: 34px; - min-height: 34px; - border: 0; - background: transparent; - color: var(--accent); - font-size: 1.1rem; - cursor: pointer; -} -.stepper button:hover:not(:disabled) { background: var(--accent); color: var(--accent-ink); } -.stepper button:disabled { color: var(--border); cursor: default; } -.stepper-value { - width: 3.4em; - font: inherit; - font-weight: 600; - text-align: center; - color: var(--bright); - background: transparent; - border: 0; - border-inline: 1px solid var(--border); - padding: 0; -} -.stepper-value:focus { outline: none; background: var(--input-bg); box-shadow: inset 0 0 0 1px var(--accent); } - -.household-actions { display: flex; align-items: center; gap: 12px; flex: none; } -.household-actions .link-btn { display: inline-flex; align-items: center; gap: 6px; } -.household-actions .link-btn:disabled { opacity: 0.4; cursor: default; } -.household-actions svg { width: 18px; height: 18px; } - -.product-list { list-style: none; margin: 0; padding: 0; max-height: 50vh; overflow-y: auto; } -.product-list li { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 8px 0; border-top: 1px dashed var(--border); } - -@media (max-width: 520px) { - .household-add { flex-wrap: wrap; } - .household-add .combo { flex-basis: 100%; } - .household-add .qty-unit { flex: 1; } - .household-add .household-qty-input { flex: 1; } - .household-add .btn { flex: 1; } - .household-panel { padding: 16px 14px; } - .household-item { gap: 8px; } - .stepper button { width: 28px; } - .stepper-value { width: 2.8em; } - .household-item > .unit-select { width: 3.9em; font-size: 0.8rem; padding: 0 2px; } - .household-actions { gap: 10px; } - .household-actions .label { display: none; } -} - -/* Rezept abgleichen */ -.recipe { display: flex; flex-direction: column; gap: 16px; margin-bottom: clamp(14px, 1.5vw, 24px); } -.recipe .household-head h2 a { color: inherit; text-decoration: none; } -.recipe .household-head h2 a:hover { color: var(--accent); } -.recipe input:not([type='checkbox']), .recipe textarea { - font: inherit; - color: var(--bright); - background: var(--input-bg); - border: 1px solid var(--border); - padding: 10px 12px; - width: 100%; -} -.recipe input:focus, .recipe textarea:focus { outline: none; border-color: var(--accent); box-shadow: var(--glow); } -.recipe input:disabled { opacity: 0.4; } -.recipe textarea { resize: vertical; } -.recipe-load { display: flex; gap: 8px; align-items: flex-start; } -.recipe-load > :first-child { flex: 1; min-width: 0; } - -.recipe-people { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 28px; } -.recipe-people label { display: flex; align-items: center; gap: 10px; color: var(--muted); } -.recipe-people input[type='number'] { width: 4.5em; text-align: center; padding: 8px; } -.recipe-people-main { color: var(--bright) !important; font-weight: 600; } -.recipe-people-main input { border-color: var(--accent) !important; } -.recipe-people .hint { margin: 0; } - -.recipe-rows { list-style: none; margin: 0; padding: 0; } -.recipe-row { - display: grid; - grid-template-columns: 24px minmax(0, 1.3fr) minmax(0, 1fr) 150px 140px; - align-items: center; - gap: 14px; - padding: 10px 0; - border-top: 1px dashed var(--border); -} -.recipe-take:checked { background: var(--accent); } -.recipe-take:checked::after { content: '✓'; color: var(--accent-ink); opacity: 1; } -.recipe-ingredient { display: flex; flex-direction: column; min-width: 0; } -.recipe-ingredient strong { overflow-wrap: anywhere; } -.recipe-ingredient small { color: var(--muted); font-size: 0.75rem; overflow-wrap: anywhere; } -.recipe-status { justify-self: start; } -.recipe .recipe-buy .recipe-qty { width: 4.5em; flex: none; text-align: center; padding: 8px; } -.recipe .recipe-buy .unit-select { flex: 1; min-width: 0; } - -.recipe-foot { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; } -.recipe-foot .hint { margin: 0; flex: 1 1 280px; } - -@media (max-width: 760px) { - .recipe-load { flex-direction: column; align-items: stretch; } - .recipe-row { - grid-template-columns: 24px minmax(0, 1fr) 9.5em; - grid-template-areas: - 'take ing ing' - '. status status' - '. prod qty'; - gap: 6px 10px; - } - .recipe-take { grid-area: take; align-self: start; } - .recipe-ingredient { grid-area: ing; } - .recipe-status { grid-area: status; justify-self: start; } - .recipe-product { grid-area: prod; } - .recipe-buy { grid-area: qty; min-width: 0; } - .recipe .recipe-buy .recipe-qty { width: 3.8em; } - .recipe-foot .btn { width: 100%; } -} - -/* ---------- Reisen: Weltkarte ---------- */ -.city-search { position: relative; max-width: 720px; margin-bottom: 16px; } -.city-search input { - font: inherit; - font-size: 1.05rem; - color: var(--bright); - background: var(--input-bg); - border: 1px solid var(--accent); - padding: 12px 16px 12px 38px; - width: 100%; -} -.city-search input:focus { outline: none; box-shadow: var(--glow); } -.city-search .combo-list li small { margin-left: 6px; } -.city-search .combo-list li.added { opacity: 0.55; cursor: default; } -.combo-info { color: var(--muted); cursor: default !important; } -.combo-info::before { content: '' !important; } -.travel-error { margin-bottom: 12px; } - -.travel-map { position: relative; padding: 0; overflow: hidden; height: clamp(340px, 68vh, 760px); } -.travel-loading { padding: 20px; } -.worldmap, .worldmap svg { width: 100%; height: 100%; display: block; } -.worldmap svg { cursor: grab; touch-action: none; --inv: 1; } -.worldmap svg:active { cursor: grabbing; } -.map-sphere { fill: var(--map-ocean); } -.map-graticule { fill: none; stroke: rgb(var(--accent-rgb) / 0.09); vector-effect: non-scaling-stroke; } -.map-country { - fill: var(--map-land); - stroke: rgb(var(--accent-rgb) / 0.45); - stroke-width: 0.6; - vector-effect: non-scaling-stroke; - cursor: pointer; - transition: fill 0.15s; -} -.map-country:hover { fill: var(--map-land-hover); } -.map-country.visited { fill: rgb(var(--accent-rgb) / 0.55); stroke: rgb(var(--accent-rgb) / 0.9); } -.map-country.visited:hover { fill: rgb(var(--accent-rgb) / 0.7); } -.map-country.selected { stroke: var(--bright); stroke-width: 1.6; fill: rgb(var(--accent-rgb) / 0.35); } -.map-country.visited.selected { fill: rgb(var(--accent-rgb) / 0.8); } - -/* Stadt-Punkte: Größe bleibt beim Zoomen gleich (--inv = 1 / Zoomfaktor) */ -.map-city { transform: scale(var(--inv)); cursor: pointer; } -.map-city-hit { fill: transparent; } -.map-city-dot { fill: var(--bright); stroke: var(--accent); stroke-width: 2; filter: drop-shadow(0 0 3px rgb(var(--accent-rgb) / 0.9)); } -.map-city:hover .map-city-dot { fill: #fff; } -.map-city-ring { fill: none; stroke: var(--bright); stroke-width: 1.5; animation: city-pulse 1.6s ease-out infinite; transform-origin: 0 0; } -@keyframes city-pulse { from { opacity: 1; transform: scale(0.6); } to { opacity: 0; transform: scale(1.8); } } -.calm .map-city-ring { animation: none; } -@media (prefers-reduced-motion: reduce) { .map-city-ring { animation: none; } } - -.map-controls { position: absolute; top: 12px; right: 12px; display: flex; flex-direction: column; border: 1px solid var(--accent); background: var(--overlay); } -.map-controls button { - font: inherit; - font-size: 1.15rem; - width: 38px; - height: 38px; - border: 0; - background: transparent; - color: var(--accent); - cursor: pointer; -} -.map-controls button + button { border-top: 1px solid var(--border); } -.map-controls button:hover { background: var(--accent); color: var(--accent-ink); } - -/* Info-Kasten: Desktop unten links über der Karte, Handy unter der Karte */ -.info-card { - position: absolute; - left: 14px; - bottom: 14px; - width: min(380px, calc(100% - 28px)); - max-height: calc(100% - 28px); - overflow-y: auto; - display: flex; - flex-direction: column; - gap: 10px; - padding: 16px 18px; - background: var(--panel); - border: 1px solid var(--accent); - box-shadow: var(--glow); -} -.info-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; } -.info-head h2 { margin: 0; font-size: calc(var(--h2-size) * 1.15); } -.info-sub { margin: -6px 0 0; color: var(--muted); font-size: 0.82rem; } -.info-facts { margin: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 14px; } -.info-facts dt { font-size: 0.7rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.1em; } -.info-facts dd { margin: 1px 0 0; color: var(--bright); font-size: 0.88rem; overflow-wrap: anywhere; } -.info-extract { - margin: 0; - color: var(--read); - font-size: 0.85rem; - line-height: 1.55; - text-shadow: none; - display: -webkit-box; - -webkit-line-clamp: 5; - -webkit-box-orient: vertical; - overflow: hidden; -} -.info-more { font-size: 0.8rem; align-self: flex-start; } -.info-visit { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding-top: 10px; border-top: 1px dashed var(--border); } -.info-cities { display: flex; flex-wrap: wrap; gap: 6px; } -.info-card .chip { font-size: 0.78rem; } -.info-others { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; } -.info-others .hint { margin: 0; font-size: 0.78rem; } - -/* Städte anderer Konten */ -.map-city.other .map-city-dot { fill: var(--dot); stroke: var(--bg); stroke-width: 1.5; filter: drop-shadow(0 0 3px var(--dot)); } -.map-city.other:hover .map-city-dot { fill: var(--dot); stroke: var(--bright); } -.map-city.other .map-city-ring { stroke: var(--dot); } -.travel-others { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin: -4px 0 14px; } -.travel-legend { display: inline-flex; align-items: center; gap: 6px; font-size: 0.82rem; color: var(--muted); margin-left: 6px; } -.legend-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: var(--dot); box-shadow: 0 0 4px var(--dot); flex: none; } -.legend-dot.own { background: var(--bright); box-shadow: 0 0 0 2px var(--accent); } -.travel-person { display: inline-flex; align-items: center; gap: 6px; } -.travel-person:not(.active) { opacity: 0.55; } -.travel-person:not(.active) .legend-dot { background: transparent; box-shadow: inset 0 0 0 2px var(--dot); } -.travel-person small { color: var(--muted); } -.badge.travel-owner { color: var(--dot); } - -/* Besuchte Orte: Kontinente nebeneinander, Länder ausklappbar */ -.visited-list { display: grid; gap: 28px 32px; margin-top: 28px; align-items: start; } -@media (min-width: 900px) { .visited-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } } -@media (min-width: 1400px) { .visited-list { grid-template-columns: repeat(3, minmax(0, 1fr)); } } -.travel-empty { margin-top: 24px; } -.visited-continent .section-title { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; white-space: normal; } -.continent-toggle { - display: flex; - align-items: baseline; - gap: 10px; - flex-wrap: wrap; - padding: 2px 0; - border: 0; - background: none; - color: inherit; - font: inherit; - letter-spacing: inherit; - text-transform: inherit; - text-align: left; - cursor: pointer; -} -.continent-toggle:hover { color: var(--accent); } -.continent-arrow { display: inline-block; color: var(--accent); transform: rotate(90deg); transition: transform var(--dur) var(--ease-out); } -.continent-toggle[aria-expanded='false'] .continent-arrow { transform: none; } -.visited-continent.closed .section-title { margin-bottom: 0; } -.visited-count { font-family: var(--font); font-size: 0.75rem; font-weight: 400; letter-spacing: 0.02em; text-transform: none; color: var(--muted); text-shadow: none; } -.visited-countries { list-style: none; margin: 0; padding: 0; border: 1px solid var(--border); border-radius: var(--radius-m); background: var(--surface); overflow: hidden; } -.visited-country + .visited-country { border-top: 1px solid var(--border); } -.visited-row { display: flex; align-items: center; gap: 4px; padding: 2px 12px 2px 4px; } -.visited-country.active .visited-row { background: var(--accent-soft); box-shadow: inset 2px 0 0 var(--accent); } -.visited-toggle { - flex: none; - width: 34px; - height: 34px; - display: grid; - place-items: center; - border: 0; - border-radius: var(--radius-s); - background: transparent; - color: var(--accent); - font: inherit; - cursor: pointer; -} -.visited-toggle span { transition: transform var(--dur) var(--ease-out); } -.visited-toggle[aria-expanded='true'] span { transform: rotate(90deg); } -.visited-toggle:hover:not(:disabled) { background: var(--accent-soft); } -.visited-toggle:disabled { color: var(--muted); cursor: default; } -.visited-name { - flex: 1; - min-width: 0; - display: flex; - align-items: center; - gap: 8px; - padding: 8px 6px; - border: 0; - background: transparent; - color: var(--bright); - font: inherit; - font-weight: 600; - text-align: left; - cursor: pointer; - overflow-wrap: anywhere; -} -.visited-name:hover { color: var(--accent); } -.visited-flag { font-size: 1.1em; } -.visited-meta { flex: none; font-size: 0.75rem; color: var(--muted); } -.visited-country .visited-cities { padding: 2px 14px 14px 46px; } -.chip-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; } -.chip.active { border-style: solid; border-color: var(--accent); color: var(--bright); background: var(--accent-soft); } -.travel-credits { margin-top: 28px; font-size: 0.72rem; } - -@media (max-width: 759px) { - .travel-map { height: auto; overflow: visible; } - .worldmap { height: clamp(260px, 52vh, 420px); } - .info-card { position: relative; left: auto; bottom: auto; width: auto; max-height: none; border-width: 1px 0 0; box-shadow: none; } - .info-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); } -} - -/* ---------- Kanban ---------- */ -.kanban-filter { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.08em; } -.kanban-filter select { - font: inherit; - text-transform: none; - letter-spacing: normal; - font-size: 0.88rem; - color: var(--bright); - background: var(--input-bg); - border: 1px solid var(--border); - padding: 9px 10px; -} -.kanban-filter select:focus { outline: none; border-color: var(--accent); box-shadow: var(--glow); } -.kanban-error { margin-bottom: 12px; } - -.board { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(12px, 1.2vw, 20px); align-items: start; } -.board-column { - display: flex; - flex-direction: column; - min-height: 220px; - background: var(--surface); - border: 1px solid var(--border); - border-top: 3px solid var(--border); - transition: border-color 0.12s, box-shadow 0.12s; -} -.board-column.arbeit { border-top-color: var(--accent); } -.board-column.wartet { border-top-color: var(--warn); } -.board-column.erledigt { border-top-color: var(--ok); } -.board-column.drop-target { border-color: var(--accent); box-shadow: var(--glow); } -.board-head { display: flex; justify-content: space-between; align-items: center; padding: 12px 14px 8px; } -.board-head h2 { margin: 0; } -.board-head .count { font-family: var(--font); font-size: 0.8rem; color: var(--muted); text-shadow: none; vertical-align: middle; } -.board-head .count::before { content: '['; } -.board-head .count::after { content: ']'; } -.board-head .link-btn { font-size: 1.3rem; line-height: 1; padding: 2px 6px; color: var(--accent); } -.board-cards { list-style: none; margin: 0; padding: 4px 10px 12px; display: flex; flex-direction: column; gap: 8px; flex: 1; } -.board-empty { color: var(--muted); font-size: 0.8rem; padding: 14px 4px; text-align: center; border: 1px dashed var(--border); } -.drop-line { height: 3px; background: var(--accent); box-shadow: var(--glow); margin: 2px 0; } - -.task-card { - width: 100%; - display: flex; - flex-direction: column; - gap: 6px; - padding: 10px 12px; - font: inherit; - text-align: left; - color: var(--text); - background: var(--card-inner); - border: 1px solid var(--border); - cursor: grab; - text-shadow: none; - transition: border-color 0.12s, box-shadow 0.12s, opacity 0.12s; -} -.task-card:hover { border-color: var(--accent); box-shadow: 0 0 10px rgb(var(--accent-rgb) / 0.3); } -.task-card.dragging { opacity: 0.35; } -.task-title { color: var(--bright); font-weight: 600; overflow-wrap: anywhere; } -.task-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; } -/* Priorität: Kennzeichen auf der Karte + farbige Kante links (Mittel ohne Kennzeichen, damit es ruhig bleibt) */ -.prio { - flex: none; - padding: 1px 8px; - border-radius: var(--radius-pill); - font-family: var(--font-label); - font-size: 0.66rem; - font-weight: 700; - letter-spacing: 0.08em; - text-transform: uppercase; - white-space: nowrap; -} -.prio-hoch { color: var(--accent-ink); background: var(--bad); } -.prio-niedrig { color: var(--muted); box-shadow: inset 0 0 0 1px var(--border); } -.task-card.prio-card-hoch { box-shadow: inset 3px 0 0 var(--bad); } -.task-card.prio-card-niedrig .task-title { font-weight: 500; } -.task-desc { - color: var(--read); - font-size: 0.8rem; - white-space: pre-line; - overflow-wrap: anywhere; - display: -webkit-box; - -webkit-line-clamp: 3; - -webkit-box-orient: vertical; - overflow: hidden; -} -.task-meta { display: flex; justify-content: space-between; align-items: center; margin-top: 2px; } -.assignee { display: inline-flex; align-items: center; gap: 6px; font-size: 0.75rem; color: var(--muted); } -.assignee.none { font-style: italic; } -.avatar { - display: inline-grid; - place-items: center; - width: 22px; - height: 22px; - font-size: 0.65rem; - font-weight: 600; - color: var(--accent-ink); - background: var(--accent); -} -.board-column.erledigt .task-title { text-decoration: line-through; text-decoration-color: rgb(var(--accent-rgb) / 0.6); color: var(--muted); } - -.task-dialog { width: min(620px, calc(100% - 32px)); } -.task-dialog textarea { - font: inherit; - font-weight: 400; - text-transform: none; - letter-spacing: normal; - color: var(--bright); - background: var(--input-bg); - border: 1px solid var(--border); - padding: 10px 12px; - width: 100%; - resize: vertical; -} -.task-dialog textarea:focus { outline: none; border-color: var(--accent); box-shadow: var(--glow); } -.task-dialog-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; } -.task-history { margin: 0; font-size: 0.78rem; } -.task-delete { margin-right: auto; } - -/* Kanban-Übersicht */ -.kanban-projects { grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); } -.kanban-project-card { position: relative; display: flex; flex-direction: column; gap: 10px; transition: border-color 0.12s, box-shadow 0.12s; } -.kanban-project-card:hover { border-color: var(--accent); box-shadow: var(--glow); } -.kanban-project-card h3 { margin: 0; overflow-wrap: anywhere; } -.kanban-project-link { color: inherit; text-decoration: none; } -.kanban-project-link::after { content: ''; position: absolute; inset: 0; } /* ganze Karte klickbar */ -.kanban-project-actions { position: relative; z-index: 1; display: flex; gap: 16px; padding-top: 8px; border-top: 1px dashed var(--border); } -.kanban-project-card.completed { opacity: 0.8; } -.kanban-project-card.completed h3 { text-decoration: line-through; text-decoration-color: rgb(var(--accent-rgb) / 0.6); } -.kanban-done-badge { align-self: flex-start; margin-top: -4px; white-space: normal; font-size: 0.72rem; max-width: 100%; } -.kanban-project-desc { - margin: 0; - color: var(--read); - font-size: 0.85rem; - white-space: pre-line; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; -} -.status-bar { display: flex; height: 6px; gap: 2px; margin-top: auto; } -.status-bar span { min-width: 6px; background: var(--border); } -.status-bar .arbeit { background: var(--accent); } -.status-bar .wartet { background: var(--warn); } -.status-bar .erledigt { background: var(--ok); } -.kanban-project-counts { margin: 0; font-size: 0.75rem; color: var(--muted); } -.kanban-project-links { margin: 0; font-size: 0.75rem; color: var(--bright); overflow-wrap: anywhere; } -.kanban-done { margin-top: clamp(28px, 4vw, 48px); } -.kanban-done summary { cursor: pointer; list-style: none; margin-bottom: 14px; } -.kanban-done summary::-webkit-details-marker { display: none; } -.kanban-done summary h2 { display: inline; } -.kanban-done summary h2::after { content: ' ▸'; color: var(--accent); } -.kanban-done[open] summary h2::after { content: ' ▾'; } -.kanban-done .count { font-family: var(--font); font-size: 0.8rem; color: var(--muted); text-shadow: none; } -.kanban-done .count::before { content: '['; } -.kanban-done .count::after { content: ']'; } - -/* Board-Kopf */ -.board-completed { margin-bottom: 16px; } -.btn.ghost.danger-btn { color: var(--bad); border-color: var(--bad); } -.btn.ghost.danger-btn:hover:not(:disabled) { background: var(--bad); color: var(--accent-ink); } -.board-page-head { margin-bottom: 18px; } -.board-description { white-space: pre-line; margin-bottom: 12px; max-width: 75ch; } -.board-links { margin-top: 4px; } -.board-links .chip { text-decoration: none; display: inline-block; } - -/* Artikel-Auswahl im Projekt-Dialog */ -.link-picker { border: 1px solid var(--border); padding: 10px 12px 12px; margin: 0; min-width: 0; } -.link-picker legend { font-size: 0.8rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; padding: 0 6px; } -.link-picker legend small { font-weight: 400; color: var(--muted); text-transform: none; letter-spacing: 0; } -.link-picker ul { list-style: none; margin: 8px 0 0; padding: 0; max-height: 200px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; } -.link-picker .checkbox { text-transform: none !important; letter-spacing: 0 !important; font-weight: 400 !important; font-size: 0.9rem !important; padding: 4px 0; } -.link-picker input[type='search'] { margin-top: 4px; } -.aside-boards { display: flex; flex-direction: column; gap: 4px; } -.aside-boards a { text-decoration: none; } -.aside-boards a.sub { font-size: 0.8rem; color: var(--muted); } -.aside-boards a.sub:hover { color: var(--bright); } - -/* Handy/Tablet: Spalten nebeneinander wischen */ -@media (max-width: 999px) { - .board { - grid-template-columns: repeat(4, minmax(78%, 1fr)); - overflow-x: auto; - scroll-snap-type: x mandatory; - padding-bottom: 8px; - overscroll-behavior-x: contain; - } - .board-column { scroll-snap-align: start; } -} -@media (min-width: 640px) and (max-width: 999px) { - .board { grid-template-columns: repeat(4, minmax(46%, 1fr)); } -} -@media (max-width: 520px) { - .task-dialog-row { grid-template-columns: 1fr; } - .kanban-filter { width: 100%; } - .kanban-filter select { flex: 1; } -} - -/* ---------- Konto & Benutzerverwaltung ---------- */ -.settings-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr)); - gap: clamp(14px, 1.5vw, 24px); - align-items: start; -} -.user-list { display: grid; gap: 12px; } -.user-row { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 16px; padding: 16px 20px; } -.user-info { display: flex; flex-direction: column; min-width: 0; } -.user-info .hint { margin: 2px 0 0; } -.user-badges { display: flex; gap: 6px; } -.user-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; justify-content: flex-end; } -.user-edit { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; } -.user-edit input { - font: inherit; - color: var(--bright); - background: var(--input-bg); - border: 1px solid var(--accent); - padding: 6px 10px; - min-width: 0; - flex: 1 1 160px; -} -@media (max-width: 800px) { - .user-row { grid-template-columns: minmax(0, 1fr) auto; } - .user-actions { grid-column: 1 / -1; justify-content: flex-start; } -} - -/* ============================================================ - Artikel (Ansicht + Bearbeitung) – volle Breite mit Seitenleiste - ============================================================ */ -.back { display: inline-block; margin-bottom: 20px; text-decoration: none; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.08em; } - -.article-cover { margin: 0 0 clamp(20px, 3vw, 36px); position: relative; border: 1px solid var(--accent); box-shadow: var(--glow); } -.article-cover img { display: block; width: 100%; height: clamp(200px, 42vh, 560px); object-fit: cover; cursor: zoom-in; } -.article-cover.empty { display: grid; place-items: center; min-height: 160px; border: 1px dashed var(--border); box-shadow: none; background: var(--surface); } -.cover-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; } -.article-cover:not(.empty) .cover-actions { position: absolute; right: 14px; bottom: 14px; } -.article-cover:not(.empty) .cover-actions .btn.ghost { background: var(--overlay); } -.editing .article-cover img { cursor: default; } - -.article-layout { display: grid; gap: clamp(20px, 2.5vw, 40px); align-items: start; } -@media (min-width: 1100px) { - .article-layout { grid-template-columns: minmax(0, 1fr) clamp(280px, 20vw, 360px); } - .article-aside { position: sticky; top: calc(var(--topbar-h) + 20px); } -} - -.article-main { min-width: 0; } -/* Lesefenster: Artikeltext auf ruhigem, dunklem Grund statt über dem Matrix-Regen */ -.article-page:not(.editing) .article-main { - background: var(--surface); - border: 1px solid var(--border); - padding: clamp(18px, 2.5vw, 36px); -} -.article-title { font-size: clamp(2.6rem, 4.4vw, 4.4rem); line-height: 0.95; margin: 0; } -.article-byline { margin: 12px 0 0; color: var(--muted); font-size: 0.88rem; } -.article-lead { max-width: 60ch; font-size: clamp(1.05rem, 1.3vw, 1.25rem); color: var(--text); margin: 14px 0 0; white-space: pre-wrap; border-left: 3px solid var(--accent); padding-left: 14px; } -.article-empty { margin-top: 32px; } - -.title-input { font-family: var(--font-display); font-size: clamp(2rem, 3.4vw, 3.2rem); text-transform: uppercase; padding: 6px 12px; } -.lead-input { font-size: 1.05rem; margin-top: 10px; resize: vertical; } - -.article-body { - margin-top: clamp(24px, 3vw, 40px); - max-width: 75ch; - color: var(--read); - text-shadow: none; - font-size: clamp(0.98rem, 0.92rem + 0.22vw, 1.12rem); - line-height: 1.8; - overflow-wrap: break-word; -} -.article-body > :first-child { margin-top: 0; } -.article-body h2 { font-size: 2.3em; margin: 1.3em 0 0.4em; } -.article-body h2::before { content: '## '; color: var(--accent); } -.article-body h3 { font-size: 1.7em; margin: 1.2em 0 0.3em; } -.article-body h3::before { content: '### '; color: var(--accent); } -.article-body p { margin: 0 0 1em; } -.article-body ul, .article-body ol { padding-left: 1.6em; margin: 0 0 1em; } -.article-body ul { list-style: none; } -.article-body ul > li::before { content: '■'; color: var(--accent); margin-left: -1.3em; margin-right: 0.7em; font-size: 0.7em; vertical-align: middle; } -.article-body ol li::marker { color: var(--accent); } -.article-body li { margin: 0.2em 0; } -.article-body li > p { margin: 0; display: inline; } -.article-body blockquote { margin: 1.4em 0; padding: 4px 0 4px 18px; border-left: 3px solid var(--accent); color: var(--bright); } -.article-body img { display: block; max-width: 100%; max-height: 80vh; height: auto; margin: 1.4em auto; border: 1px solid var(--border); cursor: zoom-in; } -.article-body hr { border: 0; border-top: 1px dashed var(--accent); margin: 2em 0; } -.article-body a { color: var(--bright); } - -/* Seitenleiste */ -.aside-card { display: flex; flex-direction: column; gap: 18px; border-color: var(--accent); } -.aside-facts { margin: 0; display: grid; gap: 12px; } -.aside-facts dd { margin: 3px 0 0; color: var(--bright); } -.aside-facts .sub { display: block; font-size: 0.8rem; color: var(--muted); } -.edit-actions { display: flex; flex-direction: column; gap: 12px; } -.edit-buttons { display: flex; gap: 8px; } -.edit-buttons .btn { flex: 1; } -.edit-actions .link-btn { align-self: flex-start; } - -@media (max-width: 1099px) { - /* Beim Lesen zuerst der Titel, beim Bearbeiten zuerst Status & Aktionen */ - .editing .article-aside { order: -1; } - .aside-card { flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: space-between; padding: 14px 18px; } - .aside-facts { grid-auto-flow: column; gap: 24px; } - .aside-card > .btn.full { width: auto; } - .editing .edit-actions { - position: fixed; - left: 0; - right: 0; - bottom: 0; - z-index: 15; - flex-direction: row; - flex-wrap: wrap; - align-items: center; - padding: 12px var(--gutter) calc(12px + env(safe-area-inset-bottom)); - background: var(--bg); - border-top: 1px solid var(--accent); - box-shadow: 0 -4px 20px rgb(var(--accent-rgb) / 0.15); - } - .editing .edit-actions .error { flex-basis: 100%; } - .editing .edit-buttons { order: 2; margin-left: auto; } - .editing .edit-buttons .btn { flex: none; } - .editing.article-page { padding-bottom: 80px; } -} - -@media (max-width: 640px) { - .aside-facts { grid-auto-flow: row; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px 20px; width: 100%; } - .aside-card > .btn.full { width: 100%; } -} - -/* Editor */ -.editor { margin-top: 20px; } -.toolbar { - position: sticky; - top: var(--topbar-h); - z-index: 10; - display: flex; - flex-wrap: wrap; - align-items: center; - gap: 2px; - padding: 6px; - background: var(--input-bg); - border: 1px solid var(--accent); -} -.toolbar button { - font: inherit; - font-size: 0.8rem; - text-transform: uppercase; - letter-spacing: 0.04em; - min-height: 32px; - padding: 5px 10px; - border: 1px solid transparent; - background: transparent; - color: var(--text); - cursor: pointer; - text-shadow: inherit; -} -.toolbar button:hover:not(:disabled) { border-color: var(--border); color: var(--bright); } -.toolbar button:disabled { opacity: 0.35; cursor: default; } -.toolbar button.active { background: var(--accent); color: var(--accent-ink); text-shadow: none; } -.toolbar button b, .toolbar button i, .toolbar button u { color: inherit; } -.toolbar-sep { width: 1px; height: 20px; background: var(--border); margin: 0 4px; } - -.editor-content.article-body { - margin-top: 0; - max-width: none; - min-height: max(320px, 50vh); - padding: clamp(16px, 2vw, 28px); - border: 1px solid var(--accent); - border-top: 0; - background: var(--editor-bg); - outline: none; -} -.editor-content.article-body:focus { box-shadow: var(--glow); } -.editor-content img { cursor: pointer; } -.editor-content img.ProseMirror-selectednode { outline: 2px solid var(--bright); outline-offset: 2px; } -.editor-content p.is-editor-empty:first-child::before { - content: attr(data-placeholder); - color: var(--muted); - float: left; - height: 0; - pointer-events: none; -} - -/* ---------- Handy ---------- */ -@media (max-width: 640px) { - body { font-size: 14px; } - .brand { font-size: 1.6rem; } - .toolbar { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; } - .toolbar button { flex: none; } - .track-form { flex-direction: column; } - .tiles { gap: 12px; } - .tiles > * { flex-basis: 140px; } - .tile { padding: 16px; } - .tile small { display: none; } - .page-head .btn, .page-actions { width: 100%; } - .page-actions .btn { flex: 1; } -} - -/* Weniger Bewegung, wenn im System eingestellt */ -.calm .page-head h1::after, .calm .hero h1::after, .calm .dot.bad { animation: none; } -@media (prefers-reduced-motion: reduce) { - .page-head h1::after, .hero h1::after, .dot.bad { animation: none; } - * { transition: none !important; } -} - -/* ============================================================ - Moderne Grundschicht (gilt für alle Designs, Werte aus den Tokens) - ============================================================ */ - -/* Alle Eingabefelder einheitlich: gleiche Höhe, Radius, weicher Fokusring */ -.form input:not([type='checkbox']), .form select, .form textarea, -.aside-card select, .title-input, .lead-input, .track-form input, -.household-add input, .recipe input:not([type='checkbox']), .recipe textarea, -.city-search input, .kanban-filter select, .user-edit input, .task-dialog textarea { - font-family: var(--font); - color: var(--bright); - background: var(--input-bg); - border: 1px solid var(--border); - border-radius: var(--radius-s); - min-height: var(--control-h); - text-shadow: none; - transition: transform var(--dur) var(--ease-out); -} -.form textarea, .recipe textarea, .task-dialog textarea, .lead-input { min-height: 0; padding: 10px 12px; } -.form input:not([type='checkbox']):focus, .form select:focus, .form textarea:focus, -.aside-card select:focus, .title-input:focus, .lead-input:focus, .track-form input:focus, -.household-add input:focus, .recipe input:focus, .recipe textarea:focus, -.city-search input:focus, .kanban-filter select:focus, .user-edit input:focus, .task-dialog textarea:focus, -.unit-select:focus { - outline: none; - border-color: var(--accent); - box-shadow: var(--focus-ring); -} -.track-form input, .city-search input { min-height: 50px; border-color: var(--line-strong); } -.track-form .btn { min-height: 50px; } -.unit-select { border-radius: var(--radius-s); min-height: 34px; } -.qty-unit > input { border-radius: var(--radius-s) 0 0 var(--radius-s) !important; } -.qty-unit > .unit-select { border-radius: 0 var(--radius-s) var(--radius-s) 0; } -[aria-invalid='true'] { box-shadow: 0 0 0 3px rgb(255 61 61 / 0.25) !important; } - -/* Beschriftungen in Fakten-Listen */ -.info-facts dt { font-size: var(--label-size); letter-spacing: var(--label-tracking); } - -/* Startseite: Kacheln als App-Starter mit Icon-Feld */ -.tile { - position: relative; - border-radius: var(--radius-m); - box-shadow: var(--shadow-1); - gap: 12px; - transition: transform var(--dur) var(--ease-out); -} -.tile svg { - box-sizing: content-box; - width: 26px; - height: 26px; - padding: 10px; - border-radius: var(--radius-s); - background: var(--accent-soft); - filter: none; -} -.tile-empty svg { background: transparent; box-shadow: inset 0 0 0 1px var(--border); } - -/* Interaktive Karten heben sich leicht an (nur transform) */ -.tile, .project-card, .kanban-project-card, .task-card { transition: transform var(--dur) var(--ease-out); } -.tile:hover, .project-card:hover, .kanban-project-card:hover, .task-card:hover:not(.dragging) { transform: translateY(var(--lift)); box-shadow: var(--shadow-1); } -.project-card:hover, .kanban-project-card:hover, .tile:hover { border-color: var(--line-strong); } -.project-cover { border-bottom-color: var(--border); } - -/* Listen: Zeilen mit feinen Linien und Hover-Fläche */ -.household-item, .recipe-row, .product-list li { border-top-style: solid; border-top-color: var(--border); } -.household-item { padding-inline: 6px; margin-inline: -6px; border-radius: var(--radius-s); } -.household-item:hover { background: var(--accent-soft); } -.monitor-facts, .info-visit { border-top-style: solid; } -.timeline li { border-left-style: solid; border-left-color: var(--border); } -.timeline li::before { border-radius: 50%; background: var(--surface-2); } - -/* Bedienelemente */ -.stepper { border-radius: var(--radius-s); overflow: hidden; } -.household-check { border-radius: var(--radius-s); border-color: var(--line-strong); } -.segmented { border-color: var(--line-strong); border-radius: var(--radius-m); overflow: hidden; padding: 3px; gap: 3px; background: var(--card-inner); } -.segmented button { border-radius: calc(var(--radius-m) - 3px); } -.segmented .count::before, .segmented .count::after { content: none; } -.segmented .count { margin-left: 4px; } -.combo-list { border-color: var(--line-strong); border-radius: var(--radius-m); box-shadow: var(--shadow-2); background: var(--panel); padding: 6px; } -.combo-list li { border-radius: var(--radius-s); } -.toolbar { border-color: var(--line-strong); border-radius: var(--radius-m) var(--radius-m) 0 0; background: var(--panel); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur); } -.toolbar button { border-radius: var(--radius-s); } -.editor-content.article-body { border-color: var(--line-strong); border-radius: 0 0 var(--radius-m) var(--radius-m); } -.monitor-summary { border-radius: var(--radius-m); } -.monitor-card { border-left-width: 3px; } -.aside-card { border-color: var(--line-strong); } -.article-cover { border-color: var(--line-strong); border-radius: var(--radius-l); overflow: hidden; box-shadow: var(--shadow-1); } -.article-page:not(.editing) .article-main { border-radius: var(--radius-l); box-shadow: var(--shadow-1); } -.article-lead { border-left-width: 2px; } -.link-picker { border-color: var(--border); border-radius: var(--radius-m); } - -/* Kanban */ -.board-column { border-radius: var(--radius-m); border-top-width: 2px; box-shadow: var(--shadow-1); } -.board-column.drop-target { box-shadow: var(--focus-ring); } -.board-head .count::before, .board-head .count::after { content: none; } -.board-head .count { - display: inline-grid; - place-items: center; - min-width: 1.6em; - height: 1.6em; - margin-left: 6px; - padding: 0 6px; - border-radius: var(--radius-pill); - background: var(--accent-soft); - color: var(--text); - font-family: var(--font-label); - font-size: 0.7rem; - vertical-align: 0.15em; -} -.board-empty { border-radius: var(--radius-s); border-style: dashed; } -.task-card { border-radius: var(--radius-s); border-color: var(--border); } -.task-card:hover { border-color: var(--line-strong); box-shadow: var(--shadow-1); } -.drop-line { border-radius: 2px; box-shadow: none; } -.avatar { border-radius: 50%; } -.status-bar { border-radius: var(--radius-pill); overflow: hidden; } - -/* Reisen */ -.travel-map { border-radius: var(--radius-l); } -.map-controls { border-color: var(--line-strong); border-radius: var(--radius-m); overflow: hidden; backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur); } -.info-card { border-color: var(--line-strong); border-radius: var(--radius-m); box-shadow: var(--shadow-2); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur); } - -/* Sanfter Wechsel zwischen den Designs (View Transitions, wo der Browser es kann) */ -::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.35s; animation-timing-function: var(--ease-out); } - -@media (prefers-reduced-motion: reduce) { - .tile:hover, .project-card:hover, .kanban-project-card:hover, .task-card:hover, .btn:hover:not(:disabled) { transform: none; } - ::view-transition-old(root), ::view-transition-new(root) { animation: none; } -} -html.calm .tile:hover, html.calm .project-card:hover, html.calm .kanban-project-card:hover, html.calm .task-card:hover { transform: none; } - -/* Kanban-Archiv */ -.kanban-archive { margin-top: clamp(16px, 2vw, 28px); display: flex; flex-direction: column; gap: 12px; } -.archive-list { list-style: none; margin: 0; padding: 0; } -.archive-item { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; padding: 10px 0; border-top: 1px dashed var(--border); } -.archive-title { flex: 1 1 220px; min-width: 0; text-align: left; font: inherit; font-weight: 600; color: var(--bright); background: none; border: 0; padding: 0; cursor: pointer; text-decoration: line-through; text-decoration-color: var(--muted); } -.archive-title:hover { color: var(--accent); } -.archive-dates { color: var(--muted); font-size: 0.78rem; } - -/* Auswahlknöpfe (z. B. Sichtbarkeit einer Einkaufsliste) nicht wie Eingabefelder gestalten */ -.form label.checkbox input[type='radio'] { width: 18px; height: 18px; min-height: 0; padding: 0; margin: 0; border: 0; background: none; box-shadow: none; accent-color: var(--accent); flex: none; } diff --git a/frontend/src/styles/base.css b/frontend/src/styles/base.css new file mode 100644 index 0000000..26b169f --- /dev/null +++ b/frontend/src/styles/base.css @@ -0,0 +1,189 @@ +/* ============================================================ + P42 Dashboard – Retro-Terminal in Rot ("Matrix in Rot") + Volle Breite, responsiv (Handy → Tablet → PC → Ultrawide) + ============================================================ */ + +/* Token-System: Farbrollen, Form, Bewegung, Schrift. Die Designs in designs/ setzen vor allem diese Werte. */ +:root { + /* Farbrollen (für Glow & Transparenzen: --accent-rgb; der Matrix-Regen liest sie mit) */ + --accent-rgb: 255 70 70; + --bg: #080203; + --surface: rgb(20 6 7 / 0.84); + --surface-hover: rgb(34 9 10 / 0.92); + --surface-2: #180607; + --border: rgb(var(--accent-rgb) / 0.22); /* feine Linie */ + --line-strong: rgb(var(--accent-rgb) / 0.55); /* betonte Linie */ + --accent: rgb(var(--accent-rgb)); + --accent-ink: #140203; /* Schrift auf Akzentgrund */ + --accent-soft: rgb(var(--accent-rgb) / 0.13); + --text: #f1c3c3; + --read: #f6d8d8; /* langer Fließtext */ + --bright: #fff1f1; + --muted: #d08e8e; /* getönt, nicht grau */ + --ok: #fff1f1; + --warn: #ffa66e; + --bad: #ff3d3d; + --bad-glow: rgb(255 61 61 / 0.6); + /* Diagramm-Reihen (geprüft auf Farbenblindheit vor --surface): 1 = Akzent, 2 = Gegenfarbe */ + --series-1: #ff4646; + --series-2: #9b7fe0; + --topbar-bg: rgb(8 2 3 / 0.76); + --glow: 0 0 6px rgb(var(--accent-rgb) / 0.55), 0 0 20px rgb(var(--accent-rgb) / 0.2); + --heading-glow: 0 0 6px rgb(var(--accent-rgb) / 0.55), 0 0 26px rgb(var(--accent-rgb) / 0.25); + --text-glow: none; + + /* Flächen, die Designs überschreiben können */ + --input-bg: rgb(4 1 1 / 0.85); + --card-inner: rgb(12 3 4 / 0.9); + --panel: rgb(12 3 4 / 0.96); + --overlay: rgb(6 1 2 / 0.86); + --backdrop: rgb(0 0 0 / 0.72); + --editor-bg: rgb(4 1 1 / 0.9); + --map-ocean: #050102; + --map-land: #1a0506; + --map-land-hover: #3a0b0c; + /* Reise-Karte: Punkte anderer Konten, je Person eine Farbe (deutlich anders als die eigenen Punkte) */ + --other-1: #9b7fe0; + --other-2: #4fd1a5; + --other-3: #ffd84a; + --other-4: #5fb4ff; + --other-5: #c6ff5c; + --other-6: #ff9f43; + + /* Form */ + --radius-s: 4px; + --radius-m: 8px; + --radius-l: 12px; + --radius-pill: 999px; + --shadow-1: inset 0 1px 0 rgb(255 255 255 / 0.035), 0 12px 32px -20px rgb(0 0 0 / 0.95); + --shadow-2: 0 32px 80px -24px rgb(0 0 0 / 0.95), 0 0 0 1px rgb(var(--accent-rgb) / 0.1); + --focus-ring: 0 0 0 3px rgb(var(--accent-rgb) / 0.3); + --blur: blur(14px) saturate(1.15); + --control-h: 40px; + + /* Bewegung (nur transform/opacity) */ + --ease-out: cubic-bezier(0.16, 1, 0.3, 1); + --dur: 0.2s; + --lift: -2px; + + /* Schrift: Text, Display (Marke/Seitentitel), Überschriften, Beschriftungen */ + --font: 'IBM Plex Mono', ui-monospace, 'Cascadia Mono', Menlo, monospace; + --font-display: 'VT323', 'IBM Plex Mono', monospace; + --font-heading: var(--font); + --font-label: var(--font); + --body-size: clamp(14.5px, 0.86rem + 0.15vw, 15.5px); + --h1-font: var(--font-display); + --h1-size: clamp(2.4rem, 3.8vw, 3.6rem); + --h1-weight: 400; + --h1-tracking: 0.04em; + --h2-size: 1.05rem; + --h3-size: 1rem; + --heading-weight: 600; + --heading-tracking: 0.05em; + --heading-case: uppercase; + --label-size: 0.72rem; + --label-tracking: 0.12em; + --tile-font: var(--font-display); + --tile-size: 1.55rem; + + --gutter: clamp(16px, 3vw, 56px); + --topbar-h: 64px; + color-scheme: dark; +} + +* { box-sizing: border-box; } + +html { background: var(--bg); -webkit-text-size-adjust: 100%; } + +body { + margin: 0; + background: transparent; + color: var(--text); + font-family: var(--font); + font-size: var(--body-size); + line-height: 1.6; + text-shadow: var(--text-glow); + caret-color: var(--accent); + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; +} +p { text-wrap: pretty; } + +/* Röhrenmonitor: Scanlines + abgedunkelte Ränder */ +body::after { + content: ''; + position: fixed; + inset: 0; + z-index: 100; + pointer-events: none; + background: + repeating-linear-gradient(to bottom, transparent 0 2px, rgb(0 0 0 / 0.07) 2px 3px), + radial-gradient(ellipse at center, transparent 62%, rgb(0 0 0 / 0.32) 100%); +} + +.matrix-rain { + position: fixed; + inset: 0; + z-index: -1; + width: 100%; + height: 100%; + opacity: 0.2; + pointer-events: none; + /* In der Mitte, wo der Inhalt steht, fast unsichtbar; an den Rändern deutlich */ + mask-image: radial-gradient(ellipse 70% 75% at 50% 45%, rgb(0 0 0 / 0.18) 0 45%, #000 100%); +} +.calm .matrix-rain { display: none; } + +::selection { background: var(--accent); color: var(--accent-ink); text-shadow: none; } + +* { scrollbar-color: var(--line-strong) transparent; scrollbar-width: thin; } + +#root { min-height: 100vh; display: flex; flex-direction: column; } + +a { color: var(--bright); text-decoration-style: dotted; text-underline-offset: 3px; } +a:hover { color: var(--accent); } +img { max-width: 100%; } +strong, b { color: var(--bright); } +code { font-family: var(--font); color: var(--bright); } + +/* Überschriften: Seitentitel in der Display-Schrift, alles darunter ruhig und klar */ +h1, h2, h3 { + font-family: var(--font-heading); + font-weight: var(--heading-weight); + text-transform: var(--heading-case); + letter-spacing: var(--heading-tracking); + color: var(--bright); + text-wrap: balance; +} +h1 { + font-family: var(--h1-font); + font-weight: var(--h1-weight); + font-size: var(--h1-size); + letter-spacing: var(--h1-tracking); + line-height: 1.02; + margin: 0 0 6px; + text-shadow: var(--heading-glow); +} +h2 { font-size: var(--h2-size); line-height: 1.25; } +h3 { font-size: var(--h3-size); line-height: 1.3; } +/* Kleine Beschriftungen (Eyebrows): weit gesperrt, klein */ +.eyebrow, .fact dt, .aside-facts dt, .monitor-facts dt, .info-facts dt, .form label, .menu-label { + font-family: var(--font-label); +} + +/* Blinkender Cursor hinter Seitenüberschriften */ +.page-head h1::after, .hero h1::after { + content: '_'; + margin-left: 0.1em; + animation: blink 1.1s steps(1) infinite; +} +@keyframes blink { 50% { opacity: 0; } } + +.lead { color: var(--muted); margin: 0 0 28px; } +.lead::before { content: '// '; } +.hint { color: var(--muted); font-size: 0.88rem; margin: 12px 0 0; } +.error { color: var(--bad); margin: 0; text-shadow: 0 0 4px var(--bad-glow); } +.error::before { content: '! '; font-weight: 700; } +.success { color: var(--ok); margin: 0; } +.success::before { content: '✓ '; } +.center { text-align: center; } diff --git a/frontend/src/styles/components.css b/frontend/src/styles/components.css new file mode 100644 index 0000000..6c87517 --- /dev/null +++ b/frontend/src/styles/components.css @@ -0,0 +1,190 @@ +/* ---------- Bausteine ---------- */ +.card { + background: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius-m); + box-shadow: var(--shadow-1); + padding: clamp(16px, 1.6vw, 22px); +} + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + min-height: var(--control-h); + font: inherit; + font-family: var(--font-label); + font-size: 0.82rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.08em; + padding: 0 20px; + border: 1px solid var(--accent); + border-radius: var(--radius-s); + background: var(--accent); + color: var(--accent-ink); + text-shadow: none; + cursor: pointer; + white-space: nowrap; + transition: transform var(--dur) var(--ease-out); +} +.btn:hover:not(:disabled) { background: var(--bright); border-color: var(--bright); transform: translateY(-1px); } +.btn:active:not(:disabled) { transform: translateY(0); } +.btn:disabled { opacity: 0.5; cursor: wait; } +.btn.ghost { background: transparent; color: var(--accent); border-color: var(--line-strong); } +.btn.ghost:hover:not(:disabled) { background: var(--accent-soft); border-color: var(--accent); color: var(--bright); } +.btn.ghost.danger-btn { color: var(--bad); border-color: rgb(255 61 61 / 0.5); } +.btn.ghost.danger-btn:hover:not(:disabled) { background: var(--bad); border-color: var(--bad); color: var(--accent-ink); } +.btn.small { min-height: 30px; padding: 0 12px; font-size: 0.74rem; } +.btn.full { width: 100%; } +:focus-visible { + outline: 2px solid var(--bright); + outline-offset: 2px; +} + +.link-btn { + font: inherit; + font-size: 0.82rem; + border: 0; + background: none; + padding: 0; + color: var(--muted); + text-transform: uppercase; + letter-spacing: 0.06em; + cursor: pointer; + text-shadow: inherit; +} +.link-btn:hover { color: var(--bright); } +.link-btn.danger:hover { color: var(--bad); } + +/* Status-Chips: getönte Pillen; "bad" gefüllt, damit es sofort auffällt */ +.badge { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 2px 10px; + border-radius: var(--radius-pill); + font-family: var(--font-label); + font-size: 0.72rem; + font-weight: 600; + line-height: 1.5; + text-transform: uppercase; + letter-spacing: 0.08em; + white-space: nowrap; + color: var(--accent); + background: color-mix(in oklab, currentColor 13%, transparent); + box-shadow: inset 0 0 0 1px color-mix(in oklab, currentColor 32%, transparent); + text-shadow: none; +} +.badge::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; } +.badge.ok { color: var(--ok); } +.badge.warn { color: var(--warn); } +.badge.bad { color: var(--accent-ink); background: var(--bad); box-shadow: none; } +.badge.muted { color: var(--muted); } +.badge.muted::before { opacity: 0.5; } + +.chip { + font: inherit; + font-size: 0.78rem; + padding: 4px 12px; + border: 1px solid var(--border); + border-radius: var(--radius-pill); + background: var(--card-inner); + color: var(--text); + cursor: pointer; + text-shadow: inherit; + text-decoration: none; +} +.chip:hover { color: var(--bright); border-color: var(--line-strong); background: var(--accent-soft); } + +.notice { border: 1px solid var(--border); border-left: 3px solid var(--accent); border-radius: var(--radius-m); padding: 14px 18px; color: var(--text); margin-bottom: 24px; background: var(--surface); } +.notice::before { content: '# '; color: var(--accent); } + +.meta { display: flex; gap: 8px; align-items: center; margin-top: 14px; font-size: 0.8rem; color: var(--muted); } +.dot { width: 10px; height: 10px; border-radius: 50%; background: var(--muted); display: inline-block; flex: none; } +.dot.ok { background: var(--ok); box-shadow: 0 0 6px var(--ok); } +.dot.warn { background: var(--warn); box-shadow: 0 0 6px var(--warn); } +.dot.bad { background: var(--bad); box-shadow: 0 0 6px var(--bad); animation: blink 1.1s steps(1) infinite; } + +.grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); + gap: clamp(14px, 1.5vw, 24px); +} +.grid h3 { margin: 0; } + +/* ---------- Formulare & Dialoge ---------- */ +.form { display: flex; flex-direction: column; gap: 14px; } +.form h2 { margin: 0 0 4px; } +.form label { + display: flex; + flex-direction: column; + gap: 6px; + font-size: var(--label-size); + font-weight: 600; + color: var(--muted); + text-transform: uppercase; + letter-spacing: var(--label-tracking); +} +.form label small { font-weight: 400; color: var(--muted); text-transform: none; letter-spacing: 0; } +.form label.checkbox { flex-direction: row; align-items: center; gap: 10px; } +.form label.checkbox input { width: 18px; height: 18px; accent-color: var(--accent); } + +.form input:not([type='checkbox']), .form select, .aside-card select, .title-input, .lead-input, .track-form input { + font: inherit; + font-weight: 400; + text-transform: none; + letter-spacing: normal; + color: var(--bright); + background: var(--input-bg); + border: 1px solid var(--border); + border-radius: 0; + padding: 10px 12px; + width: 100%; + text-shadow: none; +} +.form input:focus, .form select:focus, .aside-card select:focus, .title-input:focus, .lead-input:focus, .track-form input:focus { + outline: none; + border-color: var(--accent); + box-shadow: var(--glow); +} +::placeholder { color: var(--muted); opacity: 0.8; } +.form-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; } + +.modal { + width: min(520px, calc(100% - 32px)); + border: 1px solid var(--line-strong); + border-radius: var(--radius-l); + background: var(--panel); + color: var(--text); + padding: clamp(20px, 3vw, 28px); + box-shadow: var(--shadow-2); +} +.modal::backdrop, .lightbox::backdrop { background: var(--backdrop); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); } + +.lightbox { border: 1px solid var(--accent); padding: 0; background: var(--input-bg); max-width: 96vw; max-height: 96vh; cursor: zoom-out; } +.lightbox img { display: block; max-width: 96vw; max-height: 96vh; object-fit: contain; } + +/* ---------- Anmeldung ---------- */ +.auth-page { min-height: 100vh; display: grid; place-items: center; padding: 24px var(--gutter); } +.auth-card { + width: min(440px, 100%); + padding: clamp(22px, 4vw, 34px); + display: flex; + flex-direction: column; + gap: 14px; + border-color: var(--line-strong); + border-radius: var(--radius-l); + box-shadow: var(--shadow-2); + backdrop-filter: var(--blur); + -webkit-backdrop-filter: var(--blur); +} +.auth-brand { margin-bottom: 4px; } +.link-picker { border: 1px solid var(--border); padding: 10px 12px 12px; margin: 0; min-width: 0; border-color: var(--border); border-radius: var(--radius-m); } +.link-picker legend { font-size: 0.8rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; padding: 0 6px; } +.link-picker legend small { font-weight: 400; color: var(--muted); text-transform: none; letter-spacing: 0; } +.link-picker ul { list-style: none; margin: 8px 0 0; padding: 0; max-height: 200px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; } +.link-picker .checkbox { text-transform: none !important; letter-spacing: 0 !important; font-weight: 400 !important; font-size: 0.9rem !important; padding: 4px 0; } +.link-picker input[type='search'] { margin-top: 4px; } +.form label.checkbox input[type='radio'] { width: 18px; height: 18px; min-height: 0; padding: 0; margin: 0; border: 0; background: none; box-shadow: none; accent-color: var(--accent); flex: none; } diff --git a/frontend/src/styles/designs/blackwall.css b/frontend/src/styles/designs/blackwall.css new file mode 100644 index 0000000..a5d183b --- /dev/null +++ b/frontend/src/styles/designs/blackwall.css @@ -0,0 +1,325 @@ +/* ============================================================ + BLACKWALL – Cyberpunk / Netrunner + Schwarz-Rot wie die Datenwand, Cyan als Gegenfarbe (Fokus, Links, "online"). + Abgeschrägte Ecken mit nachgezogener Kante, Panels mit Kopfstreifen, chromatisch + versetzte Seitentitel, seltener Glitch. Chakra Petch für Text, Oxanium für Titel. + ============================================================ */ +html[data-theme='blackwall'] { + --bw-red: #ff2d6f; + --bw-red-deep: #8a0f3c; + --bw-cyan: #3ff6ff; + --bw-yellow: #f6e34a; + + --accent-rgb: 255 45 111; + --bg: #060104; + --surface: rgb(14 2 6 / 0.9); + --surface-hover: rgb(30 5 12 / 0.95); + --surface-2: #19050b; + --border: rgb(255 45 111 / 0.24); + --line-strong: rgb(255 45 111 / 0.6); + --accent: var(--bw-red); + --accent-ink: #12020a; + --accent-soft: rgb(255 45 111 / 0.13); + --text: #f1d6da; + --read: #f6e6e8; + --bright: #fff3f4; + --muted: #c48a93; + --ok: var(--bw-cyan); + --warn: var(--bw-yellow); + --bad: #ff3b30; + --bad-glow: rgb(255 59 48 / 0.55); + --series-1: #ff2d6f; + --series-2: #00a8b0; + --topbar-bg: rgb(6 1 4 / 0.72); + --glow: 0 0 8px rgb(255 45 111 / 0.55), 0 0 26px rgb(255 45 111 / 0.2); + --heading-glow: -2px 0 0 rgb(63 246 255 / 0.55), 2px 0 0 rgb(255 45 111 / 0.75), 0 0 22px rgb(255 45 111 / 0.35); + --text-glow: none; + --input-bg: rgb(4 1 3 / 0.88); + --card-inner: rgb(10 2 5 / 0.94); + --panel: rgb(13 2 7 / 0.97); + --overlay: rgb(6 1 4 / 0.88); + --backdrop: rgb(2 0 1 / 0.7); + --editor-bg: rgb(4 1 3 / 0.92); + --map-ocean: #060104; + --map-land: #1d060c; + --map-land-hover: #3a0b17; + /* Eigene Punkte sind hier Cyan, darum andere Farben für die übrigen Konten */ + --other-1: #f6e34a; + --other-2: #b388ff; + --other-3: #7dff9e; + --other-4: #ff8a3d; + --other-5: #ffffff; + --other-6: #5c7cff; + + --radius-s: 0px; + --radius-m: 0px; + --radius-l: 0px; + --shadow-1: inset 0 1px 0 rgb(255 45 111 / 0.08), 0 18px 40px -28px #000; + --shadow-2: 0 30px 90px -30px #000, 0 0 0 1px rgb(255 45 111 / 0.22), 0 0 50px -16px rgb(255 45 111 / 0.35); + --focus-ring: 0 0 0 2px var(--bw-cyan), 0 0 14px rgb(63 246 255 / 0.35); + --blur: blur(10px) saturate(1.2); + --cut: 14px; + + --font: 'Chakra Petch', 'Segoe UI', system-ui, sans-serif; + --font-display: 'Oxanium', 'Chakra Petch', sans-serif; + --font-heading: 'Chakra Petch', 'Segoe UI', sans-serif; + --font-label: 'Chakra Petch', 'Segoe UI', sans-serif; + --body-size: clamp(15px, 0.92rem + 0.15vw, 16.5px); + --h1-font: 'Oxanium', 'Chakra Petch', sans-serif; + --h1-size: clamp(2rem, 3.4vw, 3.1rem); + --h1-weight: 800; + --h1-tracking: 0.04em; + --h2-size: 1.12rem; + --h3-size: 1.02rem; + --heading-weight: 600; + --heading-tracking: 0.08em; + --label-size: 0.7rem; + --label-tracking: 0.16em; + --tile-font: 'Oxanium', 'Chakra Petch', sans-serif; + --tile-size: 1.05rem; + + background: + radial-gradient(ellipse 70% 50% at 100% 0%, rgb(138 15 60 / 0.35), transparent 70%), + radial-gradient(ellipse 60% 45% at 0% 100%, rgb(138 15 60 / 0.28), transparent 70%), + #060104; + background-attachment: fixed; +} +html[data-theme='blackwall'] ::selection { background: var(--bw-cyan); color: #000; } +html[data-theme='blackwall'] :focus-visible { outline: 2px solid var(--bw-cyan); outline-offset: 2px; } +html[data-theme='blackwall'] * { scrollbar-color: var(--bw-red-deep) transparent; } +/* feine Bildschirmzeilen, kaum sichtbar */ +html[data-theme='blackwall'] body::after { + content: ''; + background: repeating-linear-gradient(to bottom, transparent 0 2px, rgb(0 0 0 / 0.14) 2px 3px); +} +.blackwall-field { width: 100%; height: 100%; opacity: 0.92; } +/* Text, der frei vor dem Lichtband steht: dunkler Halo nur unter der Schrift (statt Vollflächen-Abdunklung) */ +html[data-theme='blackwall'] .lead, +html[data-theme='blackwall'] .hint, +html[data-theme='blackwall'] .back, +html[data-theme='blackwall'] .section-title, +html[data-theme='blackwall'] .tiles-head .link-btn, +html[data-theme='blackwall'] .page-head .link-btn, +html[data-theme='blackwall'] .kanban-filter, +html[data-theme='blackwall'] .footer, +html[data-theme='blackwall'] .travel-credits, +html[data-theme='blackwall'] .recent .chip { text-shadow: 0 0 3px #000, 0 0 10px #000, 0 0 18px rgb(0 0 0 / 0.8); } +html[data-theme='blackwall'] h1 { text-shadow: var(--heading-glow), 0 0 24px rgb(0 0 0 / 0.9); } +html[data-theme='blackwall'] body { font-weight: 500; } +/* Links allgemein cyan, aber Navigation, Marke und Menü behalten ihre eigenen Farben */ +html[data-theme='blackwall'] .brand, +html[data-theme='blackwall'] .brand:hover { color: var(--bright); } +html[data-theme='blackwall'] .topnav a { color: var(--muted); } +html[data-theme='blackwall'] .topnav a:hover { color: var(--bright); } +html[data-theme='blackwall'] .topnav a.active { color: #12020a; } +html[data-theme='blackwall'] .menu-panel a { color: var(--text); } +html[data-theme='blackwall'] .menu-panel a:hover { color: var(--bright); } +html[data-theme='blackwall'] .menu-panel a.active { color: #12020a; } +html[data-theme='blackwall'] .tile, html[data-theme='blackwall'] .tile:hover, +html[data-theme='blackwall'] .project-card, html[data-theme='blackwall'] .kanban-project-link { color: var(--text); } + +/* Seitentitel: chromatisch versetzt, mit Kennung davor */ +html[data-theme='blackwall'] h1 { color: var(--bright); text-transform: uppercase; } +html[data-theme='blackwall'] .page-head h1::before { + content: '//'; + margin-right: 0.3em; + color: var(--bw-red); + text-shadow: none; +} +html[data-theme='blackwall'] h2, html[data-theme='blackwall'] h3 { color: var(--bright); } +html[data-theme='blackwall'] .lead { color: var(--muted); } +html[data-theme='blackwall'] .lead::before { content: '> '; color: var(--bw-cyan); } +html[data-theme='blackwall'] .section-title::before, +html[data-theme='blackwall'] .household-head h2::before { + content: ''; + display: inline-block; + width: 10px; + height: 10px; + margin-right: 10px; + background: var(--bw-red); + clip-path: polygon(0 0, 100% 0, 100% 100%); + vertical-align: 0.05em; +} +html[data-theme='blackwall'] .error::before { content: '⚠ '; } +html[data-theme='blackwall'] .notice::before { content: '!! '; color: var(--bw-yellow); font-weight: 700; } +html[data-theme='blackwall'] a { color: var(--bw-cyan); text-decoration-style: solid; text-decoration-color: rgb(63 246 255 / 0.4); } +html[data-theme='blackwall'] a:hover { color: var(--bright); } + +/* Kopfzeile: Marke mit Glitch beim Überfahren, roter Kantenstrich mit Lücke */ +html[data-theme='blackwall'] .topbar { border-bottom: 1px solid rgb(255 45 111 / 0.35); } +html[data-theme='blackwall'] .topbar::after { + content: ''; + position: absolute; + left: var(--gutter); + bottom: -2px; + width: 180px; + height: 3px; + background: var(--bw-red); + box-shadow: 0 0 12px rgb(255 45 111 / 0.7); + clip-path: polygon(0 0, 100% 0, calc(100% - 3px) 100%, 0 100%); +} +html[data-theme='blackwall'] .brand { + font-family: var(--font-display); + font-weight: 800; + font-size: 1.25rem; + letter-spacing: 0.12em; + text-shadow: -1px 0 0 rgb(63 246 255 / 0.5), 1px 0 0 rgb(255 45 111 / 0.7); +} +html[data-theme='blackwall'] .brand span { color: var(--bw-red); } +html[data-theme='blackwall'] .brand:hover { animation: bw-glitch 0.4s steps(2) 1; } +@keyframes bw-glitch { + 0% { clip-path: inset(0 0 0 0); transform: translateX(0); } + 20% { clip-path: inset(10% 0 55% 0); transform: translateX(-3px); } + 40% { clip-path: inset(60% 0 8% 0); transform: translateX(3px); } + 60% { clip-path: inset(30% 0 35% 0); transform: translateX(-2px); } + 100% { clip-path: inset(0 0 0 0); transform: translateX(0); } +} +html[data-theme='blackwall'] .topnav a { font-family: var(--font-label); font-weight: 600; font-size: 0.78rem; letter-spacing: 0.14em; border: 0; border-radius: 0; position: relative; } +html[data-theme='blackwall'] .topnav a:hover { color: var(--bright); background: var(--accent-soft); } +html[data-theme='blackwall'] .topnav a.active { color: #12020a; background: var(--bw-red); clip-path: polygon(0 0, 100% 0, 100% calc(100% - 7px), calc(100% - 7px) 100%, 0 100%); } +html[data-theme='blackwall'] .menu-btn { border-radius: 0; border-color: var(--line-strong); color: var(--bw-red); } +html[data-theme='blackwall'] .menu-btn:hover, +html[data-theme='blackwall'] .menu-btn[aria-expanded='true'] { background: var(--bw-red); color: #12020a; } +html[data-theme='blackwall'] .menu-panel { border-top: 2px solid var(--bw-red); } +html[data-theme='blackwall'] .menu-panel a, html[data-theme='blackwall'] .menu-item { font-weight: 500; letter-spacing: 0.08em; } +html[data-theme='blackwall'] .menu-panel a.active { background: var(--bw-red); color: #12020a; } +html[data-theme='blackwall'] .theme-option[aria-checked='true'] { box-shadow: inset 3px 0 0 var(--bw-cyan); } + +/* Panels: rechts oben abgeschrägt (Kante wird nachgezogen), roter Kopfstreifen links oben */ +html[data-theme='blackwall'] .info-card { clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, 0 100%); } +html[data-theme='blackwall'] .card, +html[data-theme='blackwall'] .tile, +html[data-theme='blackwall'] .board-column, +html[data-theme='blackwall'] .article-page:not(.editing) .article-main { + position: relative; +} +html[data-theme='blackwall'] .card, +html[data-theme='blackwall'] .tile, +html[data-theme='blackwall'] .board-column, +html[data-theme='blackwall'] .modal, +html[data-theme='blackwall'] .article-page:not(.editing) .article-main { + clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, 0 100%); +} +html[data-theme='blackwall'] .card::after, +html[data-theme='blackwall'] .tile::after, +html[data-theme='blackwall'] .board-column::after, +html[data-theme='blackwall'] .modal::after, +html[data-theme='blackwall'] .info-card::after, +html[data-theme='blackwall'] .article-page:not(.editing) .article-main::after { + content: ''; + position: absolute; + top: 0; + right: 0; + width: var(--cut); + height: var(--cut); + pointer-events: none; + background: linear-gradient(to top right, transparent calc(50% - 1px), var(--line-strong) calc(50% - 1px) calc(50% + 0.5px), transparent calc(50% + 0.5px)); +} +html[data-theme='blackwall'] .card::before, +html[data-theme='blackwall'] .tile::before, +html[data-theme='blackwall'] .board-column::before, +html[data-theme='blackwall'] .info-card::before { + content: ''; + position: absolute; + left: -1px; + top: -1px; + width: 54px; + height: 3px; + background: var(--bw-red); + box-shadow: 0 0 10px rgb(255 45 111 / 0.6); + pointer-events: none; +} +html[data-theme='blackwall'] .tile:hover, +html[data-theme='blackwall'] .project-card:hover, +html[data-theme='blackwall'] .kanban-project-card:hover, +html[data-theme='blackwall'] .task-card:hover { + border-color: var(--line-strong); + background-color: var(--surface-hover); + box-shadow: var(--shadow-1), inset 0 0 0 1px rgb(255 45 111 / 0.25), 0 0 30px -10px rgb(255 45 111 / 0.5); +} +html[data-theme='blackwall'] .tile svg { color: var(--bw-red); background: rgb(255 45 111 / 0.1); box-shadow: inset 0 0 0 1px rgb(255 45 111 / 0.35); } +html[data-theme='blackwall'] .tile:hover svg { color: var(--bw-cyan); box-shadow: inset 0 0 0 1px rgb(63 246 255 / 0.5); background: rgb(63 246 255 / 0.08); } +html[data-theme='blackwall'] .tile strong { font-weight: 700; letter-spacing: 0.08em; } +html[data-theme='blackwall'] .modal { border-color: var(--line-strong); } +html[data-theme='blackwall'] .modal h2 { font-family: var(--font-display); font-weight: 700; text-transform: uppercase; } + +/* Buttons: gefüllt rot mit Schräge; umrandet in Cyan */ +html[data-theme='blackwall'] .btn { font-family: var(--font-label); font-weight: 600; letter-spacing: 0.12em; border-radius: 0; } +html[data-theme='blackwall'] .btn:not(.ghost) { + background: var(--bw-red); + border-color: var(--bw-red); + color: #12020a; + clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%); + box-shadow: 0 0 24px -6px rgb(255 45 111 / 0.8); +} +html[data-theme='blackwall'] .btn:not(.ghost):hover:not(:disabled) { background: var(--bright); border-color: var(--bright); } +html[data-theme='blackwall'] .btn.ghost { color: var(--bw-cyan); border-color: rgb(63 246 255 / 0.45); background: rgb(63 246 255 / 0.04); } +html[data-theme='blackwall'] .btn.ghost:hover:not(:disabled) { color: #001417; background: var(--bw-cyan); border-color: var(--bw-cyan); } +html[data-theme='blackwall'] .btn.ghost.danger-btn { color: var(--bad); border-color: rgb(255 59 48 / 0.5); background: transparent; } +html[data-theme='blackwall'] .btn.ghost.danger-btn:hover:not(:disabled) { background: var(--bad); color: #12020a; } +html[data-theme='blackwall'] .link-btn { color: var(--bw-cyan); font-weight: 600; } +html[data-theme='blackwall'] .link-btn:hover { color: var(--bright); } +html[data-theme='blackwall'] .link-btn.danger { color: var(--bad); } + +/* Status: eckige Tags; "online" in Cyan, Warnung gelb */ +html[data-theme='blackwall'] .badge { border-radius: 0; font-weight: 700; letter-spacing: 0.12em; clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 0 100%); } +html[data-theme='blackwall'] .badge::before { border-radius: 0; width: 5px; height: 5px; } +html[data-theme='blackwall'] .chip { border-radius: 0; font-weight: 600; } +html[data-theme='blackwall'] .chip.active { border-color: var(--bw-cyan); color: var(--bw-cyan); background: rgb(63 246 255 / 0.08); } +html[data-theme='blackwall'] .dot { border-radius: 0; } +html[data-theme='blackwall'] .monitor-card.ok { border-left-color: var(--bw-cyan); } +html[data-theme='blackwall'] .monitor-card.ok h3 { color: var(--bw-cyan); } +html[data-theme='blackwall'] .board-column.arbeit { border-top-color: var(--bw-red); } +html[data-theme='blackwall'] .board-column.wartet { border-top-color: var(--bw-yellow); } +html[data-theme='blackwall'] .board-column.erledigt { border-top-color: var(--bw-cyan); } +html[data-theme='blackwall'] .board-head h2 { font-family: var(--font-display); font-weight: 700; letter-spacing: 0.1em; } +html[data-theme='blackwall'] .status-bar .arbeit { background: var(--bw-red); } +html[data-theme='blackwall'] .status-bar .wartet { background: var(--bw-yellow); } +html[data-theme='blackwall'] .status-bar .erledigt { background: var(--bw-cyan); } +html[data-theme='blackwall'] .avatar { border-radius: 0; background: var(--bw-red); color: #12020a; } +html[data-theme='blackwall'] .task-title, html[data-theme='blackwall'] .household-name strong { font-weight: 600; letter-spacing: 0.02em; } +html[data-theme='blackwall'] .drop-line { background: var(--bw-cyan); box-shadow: 0 0 10px rgb(63 246 255 / 0.7); } +html[data-theme='blackwall'] .household-check { border-color: rgb(63 246 255 / 0.55); } +html[data-theme='blackwall'] .recipe-take:checked { background: var(--bw-cyan); } +html[data-theme='blackwall'] .stepper button { color: var(--bw-red); } +html[data-theme='blackwall'] .segmented button[aria-selected='true'] { background: var(--bw-red); color: #12020a; } +html[data-theme='blackwall'] .stepper-value, html[data-theme='blackwall'] .monitor-facts dd, html[data-theme='blackwall'] .fact dd, html[data-theme='blackwall'] .info-facts dd { font-variant-numeric: tabular-nums; } + +/* Artikel */ +html[data-theme='blackwall'] .article-title { font-family: var(--font-display); font-weight: 800; } +html[data-theme='blackwall'] .article-body h2 { font-family: var(--font-display); font-size: 1.6em; color: var(--bright); } +html[data-theme='blackwall'] .article-body h2::before { content: '// '; color: var(--bw-red); } +html[data-theme='blackwall'] .article-body h3 { color: var(--bw-cyan); font-size: 1.2em; } +html[data-theme='blackwall'] .article-body ul > li::before { content: '▸'; color: var(--bw-red); } +html[data-theme='blackwall'] .article-body blockquote { border-left-color: var(--bw-cyan); } +html[data-theme='blackwall'] .article-lead { border-left-color: var(--bw-red); } +html[data-theme='blackwall'] .project-cover { filter: saturate(0.75) contrast(1.05); } + +/* Karte */ +html[data-theme='blackwall'] .map-graticule { stroke: rgb(255 45 111 / 0.08); } +html[data-theme='blackwall'] .map-country { stroke: rgb(255 45 111 / 0.4); } +html[data-theme='blackwall'] .map-country.visited { fill: rgb(255 45 111 / 0.55); stroke: var(--bw-red); } +html[data-theme='blackwall'] .map-country.selected { stroke: var(--bw-cyan); } +html[data-theme='blackwall'] .map-city-dot { fill: var(--bw-cyan); stroke: #001417; filter: drop-shadow(0 0 4px rgb(63 246 255 / 0.9)); } +html[data-theme='blackwall'] .map-city-ring { stroke: var(--bw-cyan); } +html[data-theme='blackwall'] .map-city.other .map-city-dot { fill: var(--dot); stroke: #000; filter: drop-shadow(0 0 4px var(--dot)); } +html[data-theme='blackwall'] .map-city.other .map-city-ring { stroke: var(--dot); } +html[data-theme='blackwall'] .legend-dot.own { background: var(--bw-cyan); box-shadow: 0 0 4px var(--bw-cyan); } + +/* Ruhe: kein Glitch, wenn Bewegung reduziert oder Animation aus */ +html.calm[data-theme='blackwall'] .brand:hover { animation: none; } +@media (prefers-reduced-motion: reduce) { + html[data-theme='blackwall'] .brand:hover { animation: none; } +} +@media (max-width: 640px) { + html[data-theme='blackwall'] { --h1-size: 1.6rem; --tile-size: 0.86rem; --cut: 10px; } + html[data-theme='blackwall'] h1 { overflow-wrap: anywhere; } + html[data-theme='blackwall'] .brand { letter-spacing: 0.06em; font-size: 1.05rem; } + html[data-theme='blackwall'] .tile strong { letter-spacing: 0.03em; } +} +/* Leere Kachel nicht durchsichtig: sonst steht ihr Text im hellen Lichtband */ +html[data-theme='blackwall'] .tile-empty { background: var(--surface); border-style: dashed; } +/* Umrandete Buttons mit dunklem Grund, damit sie vor dem Lichtband lesbar bleiben */ +html[data-theme='blackwall'] .btn.ghost { background-color: rgb(6 1 4 / 0.88); } +html[data-theme='blackwall'] .btn.ghost.danger-btn { background: rgb(6 1 4 / 0.88); color: #ff6a60; } +html[data-theme='blackwall'] .kanban-filter span { color: var(--text); } diff --git a/frontend/src/themes.css b/frontend/src/styles/designs/fabrik.css similarity index 53% rename from frontend/src/themes.css rename to frontend/src/styles/designs/fabrik.css index 6a3ce25..6a2f749 100644 --- a/frontend/src/themes.css +++ b/frontend/src/styles/designs/fabrik.css @@ -1,378 +1,3 @@ -/* ============================================================ - Designs: Blackwall (Cyberpunk), Fabrik (Industrie-UI à la Satisfactory) - Das Matrix-Design sind die Standardwerte in styles.css. Jedes Design setzt hier vor allem - Tokens (Farbrollen, Schrift, Form) und nur noch seine Erkennungsmerkmale. - Inspiriert von den Vorbildern: keine Original-Logos, freie Schriften (OFL), alles lokal. - ============================================================ */ - -/* ---------- Gemeinsam ---------- */ -.theme-bg { position: fixed; inset: 0; z-index: -1; pointer-events: none; } - -/* Design-Auswahl im Menü */ -.menu-panel { max-height: calc(100vh - var(--topbar-h) - 16px); overflow-y: auto; } -.menu-label { padding: 8px 12px 4px; font-size: var(--label-size); color: var(--muted); text-transform: uppercase; letter-spacing: var(--label-tracking); } -.theme-picker { display: flex; flex-direction: column; gap: 2px; } -.menu-item.theme-option { display: flex; align-items: center; gap: 12px; } -.theme-option .swatch { display: inline-flex; flex: none; border-radius: 4px; overflow: hidden; box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.12); } -.theme-option .swatch i { width: 9px; height: 22px; } -.theme-name { display: flex; flex-direction: column; line-height: 1.25; } -.theme-name small { font-size: 0.7rem; text-transform: none; letter-spacing: 0.02em; color: var(--muted); } -.theme-option[aria-checked='true'] { color: var(--bright); background: var(--accent-soft); box-shadow: inset 2px 0 0 var(--accent); } -.theme-option[aria-checked='true'] .theme-name::after { content: '✓ aktiv'; font-size: 0.68rem; color: var(--accent); } - -/* Matrix-Zierrat in den anderen Designs abschalten (jedes Design setzt eigenen) */ -html:not([data-theme='matrix']) body::after, -html:not([data-theme='matrix']) .page-head h1::after, -html:not([data-theme='matrix']) .hero h1::after, -html:not([data-theme='matrix']) .brand::before, -html:not([data-theme='matrix']) .lead::before, -html:not([data-theme='matrix']) .section-title::before, -html:not([data-theme='matrix']) .household-head h2::before, -html:not([data-theme='matrix']) .article-body h2::before, -html:not([data-theme='matrix']) .article-body h3::before, -html:not([data-theme='matrix']) .menu-panel a::before, -html:not([data-theme='matrix']) .menu-item::before, -html:not([data-theme='matrix']) .topnav a.active::before, -html:not([data-theme='matrix']) .notice::before, -html:not([data-theme='matrix']) .error::before, -html:not([data-theme='matrix']) .prompt-input::before, -html:not([data-theme='matrix']) .combo-list li::before { content: none; } -html:not([data-theme='matrix']) .track-form input { padding-left: 18px; } -html:not([data-theme='matrix']) .city-search input { padding-left: 16px; } -html:not([data-theme='matrix']) .article-body ul > li::before { content: '●'; } -html:not([data-theme='matrix']) .tile strong { overflow-wrap: anywhere; max-width: 100%; } - -@keyframes theme-spin { to { transform: rotate(360deg); } } -@keyframes theme-scan { from { transform: translateY(-10vh); } to { transform: translateY(110vh); } } - - -/* ============================================================ - BLACKWALL – Cyberpunk / Netrunner - Schwarz-Rot wie die Datenwand, Cyan als Gegenfarbe (Fokus, Links, "online"). - Abgeschrägte Ecken mit nachgezogener Kante, Panels mit Kopfstreifen, chromatisch - versetzte Seitentitel, seltener Glitch. Chakra Petch für Text, Oxanium für Titel. - ============================================================ */ -html[data-theme='blackwall'] { - --bw-red: #ff2d6f; - --bw-red-deep: #8a0f3c; - --bw-cyan: #3ff6ff; - --bw-yellow: #f6e34a; - - --accent-rgb: 255 45 111; - --bg: #060104; - --surface: rgb(14 2 6 / 0.9); - --surface-hover: rgb(30 5 12 / 0.95); - --surface-2: #19050b; - --border: rgb(255 45 111 / 0.24); - --line-strong: rgb(255 45 111 / 0.6); - --accent: var(--bw-red); - --accent-ink: #12020a; - --accent-soft: rgb(255 45 111 / 0.13); - --text: #f1d6da; - --read: #f6e6e8; - --bright: #fff3f4; - --muted: #c48a93; - --ok: var(--bw-cyan); - --warn: var(--bw-yellow); - --bad: #ff3b30; - --bad-glow: rgb(255 59 48 / 0.55); - --series-1: #ff2d6f; - --series-2: #00a8b0; - --topbar-bg: rgb(6 1 4 / 0.72); - --glow: 0 0 8px rgb(255 45 111 / 0.55), 0 0 26px rgb(255 45 111 / 0.2); - --heading-glow: -2px 0 0 rgb(63 246 255 / 0.55), 2px 0 0 rgb(255 45 111 / 0.75), 0 0 22px rgb(255 45 111 / 0.35); - --text-glow: none; - --input-bg: rgb(4 1 3 / 0.88); - --card-inner: rgb(10 2 5 / 0.94); - --panel: rgb(13 2 7 / 0.97); - --overlay: rgb(6 1 4 / 0.88); - --backdrop: rgb(2 0 1 / 0.7); - --editor-bg: rgb(4 1 3 / 0.92); - --map-ocean: #060104; - --map-land: #1d060c; - --map-land-hover: #3a0b17; - /* Eigene Punkte sind hier Cyan, darum andere Farben für die übrigen Konten */ - --other-1: #f6e34a; - --other-2: #b388ff; - --other-3: #7dff9e; - --other-4: #ff8a3d; - --other-5: #ffffff; - --other-6: #5c7cff; - - --radius-s: 0px; - --radius-m: 0px; - --radius-l: 0px; - --shadow-1: inset 0 1px 0 rgb(255 45 111 / 0.08), 0 18px 40px -28px #000; - --shadow-2: 0 30px 90px -30px #000, 0 0 0 1px rgb(255 45 111 / 0.22), 0 0 50px -16px rgb(255 45 111 / 0.35); - --focus-ring: 0 0 0 2px var(--bw-cyan), 0 0 14px rgb(63 246 255 / 0.35); - --blur: blur(10px) saturate(1.2); - --cut: 14px; - - --font: 'Chakra Petch', 'Segoe UI', system-ui, sans-serif; - --font-display: 'Oxanium', 'Chakra Petch', sans-serif; - --font-heading: 'Chakra Petch', 'Segoe UI', sans-serif; - --font-label: 'Chakra Petch', 'Segoe UI', sans-serif; - --body-size: clamp(15px, 0.92rem + 0.15vw, 16.5px); - --h1-font: 'Oxanium', 'Chakra Petch', sans-serif; - --h1-size: clamp(2rem, 3.4vw, 3.1rem); - --h1-weight: 800; - --h1-tracking: 0.04em; - --h2-size: 1.12rem; - --h3-size: 1.02rem; - --heading-weight: 600; - --heading-tracking: 0.08em; - --label-size: 0.7rem; - --label-tracking: 0.16em; - --tile-font: 'Oxanium', 'Chakra Petch', sans-serif; - --tile-size: 1.05rem; - - background: - radial-gradient(ellipse 70% 50% at 100% 0%, rgb(138 15 60 / 0.35), transparent 70%), - radial-gradient(ellipse 60% 45% at 0% 100%, rgb(138 15 60 / 0.28), transparent 70%), - #060104; - background-attachment: fixed; -} -html[data-theme='blackwall'] ::selection { background: var(--bw-cyan); color: #000; } -html[data-theme='blackwall'] :focus-visible { outline: 2px solid var(--bw-cyan); outline-offset: 2px; } -html[data-theme='blackwall'] * { scrollbar-color: var(--bw-red-deep) transparent; } -/* feine Bildschirmzeilen, kaum sichtbar */ -html[data-theme='blackwall'] body::after { - content: ''; - background: repeating-linear-gradient(to bottom, transparent 0 2px, rgb(0 0 0 / 0.14) 2px 3px); -} -.blackwall-field { width: 100%; height: 100%; opacity: 0.92; } -/* Text, der frei vor dem Lichtband steht: dunkler Halo nur unter der Schrift (statt Vollflächen-Abdunklung) */ -html[data-theme='blackwall'] .lead, -html[data-theme='blackwall'] .hint, -html[data-theme='blackwall'] .back, -html[data-theme='blackwall'] .section-title, -html[data-theme='blackwall'] .tiles-head .link-btn, -html[data-theme='blackwall'] .page-head .link-btn, -html[data-theme='blackwall'] .kanban-filter, -html[data-theme='blackwall'] .footer, -html[data-theme='blackwall'] .travel-credits, -html[data-theme='blackwall'] .recent .chip { text-shadow: 0 0 3px #000, 0 0 10px #000, 0 0 18px rgb(0 0 0 / 0.8); } -html[data-theme='blackwall'] h1 { text-shadow: var(--heading-glow), 0 0 24px rgb(0 0 0 / 0.9); } -html[data-theme='blackwall'] body { font-weight: 500; } -/* Links allgemein cyan, aber Navigation, Marke und Menü behalten ihre eigenen Farben */ -html[data-theme='blackwall'] .brand, -html[data-theme='blackwall'] .brand:hover { color: var(--bright); } -html[data-theme='blackwall'] .topnav a { color: var(--muted); } -html[data-theme='blackwall'] .topnav a:hover { color: var(--bright); } -html[data-theme='blackwall'] .topnav a.active { color: #12020a; } -html[data-theme='blackwall'] .menu-panel a { color: var(--text); } -html[data-theme='blackwall'] .menu-panel a:hover { color: var(--bright); } -html[data-theme='blackwall'] .menu-panel a.active { color: #12020a; } -html[data-theme='blackwall'] .tile, html[data-theme='blackwall'] .tile:hover, -html[data-theme='blackwall'] .project-card, html[data-theme='blackwall'] .kanban-project-link { color: var(--text); } - -/* Seitentitel: chromatisch versetzt, mit Kennung davor */ -html[data-theme='blackwall'] h1 { color: var(--bright); text-transform: uppercase; } -html[data-theme='blackwall'] .page-head h1::before { - content: '//'; - margin-right: 0.3em; - color: var(--bw-red); - text-shadow: none; -} -html[data-theme='blackwall'] h2, html[data-theme='blackwall'] h3 { color: var(--bright); } -html[data-theme='blackwall'] .lead { color: var(--muted); } -html[data-theme='blackwall'] .lead::before { content: '> '; color: var(--bw-cyan); } -html[data-theme='blackwall'] .section-title::before, -html[data-theme='blackwall'] .household-head h2::before { - content: ''; - display: inline-block; - width: 10px; - height: 10px; - margin-right: 10px; - background: var(--bw-red); - clip-path: polygon(0 0, 100% 0, 100% 100%); - vertical-align: 0.05em; -} -html[data-theme='blackwall'] .error::before { content: '⚠ '; } -html[data-theme='blackwall'] .notice::before { content: '!! '; color: var(--bw-yellow); font-weight: 700; } -html[data-theme='blackwall'] a { color: var(--bw-cyan); text-decoration-style: solid; text-decoration-color: rgb(63 246 255 / 0.4); } -html[data-theme='blackwall'] a:hover { color: var(--bright); } - -/* Kopfzeile: Marke mit Glitch beim Überfahren, roter Kantenstrich mit Lücke */ -html[data-theme='blackwall'] .topbar { border-bottom: 1px solid rgb(255 45 111 / 0.35); } -html[data-theme='blackwall'] .topbar::after { - content: ''; - position: absolute; - left: var(--gutter); - bottom: -2px; - width: 180px; - height: 3px; - background: var(--bw-red); - box-shadow: 0 0 12px rgb(255 45 111 / 0.7); - clip-path: polygon(0 0, 100% 0, calc(100% - 3px) 100%, 0 100%); -} -html[data-theme='blackwall'] .brand { - font-family: var(--font-display); - font-weight: 800; - font-size: 1.25rem; - letter-spacing: 0.12em; - text-shadow: -1px 0 0 rgb(63 246 255 / 0.5), 1px 0 0 rgb(255 45 111 / 0.7); -} -html[data-theme='blackwall'] .brand span { color: var(--bw-red); } -html[data-theme='blackwall'] .brand:hover { animation: bw-glitch 0.4s steps(2) 1; } -@keyframes bw-glitch { - 0% { clip-path: inset(0 0 0 0); transform: translateX(0); } - 20% { clip-path: inset(10% 0 55% 0); transform: translateX(-3px); } - 40% { clip-path: inset(60% 0 8% 0); transform: translateX(3px); } - 60% { clip-path: inset(30% 0 35% 0); transform: translateX(-2px); } - 100% { clip-path: inset(0 0 0 0); transform: translateX(0); } -} -html[data-theme='blackwall'] .topnav a { font-family: var(--font-label); font-weight: 600; font-size: 0.78rem; letter-spacing: 0.14em; border: 0; border-radius: 0; position: relative; } -html[data-theme='blackwall'] .topnav a:hover { color: var(--bright); background: var(--accent-soft); } -html[data-theme='blackwall'] .topnav a.active { color: #12020a; background: var(--bw-red); clip-path: polygon(0 0, 100% 0, 100% calc(100% - 7px), calc(100% - 7px) 100%, 0 100%); } -html[data-theme='blackwall'] .menu-btn { border-radius: 0; border-color: var(--line-strong); color: var(--bw-red); } -html[data-theme='blackwall'] .menu-btn:hover, -html[data-theme='blackwall'] .menu-btn[aria-expanded='true'] { background: var(--bw-red); color: #12020a; } -html[data-theme='blackwall'] .menu-panel { border-top: 2px solid var(--bw-red); } -html[data-theme='blackwall'] .menu-panel a, html[data-theme='blackwall'] .menu-item { font-weight: 500; letter-spacing: 0.08em; } -html[data-theme='blackwall'] .menu-panel a.active { background: var(--bw-red); color: #12020a; } -html[data-theme='blackwall'] .theme-option[aria-checked='true'] { box-shadow: inset 3px 0 0 var(--bw-cyan); } - -/* Panels: rechts oben abgeschrägt (Kante wird nachgezogen), roter Kopfstreifen links oben */ -html[data-theme='blackwall'] .info-card { clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, 0 100%); } -html[data-theme='blackwall'] .card, -html[data-theme='blackwall'] .tile, -html[data-theme='blackwall'] .board-column, -html[data-theme='blackwall'] .article-page:not(.editing) .article-main { - position: relative; -} -html[data-theme='blackwall'] .card, -html[data-theme='blackwall'] .tile, -html[data-theme='blackwall'] .board-column, -html[data-theme='blackwall'] .modal, -html[data-theme='blackwall'] .article-page:not(.editing) .article-main { - clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, 0 100%); -} -html[data-theme='blackwall'] .card::after, -html[data-theme='blackwall'] .tile::after, -html[data-theme='blackwall'] .board-column::after, -html[data-theme='blackwall'] .modal::after, -html[data-theme='blackwall'] .info-card::after, -html[data-theme='blackwall'] .article-page:not(.editing) .article-main::after { - content: ''; - position: absolute; - top: 0; - right: 0; - width: var(--cut); - height: var(--cut); - pointer-events: none; - background: linear-gradient(to top right, transparent calc(50% - 1px), var(--line-strong) calc(50% - 1px) calc(50% + 0.5px), transparent calc(50% + 0.5px)); -} -html[data-theme='blackwall'] .card::before, -html[data-theme='blackwall'] .tile::before, -html[data-theme='blackwall'] .board-column::before, -html[data-theme='blackwall'] .info-card::before { - content: ''; - position: absolute; - left: -1px; - top: -1px; - width: 54px; - height: 3px; - background: var(--bw-red); - box-shadow: 0 0 10px rgb(255 45 111 / 0.6); - pointer-events: none; -} -html[data-theme='blackwall'] .tile:hover, -html[data-theme='blackwall'] .project-card:hover, -html[data-theme='blackwall'] .kanban-project-card:hover, -html[data-theme='blackwall'] .task-card:hover { - border-color: var(--line-strong); - background-color: var(--surface-hover); - box-shadow: var(--shadow-1), inset 0 0 0 1px rgb(255 45 111 / 0.25), 0 0 30px -10px rgb(255 45 111 / 0.5); -} -html[data-theme='blackwall'] .tile svg { color: var(--bw-red); background: rgb(255 45 111 / 0.1); box-shadow: inset 0 0 0 1px rgb(255 45 111 / 0.35); } -html[data-theme='blackwall'] .tile:hover svg { color: var(--bw-cyan); box-shadow: inset 0 0 0 1px rgb(63 246 255 / 0.5); background: rgb(63 246 255 / 0.08); } -html[data-theme='blackwall'] .tile strong { font-weight: 700; letter-spacing: 0.08em; } -html[data-theme='blackwall'] .modal { border-color: var(--line-strong); } -html[data-theme='blackwall'] .modal h2 { font-family: var(--font-display); font-weight: 700; text-transform: uppercase; } - -/* Buttons: gefüllt rot mit Schräge; umrandet in Cyan */ -html[data-theme='blackwall'] .btn { font-family: var(--font-label); font-weight: 600; letter-spacing: 0.12em; border-radius: 0; } -html[data-theme='blackwall'] .btn:not(.ghost) { - background: var(--bw-red); - border-color: var(--bw-red); - color: #12020a; - clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%); - box-shadow: 0 0 24px -6px rgb(255 45 111 / 0.8); -} -html[data-theme='blackwall'] .btn:not(.ghost):hover:not(:disabled) { background: var(--bright); border-color: var(--bright); } -html[data-theme='blackwall'] .btn.ghost { color: var(--bw-cyan); border-color: rgb(63 246 255 / 0.45); background: rgb(63 246 255 / 0.04); } -html[data-theme='blackwall'] .btn.ghost:hover:not(:disabled) { color: #001417; background: var(--bw-cyan); border-color: var(--bw-cyan); } -html[data-theme='blackwall'] .btn.ghost.danger-btn { color: var(--bad); border-color: rgb(255 59 48 / 0.5); background: transparent; } -html[data-theme='blackwall'] .btn.ghost.danger-btn:hover:not(:disabled) { background: var(--bad); color: #12020a; } -html[data-theme='blackwall'] .link-btn { color: var(--bw-cyan); font-weight: 600; } -html[data-theme='blackwall'] .link-btn:hover { color: var(--bright); } -html[data-theme='blackwall'] .link-btn.danger { color: var(--bad); } - -/* Status: eckige Tags; "online" in Cyan, Warnung gelb */ -html[data-theme='blackwall'] .badge { border-radius: 0; font-weight: 700; letter-spacing: 0.12em; clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 0 100%); } -html[data-theme='blackwall'] .badge::before { border-radius: 0; width: 5px; height: 5px; } -html[data-theme='blackwall'] .chip { border-radius: 0; font-weight: 600; } -html[data-theme='blackwall'] .chip.active { border-color: var(--bw-cyan); color: var(--bw-cyan); background: rgb(63 246 255 / 0.08); } -html[data-theme='blackwall'] .dot { border-radius: 0; } -html[data-theme='blackwall'] .monitor-card.ok { border-left-color: var(--bw-cyan); } -html[data-theme='blackwall'] .monitor-card.ok h3 { color: var(--bw-cyan); } -html[data-theme='blackwall'] .board-column.arbeit { border-top-color: var(--bw-red); } -html[data-theme='blackwall'] .board-column.wartet { border-top-color: var(--bw-yellow); } -html[data-theme='blackwall'] .board-column.erledigt { border-top-color: var(--bw-cyan); } -html[data-theme='blackwall'] .board-head h2 { font-family: var(--font-display); font-weight: 700; letter-spacing: 0.1em; } -html[data-theme='blackwall'] .status-bar .arbeit { background: var(--bw-red); } -html[data-theme='blackwall'] .status-bar .wartet { background: var(--bw-yellow); } -html[data-theme='blackwall'] .status-bar .erledigt { background: var(--bw-cyan); } -html[data-theme='blackwall'] .avatar { border-radius: 0; background: var(--bw-red); color: #12020a; } -html[data-theme='blackwall'] .task-title, html[data-theme='blackwall'] .household-name strong { font-weight: 600; letter-spacing: 0.02em; } -html[data-theme='blackwall'] .drop-line { background: var(--bw-cyan); box-shadow: 0 0 10px rgb(63 246 255 / 0.7); } -html[data-theme='blackwall'] .household-check { border-color: rgb(63 246 255 / 0.55); } -html[data-theme='blackwall'] .recipe-take:checked { background: var(--bw-cyan); } -html[data-theme='blackwall'] .stepper button { color: var(--bw-red); } -html[data-theme='blackwall'] .segmented button[aria-selected='true'] { background: var(--bw-red); color: #12020a; } -html[data-theme='blackwall'] .stepper-value, html[data-theme='blackwall'] .monitor-facts dd, html[data-theme='blackwall'] .fact dd, html[data-theme='blackwall'] .info-facts dd { font-variant-numeric: tabular-nums; } - -/* Artikel */ -html[data-theme='blackwall'] .article-title { font-family: var(--font-display); font-weight: 800; } -html[data-theme='blackwall'] .article-body h2 { font-family: var(--font-display); font-size: 1.6em; color: var(--bright); } -html[data-theme='blackwall'] .article-body h2::before { content: '// '; color: var(--bw-red); } -html[data-theme='blackwall'] .article-body h3 { color: var(--bw-cyan); font-size: 1.2em; } -html[data-theme='blackwall'] .article-body ul > li::before { content: '▸'; color: var(--bw-red); } -html[data-theme='blackwall'] .article-body blockquote { border-left-color: var(--bw-cyan); } -html[data-theme='blackwall'] .article-lead { border-left-color: var(--bw-red); } -html[data-theme='blackwall'] .project-cover { filter: saturate(0.75) contrast(1.05); } - -/* Karte */ -html[data-theme='blackwall'] .map-graticule { stroke: rgb(255 45 111 / 0.08); } -html[data-theme='blackwall'] .map-country { stroke: rgb(255 45 111 / 0.4); } -html[data-theme='blackwall'] .map-country.visited { fill: rgb(255 45 111 / 0.55); stroke: var(--bw-red); } -html[data-theme='blackwall'] .map-country.selected { stroke: var(--bw-cyan); } -html[data-theme='blackwall'] .map-city-dot { fill: var(--bw-cyan); stroke: #001417; filter: drop-shadow(0 0 4px rgb(63 246 255 / 0.9)); } -html[data-theme='blackwall'] .map-city-ring { stroke: var(--bw-cyan); } -html[data-theme='blackwall'] .map-city.other .map-city-dot { fill: var(--dot); stroke: #000; filter: drop-shadow(0 0 4px var(--dot)); } -html[data-theme='blackwall'] .map-city.other .map-city-ring { stroke: var(--dot); } -html[data-theme='blackwall'] .legend-dot.own { background: var(--bw-cyan); box-shadow: 0 0 4px var(--bw-cyan); } - -/* Ruhe: kein Glitch, wenn Bewegung reduziert oder Animation aus */ -html.calm[data-theme='blackwall'] .brand:hover { animation: none; } -@media (prefers-reduced-motion: reduce) { - html[data-theme='blackwall'] .brand:hover { animation: none; } -} -@media (max-width: 640px) { - html[data-theme='blackwall'] { --h1-size: 1.6rem; --tile-size: 0.86rem; --cut: 10px; } - html[data-theme='blackwall'] h1 { overflow-wrap: anywhere; } - html[data-theme='blackwall'] .brand { letter-spacing: 0.06em; font-size: 1.05rem; } - html[data-theme='blackwall'] .tile strong { letter-spacing: 0.03em; } -} -/* Leere Kachel nicht durchsichtig: sonst steht ihr Text im hellen Lichtband */ -html[data-theme='blackwall'] .tile-empty { background: var(--surface); border-style: dashed; } -/* Umrandete Buttons mit dunklem Grund, damit sie vor dem Lichtband lesbar bleiben */ -html[data-theme='blackwall'] .btn.ghost { background-color: rgb(6 1 4 / 0.88); } -html[data-theme='blackwall'] .btn.ghost.danger-btn { background: rgb(6 1 4 / 0.88); color: #ff6a60; } -html[data-theme='blackwall'] .kanban-filter span { color: var(--text); } - - /* ============================================================ FABRIK – Industrie-Inventar im Stil von Satisfactory Fenster aus gebürstetem Stahl mit Schrauben in den Ecken, dunkle Titelleiste mit Fenstersymbol, diff --git a/frontend/src/styles/designs/gemeinsam.css b/frontend/src/styles/designs/gemeinsam.css new file mode 100644 index 0000000..fcf6522 --- /dev/null +++ b/frontend/src/styles/designs/gemeinsam.css @@ -0,0 +1,46 @@ +/* ============================================================ + Designs: Blackwall (Cyberpunk), Fabrik (Industrie-UI à la Satisfactory) + Das Matrix-Design sind die Standardwerte in base.css. Jedes Design setzt hier vor allem + Tokens (Farbrollen, Schrift, Form) und nur noch seine Erkennungsmerkmale. + Inspiriert von den Vorbildern: keine Original-Logos, freie Schriften (OFL), alles lokal. + ============================================================ */ + +/* ---------- Gemeinsam ---------- */ +.theme-bg { position: fixed; inset: 0; z-index: -1; pointer-events: none; } + +/* Design-Auswahl im Menü */ +.menu-panel { max-height: calc(100vh - var(--topbar-h) - 16px); overflow-y: auto; } +.menu-label { padding: 8px 12px 4px; font-size: var(--label-size); color: var(--muted); text-transform: uppercase; letter-spacing: var(--label-tracking); } +.theme-picker { display: flex; flex-direction: column; gap: 2px; } +.menu-item.theme-option { display: flex; align-items: center; gap: 12px; } +.theme-option .swatch { display: inline-flex; flex: none; border-radius: 4px; overflow: hidden; box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.12); } +.theme-option .swatch i { width: 9px; height: 22px; } +.theme-name { display: flex; flex-direction: column; line-height: 1.25; } +.theme-name small { font-size: 0.7rem; text-transform: none; letter-spacing: 0.02em; color: var(--muted); } +.theme-option[aria-checked='true'] { color: var(--bright); background: var(--accent-soft); box-shadow: inset 2px 0 0 var(--accent); } +.theme-option[aria-checked='true'] .theme-name::after { content: '✓ aktiv'; font-size: 0.68rem; color: var(--accent); } + +/* Matrix-Zierrat in den anderen Designs abschalten (jedes Design setzt eigenen) */ +html:not([data-theme='matrix']) body::after, +html:not([data-theme='matrix']) .page-head h1::after, +html:not([data-theme='matrix']) .hero h1::after, +html:not([data-theme='matrix']) .brand::before, +html:not([data-theme='matrix']) .lead::before, +html:not([data-theme='matrix']) .section-title::before, +html:not([data-theme='matrix']) .household-head h2::before, +html:not([data-theme='matrix']) .article-body h2::before, +html:not([data-theme='matrix']) .article-body h3::before, +html:not([data-theme='matrix']) .menu-panel a::before, +html:not([data-theme='matrix']) .menu-item::before, +html:not([data-theme='matrix']) .topnav a.active::before, +html:not([data-theme='matrix']) .notice::before, +html:not([data-theme='matrix']) .error::before, +html:not([data-theme='matrix']) .prompt-input::before, +html:not([data-theme='matrix']) .combo-list li::before { content: none; } +html:not([data-theme='matrix']) .track-form input { padding-left: 18px; } +html:not([data-theme='matrix']) .city-search input { padding-left: 16px; } +html:not([data-theme='matrix']) .article-body ul > li::before { content: '●'; } +html:not([data-theme='matrix']) .tile strong { overflow-wrap: anywhere; max-width: 100%; } + +@keyframes theme-spin { to { transform: rotate(360deg); } } +@keyframes theme-scan { from { transform: translateY(-10vh); } to { transform: translateY(110vh); } } diff --git a/frontend/src/styles/grundschicht.css b/frontend/src/styles/grundschicht.css new file mode 100644 index 0000000..c3736c9 --- /dev/null +++ b/frontend/src/styles/grundschicht.css @@ -0,0 +1,50 @@ +/* ============================================================ + Grundschicht – bereichsübergreifend, gilt für alle Designs (Werte aus den Tokens) + Steht bewusst nach allen Bereichsdateien: die einheitlichen Eingabefelder überschreiben + die Feld-Regeln der Bereiche, Hover-Anheben und Bewegung gelten für Karten aller Bereiche. + ============================================================ */ + +/* Alle Eingabefelder einheitlich: gleiche Höhe, Radius, weicher Fokusring */ +.form input:not([type='checkbox']), .form select, .form textarea, +.aside-card select, .title-input, .lead-input, .track-form input, +.household-add input, .recipe input:not([type='checkbox']), .recipe textarea, +.city-search input, .kanban-filter select, .user-edit input, .task-dialog textarea { + font-family: var(--font); + color: var(--bright); + background: var(--input-bg); + border: 1px solid var(--border); + border-radius: var(--radius-s); + min-height: var(--control-h); + text-shadow: none; + transition: transform var(--dur) var(--ease-out); +} +.form textarea, .recipe textarea, .task-dialog textarea, .lead-input { min-height: 0; padding: 10px 12px; } +.form input:not([type='checkbox']):focus, .form select:focus, .form textarea:focus, +.aside-card select:focus, .title-input:focus, .lead-input:focus, .track-form input:focus, +.household-add input:focus, .recipe input:focus, .recipe textarea:focus, +.city-search input:focus, .kanban-filter select:focus, .user-edit input:focus, .task-dialog textarea:focus, +.unit-select:focus { + outline: none; + border-color: var(--accent); + box-shadow: var(--focus-ring); +} +.track-form input, .city-search input { min-height: 50px; border-color: var(--line-strong); } +.track-form .btn { min-height: 50px; } +.unit-select { border-radius: var(--radius-s); min-height: 34px; } +.qty-unit > input { border-radius: var(--radius-s) 0 0 var(--radius-s) !important; } +.qty-unit > .unit-select { border-radius: 0 var(--radius-s) var(--radius-s) 0; } +[aria-invalid='true'] { box-shadow: 0 0 0 3px rgb(255 61 61 / 0.25) !important; } + +/* Interaktive Karten heben sich leicht an (nur transform) */ +.tile, .project-card, .kanban-project-card, .task-card { transition: transform var(--dur) var(--ease-out); } +.tile:hover, .project-card:hover, .kanban-project-card:hover, .task-card:hover:not(.dragging) { transform: translateY(var(--lift)); box-shadow: var(--shadow-1); } +.project-card:hover, .kanban-project-card:hover, .tile:hover { border-color: var(--line-strong); } + +/* Sanfter Wechsel zwischen den Designs (View Transitions, wo der Browser es kann) */ +::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.35s; animation-timing-function: var(--ease-out); } + +@media (prefers-reduced-motion: reduce) { + .tile:hover, .project-card:hover, .kanban-project-card:hover, .task-card:hover, .btn:hover:not(:disabled) { transform: none; } + ::view-transition-old(root), ::view-transition-new(root) { animation: none; } +} +html.calm .tile:hover, html.calm .project-card:hover, html.calm .kanban-project-card:hover, html.calm .task-card:hover { transform: none; } diff --git a/frontend/src/styles/haushalt.css b/frontend/src/styles/haushalt.css new file mode 100644 index 0000000..379c554 --- /dev/null +++ b/frontend/src/styles/haushalt.css @@ -0,0 +1,282 @@ +/* ---------- Vorrat & Einkauf ---------- */ +.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } + +.household-error { margin-bottom: 16px; } +.household { display: grid; gap: clamp(14px, 1.5vw, 24px); align-items: start; } +@media (min-width: 900px) { + .household { grid-template-columns: repeat(2, minmax(0, 1fr)); } +} + +/* Handy: Umschalter, nur die gewählte Liste zeigen */ +.segmented { display: none; margin-bottom: 14px; border: 1px solid var(--accent); border-color: var(--line-strong); border-radius: var(--radius-m); overflow: hidden; padding: 3px; gap: 3px; background: var(--card-inner); } +@media (max-width: 899px) { + .segmented { display: flex; } + .household-panel[data-hidden] { display: none; } +} +.segmented button { + flex: 1; + font: inherit; + font-size: 0.88rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.08em; + padding: 11px 8px; + border: 0; + background: transparent; + color: var(--text); + cursor: pointer; + border-radius: calc(var(--radius-m) - 3px); +} +.segmented button[aria-selected='true'] { background: var(--accent); color: var(--accent-ink); } +.segmented .count { opacity: 0.75; margin-left: 4px; } +.segmented .count::before { content: '['; } +.segmented .count::after { content: ']'; } + +.household-panel { display: flex; flex-direction: column; gap: 16px; } +.household-panel.einkauf { border-color: var(--accent); } +.shopping-lists { display: flex; flex-direction: column; gap: 8px; margin-bottom: 18px; } +.shopping-lists-label { color: var(--muted); font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.08em; margin-right: 2px; } +.shopping-lists .chip-list { align-items: center; } +.shopping-visibility { margin: 0; font-size: 0.8rem; } +.list-delete { margin-right: auto; } +.household-head { display: flex; align-items: baseline; justify-content: space-between; gap: 6px 12px; flex-wrap: wrap; } +.household-head h2 { margin: 0; } +.household-head h2::before { content: '// '; color: var(--accent); } +.household-head .hint { margin: 0; } +.household-empty { margin: 0; } + +.household-add { display: flex; gap: 8px; } +.household-add .combo { flex: 1; min-width: 0; } +.household-add input { + font: inherit; + color: var(--bright); + background: var(--input-bg); + border: 1px solid var(--border); + padding: 10px 12px; + width: 100%; +} +.household-add input:focus { outline: none; border-color: var(--accent); box-shadow: var(--glow); } +.household-add { flex-wrap: wrap; } +.household-add .household-qty-input { width: 4.5em; flex: none; text-align: center; } +.household-add-error { flex-basis: 100%; } +[aria-invalid='true'] { border-color: var(--bad) !important; box-shadow: 0 0 6px var(--bad-glow) !important; } + +/* Menge + Einheit als zusammenhängender Block */ +.qty-unit { display: flex; flex: none; } +.qty-unit > input { border-right: 0 !important; } +.unit-select { + font: inherit; + font-size: 0.85rem; + color: var(--bright); + background: var(--input-bg); + border: 1px solid var(--border); + padding: 0 6px; + min-height: 34px; + cursor: pointer; +} +.unit-select:focus { outline: none; border-color: var(--accent); box-shadow: var(--glow); } +.unit-select:disabled { opacity: 0.4; cursor: default; } +.household-item > .unit-select { flex: none; width: 4.4em; margin-left: -12px; border-left: 0; } + +/* Vorschlagsliste */ +.combo { position: relative; } +.combo-list { + position: absolute; + z-index: 12; + left: 0; + right: 0; + top: calc(100% + 4px); + margin: 0; + list-style: none; + border: 1px solid var(--accent); + max-height: 300px; + overflow-y: auto; + border-color: var(--line-strong); + border-radius: var(--radius-m); + box-shadow: var(--shadow-2); + background: var(--panel); + padding: 6px; +} +.combo-list li { + display: flex; + justify-content: space-between; + align-items: baseline; + gap: 12px; + padding: 8px 10px; + cursor: pointer; + color: var(--text); + border-radius: var(--radius-s); +} +.combo-list li::before { content: ' '; white-space: pre; } +.combo-list li > span { flex: 1; } +.combo-list li:hover, .combo-list li.active { background: var(--accent-soft); color: var(--bright); } +.combo-list li.active::before { content: '> '; color: var(--accent); } +.combo-list small { color: var(--muted); font-size: 0.75rem; white-space: nowrap; } + +.household-list { list-style: none; margin: 0; padding: 0; } +.household-item { + display: flex; + align-items: center; + gap: 12px; + padding: 10px 0; + border-top: 1px dashed var(--border); + padding-inline: 6px; + margin-inline: -6px; + border-radius: var(--radius-s); +} +.household-name { flex: 1; min-width: 0; display: flex; flex-direction: column; } +.household-name strong { overflow-wrap: anywhere; } +.household-name small { color: var(--muted); font-size: 0.75rem; } + +.household-check { + appearance: none; + flex: none; + width: 24px; + height: 24px; + margin: 0; + border: 1px solid var(--accent); + background: var(--input-bg); + cursor: pointer; + display: grid; + place-items: center; + border-radius: var(--radius-s); + border-color: var(--line-strong); +} +.household-check::after { content: '✓'; color: var(--accent); opacity: 0; font-weight: 700; } +.household-check:hover::after { opacity: 0.6; } +.household-check:checked::after { opacity: 1; } + +/* Einkauf: abgehakt = im Wagen, unten in der Liste */ +.household-cart-head { + margin: 14px 0 4px; + font-size: var(--label-size); + letter-spacing: var(--label-tracking); + text-transform: uppercase; + color: var(--muted); +} +.household-item.checked .household-name strong { text-decoration: line-through; text-decoration-thickness: 2px; color: var(--muted); } +.household-item.checked .stepper, +.household-item.checked > .unit-select, +.household-item.checked .household-actions { opacity: 0.55; } +.household-finish { display: flex; align-items: center; justify-content: space-between; gap: 8px 12px; flex-wrap: wrap; padding-top: 12px; border-top: 1px solid var(--border); } +.household-finish .hint { margin: 0; } +/* Gleiten beim Abhaken/Einkauf beenden (nur während des Übergangs benannt, damit Designwechsel unberührt bleibt) */ +html.vt-items .household-item { view-transition-name: var(--vt); } +::view-transition-group(*) { animation-duration: 0.32s; animation-timing-function: var(--ease-out); } + +.stepper { display: flex; align-items: stretch; flex: none; border: 1px solid var(--border); border-radius: var(--radius-s); overflow: hidden; } +.stepper button { + font: inherit; + width: 34px; + min-height: 34px; + border: 0; + background: transparent; + color: var(--accent); + font-size: 1.1rem; + cursor: pointer; +} +.stepper button:hover:not(:disabled) { background: var(--accent); color: var(--accent-ink); } +.stepper button:disabled { color: var(--border); cursor: default; } +.stepper-value { + width: 3.4em; + font: inherit; + font-weight: 600; + text-align: center; + color: var(--bright); + background: transparent; + border: 0; + border-inline: 1px solid var(--border); + padding: 0; +} +.stepper-value:focus { outline: none; background: var(--input-bg); box-shadow: inset 0 0 0 1px var(--accent); } + +.household-actions { display: flex; align-items: center; gap: 12px; flex: none; } +.household-actions .link-btn { display: inline-flex; align-items: center; gap: 6px; } +.household-actions .link-btn:disabled { opacity: 0.4; cursor: default; } +.household-actions svg { width: 18px; height: 18px; } + +.product-list { list-style: none; margin: 0; padding: 0; max-height: 50vh; overflow-y: auto; } +.product-list li { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 8px 0; border-top: 1px dashed var(--border); } + +@media (max-width: 520px) { + .household-add { flex-wrap: wrap; } + .household-add .combo { flex-basis: 100%; } + .household-add .qty-unit { flex: 1; } + .household-add .household-qty-input { flex: 1; } + .household-add .btn { flex: 1; } + .household-panel { padding: 16px 14px; } + .household-item { gap: 8px; } + .stepper button { width: 28px; } + .stepper-value { width: 2.8em; } + .household-item > .unit-select { width: 3.9em; font-size: 0.8rem; padding: 0 2px; } + .household-actions { gap: 10px; } + .household-actions .label { display: none; } +} + +/* Rezept abgleichen */ +.recipe { display: flex; flex-direction: column; gap: 16px; margin-bottom: clamp(14px, 1.5vw, 24px); } +.recipe .household-head h2 a { color: inherit; text-decoration: none; } +.recipe .household-head h2 a:hover { color: var(--accent); } +.recipe input:not([type='checkbox']), .recipe textarea { + font: inherit; + color: var(--bright); + background: var(--input-bg); + border: 1px solid var(--border); + padding: 10px 12px; + width: 100%; +} +.recipe input:focus, .recipe textarea:focus { outline: none; border-color: var(--accent); box-shadow: var(--glow); } +.recipe input:disabled { opacity: 0.4; } +.recipe textarea { resize: vertical; } +.recipe-load { display: flex; gap: 8px; align-items: flex-start; } +.recipe-load > :first-child { flex: 1; min-width: 0; } + +.recipe-people { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 28px; } +.recipe-people label { display: flex; align-items: center; gap: 10px; color: var(--muted); } +.recipe-people input[type='number'] { width: 4.5em; text-align: center; padding: 8px; } +.recipe-people-main { color: var(--bright) !important; font-weight: 600; } +.recipe-people-main input { border-color: var(--accent) !important; } +.recipe-people .hint { margin: 0; } + +.recipe-rows { list-style: none; margin: 0; padding: 0; } +.recipe-row { + display: grid; + grid-template-columns: 24px minmax(0, 1.3fr) minmax(0, 1fr) 150px 140px; + align-items: center; + gap: 14px; + padding: 10px 0; + border-top: 1px dashed var(--border); +} +.recipe-take:checked { background: var(--accent); } +.recipe-take:checked::after { content: '✓'; color: var(--accent-ink); opacity: 1; } +.recipe-ingredient { display: flex; flex-direction: column; min-width: 0; } +.recipe-ingredient strong { overflow-wrap: anywhere; } +.recipe-ingredient small { color: var(--muted); font-size: 0.75rem; overflow-wrap: anywhere; } +.recipe-status { justify-self: start; } +.recipe .recipe-buy .recipe-qty { width: 4.5em; flex: none; text-align: center; padding: 8px; } +.recipe .recipe-buy .unit-select { flex: 1; min-width: 0; } + +.recipe-foot { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; } +.recipe-foot .hint { margin: 0; flex: 1 1 280px; } + +@media (max-width: 760px) { + .recipe-load { flex-direction: column; align-items: stretch; } + .recipe-row { + grid-template-columns: 24px minmax(0, 1fr) 9.5em; + grid-template-areas: + 'take ing ing' + '. status status' + '. prod qty'; + gap: 6px 10px; + } + .recipe-take { grid-area: take; align-self: start; } + .recipe-ingredient { grid-area: ing; } + .recipe-status { grid-area: status; justify-self: start; } + .recipe-product { grid-area: prod; } + .recipe-buy { grid-area: qty; min-width: 0; } + .recipe .recipe-buy .recipe-qty { width: 3.8em; } + .recipe-foot .btn { width: 100%; } +} +.household-item, .recipe-row, .product-list li { border-top-style: solid; border-top-color: var(--border); } +.household-item:hover { background: var(--accent-soft); } +.segmented .count::before, .segmented .count::after { content: none; } diff --git a/frontend/src/styles/index.css b/frontend/src/styles/index.css new file mode 100644 index 0000000..5b2d7b6 --- /dev/null +++ b/frontend/src/styles/index.css @@ -0,0 +1,17 @@ +/* Reihenfolge zählt: Grundlagen → Bereiche → Grundschicht (bereichsübergreifend) → Handy/Bewegung → Designs. + Matrix ist das Standard-Design (Werte in base.css); Blackwall und Fabrik überschreiben vor allem Tokens. */ +@import './base.css'; +@import './layout.css'; +@import './components.css'; +@import './start.css'; +@import './projekte.css'; +@import './monitoring.css'; +@import './haushalt.css'; +@import './reisen.css'; +@import './kanban.css'; +@import './konto.css'; +@import './responsive.css'; +@import './grundschicht.css'; +@import './designs/gemeinsam.css'; +@import './designs/blackwall.css'; +@import './designs/fabrik.css'; diff --git a/frontend/src/styles/kanban.css b/frontend/src/styles/kanban.css new file mode 100644 index 0000000..e0064b4 --- /dev/null +++ b/frontend/src/styles/kanban.css @@ -0,0 +1,203 @@ +/* ---------- Kanban ---------- */ +.kanban-filter { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.08em; } +.kanban-filter select { + font: inherit; + text-transform: none; + letter-spacing: normal; + font-size: 0.88rem; + color: var(--bright); + background: var(--input-bg); + border: 1px solid var(--border); + padding: 9px 10px; +} +.kanban-filter select:focus { outline: none; border-color: var(--accent); box-shadow: var(--glow); } +.kanban-error { margin-bottom: 12px; } + +.board { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(12px, 1.2vw, 20px); align-items: start; } +.board-column { + display: flex; + flex-direction: column; + min-height: 220px; + background: var(--surface); + border: 1px solid var(--border); + border-top: 3px solid var(--border); + transition: border-color 0.12s, box-shadow 0.12s; + border-radius: var(--radius-m); + border-top-width: 2px; + box-shadow: var(--shadow-1); +} +.board-column.arbeit { border-top-color: var(--accent); } +.board-column.wartet { border-top-color: var(--warn); } +.board-column.erledigt { border-top-color: var(--ok); } +.board-column.drop-target { border-color: var(--accent); box-shadow: var(--focus-ring); } +.board-head { display: flex; justify-content: space-between; align-items: center; padding: 12px 14px 8px; } +.board-head h2 { margin: 0; } +.board-head .count { text-shadow: none; display: inline-grid; place-items: center; min-width: 1.6em; height: 1.6em; margin-left: 6px; padding: 0 6px; border-radius: var(--radius-pill); background: var(--accent-soft); color: var(--text); font-family: var(--font-label); font-size: 0.7rem; vertical-align: 0.15em; } +.board-head .count::before { content: '['; } +.board-head .count::after { content: ']'; } +.board-head .link-btn { font-size: 1.3rem; line-height: 1; padding: 2px 6px; color: var(--accent); } +.board-cards { list-style: none; margin: 0; padding: 4px 10px 12px; display: flex; flex-direction: column; gap: 8px; flex: 1; } +.board-empty { color: var(--muted); font-size: 0.8rem; padding: 14px 4px; text-align: center; border: 1px dashed var(--border); border-radius: var(--radius-s); border-style: dashed; } +.drop-line { height: 3px; background: var(--accent); margin: 2px 0; border-radius: 2px; box-shadow: none; } + +.task-card { + width: 100%; + display: flex; + flex-direction: column; + gap: 6px; + padding: 10px 12px; + font: inherit; + text-align: left; + color: var(--text); + background: var(--card-inner); + border: 1px solid var(--border); + cursor: grab; + text-shadow: none; + transition: border-color 0.12s, box-shadow 0.12s, opacity 0.12s; + border-radius: var(--radius-s); + border-color: var(--border); +} +.task-card:hover { border-color: var(--line-strong); box-shadow: var(--shadow-1); } +.task-card.dragging { opacity: 0.35; } +.task-title { color: var(--bright); font-weight: 600; overflow-wrap: anywhere; } +.task-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; } +/* Priorität: Kennzeichen auf der Karte + farbige Kante links (Mittel ohne Kennzeichen, damit es ruhig bleibt) */ +.prio { + flex: none; + padding: 1px 8px; + border-radius: var(--radius-pill); + font-family: var(--font-label); + font-size: 0.66rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; + white-space: nowrap; +} +.prio-hoch { color: var(--accent-ink); background: var(--bad); } +.prio-niedrig { color: var(--muted); box-shadow: inset 0 0 0 1px var(--border); } +.task-card.prio-card-hoch { box-shadow: inset 3px 0 0 var(--bad); } +.task-card.prio-card-niedrig .task-title { font-weight: 500; } +.task-desc { + color: var(--read); + font-size: 0.8rem; + white-space: pre-line; + overflow-wrap: anywhere; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; +} +.task-meta { display: flex; justify-content: space-between; align-items: center; margin-top: 2px; } +.assignee { display: inline-flex; align-items: center; gap: 6px; font-size: 0.75rem; color: var(--muted); } +.assignee.none { font-style: italic; } +.avatar { + display: inline-grid; + place-items: center; + width: 22px; + height: 22px; + font-size: 0.65rem; + font-weight: 600; + color: var(--accent-ink); + background: var(--accent); + border-radius: 50%; +} +.board-column.erledigt .task-title { text-decoration: line-through; text-decoration-color: rgb(var(--accent-rgb) / 0.6); color: var(--muted); } + +.task-dialog { width: min(620px, calc(100% - 32px)); } +.task-dialog textarea { + font: inherit; + font-weight: 400; + text-transform: none; + letter-spacing: normal; + color: var(--bright); + background: var(--input-bg); + border: 1px solid var(--border); + padding: 10px 12px; + width: 100%; + resize: vertical; +} +.task-dialog textarea:focus { outline: none; border-color: var(--accent); box-shadow: var(--glow); } +.task-dialog-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; } +.task-history { margin: 0; font-size: 0.78rem; } +.task-delete { margin-right: auto; } + +/* Kanban-Übersicht */ +.kanban-projects { grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); } +.kanban-project-card { position: relative; display: flex; flex-direction: column; gap: 10px; transition: border-color 0.12s, box-shadow 0.12s; } +.kanban-project-card:hover { border-color: var(--accent); box-shadow: var(--glow); } +.kanban-project-card h3 { margin: 0; overflow-wrap: anywhere; } +.kanban-project-link { color: inherit; text-decoration: none; } +.kanban-project-link::after { content: ''; position: absolute; inset: 0; } /* ganze Karte klickbar */ +.kanban-project-actions { position: relative; z-index: 1; display: flex; gap: 16px; padding-top: 8px; border-top: 1px dashed var(--border); } +.kanban-project-card.completed { opacity: 0.8; } +.kanban-project-card.completed h3 { text-decoration: line-through; text-decoration-color: rgb(var(--accent-rgb) / 0.6); } +.kanban-done-badge { align-self: flex-start; margin-top: -4px; white-space: normal; font-size: 0.72rem; max-width: 100%; } +.kanban-project-desc { + margin: 0; + color: var(--read); + font-size: 0.85rem; + white-space: pre-line; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} +.status-bar { display: flex; height: 6px; gap: 2px; margin-top: auto; border-radius: var(--radius-pill); overflow: hidden; } +.status-bar span { min-width: 6px; background: var(--border); } +.status-bar .arbeit { background: var(--accent); } +.status-bar .wartet { background: var(--warn); } +.status-bar .erledigt { background: var(--ok); } +.kanban-project-counts { margin: 0; font-size: 0.75rem; color: var(--muted); } +.kanban-project-links { margin: 0; font-size: 0.75rem; color: var(--bright); overflow-wrap: anywhere; } +.kanban-done { margin-top: clamp(28px, 4vw, 48px); } +.kanban-done summary { cursor: pointer; list-style: none; margin-bottom: 14px; } +.kanban-done summary::-webkit-details-marker { display: none; } +.kanban-done summary h2 { display: inline; } +.kanban-done summary h2::after { content: ' ▸'; color: var(--accent); } +.kanban-done[open] summary h2::after { content: ' ▾'; } +.kanban-done .count { font-family: var(--font); font-size: 0.8rem; color: var(--muted); text-shadow: none; } +.kanban-done .count::before { content: '['; } +.kanban-done .count::after { content: ']'; } + +/* Board-Kopf */ +.board-completed { margin-bottom: 16px; } +.btn.ghost.danger-btn { color: var(--bad); border-color: var(--bad); } +.btn.ghost.danger-btn:hover:not(:disabled) { background: var(--bad); color: var(--accent-ink); } +.board-page-head { margin-bottom: 18px; } +.board-description { white-space: pre-line; margin-bottom: 12px; max-width: 75ch; } +.board-links { margin-top: 4px; } +.board-links .chip { text-decoration: none; display: inline-block; } + +/* Artikel-Auswahl im Projekt-Dialog */ + +.aside-boards { display: flex; flex-direction: column; gap: 4px; } +.aside-boards a { text-decoration: none; } +.aside-boards a.sub { font-size: 0.8rem; color: var(--muted); } +.aside-boards a.sub:hover { color: var(--bright); } + +/* Handy/Tablet: Spalten nebeneinander wischen */ +@media (max-width: 999px) { + .board { + grid-template-columns: repeat(4, minmax(78%, 1fr)); + overflow-x: auto; + scroll-snap-type: x mandatory; + padding-bottom: 8px; + overscroll-behavior-x: contain; + } + .board-column { scroll-snap-align: start; } +} +@media (min-width: 640px) and (max-width: 999px) { + .board { grid-template-columns: repeat(4, minmax(46%, 1fr)); } +} +@media (max-width: 520px) { + .task-dialog-row { grid-template-columns: 1fr; } + .kanban-filter { width: 100%; } + .kanban-filter select { flex: 1; } +} +.board-head .count::before, .board-head .count::after { content: none; } +.kanban-archive { margin-top: clamp(16px, 2vw, 28px); display: flex; flex-direction: column; gap: 12px; } +.archive-list { list-style: none; margin: 0; padding: 0; } +.archive-item { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; padding: 10px 0; border-top: 1px dashed var(--border); } +.archive-title { flex: 1 1 220px; min-width: 0; text-align: left; font: inherit; font-weight: 600; color: var(--bright); background: none; border: 0; padding: 0; cursor: pointer; text-decoration: line-through; text-decoration-color: var(--muted); } +.archive-title:hover { color: var(--accent); } +.archive-dates { color: var(--muted); font-size: 0.78rem; } diff --git a/frontend/src/styles/konto.css b/frontend/src/styles/konto.css new file mode 100644 index 0000000..e70be87 --- /dev/null +++ b/frontend/src/styles/konto.css @@ -0,0 +1,27 @@ +/* ---------- Konto & Benutzerverwaltung ---------- */ +.settings-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr)); + gap: clamp(14px, 1.5vw, 24px); + align-items: start; +} +.user-list { display: grid; gap: 12px; } +.user-row { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 16px; padding: 16px 20px; } +.user-info { display: flex; flex-direction: column; min-width: 0; } +.user-info .hint { margin: 2px 0 0; } +.user-badges { display: flex; gap: 6px; } +.user-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; justify-content: flex-end; } +.user-edit { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; } +.user-edit input { + font: inherit; + color: var(--bright); + background: var(--input-bg); + border: 1px solid var(--accent); + padding: 6px 10px; + min-width: 0; + flex: 1 1 160px; +} +@media (max-width: 800px) { + .user-row { grid-template-columns: minmax(0, 1fr) auto; } + .user-actions { grid-column: 1 / -1; justify-content: flex-start; } +} diff --git a/frontend/src/styles/layout.css b/frontend/src/styles/layout.css new file mode 100644 index 0000000..1fa15f7 --- /dev/null +++ b/frontend/src/styles/layout.css @@ -0,0 +1,116 @@ +/* ---------- Kopfzeile + Menü ---------- */ +.topbar { + position: sticky; + top: 0; + z-index: 20; + height: var(--topbar-h); + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + padding: 0 var(--gutter); + border-bottom: 1px solid var(--border); + background: var(--topbar-bg); + backdrop-filter: var(--blur); + -webkit-backdrop-filter: var(--blur); +} +.brand { + font-family: var(--font-display); + font-size: 1.85rem; + letter-spacing: 0.06em; + text-transform: uppercase; + color: var(--bright); + text-decoration: none; + text-shadow: var(--heading-glow); + white-space: nowrap; +} +.brand::before { content: '>_ '; color: var(--accent); } +.brand span { color: var(--accent); } + +.menu { position: relative; } +.menu-btn { + display: grid; + place-items: center; + width: var(--control-h); + height: var(--control-h); + border: 1px solid var(--line-strong); + border-radius: var(--radius-s); + background: transparent; + color: var(--accent); + cursor: pointer; +} +.menu-btn:hover, .menu-btn[aria-expanded='true'] { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); } +.menu-btn svg { width: 22px; height: 22px; } +.menu-panel { + position: absolute; + right: 0; + top: calc(100% + 10px); + min-width: 260px; + display: flex; + flex-direction: column; + padding: 6px; + background: var(--panel); + border: 1px solid var(--border); + border-radius: var(--radius-m); + box-shadow: var(--shadow-2); + backdrop-filter: var(--blur); + -webkit-backdrop-filter: var(--blur); +} +.menu-panel a, .menu-item { + font: inherit; + text-align: left; + padding: 9px 12px; + border: 0; + border-radius: var(--radius-s); + background: none; + color: var(--text); + text-decoration: none; + text-transform: uppercase; + letter-spacing: 0.06em; + font-size: 0.88rem; + cursor: pointer; + text-shadow: inherit; +} +.menu-panel a::before, .menu-item::before { content: ' '; white-space: pre; } +.menu-panel a:hover, .menu-item:hover { background: var(--accent-soft); color: var(--bright); } +.menu-panel a:hover::before, .menu-item:hover::before { content: '> '; } +.menu-panel a.active { background: var(--accent); color: var(--accent-ink); text-shadow: none; } +.menu-panel a.active::before { content: '> '; } +.menu-panel hr { border: 0; border-top: 1px solid var(--border); margin: 6px 4px; } +.menu-user { padding: 6px 12px 4px; font-size: 0.78rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; } + +/* Hauptnavigation in der Kopfzeile (ab Tablet), darunter im Menü */ +.topnav { display: flex; gap: 4px; margin-left: auto; } +.topnav a { + padding: 8px 14px; + color: var(--muted); + text-decoration: none; + text-transform: uppercase; + letter-spacing: 0.08em; + font-size: 0.82rem; + border: 1px solid transparent; + border-radius: var(--radius-s); +} +.topnav a:hover { color: var(--bright); background: var(--accent-soft); } +.topnav a.active { color: var(--bright); border-color: var(--line-strong); background: var(--accent-soft); } +.topnav a.active::before { content: '> '; color: var(--accent); } +.menu-primary { display: none; flex-direction: column; } +@media (max-width: 999px) { + .topnav { display: none; } + .menu-primary { display: flex; } +} + +/* ---------- Seitenrahmen: volle Breite ---------- */ +.page { flex: 1; width: 100%; padding: clamp(24px, 4vw, 48px) var(--gutter) 64px; } +.footer { text-align: center; color: var(--muted); font-size: 0.75rem; padding: 24px 20px; letter-spacing: 0.14em; text-transform: uppercase; } + +.page-head { + display: flex; + justify-content: space-between; + align-items: flex-end; + gap: 16px 24px; + flex-wrap: wrap; + margin-bottom: 20px; +} +.page-head .lead { margin-bottom: 0; } +.page-actions { display: flex; gap: 8px; flex-wrap: wrap; } diff --git a/frontend/src/styles/monitoring.css b/frontend/src/styles/monitoring.css new file mode 100644 index 0000000..80562a6 --- /dev/null +++ b/frontend/src/styles/monitoring.css @@ -0,0 +1,124 @@ +/* ---------- Monitoring ---------- */ +.monitor-summary { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 10px; + margin: 0 0 16px; + padding: 10px 14px; + border: 1px solid var(--border); + background: var(--surface); + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.08em; + border-radius: var(--radius-m); +} +.monitor-summary-time { margin-left: auto; font-weight: 400; color: var(--muted); font-size: 0.8rem; } +.monitor-card { display: flex; flex-direction: column; border-left: 4px solid var(--border); border-left-width: 3px; } +.monitor-card.ok { border-left-color: var(--ok); } +.monitor-card.bad { border-color: var(--bad); border-left-color: var(--bad); box-shadow: inset 4px 0 12px -6px var(--bad), 0 0 14px rgb(255 43 43 / 0.25); } +.monitor-card.ok h3 { color: var(--ok); } +.monitor-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; } +.monitor-target { margin: 6px 0 0; color: var(--muted); font-size: 0.85rem; word-break: break-all; } +.monitor-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 12px 16px; margin: 16px 0 0; padding-top: 14px; border-top: 1px dashed var(--border); border-top-style: solid; } +.monitor-facts dd { margin: 2px 0 0; color: var(--bright); font-size: 0.88rem; } +.monitor-foot { justify-content: space-between; margin-top: auto; padding-top: 16px; flex-wrap: wrap; } +.monitor-actions { display: flex; gap: 14px; } + +/* Server-Auslastung (P42-S.M.): Karte → große Ansicht */ +.monitor-card.clickable { cursor: pointer; transition: transform var(--dur) var(--ease-out), border-color var(--dur); } +.monitor-card.clickable:hover { transform: translateY(var(--lift)); border-color: var(--line-strong); } +.monitor-card.clickable:focus-visible { outline: none; box-shadow: var(--focus-ring); } +.monitor-card.clickable .monitor-target { word-break: normal; overflow-wrap: anywhere; } +.agent-summary { display: grid; gap: 10px; margin-top: 14px; } +.agent-summary .monitor-facts { margin-top: 4px; } + +.meter { display: grid; gap: 4px; min-width: 0; } +.meter-label { display: flex; justify-content: space-between; gap: 8px; font-size: 0.82rem; color: var(--text); } +.meter-label span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.meter-label strong { color: var(--bright); font-weight: 600; white-space: nowrap; } +.meter small { color: var(--muted); font-size: 0.76rem; } +.meter-bar { display: block; height: 6px; border-radius: var(--radius-pill); background: var(--accent-soft); overflow: hidden; } +.meter-bar i { display: block; height: 100%; border-radius: inherit; background: var(--accent); transition: width 0.6s var(--ease-out); } +.meter.warn .meter-bar i, .server-tile.warn .meter-bar i { background: var(--warn); } +.meter.bad .meter-bar i, .server-tile.bad .meter-bar i { background: var(--bad); } +.meter.bad .meter-label strong { color: var(--bad); } +.meter.compact .meter-label { font-size: 0.74rem; } + +.server-modal { width: min(1280px, calc(100% - 24px)); max-height: calc(100vh - 24px); overflow-y: auto; padding: clamp(16px, 2.4vw, 30px); } +.server-detail { display: grid; gap: 18px; } +.server-detail-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; } +.server-detail-head h2 { margin: 0; } +.server-detail-sub { margin: 6px 0 0; color: var(--muted); font-size: 0.84rem; line-height: 1.6; } +.server-detail-actions { display: flex; align-items: center; gap: 10px; } +.server-detail-actions .btn { padding: 0 14px; } + +.server-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; } +.server-tile { display: grid; gap: 4px; align-content: start; padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius-m); background: var(--card-inner); } +.server-tile strong { font-family: var(--tile-font); font-size: var(--tile-size); font-weight: 400; color: var(--bright); line-height: 1.1; } +.server-tile small { color: var(--muted); font-size: 0.76rem; } +.server-tile .meter-bar { margin-top: 4px; } +.server-tile.bad strong { color: var(--bad); } +.sr-flag { font-family: var(--font-label); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.08em; } + +.server-range { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; } +.server-range .eyebrow { margin-right: 4px; } +.server-range .hint { margin: 0 0 0 auto; font-size: 0.8rem; } + +.server-charts { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; } +@media (min-width: 900px) { .server-charts { grid-template-columns: repeat(2, minmax(0, 1fr)); } } + +.chart { margin: 0; padding: 12px 14px 8px; border: 1px solid var(--border); border-radius: var(--radius-m); background: var(--card-inner); min-width: 0; transition: opacity var(--dur); } +.chart.is-loading { opacity: 0.6; } +.chart-head { display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap; gap: 6px 14px; margin-bottom: 6px; } +.chart-title { font-family: var(--font-label); font-size: var(--label-size); letter-spacing: var(--label-tracking); text-transform: uppercase; color: var(--text); } +.chart-legend { display: flex; gap: 14px; flex-wrap: wrap; font-size: 0.78rem; color: var(--text); } +.chart-key { display: inline-flex; align-items: center; gap: 6px; } +.chart-key i, .chart-tip-row i { width: 14px; height: 2px; border-radius: 1px; display: inline-block; flex: none; } +.chart-plot { position: relative; width: 100%; } +.chart-plot svg { display: block; touch-action: pan-y; outline: none; } +.chart-plot svg:focus-visible { box-shadow: var(--focus-ring); } +.chart-grid { stroke: var(--border); stroke-width: 1; shape-rendering: crispEdges; } +.chart-axis { fill: var(--muted); font-size: 10.5px; font-family: var(--font); } +.chart-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; } +.chart-dot { stroke: var(--card-inner); stroke-width: 2; } +.chart-cross { stroke: var(--line-strong); stroke-width: 1; } +.chart-empty { margin: 0; height: 190px; display: grid; place-items: center; color: var(--muted); font-size: 0.85rem; text-align: center; } +.chart-tip { + position: absolute; + top: 4px; + transform: translateX(-50%); + min-width: 160px; + padding: 8px 10px; + border: 1px solid var(--line-strong); + border-radius: var(--radius-s); + background: var(--panel); + box-shadow: var(--shadow-2); + pointer-events: none; + font-size: 0.78rem; + z-index: 2; +} +.chart-tip-time { color: var(--muted); margin-bottom: 4px; } +.chart-tip-row { display: flex; align-items: center; gap: 8px; } +.chart-tip-row strong { color: var(--bright); font-weight: 600; } +.chart-tip-row span { color: var(--muted); } + +.server-table summary, .server-sections details summary { cursor: pointer; } +.server-table summary { color: var(--muted); font-size: 0.85rem; } +.server-table-scroll { max-height: 320px; overflow: auto; margin-top: 8px; border: 1px solid var(--border); } +.server-table table { width: 100%; border-collapse: collapse; font-size: 0.78rem; white-space: nowrap; } +.server-table th, .server-table td { padding: 5px 10px; text-align: right; border-bottom: 1px solid var(--border); } +.server-table th:first-child, .server-table td:first-child { text-align: left; } +.server-table th { position: sticky; top: 0; background: var(--panel); color: var(--muted); font-weight: 600; } + +.server-sections { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; } +@media (min-width: 900px) { .server-sections { grid-template-columns: repeat(2, minmax(0, 1fr)); } } +.server-sections section { display: grid; gap: 10px; align-content: start; padding: 14px; border: 1px solid var(--border); border-radius: var(--radius-m); background: var(--card-inner); min-width: 0; } +.server-sections h3 { margin: 0; } +.server-sections .hint { margin: 0; font-size: 0.8rem; } +.server-cores { display: grid; grid-template-columns: repeat(auto-fill, minmax(90px, 1fr)); gap: 8px 12px; } +.server-list { display: grid; gap: 6px; margin: 0; } +.server-list div { display: flex; justify-content: space-between; gap: 12px; font-size: 0.84rem; border-bottom: 1px solid var(--border); padding-bottom: 5px; } +.server-list dt { color: var(--muted); overflow-wrap: anywhere; } +.server-list dd { margin: 0; color: var(--bright); text-align: right; } +.server-list small { color: var(--muted); } diff --git a/frontend/src/styles/projekte.css b/frontend/src/styles/projekte.css new file mode 100644 index 0000000..7a0b724 --- /dev/null +++ b/frontend/src/styles/projekte.css @@ -0,0 +1,198 @@ +/* ---------- Projektübersicht ---------- */ +.projects-grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr)); } +.project-card { + padding: 0; + overflow: hidden; + display: flex; + flex-direction: column; + color: var(--text); + text-decoration: none; + transition: border-color 0.12s, box-shadow 0.12s; +} +.project-card:hover { border-color: var(--accent); box-shadow: var(--glow); color: var(--text); } +.project-cover-wrap { position: relative; } +.project-cover-wrap .badge { position: absolute; left: 12px; top: 12px; background: var(--overlay); padding: 3px 8px; } +.project-cover-wrap .badge.ok { background: var(--accent); color: var(--accent-ink); text-shadow: none; } +.project-body h3 { overflow-wrap: anywhere; } +.project-cover { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border-bottom: 1px solid var(--border); filter: saturate(0.8) contrast(1.05); border-bottom-color: var(--border); } +.project-card:hover .project-cover { filter: none; } +.project-cover.empty { + background: repeating-linear-gradient(45deg, transparent 0 10px, rgb(var(--accent-rgb) / 0.07) 10px 20px), var(--input-bg); +} +.project-body { padding: 16px 18px 18px; display: flex; flex-direction: column; flex: 1; } +.project-body .meta { margin-top: auto; padding-top: 14px; } +.project-meta { flex-direction: column; align-items: flex-start; gap: 2px; } +.project-title-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; } +.project-teaser { + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + margin: 8px 0 0; + color: var(--muted); + font-size: 0.9rem; +} + +/* ============================================================ + Artikel (Ansicht + Bearbeitung) – volle Breite mit Seitenleiste + ============================================================ */ +.back { display: inline-block; margin-bottom: 20px; text-decoration: none; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.08em; } + +.article-cover { margin: 0 0 clamp(20px, 3vw, 36px); position: relative; border: 1px solid var(--accent); border-color: var(--line-strong); border-radius: var(--radius-l); overflow: hidden; box-shadow: var(--shadow-1); } +.article-cover img { display: block; width: 100%; height: clamp(200px, 42vh, 560px); object-fit: cover; cursor: zoom-in; } +.article-cover.empty { display: grid; place-items: center; min-height: 160px; border: 1px dashed var(--border); box-shadow: none; background: var(--surface); } +.cover-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; } +.article-cover:not(.empty) .cover-actions { position: absolute; right: 14px; bottom: 14px; } +.article-cover:not(.empty) .cover-actions .btn.ghost { background: var(--overlay); } +.editing .article-cover img { cursor: default; } + +.article-layout { display: grid; gap: clamp(20px, 2.5vw, 40px); align-items: start; } +@media (min-width: 1100px) { + .article-layout { grid-template-columns: minmax(0, 1fr) clamp(280px, 20vw, 360px); } + .article-aside { position: sticky; top: calc(var(--topbar-h) + 20px); } +} + +.article-main { min-width: 0; } +/* Lesefenster: Artikeltext auf ruhigem, dunklem Grund statt über dem Matrix-Regen */ +.article-page:not(.editing) .article-main { + background: var(--surface); + border: 1px solid var(--border); + padding: clamp(18px, 2.5vw, 36px); + border-radius: var(--radius-l); + box-shadow: var(--shadow-1); +} +.article-title { font-size: clamp(2.6rem, 4.4vw, 4.4rem); line-height: 0.95; margin: 0; } +.article-byline { margin: 12px 0 0; color: var(--muted); font-size: 0.88rem; } +.article-lead { max-width: 60ch; font-size: clamp(1.05rem, 1.3vw, 1.25rem); color: var(--text); margin: 14px 0 0; white-space: pre-wrap; border-left: 3px solid var(--accent); padding-left: 14px; border-left-width: 2px; } +.article-empty { margin-top: 32px; } + +.title-input { font-family: var(--font-display); font-size: clamp(2rem, 3.4vw, 3.2rem); text-transform: uppercase; padding: 6px 12px; } +.lead-input { font-size: 1.05rem; margin-top: 10px; resize: vertical; } + +.article-body { + margin-top: clamp(24px, 3vw, 40px); + max-width: 75ch; + color: var(--read); + text-shadow: none; + font-size: clamp(0.98rem, 0.92rem + 0.22vw, 1.12rem); + line-height: 1.8; + overflow-wrap: break-word; +} +.article-body > :first-child { margin-top: 0; } +.article-body h2 { font-size: 2.3em; margin: 1.3em 0 0.4em; } +.article-body h2::before { content: '## '; color: var(--accent); } +.article-body h3 { font-size: 1.7em; margin: 1.2em 0 0.3em; } +.article-body h3::before { content: '### '; color: var(--accent); } +.article-body p { margin: 0 0 1em; } +.article-body ul, .article-body ol { padding-left: 1.6em; margin: 0 0 1em; } +.article-body ul { list-style: none; } +.article-body ul > li::before { content: '■'; color: var(--accent); margin-left: -1.3em; margin-right: 0.7em; font-size: 0.7em; vertical-align: middle; } +.article-body ol li::marker { color: var(--accent); } +.article-body li { margin: 0.2em 0; } +.article-body li > p { margin: 0; display: inline; } +.article-body blockquote { margin: 1.4em 0; padding: 4px 0 4px 18px; border-left: 3px solid var(--accent); color: var(--bright); } +.article-body img { display: block; max-width: 100%; max-height: 80vh; height: auto; margin: 1.4em auto; border: 1px solid var(--border); cursor: zoom-in; } +.article-body hr { border: 0; border-top: 1px dashed var(--accent); margin: 2em 0; } +.article-body a { color: var(--bright); } + +/* Seitenleiste */ +.aside-card { display: flex; flex-direction: column; gap: 18px; border-color: var(--line-strong); } +.aside-facts { margin: 0; display: grid; gap: 12px; } +.aside-facts dd { margin: 3px 0 0; color: var(--bright); } +.aside-facts .sub { display: block; font-size: 0.8rem; color: var(--muted); } +.edit-actions { display: flex; flex-direction: column; gap: 12px; } +.edit-buttons { display: flex; gap: 8px; } +.edit-buttons .btn { flex: 1; } +.edit-actions .link-btn { align-self: flex-start; } + +@media (max-width: 1099px) { + /* Beim Lesen zuerst der Titel, beim Bearbeiten zuerst Status & Aktionen */ + .editing .article-aside { order: -1; } + .aside-card { flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: space-between; padding: 14px 18px; } + .aside-facts { grid-auto-flow: column; gap: 24px; } + .aside-card > .btn.full { width: auto; } + .editing .edit-actions { + position: fixed; + left: 0; + right: 0; + bottom: 0; + z-index: 15; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + padding: 12px var(--gutter) calc(12px + env(safe-area-inset-bottom)); + background: var(--bg); + border-top: 1px solid var(--accent); + box-shadow: 0 -4px 20px rgb(var(--accent-rgb) / 0.15); + } + .editing .edit-actions .error { flex-basis: 100%; } + .editing .edit-buttons { order: 2; margin-left: auto; } + .editing .edit-buttons .btn { flex: none; } + .editing.article-page { padding-bottom: 80px; } +} + +@media (max-width: 640px) { + .aside-facts { grid-auto-flow: row; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px 20px; width: 100%; } + .aside-card > .btn.full { width: 100%; } +} + +/* Editor */ +.editor { margin-top: 20px; } +.toolbar { + position: sticky; + top: var(--topbar-h); + z-index: 10; + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 2px; + padding: 6px; + border: 1px solid var(--accent); + border-color: var(--line-strong); + border-radius: var(--radius-m) var(--radius-m) 0 0; + background: var(--panel); + backdrop-filter: var(--blur); + -webkit-backdrop-filter: var(--blur); +} +.toolbar button { + font: inherit; + font-size: 0.8rem; + text-transform: uppercase; + letter-spacing: 0.04em; + min-height: 32px; + padding: 5px 10px; + border: 1px solid transparent; + background: transparent; + color: var(--text); + cursor: pointer; + text-shadow: inherit; + border-radius: var(--radius-s); +} +.toolbar button:hover:not(:disabled) { border-color: var(--border); color: var(--bright); } +.toolbar button:disabled { opacity: 0.35; cursor: default; } +.toolbar button.active { background: var(--accent); color: var(--accent-ink); text-shadow: none; } +.toolbar button b, .toolbar button i, .toolbar button u { color: inherit; } +.toolbar-sep { width: 1px; height: 20px; background: var(--border); margin: 0 4px; } + +.editor-content.article-body { + margin-top: 0; + max-width: none; + min-height: max(320px, 50vh); + padding: clamp(16px, 2vw, 28px); + border: 1px solid var(--accent); + border-top: 0; + background: var(--editor-bg); + outline: none; + border-color: var(--line-strong); + border-radius: 0 0 var(--radius-m) var(--radius-m); +} +.editor-content.article-body:focus { box-shadow: var(--glow); } +.editor-content img { cursor: pointer; } +.editor-content img.ProseMirror-selectednode { outline: 2px solid var(--bright); outline-offset: 2px; } +.editor-content p.is-editor-empty:first-child::before { + content: attr(data-placeholder); + color: var(--muted); + float: left; + height: 0; + pointer-events: none; +} diff --git a/frontend/src/styles/reisen.css b/frontend/src/styles/reisen.css new file mode 100644 index 0000000..2f52be2 --- /dev/null +++ b/frontend/src/styles/reisen.css @@ -0,0 +1,198 @@ +/* ---------- Reisen: Weltkarte ---------- */ +.city-search { position: relative; max-width: 720px; margin-bottom: 16px; } +.city-search input { + font: inherit; + font-size: 1.05rem; + color: var(--bright); + background: var(--input-bg); + border: 1px solid var(--accent); + padding: 12px 16px 12px 38px; + width: 100%; +} +.city-search input:focus { outline: none; box-shadow: var(--glow); } +.city-search .combo-list li small { margin-left: 6px; } +.city-search .combo-list li.added { opacity: 0.55; cursor: default; } +.combo-info { color: var(--muted); cursor: default !important; } +.combo-info::before { content: '' !important; } +.travel-error { margin-bottom: 12px; } + +.travel-map { position: relative; padding: 0; overflow: hidden; height: clamp(340px, 68vh, 760px); border-radius: var(--radius-l); } +.travel-loading { padding: 20px; } +.worldmap, .worldmap svg { width: 100%; height: 100%; display: block; } +.worldmap svg { cursor: grab; touch-action: none; --inv: 1; } +.worldmap svg:active { cursor: grabbing; } +.map-sphere { fill: var(--map-ocean); } +.map-graticule { fill: none; stroke: rgb(var(--accent-rgb) / 0.09); vector-effect: non-scaling-stroke; } +.map-country { + fill: var(--map-land); + stroke: rgb(var(--accent-rgb) / 0.45); + stroke-width: 0.6; + vector-effect: non-scaling-stroke; + cursor: pointer; + transition: fill 0.15s; +} +.map-country:hover { fill: var(--map-land-hover); } +.map-country.visited { fill: rgb(var(--accent-rgb) / 0.55); stroke: rgb(var(--accent-rgb) / 0.9); } +.map-country.visited:hover { fill: rgb(var(--accent-rgb) / 0.7); } +.map-country.selected { stroke: var(--bright); stroke-width: 1.6; fill: rgb(var(--accent-rgb) / 0.35); } +.map-country.visited.selected { fill: rgb(var(--accent-rgb) / 0.8); } + +/* Stadt-Punkte: Größe bleibt beim Zoomen gleich (--inv = 1 / Zoomfaktor) */ +.map-city { transform: scale(var(--inv)); cursor: pointer; } +.map-city-hit { fill: transparent; } +.map-city-dot { fill: var(--bright); stroke: var(--accent); stroke-width: 2; filter: drop-shadow(0 0 3px rgb(var(--accent-rgb) / 0.9)); } +.map-city:hover .map-city-dot { fill: #fff; } +.map-city-ring { fill: none; stroke: var(--bright); stroke-width: 1.5; animation: city-pulse 1.6s ease-out infinite; transform-origin: 0 0; } +@keyframes city-pulse { from { opacity: 1; transform: scale(0.6); } to { opacity: 0; transform: scale(1.8); } } +.calm .map-city-ring { animation: none; } +@media (prefers-reduced-motion: reduce) { .map-city-ring { animation: none; } } + +.map-controls { position: absolute; top: 12px; right: 12px; display: flex; flex-direction: column; border: 1px solid var(--accent); background: var(--overlay); border-color: var(--line-strong); border-radius: var(--radius-m); overflow: hidden; backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur); } +.map-controls button { + font: inherit; + font-size: 1.15rem; + width: 38px; + height: 38px; + border: 0; + background: transparent; + color: var(--accent); + cursor: pointer; +} +.map-controls button + button { border-top: 1px solid var(--border); } +.map-controls button:hover { background: var(--accent); color: var(--accent-ink); } + +/* Info-Kasten: Desktop unten links über der Karte, Handy unter der Karte */ +.info-card { + position: absolute; + left: 14px; + bottom: 14px; + width: min(380px, calc(100% - 28px)); + max-height: calc(100% - 28px); + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 10px; + padding: 16px 18px; + background: var(--panel); + border: 1px solid var(--accent); + border-color: var(--line-strong); + border-radius: var(--radius-m); + box-shadow: var(--shadow-2); + backdrop-filter: var(--blur); + -webkit-backdrop-filter: var(--blur); +} +.info-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; } +.info-head h2 { margin: 0; font-size: calc(var(--h2-size) * 1.15); } +.info-sub { margin: -6px 0 0; color: var(--muted); font-size: 0.82rem; } +.info-facts { margin: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 14px; } +.info-facts dt { color: var(--muted); text-transform: uppercase; font-size: var(--label-size); letter-spacing: var(--label-tracking); } +.info-facts dd { margin: 1px 0 0; color: var(--bright); font-size: 0.88rem; overflow-wrap: anywhere; } +.info-extract { + margin: 0; + color: var(--read); + font-size: 0.85rem; + line-height: 1.55; + text-shadow: none; + display: -webkit-box; + -webkit-line-clamp: 5; + -webkit-box-orient: vertical; + overflow: hidden; +} +.info-more { font-size: 0.8rem; align-self: flex-start; } +.info-visit { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding-top: 10px; border-top: 1px dashed var(--border); border-top-style: solid; } +.info-cities { display: flex; flex-wrap: wrap; gap: 6px; } +.info-card .chip { font-size: 0.78rem; } +.info-others { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; } +.info-others .hint { margin: 0; font-size: 0.78rem; } + +/* Städte anderer Konten */ +.map-city.other .map-city-dot { fill: var(--dot); stroke: var(--bg); stroke-width: 1.5; filter: drop-shadow(0 0 3px var(--dot)); } +.map-city.other:hover .map-city-dot { fill: var(--dot); stroke: var(--bright); } +.map-city.other .map-city-ring { stroke: var(--dot); } +.travel-others { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin: -4px 0 14px; } +.travel-legend { display: inline-flex; align-items: center; gap: 6px; font-size: 0.82rem; color: var(--muted); margin-left: 6px; } +.legend-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: var(--dot); box-shadow: 0 0 4px var(--dot); flex: none; } +.legend-dot.own { background: var(--bright); box-shadow: 0 0 0 2px var(--accent); } +.travel-person { display: inline-flex; align-items: center; gap: 6px; } +.travel-person:not(.active) { opacity: 0.55; } +.travel-person:not(.active) .legend-dot { background: transparent; box-shadow: inset 0 0 0 2px var(--dot); } +.travel-person small { color: var(--muted); } +.badge.travel-owner { color: var(--dot); } + +/* Besuchte Orte: Kontinente nebeneinander, Länder ausklappbar */ +.visited-list { display: grid; gap: 28px 32px; margin-top: 28px; align-items: start; } +@media (min-width: 900px) { .visited-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } } +@media (min-width: 1400px) { .visited-list { grid-template-columns: repeat(3, minmax(0, 1fr)); } } +.travel-empty { margin-top: 24px; } +.visited-continent .section-title { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; white-space: normal; } +.continent-toggle { + display: flex; + align-items: baseline; + gap: 10px; + flex-wrap: wrap; + padding: 2px 0; + border: 0; + background: none; + color: inherit; + font: inherit; + letter-spacing: inherit; + text-transform: inherit; + text-align: left; + cursor: pointer; +} +.continent-toggle:hover { color: var(--accent); } +.continent-arrow { display: inline-block; color: var(--accent); transform: rotate(90deg); transition: transform var(--dur) var(--ease-out); } +.continent-toggle[aria-expanded='false'] .continent-arrow { transform: none; } +.visited-continent.closed .section-title { margin-bottom: 0; } +.visited-count { font-family: var(--font); font-size: 0.75rem; font-weight: 400; letter-spacing: 0.02em; text-transform: none; color: var(--muted); text-shadow: none; } +.visited-countries { list-style: none; margin: 0; padding: 0; border: 1px solid var(--border); border-radius: var(--radius-m); background: var(--surface); overflow: hidden; } +.visited-country + .visited-country { border-top: 1px solid var(--border); } +.visited-row { display: flex; align-items: center; gap: 4px; padding: 2px 12px 2px 4px; } +.visited-country.active .visited-row { background: var(--accent-soft); box-shadow: inset 2px 0 0 var(--accent); } +.visited-toggle { + flex: none; + width: 34px; + height: 34px; + display: grid; + place-items: center; + border: 0; + border-radius: var(--radius-s); + background: transparent; + color: var(--accent); + font: inherit; + cursor: pointer; +} +.visited-toggle span { transition: transform var(--dur) var(--ease-out); } +.visited-toggle[aria-expanded='true'] span { transform: rotate(90deg); } +.visited-toggle:hover:not(:disabled) { background: var(--accent-soft); } +.visited-toggle:disabled { color: var(--muted); cursor: default; } +.visited-name { + flex: 1; + min-width: 0; + display: flex; + align-items: center; + gap: 8px; + padding: 8px 6px; + border: 0; + background: transparent; + color: var(--bright); + font: inherit; + font-weight: 600; + text-align: left; + cursor: pointer; + overflow-wrap: anywhere; +} +.visited-name:hover { color: var(--accent); } +.visited-flag { font-size: 1.1em; } +.visited-meta { flex: none; font-size: 0.75rem; color: var(--muted); } +.visited-country .visited-cities { padding: 2px 14px 14px 46px; } +.chip-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; } +.chip.active { border-style: solid; border-color: var(--accent); color: var(--bright); background: var(--accent-soft); } +.travel-credits { margin-top: 28px; font-size: 0.72rem; } + +@media (max-width: 759px) { + .travel-map { height: auto; overflow: visible; } + .worldmap { height: clamp(260px, 52vh, 420px); } + .info-card { position: relative; left: auto; bottom: auto; width: auto; max-height: none; border-width: 1px 0 0; box-shadow: none; } + .info-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); } +} diff --git a/frontend/src/styles/responsive.css b/frontend/src/styles/responsive.css new file mode 100644 index 0000000..c6c51d9 --- /dev/null +++ b/frontend/src/styles/responsive.css @@ -0,0 +1,21 @@ +/* ---------- Handy ---------- */ +@media (max-width: 640px) { + body { font-size: 14px; } + .brand { font-size: 1.6rem; } + .toolbar { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; } + .toolbar button { flex: none; } + .track-form { flex-direction: column; } + .tiles { gap: 12px; } + .tiles > * { flex-basis: 140px; } + .tile { padding: 16px; } + .tile small { display: none; } + .page-head .btn, .page-actions { width: 100%; } + .page-actions .btn { flex: 1; } +} + +/* Weniger Bewegung, wenn im System eingestellt */ +.calm .page-head h1::after, .calm .hero h1::after, .calm .dot.bad { animation: none; } +@media (prefers-reduced-motion: reduce) { + .page-head h1::after, .hero h1::after, .dot.bad { animation: none; } + * { transition: none !important; } +} diff --git a/frontend/src/styles/start.css b/frontend/src/styles/start.css new file mode 100644 index 0000000..35f1694 --- /dev/null +++ b/frontend/src/styles/start.css @@ -0,0 +1,102 @@ +/* ---------- Startseite: Sendungsverfolgung ---------- */ +.hero { text-align: center; } + +.track-form { display: flex; gap: 8px; max-width: 820px; margin: 0 auto; } +.prompt-input { flex: 1; min-width: 0; position: relative; } +.prompt-input::before { + content: '>'; + position: absolute; + left: 16px; + top: 50%; + transform: translateY(-50%); + color: var(--accent); + font-size: 1.15rem; + pointer-events: none; +} +.track-form input { font-size: 1.1rem; padding: 14px 18px 14px 38px; border-color: var(--accent); } +.track-form .btn { padding: 14px 26px; } + +.recent { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin-top: 12px; } + +.result { margin: 24px auto 0; max-width: 1280px; text-align: left; } +.result .card { border-color: var(--accent); } +.result-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; flex-wrap: wrap; } +.carrier { font-family: var(--h1-font); font-size: calc(var(--h1-size) * 0.6); line-height: 1.05; text-transform: uppercase; color: var(--bright); text-shadow: var(--heading-glow); } +.number { color: var(--muted); font-size: 0.88rem; word-break: break-all; } + +.tracking-result { display: grid; gap: 24px; } +@media (min-width: 900px) { + .tracking-result { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); gap: 36px; } + .tracking-events { border-left: 1px dashed var(--border); padding-left: 32px; } +} + +.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; margin: 18px 0 4px; } +.fact { border: 1px solid var(--border); border-radius: var(--radius-s); padding: 10px 14px; background: var(--card-inner); } +.fact dt, .aside-facts dt, .monitor-facts dt { + font-size: var(--label-size); + color: var(--muted); + text-transform: uppercase; + letter-spacing: var(--label-tracking); +} +.fact dd { margin: 2px 0 0; font-weight: 600; color: var(--bright); } + +.timeline { list-style: none; margin: 0; padding: 0; } +.timeline li { position: relative; padding: 0 0 16px 22px; border-left: 1px dashed var(--border); margin-left: 5px; border-left-style: solid; border-left-color: var(--border); } +.timeline li:last-child { border-left-color: transparent; padding-bottom: 0; } +.timeline li::before { + content: ''; + position: absolute; + left: -6px; + top: 5px; + width: 11px; + height: 11px; + border: 1px solid var(--accent); + border-radius: 50%; + background: var(--surface-2); +} +.timeline li:first-child::before { background: var(--accent); box-shadow: var(--glow); } +.timeline .when { font-size: 0.78rem; color: var(--muted); } +.timeline .what { color: var(--bright); } +.timeline .where { font-size: 0.82rem; color: var(--muted); } +.more { margin-top: 10px; } + +.links { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; } +.links a { font-size: 0.8rem; padding: 5px 12px; border: 1px solid var(--border); border-radius: var(--radius-pill); text-decoration: none; text-transform: uppercase; letter-spacing: 0.05em; } +.links a:hover { border-color: var(--accent); background: var(--accent); color: var(--accent-ink); text-shadow: none; } + +/* ---------- Startseite: Kacheln ---------- */ +.tiles-section { margin-top: clamp(40px, 6vw, 72px); } +.tiles-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 6px 12px; margin-bottom: 14px; } +.tiles-head .link-btn { white-space: nowrap; } +.section-title { margin: 0; white-space: nowrap; } +.section-title::before { content: '// '; color: var(--accent); } +/* Flex statt festem Raster: jede Zeile wird ganz gefüllt, egal wie viele Kacheln */ +.tiles { display: flex; flex-wrap: wrap; gap: clamp(14px, 1.5vw, 24px); } +.tiles > * { flex: 1 1 210px; min-width: 0; } +.tile { + display: flex; + flex-direction: column; + align-items: flex-start; + padding: clamp(18px, 2vw, 28px); + border: 1px solid var(--border); + background: var(--surface); + color: var(--text); + font: inherit; + text-align: left; + text-decoration: none; + text-shadow: inherit; + cursor: pointer; + position: relative; + border-radius: var(--radius-m); + box-shadow: var(--shadow-1); + gap: 12px; + transition: transform var(--dur) var(--ease-out); +} +.tile:hover { border-color: var(--accent); box-shadow: var(--glow); background: var(--surface-hover); color: var(--text); } +.tile:hover strong { color: var(--bright); } +.tile svg { color: var(--accent); box-sizing: content-box; width: 26px; height: 26px; padding: 10px; border-radius: var(--radius-s); background: var(--accent-soft); filter: none; } +.tile strong { font-family: var(--tile-font); font-size: var(--tile-size); font-weight: 400; line-height: 1.05; text-transform: uppercase; letter-spacing: 0.04em; } +.tile small { color: var(--muted); font-size: 0.8rem; } +.tile-empty { border-style: dashed; background: transparent; } +.tile-empty svg { color: var(--muted); filter: none; background: transparent; box-shadow: inset 0 0 0 1px var(--border); } +.tile-empty strong { color: var(--muted); }