munin/static/style.css
Thomas Adamek 466f1e40af Workspaces, Änderungshistorie, Papierkorb, Nutzungsübersicht, Hilfe
Umsetzung der Ausbaustufen 2.1, 3.6, 3.8, 3.9, 4.1, 4.2, 4.4, 4.6,
5.1–5.4 (Details in AUSBAUSTUFEN.md).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 07:44:52 +02:00

993 lines
32 KiB
CSS

/* Aussehen der Weboberfläche.
*
* ── Aufbau dieser Datei ──────────────────────────────────────────────────────
* 1. Grundwerte Farben, Abstände, Schriftgrößen, Breiten
* 2. Grundlagen body, Überschriften, Links, Code
* 3. Gerüst Kopfleisten und Inhaltsbereich
* 4. Bausteine Karten, Meldungen, Marken, Tabellen, Formulare, Knöpfe
* 5. Seiten das Wenige, das wirklich nur eine Seite betrifft
* 6. Schmale Geräte
*
* ── Zwei Regeln, die alles zusammenhalten ────────────────────────────────────
*
* ERSTENS: Abstände kommen ausschließlich aus der Skala (--s1 bis --s8). Keine
* frei gewählten Werte. Vorher standen hier 29 verschiedene Abstandswerte — das
* Ergebnis war, dass nichts zueinander ausgerichtet war und jede neue Seite
* wieder ein bisschen anders aussah.
*
* ZWEITENS: Die Breite richtet sich nach dem Inhalt, nicht nach dem Bildschirm.
* Eine Tabelle mit acht Spalten braucht Platz, ein Fließtext dagegen darf nicht
* über die ganze Breite laufen — ab etwa 75 Zeichen je Zeile findet das Auge den
* Zeilenanfang nicht mehr zuverlässig. Deshalb gibt es drei Breiten, und jede
* Seite wählt die passende Darstellung.
*/
/* ── 1. Grundwerte ────────────────────────────────────────────────────────── */
:root {
/* Farben: eine neutrale Grundfläche, ein Akzent, eine Warnfarbe. */
--grund: #faf9f7; /* Seitenhintergrund */
--flaeche: #ffffff; /* Karten, Tabellen, Eingabefelder */
--flaeche-leis: #f4f2ef; /* Tabellenköpfe, gedämpfte Bereiche */
--rahmen: #e4e1dc;
--rahmen-stark: #cfcbc4;
--text: #23211e;
--text-leise: #6d6862;
--akzent: #2c6e4e;
--akzent-flach: #ebf3ee;
--akzent-text: #205138;
--warn: #a13a2b;
--warn-flach: #fbeeeb;
/* Abstandsskala — alles Weitere ist ein Vielfaches davon. */
--s1: 0.25rem;
--s2: 0.5rem;
--s3: 0.75rem;
--s4: 1rem;
--s5: 1.5rem;
--s6: 2rem;
--s7: 3rem;
--s8: 4rem;
/* Schriftgrößen. */
--t-klein: 0.8125rem;
--t-meta: 0.875rem;
--t-normal: 1rem;
--t-gross: 1.125rem;
--t-h2: 1.25rem;
--t-h1: 1.625rem;
/* Breiten. Die Seite nutzt den Platz aus; nur der Fließtext begrenzt sich
* selbst (siehe Regel zwei oben). */
--breite-seite: 92rem; /* Seitenleiste plus Inhalt */
--breite-leiste: 15rem; /* Seitenleiste */
--breite-lesen: 44rem; /* Fließtext eines Eintrags */
--breite-schmal: 25rem; /* Anmeldung */
/* Höhe der Bedienelemente. Wichtig ist nicht der Wert, sondern dass Knopf
* und Eingabefeld denselben verwenden — sonst stehen sie in einer Zeile
* nebeneinander unterschiedlich hoch, und das fällt sofort auf. */
--hoehe-bedienelement: 2.25rem;
--hoehe-kopfleiste: 3.5rem;
--radius: 6px;
--radius-gross: 10px;
--schatten: 0 1px 2px rgb(0 0 0 / 0.04), 0 1px 3px rgb(0 0 0 / 0.06);
}
/* Dunkle Darstellung: nur die Farben werden getauscht, alle Regeln darunter
* gelten unverändert weiter. */
@media (prefers-color-scheme: dark) {
:root {
--grund: #1a1918;
--flaeche: #232120;
--flaeche-leis: #2b2927;
--rahmen: #383533;
--rahmen-stark: #4a4643;
--text: #e9e6e2;
--text-leise: #a09a94;
--akzent: #6fbf96;
--akzent-flach: #1f2d26;
--akzent-text: #8fd3ae;
--warn: #e08d7e;
--warn-flach: #2e2320;
--schatten: 0 1px 3px rgb(0 0 0 / 0.4);
}
}
*, *::before, *::after { box-sizing: border-box; }
/* ── 2. Grundlagen ───────────────────────────────────────────────────────── */
body {
margin: 0;
background: var(--grund);
color: var(--text);
font: var(--t-normal)/1.6 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
-webkit-font-smoothing: antialiased;
}
h1, h2, h3 { line-height: 1.3; font-weight: 600; margin: 0; }
h1 { font-size: var(--t-h1); letter-spacing: -0.01em; }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-gross); }
p { margin: 0 0 var(--s4); }
p:last-child { margin-bottom: 0; }
a { color: var(--akzent-text); text-decoration: none; }
a:hover { text-decoration: underline; }
/* Sichtbarer Fokusrahmen für alles, was per Tastatur erreichbar ist.
* :focus-visible statt :focus — so erscheint der Rahmen bei Tastaturbedienung,
* aber nicht bei jedem Mausklick. */
:focus-visible {
outline: 2px solid var(--akzent);
outline-offset: 2px;
border-radius: var(--radius);
}
code, pre {
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
font-size: 0.9em;
}
code {
background: var(--flaeche-leis);
border: 1px solid var(--rahmen);
padding: 0.1em 0.35em;
border-radius: 4px;
}
pre {
background: var(--flaeche-leis);
border: 1px solid var(--rahmen);
border-radius: var(--radius);
padding: var(--s4);
overflow-x: auto;
margin: 0;
}
pre code { background: none; border: none; padding: 0; }
/* Kleiner erklärender Text. Als Blockelement UND innerhalb von Beschriftungen
* verwendbar, deshalb kein eigenes display. */
.hilfe {
color: var(--text-leise);
font-size: var(--t-meta);
font-weight: normal;
}
/* ── 3. Gerüst ───────────────────────────────────────────────────────────── */
/* Schmale Kopfleiste über die ganze Breite. Sie trägt nur Marke und Abmelden —
* die eigentliche Navigation steht in der Seitenleiste. */
.kopfleiste {
background: var(--flaeche);
border-bottom: 1px solid var(--rahmen);
position: sticky;
top: 0;
z-index: 20;
}
.kopfleiste-innen {
max-width: var(--breite-seite);
margin-inline: auto;
padding-inline: var(--s5);
min-height: var(--hoehe-kopfleiste);
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--s4);
}
.marke-wort {
font-weight: 600;
color: var(--text);
letter-spacing: -0.01em;
}
.marke-wort:hover { text-decoration: none; }
/* Workspace-Umschalter in der Kopfleiste: Name des aktuellen Workspace,
* klickbar zur Auswahl-/Verwaltungsseite. Dezent gehalten — die Marke bleibt
* der optische Ankerpunkt, das hier ist Kontext, kein zweites Logo. */
.arbeitsbereich {
display: inline-flex;
align-items: center;
gap: var(--s1);
padding: var(--s1) var(--s2);
border-radius: var(--radius);
color: var(--text-leise);
font-size: var(--t-meta);
font-weight: 500;
}
.arbeitsbereich:hover {
background: var(--flaeche-leis);
color: var(--text);
text-decoration: none;
}
.arbeitsbereich-trenner { color: var(--rahmen-stark); font-weight: 400; }
.arbeitsbereich-name { color: inherit; }
.arbeitsbereich-pfeil { font-size: 0.7em; opacity: 0.6; }
/* Das Gerüst: Seitenleiste links, Inhalt rechts. */
.gerüst {
max-width: var(--breite-seite);
margin-inline: auto;
padding-inline: var(--s5);
display: grid;
grid-template-columns: var(--breite-leiste) minmax(0, 1fr);
gap: var(--s7);
align-items: start;
}
/* Seitenleiste.
*
* position: sticky hält sie beim Scrollen sichtbar. Der Wert für top entspricht
* der Höhe der Kopfleiste, damit sie genau darunter stehen bleibt und nicht
* dahinter verschwindet. */
.seitenleiste {
position: sticky;
top: var(--hoehe-kopfleiste);
max-height: calc(100dvh - var(--hoehe-kopfleiste));
overflow-y: auto;
padding-block: var(--s6);
display: flex;
flex-direction: column;
gap: var(--s5);
}
.nav-gruppe { display: flex; flex-direction: column; gap: var(--s1); }
.nav-titel {
font-size: var(--t-klein);
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--text-leise);
margin-bottom: var(--s1);
padding-inline: var(--s2);
}
.nav-liste { list-style: none; margin: 0; padding: 0; }
.nav-liste a {
display: flex;
align-items: center;
gap: var(--s2);
padding: var(--s1) var(--s2);
border-radius: var(--radius);
color: var(--text);
font-size: var(--t-meta);
line-height: 1.5;
}
.nav-liste a:hover { background: var(--flaeche-leis); text-decoration: none; }
/* Der aktive Punkt wird durch Fläche markiert, nicht durch Farbe allein —
* so bleibt er auch bei eingeschränktem Farbsehen erkennbar. */
.nav-liste a.aktiv {
background: var(--akzent-flach);
color: var(--akzent-text);
font-weight: 500;
}
.nav-liste.leise a { color: var(--text-leise); }
/* Schlagwort und Anzahl: Name links, Zahl rechtsbündig. */
.nav-text { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-zahl { color: var(--text-leise); font-size: var(--t-klein); font-variant-numeric: tabular-nums; }
.nav-liste a.aktiv .nav-zahl { color: inherit; }
/* Inhaltsbereich. */
.inhalt { padding-block: var(--s6) var(--s8); min-width: 0; }
/* Fließtext auf Lesebreite. Nur der Text selbst — Überschrift, Metazeile und
* Tabellen dürfen die volle Breite nutzen. */
.lesebreite { max-width: var(--breite-lesen); }
/* Seitenkopf: Titel links, Aktionen rechts — auf einer Linie.
*
* align-items: center statt flex-start, damit der Knopf mittig zur Überschrift
* sitzt und nicht an deren Oberkante klebt. */
.seitenkopf {
display: flex;
align-items: center;
gap: var(--s4);
flex-wrap: wrap;
margin-bottom: var(--s5);
}
.seitenkopf-titel { flex: 1; min-width: 15rem; }
.seitenkopf-titel .hilfe { display: block; margin-top: var(--s1); }
.seitenkopf-aktionen { display: flex; gap: var(--s2); align-items: center; }
/* Abschnitt innerhalb einer Seite. */
.abschnitt { margin-top: var(--s7); }
.abschnitt > h2 { margin-bottom: var(--s2); }
.abschnitt > .hilfe { display: block; margin-bottom: var(--s4); }
/* ── 4. Bausteine ────────────────────────────────────────────────────────── */
/* Karte: der Standardbehälter für alles Gruppierte. */
.karte {
background: var(--flaeche);
border: 1px solid var(--rahmen);
border-radius: var(--radius-gross);
padding: var(--s5);
box-shadow: var(--schatten);
}
.karte + .karte { margin-top: var(--s4); }
/* Kennzahlen (Nutzungsseite): eine Reihe kleiner Kacheln, die auf schmalen
* Bildschirmen umbrechen. auto-fit + minmax verteilt sie ohne Media-Query:
* so viele Spalten, wie mit mindestens 9rem Breite hineinpassen. */
.kennzahlen {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
gap: var(--s3);
}
.kennzahl {
display: flex;
flex-direction: column;
gap: var(--s1);
background: var(--flaeche);
border: 1px solid var(--rahmen);
border-radius: var(--radius-gross);
padding: var(--s4);
}
.kennzahl-wert { font-size: var(--t-h2); font-weight: 600; font-variant-numeric: tabular-nums; }
.kennzahl-name { font-size: var(--t-meta); color: var(--text-leise); }
/* Kurze Listen ohne Aufzählungspunkte, etwa "Verweise ins Leere". */
.kompakt-liste { list-style: none; padding: 0; margin: 0; }
.kompakt-liste li { padding: var(--s1) 0; border-bottom: 1px solid var(--rahmen); }
.kompakt-liste li:last-child { border-bottom: none; }
/* Summenzeile am Ende einer Tabelle. */
table.tabelle tr.summe td { font-weight: 600; border-top: 2px solid var(--rahmen); }
/* Meldungen. */
.meldung {
padding: var(--s3) var(--s4);
border: 1px solid var(--rahmen);
border-left-width: 3px;
border-radius: var(--radius);
margin-bottom: var(--s5);
font-size: var(--t-meta);
}
.meldung.hinweis { background: var(--akzent-flach); border-left-color: var(--akzent); }
.meldung.fehler { background: var(--warn-flach); border-left-color: var(--warn); }
/* Leerzustand: nicht nur ein grauer Absatz, sondern ein erkennbarer Bereich mit
* einem Hinweis, was als Nächstes zu tun wäre. */
.leer {
text-align: center;
padding: var(--s7) var(--s5);
border: 1px dashed var(--rahmen-stark);
border-radius: var(--radius-gross);
color: var(--text-leise);
}
.leer p { margin-bottom: var(--s4); }
.leer p:last-child { margin-bottom: 0; }
/* Marken: eine einzige visuelle Familie für alle kleinen Auszeichnungen. */
.marke {
display: inline-flex;
align-items: center;
gap: var(--s1);
padding: 0.1rem var(--s2);
border: 1px solid var(--rahmen);
border-radius: 999px;
font-size: var(--t-klein);
line-height: 1.5;
color: var(--text-leise);
white-space: nowrap;
}
a.marke:hover {
border-color: var(--rahmen-stark);
color: var(--text);
text-decoration: none;
}
.marke.betont {
background: var(--akzent-flach);
border-color: transparent;
color: var(--akzent-text);
}
/* Metazeile unter einem Titel: Marken und Kleintext in einer Reihe. */
.meta {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--s2);
color: var(--text-leise);
font-size: var(--t-klein);
}
/* Knöpfe. Drei Ausprägungen, mehr braucht es nicht. */
button, .knopf {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--s2);
padding: var(--s2) var(--s4);
min-height: var(--hoehe-bedienelement);
background: var(--akzent);
color: #fff;
border: 1px solid transparent;
border-radius: var(--radius);
font: inherit;
font-size: var(--t-meta);
font-weight: 500;
cursor: pointer;
text-decoration: none;
white-space: nowrap;
}
button:hover, .knopf:hover { filter: brightness(1.08); text-decoration: none; }
.knopf.zweitrangig, button.zweitrangig {
background: var(--flaeche);
color: var(--text);
border-color: var(--rahmen-stark);
}
.knopf.zweitrangig:hover, button.zweitrangig:hover {
background: var(--flaeche-leis);
filter: none;
}
button.warnung {
background: var(--flaeche);
color: var(--warn);
border-color: var(--warn);
}
button.warnung:hover { background: var(--warn-flach); filter: none; }
/* Ein Knopf, der wie ein Link aussieht — nötig, weil Abmelden ein POST sein muss
* (siehe CSRF-Schutz), aber wie ein Menüpunkt wirken soll. */
.wie-link {
background: none;
border: none;
padding: 0;
min-height: 0;
font: inherit;
font-size: var(--t-meta);
font-weight: normal;
color: var(--text-leise);
cursor: pointer;
}
.wie-link:hover { filter: none; text-decoration: underline; }
.reihe { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }
form.reihe { display: inline-flex; }
/* In rechtsbündigen Tabellenspalten (z. B. Verlauf) sollen die Aktionen
* ebenfalls rechts stehen — ein Flex-Container ignoriert text-align. */
.rechts > .reihe { justify-content: flex-end; }
/* Formulare.
*
* Jedes Feld ist ein .feld mit Beschriftung, optionalem Hinweis und Bedienelement.
* Die Breite richtet sich nach dem erwarteten Inhalt statt immer 100 % zu sein:
* Ein Feld für einen Bezeichner, das über die halbe Seite läuft, sieht aus wie
* ein Fehler. */
.formular { display: flex; flex-direction: column; gap: var(--s4); }
.feld { display: flex; flex-direction: column; gap: var(--s1); }
.feld > label { font-weight: 500; font-size: var(--t-meta); }
.feld > .hilfe { margin-bottom: var(--s1); }
input[type=text], input[type=search], input[type=password], select, textarea {
width: 100%;
padding: var(--s2) var(--s3);
min-height: var(--hoehe-bedienelement);
background: var(--flaeche);
border: 1px solid var(--rahmen-stark);
border-radius: var(--radius);
color: var(--text);
font: inherit;
font-size: var(--t-meta);
}
input::placeholder { color: var(--text-leise); opacity: 0.7; }
input:focus, select:focus, textarea:focus {
border-color: var(--akzent);
outline: 2px solid var(--akzent-flach);
outline-offset: 0;
}
textarea {
resize: vertical;
line-height: 1.6;
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
min-height: 20rem;
}
/* Reiter "Schreiben"/"Vorschau" über dem Inhaltsfeld. */
.editor-reiter {
display: flex;
gap: var(--s1);
margin-bottom: var(--s2);
border-bottom: 1px solid var(--rahmen);
}
.editor-reiter-knopf {
padding: var(--s2) var(--s3);
background: none;
border: none;
border-bottom: 2px solid transparent;
border-radius: 0;
min-height: 0;
color: var(--text-leise);
font-weight: 500;
font-size: var(--t-meta);
cursor: pointer;
margin-bottom: -1px;
}
.editor-reiter-knopf:hover { color: var(--text); filter: none; }
.editor-reiter-knopf.aktiv {
color: var(--text);
border-bottom-color: var(--akzent);
}
/* Vorschau-Fläche: dieselbe Textdarstellung wie die Detailansicht
* (.eintrag-text), aber als Formularfeld gerahmt, damit der Wechsel
* zwischen Schreiben und Vorschau nicht die Höhe des Formulars springen
* lässt. */
.eintrag-text.vorschau-flaeche {
min-height: 20rem;
max-width: none;
padding: var(--s3);
background: var(--flaeche);
border: 1px solid var(--rahmen-stark);
border-radius: var(--radius);
/* Überschreibt den großzügigen margin-top von .eintrag-text (siehe
* weiter unten) — hier steckt es in einem Formularfeld, nicht unter
* einer Überschrift. Die doppelte Klasse hebt die Reihenfolge im
* Stylesheet auf: diese Regel gewinnt unabhängig davon, wo sie steht. */
margin-top: 0;
}
.vorschau-flaeche.vorschau-laedt { color: var(--text-leise); }
/* Vorschlagsliste der Autovervollständigung für [[…]] — direkt unter dem
* Feld statt an der Schreibmarke ausgerichtet, siehe autocomplete.js. */
.autovervollstaendigung {
list-style: none;
margin: var(--s2) 0 0;
padding: 0;
max-height: 12rem;
overflow-y: auto;
background: var(--flaeche);
border: 1px solid var(--rahmen-stark);
border-radius: var(--radius);
box-shadow: var(--schatten);
}
.autovervollstaendigung li {
display: flex;
align-items: baseline;
gap: var(--s2);
padding: var(--s2) var(--s3);
cursor: pointer;
font-size: var(--t-meta);
}
.autovervollstaendigung li:not(:last-child) { border-bottom: 1px solid var(--rahmen); }
.autovervollstaendigung li span { color: var(--text-leise); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.autovervollstaendigung li.aktiv { background: var(--akzent-flach); }
.autovervollstaendigung li.aktiv span { color: var(--akzent-text); }
/* Feldbreiten nach Inhalt. */
.feld.kurz { max-width: 18rem; }
.feld.mittel { max-width: 28rem; }
.feld.lang { max-width: 40rem; }
/* Ankreuzfeld: Kästchen und Text nebeneinander, Text nicht fett. */
.ankreuz {
flex-direction: row;
align-items: flex-start;
gap: var(--s2);
}
/* Das Kästchen sitzt etwas tiefer als die Oberkante des Textes, damit es
* optisch auf der ersten Textzeile liegt statt darüber. */
.ankreuz input { width: auto; min-height: 0; margin-top: 0.3rem; }
.ankreuz label { font-weight: normal; }
.formular-aktionen {
display: flex;
gap: var(--s2);
align-items: center;
padding-top: var(--s2);
}
/* Tabellen. */
.tabelle-huelle {
background: var(--flaeche);
border: 1px solid var(--rahmen);
border-radius: var(--radius-gross);
box-shadow: var(--schatten);
overflow-x: auto; /* breite Tabellen scrollen in sich, nicht die Seite */
}
table.tabelle {
width: 100%;
border-collapse: collapse;
font-size: var(--t-meta);
}
.tabelle th, .tabelle td {
text-align: left;
padding: var(--s3) var(--s4);
border-bottom: 1px solid var(--rahmen);
vertical-align: middle;
}
.tabelle thead th {
background: var(--flaeche-leis);
color: var(--text-leise);
font-weight: 500;
font-size: var(--t-klein);
white-space: nowrap;
}
.tabelle tbody tr:last-child td { border-bottom: none; }
.tabelle tbody tr:hover { background: var(--flaeche-leis); }
.tabelle .zahl { text-align: right; font-variant-numeric: tabular-nums; }
.tabelle .schmal { width: 1%; white-space: nowrap; }
.tabelle .rechts { text-align: right; }
.tabelle tr.gedaempft { color: var(--text-leise); }
.tabelle tr.gedaempft td:first-child { text-decoration: line-through; }
/* ── 5. Seiten ───────────────────────────────────────────────────────────── */
/* Anmeldung: eigenständige, ruhige Seite ohne Navigation. */
.anmeldeseite {
min-height: 100dvh;
display: flex;
align-items: center;
justify-content: center;
padding: var(--s5);
}
.anmeldeseite .karte { width: 100%; padding: var(--s6); }
.anmeldeseite .hilfe { display: block; margin-bottom: var(--s5); }
/* Logo zentriert über der Anmeldekarte. */
.anmelde-logo { display: flex; justify-content: center; margin-bottom: var(--s4); }
.anmelde-logo img { width: 160px; height: auto; }
/* Werkzeugleiste über der Eintragsliste: Suche und Filter. */
.werkzeugleiste {
display: flex;
gap: var(--s2);
margin-bottom: var(--s4);
}
.werkzeugleiste input[type=search] { flex: 1; }
/* Eintragsliste. */
.eintraege {
list-style: none;
margin: 0;
padding: 0;
background: var(--flaeche);
border: 1px solid var(--rahmen);
border-radius: var(--radius-gross);
box-shadow: var(--schatten);
overflow: hidden;
}
.eintraege li {
display: flex;
align-items: flex-start;
gap: var(--s3);
padding: var(--s4);
border-bottom: 1px solid var(--rahmen);
}
.eintraege li:last-child { border-bottom: none; }
.eintraege li:hover { background: var(--flaeche-leis); }
/* Auswahlkästchen der Sammelbearbeitung: etwas abgesetzt vom Titel, auf
* dessen erster Zeile ausgerichtet statt an der Oberkante der ganzen Zeile. */
.eintrag-auswahl {
display: flex;
align-items: center;
padding-top: 0.35rem;
}
.eintrag-inhalt { flex: 1; min-width: 0; }
/* Sammelleiste: erscheint unter der Liste, sobald Einträge angehakt sind.
* position: sticky hält sie beim Scrollen einer langen Liste in Sichtweite. */
.sammelleiste {
display: flex;
align-items: center;
gap: var(--s2);
flex-wrap: wrap;
margin-top: var(--s3);
padding: var(--s3) var(--s4);
background: var(--flaeche);
border: 1px solid var(--rahmen);
border-radius: var(--radius-gross);
box-shadow: var(--schatten);
position: sticky;
bottom: var(--s4);
}
/* Papierkorb: "Alle von … wiederherstellen" steht mit etwas Abstand unter der
* Sammelleiste. */
.papierkorb-alle { margin-top: var(--s3); }
/* Für Screenreader lesbar, aber unsichtbar — etwa die Überschrift einer
* Spalte, die nur Kästchen enthält. display:none ginge nicht: Das würde den
* Text auch vor Screenreadern verstecken. */
.unsichtbar {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.sammelleiste input[type=text] {
width: auto;
flex: 1 1 12rem;
min-height: 2rem;
padding: var(--s1) var(--s2);
}
.eintrag-titel {
display: block;
font-size: var(--t-gross);
font-weight: 500;
color: var(--text);
margin-bottom: var(--s2);
}
.eintrag-ausschnitt {
margin: var(--s2) 0 0;
color: var(--text-leise);
font-size: var(--t-meta);
/* Auf zwei Zeilen begrenzen, damit alle Zeilen der Liste gleich hoch bleiben. */
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.eintrag-ausschnitt mark {
background: var(--akzent-flach);
color: var(--akzent-text);
padding: 0 0.15em;
border-radius: 3px;
}
/* Einzelner Eintrag: Fließtext in Lesebreite. */
.eintrag-text {
font-size: var(--t-gross);
line-height: 1.75;
margin-top: var(--s6);
}
.eintrag-text > :first-child { margin-top: 0; }
.eintrag-text h1, .eintrag-text h2, .eintrag-text h3 { margin: var(--s6) 0 var(--s3); }
.eintrag-text p, .eintrag-text ul, .eintrag-text ol { margin: 0 0 var(--s4); }
.eintrag-text ul, .eintrag-text ol { padding-left: var(--s5); }
.eintrag-text li { margin-bottom: var(--s1); }
.eintrag-text img { max-width: 100%; border-radius: var(--radius); }
.eintrag-text blockquote {
margin: var(--s4) 0;
padding: var(--s1) var(--s4);
border-left: 3px solid var(--rahmen-stark);
color: var(--text-leise);
}
.eintrag-text pre { margin-bottom: var(--s4); font-size: var(--t-meta); }
.eintrag-text table { border-collapse: collapse; width: 100%; font-size: var(--t-meta); }
.eintrag-text th, .eintrag-text td { border: 1px solid var(--rahmen); padding: var(--s2) var(--s3); }
.eintrag-text hr { border: none; border-top: 1px solid var(--rahmen); margin: var(--s6) 0; }
/* Checklisten (- [ ] / - [x]): Das Kästchen ersetzt den Aufzählungspunkt.
* :has() wählt nur Listenpunkte aus, die direkt ein Kästchen enthalten —
* gewöhnliche Aufzählungen behalten ihren Punkt. */
.eintrag-text li:has(> input[type="checkbox"]) { list-style: none; margin-left: calc(-1 * var(--s4)); }
.eintrag-text li > input[type="checkbox"] { margin: 0 var(--s2) 0 0; vertical-align: middle; }
.eintrag-text del { color: var(--text-leise); }
.rueckverweise { margin-top: var(--s7); }
.rueckverweise h2 { font-size: var(--t-meta); color: var(--text-leise); margin-bottom: var(--s3); }
.rueckverweise ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s2); }
/* Neu erzeugter Key: wird genau einmal angezeigt, also deutlich hervorheben. */
.key-anzeige { border-color: var(--akzent); background: var(--akzent-flach); }
.key-wert {
display: block;
margin: var(--s3) 0;
padding: var(--s3);
background: var(--flaeche);
border: 1px solid var(--rahmen-stark);
border-radius: var(--radius);
font-family: ui-monospace, Menlo, Consolas, monospace;
font-size: var(--t-meta);
word-break: break-all;
user-select: all; /* ein Klick markiert den ganzen Key */
}
.key-anleitung { margin-top: var(--s4); }
.key-anleitung summary {
cursor: pointer;
font-size: var(--t-meta);
color: var(--akzent-text);
}
.key-anleitung pre { margin-top: var(--s3); font-size: var(--t-klein); }
/* Fassungsvergleich. */
.diff-koepfe {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--s4);
margin-bottom: var(--s4);
}
.diff-kopf {
display: flex;
flex-direction: column;
gap: var(--s1);
padding: var(--s3) var(--s4);
background: var(--flaeche);
border: 1px solid var(--rahmen);
border-radius: var(--radius);
}
.diff-huelle {
background: var(--flaeche);
border: 1px solid var(--rahmen);
border-radius: var(--radius-gross);
box-shadow: var(--schatten);
overflow-x: auto;
}
.diff {
margin: 0;
padding: var(--s3) 0;
font-size: var(--t-meta);
line-height: 1.6;
white-space: pre-wrap;
word-break: break-word;
}
.diff span { display: block; padding: 0 var(--s4); }
.diff-hinzugefuegt { background: var(--akzent-flach); color: var(--akzent-text); }
.diff-entfernt { background: var(--warn-flach); color: var(--warn); }
/* Graph-Ansicht der Verweise. */
.graph-huelle {
background: var(--flaeche);
border: 1px solid var(--rahmen);
border-radius: var(--radius-gross);
box-shadow: var(--schatten);
overflow: hidden;
margin-bottom: var(--s4);
}
.graph-huelle svg {
display: block;
width: 100%;
height: 35rem;
cursor: grab;
touch-action: none;
}
.graph-huelle svg.graph-zieht { cursor: grabbing; }
.graph-kante { stroke: var(--rahmen-stark); stroke-width: 1.5; }
.graph-punkt {
fill: var(--akzent-flach);
stroke: var(--akzent);
stroke-width: 1.5;
}
.graph-knoten-fehlend .graph-punkt {
fill: var(--flaeche);
stroke: var(--rahmen-stark);
stroke-dasharray: 3 2;
}
.graph-beschriftung {
font-size: 0.75rem;
fill: var(--text);
dominant-baseline: middle;
/* Beschriftungen sollen das Ziehen des Graphen nicht durch
* Textmarkierung stören. */
user-select: none;
}
.graph-knoten-fehlend .graph-beschriftung { fill: var(--text-leise); }
.graph-klickbar { cursor: pointer; }
.graph-klickbar:hover .graph-punkt { stroke-width: 2.5; }
.graph-klickbar:hover .graph-beschriftung { fill: var(--akzent-text); }
/* Gefahrenzone: Löschvorgänge stehen abgesetzt am Seitenende, nicht zwischen
* den harmlosen Aktionen. Vorher steckte das Löschen eines Projekts samt
* Bestätigungsfeld in einer Tabellenzelle — zu eng und viel zu beiläufig für
* eine Aktion, die alle Einträge mitnimmt. */
.gefahrenzone { border-color: var(--warn); }
.gefahrenzone h2 { color: var(--warn); }
/* Hilfe: Themen als umbrechende Reiterleiste über dem Text, der Text selbst
* wie ein Eintrag in Lesebreite. */
.hilfe-navigation {
display: flex;
flex-wrap: wrap;
gap: var(--s2);
margin-top: var(--s5);
padding-bottom: var(--s4);
border-bottom: 1px solid var(--rahmen);
}
.hilfe-navigation a {
padding: var(--s1) var(--s3);
border: 1px solid var(--rahmen);
border-radius: var(--radius);
color: var(--text-leise);
font-size: var(--t-meta);
}
.hilfe-navigation a:hover { background: var(--flaeche-leis); color: var(--text); text-decoration: none; }
.hilfe-navigation a.aktiv {
background: var(--akzent-flach);
border-color: var(--akzent);
color: var(--akzent-text);
font-weight: 500;
}
.hilfe-text { max-width: var(--breite-lesen); }
/* Das kleine "?" neben Überschriften und Feldern (Partial "hilfelink").
* Bewusst unaufdringlich: ein Kreis in Textgröße, der erst beim Überfahren
* Farbe bekommt. Die Größe in rem (bezogen auf die Grundschrift, nicht auf
* die Umgebung), damit der Kreis neben einer großen h1 genauso klein bleibt
* wie neben einem Formular-Label. */
.hilfe-link {
display: inline-flex;
align-items: center;
justify-content: center;
width: 1.25rem;
height: 1.25rem;
margin-left: var(--s1);
border: 1px solid var(--rahmen);
border-radius: 50%;
font-size: 0.75rem;
font-weight: 600;
line-height: 1;
color: var(--text-leise);
vertical-align: middle;
}
.hilfe-link:hover {
border-color: var(--akzent);
color: var(--akzent-text);
text-decoration: none;
}
/* ── 6. Schmale Geräte ───────────────────────────────────────────────────── */
/* Unterhalb dieser Breite ist für zwei Spalten kein Platz mehr: Die Seitenleiste
* rückt über den Inhalt und wird flach — aus den Listen werden Zeilen, die bei
* Bedarf seitlich scrollen. So bleibt alles erreichbar, ohne dass eine
* ausklappbare Navigation samt JavaScript nötig wäre. */
@media (max-width: 60rem) {
.gerüst {
grid-template-columns: minmax(0, 1fr);
gap: 0;
padding-inline: var(--s4);
}
.kopfleiste-innen { padding-inline: var(--s4); }
.seitenleiste {
position: static;
max-height: none;
overflow: visible;
flex-direction: row;
flex-wrap: wrap;
gap: var(--s4);
padding-block: var(--s4);
border-bottom: 1px solid var(--rahmen);
}
/* Jede Gruppe wird zu einer Zeile: Überschrift links, Punkte daneben. */
.nav-gruppe {
flex-direction: row;
align-items: center;
gap: var(--s2);
min-width: 0;
flex: 1 1 100%;
}
.nav-titel { margin-bottom: 0; padding-inline: 0; white-space: nowrap; }
.nav-liste {
display: flex;
gap: var(--s1);
overflow-x: auto;
scrollbar-width: none; /* die Leiste scrollt, ohne einen Balken zu zeigen */
}
.nav-liste::-webkit-scrollbar { display: none; }
.nav-liste a { white-space: nowrap; }
/* Die Schlagwortliste kann lang werden — hier zählt jede Zeile. */
.schlagworte .nav-liste a { padding-inline: var(--s2); }
.inhalt { padding-block: var(--s5) var(--s7); }
.seitenkopf { gap: var(--s3); }
.seitenkopf-aktionen { width: 100%; }
.seitenkopf-aktionen .knopf { flex: 1; }
.karte { padding: var(--s4); }
.tabelle th, .tabelle td { padding: var(--s2) var(--s3); }
.feld.kurz, .feld.mittel, .feld.lang { max-width: none; }
textarea { min-height: 14rem; }
.diff-koepfe { grid-template-columns: 1fr; }
}