Files
nebula/src/app/components.css
T
Florian WildeandClaude Opus 5 4ba53a239f fix(ui): Anzeigefehler aus der Browser-Pruefung beheben
Erstmals mit echtem Browser nachgesehen (headless Chrome ueber Playwright,
Screenshots aller Ansichten). Dabei fuenf Dinge gefunden:

1. Menue klebte am Fensterrand statt am Ausloeser. Bei einem Ausloeser weit
   links wurde die bevorzugte rechtsbuendige Ausrichtung negativ und dann auf
   den Rand geklemmt - das Menue stand quer ueber der Seite. Jetzt wird bei
   Ueberlauf auf die andere Ausrichtung gewechselt und erst danach geklemmt.

2. .popover war mit 97 % nicht ganz deckend, wodurch "Bearbeiten" und
   "Loeschen" schwach durchschienen. Jetzt vollstaendig deckend.

3. Der Schieberegler zeichnete die Spur rechts vom Griff in einem hellen
   Standardton - ein grelles Band im dunklen Layout. Ersetzt durch eine
   selbst gezeichnete Variante mit Farbverlauf und sichtbarem Griff. Auf der
   Projektseite ersetzt sie zugleich das bisherige unsichtbare Eingabefeld
   ueber einem gezeichneten Balken, das gar keinen Griff hatte.

4. Der Hinweis der Kachel "Ideen" wurde mitten im Wort abgeschnitten
   ("Noch ein Gedanke - nichts ge..."). Kurzer Text statt der langen
   Statusbeschreibung.

5. Nach der Einrichtung stand im Adminbereich "noch nie angemeldet", obwohl
   gerade eine Sitzung lief. Einrichtung und Registrierung setzen lastLoginAt
   jetzt mit.

Die Konsole blieb ueber alle Ansichten hinweg frei von Fehlern und Warnungen
- die strikte CSP mit Nonce und strict-dynamic bricht also nichts.

Geprueft an einer separaten Wegwerf-Datenbank auf Port 3100, damit die
laufende Instanz unberuehrt blieb.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 22:46:00 +02:00

271 lines
7.5 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ─────────────────────────────────────────────────────────────
Nebula – wiederkehrende Bausteine.
Bewusst in @layer components: Tailwind sortiert die Layer als
theme → base → components → utilities. Ohne diese Zuordnung wuerden
die Kurzschreibweisen hier (padding, border-radius …) die Utilities
ueberschreiben, weil sie spaeter im Stylesheet stehen – aus
"field pl-9" wuerde dann wieder das linke Standardpadding und das
Suchsymbol laege auf dem Platzhaltertext.
───────────────────────────────────────────────────────────── */
@layer components {
/* ── Glasflaechen ─────────────────────────────────────────── */
.glass {
position: relative;
background: var(--glass-bg);
border: 1px solid var(--glass-border);
backdrop-filter: blur(18px) saturate(140%);
-webkit-backdrop-filter: blur(18px) saturate(140%);
border-radius: var(--radius-card);
box-shadow:
0 1px 0 0 var(--glass-highlight) inset,
0 24px 60px -30px rgba(0, 0, 0, 0.9);
}
.glass-soft {
background: rgba(255, 255, 255, 0.025);
border: 1px solid rgba(255, 255, 255, 0.07);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border-radius: 0.9rem;
}
/* Karte mit Akzent-Glow. --accent-from/--accent-to setzt die Komponente. */
.card-glow {
transition:
transform 0.35s cubic-bezier(0.22, 1, 0.36, 1),
box-shadow 0.35s ease,
border-color 0.35s ease;
}
.card-glow::before {
content: "";
position: absolute;
inset: -1px;
border-radius: inherit;
padding: 1px;
background: linear-gradient(135deg, var(--accent-from, #8b5cf6), var(--accent-to, #d946ef));
-webkit-mask:
linear-gradient(#000 0 0) content-box,
linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
opacity: 0;
transition: opacity 0.35s ease;
pointer-events: none;
}
.card-glow:hover {
transform: translateY(-4px);
box-shadow:
0 1px 0 0 var(--glass-highlight) inset,
0 30px 70px -30px rgba(0, 0, 0, 0.95),
0 0 46px -12px var(--accent-from, #8b5cf6);
}
.card-glow:hover::before {
opacity: 0.85;
}
/**
* Flaeche fuer alles, was ueber dem Inhalt schwebt: Menues, Dialoge.
*
* Bewusst nahezu deckend statt Glas. Ein Overlay muss lesbar sein, egal
* was darunter liegt - bei 3,5 % Deckkraft schien der Inhalt dahinter
* durch. backdrop-filter hilft hier nicht: liegt das Element in einem
* Vorfahren, der selbst backdrop-filter setzt (unsere Karten), bleibt die
* Weichzeichnung wirkungslos.
*/
.popover {
/* Vollstaendig deckend: bei 97 % schimmerte darunterliegender Text
(die Schaltflaechen "Bearbeiten" und "Loeschen") noch durch. */
background: #090b18;
border: 1px solid rgba(255, 255, 255, 0.11);
border-radius: 0.9rem;
box-shadow:
0 1px 0 0 rgba(255, 255, 255, 0.07) inset,
0 28px 70px -24px rgba(0, 0, 0, 0.95);
}
/* ── Text & Akzente ───────────────────────────────────────── */
.text-gradient {
background: linear-gradient(120deg, #c4b5fd 0%, #67e8f9 45%, #f0abfc 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.accent-bar {
background: linear-gradient(90deg, var(--accent-from, #8b5cf6), var(--accent-to, #d946ef));
}
.accent-dot {
box-shadow: 0 0 12px 1px currentColor;
}
/* ── Buttons ──────────────────────────────────────────────── */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
border-radius: 0.75rem;
font-size: 0.875rem;
font-weight: 500;
padding: 0.55rem 1rem;
transition:
background-color 0.2s ease,
border-color 0.2s ease,
color 0.2s ease,
box-shadow 0.2s ease,
filter 0.2s ease;
cursor: pointer;
white-space: nowrap;
border: 1px solid transparent;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.btn:focus-visible {
outline: 2px solid rgba(167, 139, 250, 0.8);
outline-offset: 2px;
}
.btn-primary {
background: linear-gradient(120deg, #7c3aed, #c026d3);
color: #fff;
box-shadow: 0 10px 30px -12px rgba(168, 85, 247, 0.9);
}
.btn-primary:hover:not(:disabled) {
filter: brightness(1.12);
box-shadow: 0 14px 36px -12px rgba(168, 85, 247, 1);
}
.btn-ghost {
background: rgba(255, 255, 255, 0.04);
border-color: rgba(255, 255, 255, 0.1);
color: #cbd5f5;
}
.btn-ghost:hover:not(:disabled) {
background: rgba(255, 255, 255, 0.09);
color: #fff;
}
.btn-danger {
background: rgba(244, 63, 94, 0.12);
border-color: rgba(244, 63, 94, 0.35);
color: #fda4af;
}
.btn-danger:hover:not(:disabled) {
background: rgba(244, 63, 94, 0.22);
color: #fff;
}
/* ── Formularfelder ───────────────────────────────────────── */
.field {
width: 100%;
border-radius: 0.75rem;
background: rgba(8, 10, 24, 0.6);
border: 1px solid rgba(255, 255, 255, 0.09);
padding: 0.6rem 0.85rem;
font-size: 0.875rem;
color: #e6e8f5;
transition:
border-color 0.2s ease,
box-shadow 0.2s ease;
}
.field::placeholder {
color: rgba(148, 163, 184, 0.6);
}
.field:focus {
outline: none;
border-color: rgba(167, 139, 250, 0.6);
box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.18);
}
.field-label {
display: block;
font-size: 0.7rem;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
color: rgba(148, 163, 184, 0.85);
margin-bottom: 0.4rem;
}
select.field option {
background: #0a0c1a;
color: #e6e8f5;
}
/**
* Schieberegler. Der native Regler zeichnet die Spur rechts vom Griff in
* einem hellen Standardton - im dunklen Layout ein grelles Band. Deshalb
* vollstaendig selbst gezeichnet: der gefuellte Anteil kommt aus der
* Variablen --fill, die die Komponente aus dem Wert setzt.
*/
.range {
-webkit-appearance: none;
appearance: none;
width: 100%;
height: 6px;
border-radius: 9999px;
cursor: pointer;
background: linear-gradient(
90deg,
#8b5cf6 0%,
#d946ef var(--fill, 0%),
rgba(255, 255, 255, 0.1) var(--fill, 0%),
rgba(255, 255, 255, 0.1) 100%
);
}
.range:focus-visible {
outline: 2px solid rgba(167, 139, 250, 0.8);
outline-offset: 4px;
}
.range::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
height: 16px;
width: 16px;
border-radius: 9999px;
background: #f5f3ff;
border: 2px solid #7c3aed;
box-shadow: 0 0 14px -2px rgba(168, 85, 247, 0.9);
cursor: grab;
}
.range::-webkit-slider-thumb:active {
cursor: grabbing;
}
.range::-moz-range-thumb {
height: 14px;
width: 14px;
border-radius: 9999px;
background: #f5f3ff;
border: 2px solid #7c3aed;
box-shadow: 0 0 14px -2px rgba(168, 85, 247, 0.9);
cursor: grab;
}
.range::-moz-range-track {
background: transparent;
}
}